From 7ecc1006dad6ab1c799ff9e98c8065f3b5bec2c5 Mon Sep 17 00:00:00 2001 From: Alejandro Gullon Date: Wed, 17 Dec 2025 17:00:38 +0100 Subject: [PATCH 1/3] add z-1 bootc release testing scenarios --- .claude/.gitignore | 1 + .claude/agents/openshift-ci-analyzis.md | 105 + .claude/commands/analyze-ci-test-job.md | 416 + .claude/commands/analyze-ci-test-scenario.md | 408 + .claude/commands/analyze-microshift-start.md | 142 + .claude/commands/analyze-sos-report.md | 393 + .claude/commands/generate-tests-template.md | 244 + .claude/commands/generate-tests.md | 241 + .../commands/microshift-release-versions.md | 382 + .claude/scripts/extract_microshift_version.py | 302 + .claude/settings.json | 18 + .github/PULL_REQUEST_TEMPLATE.md | 9 - Makefile.kube_git.var | 4 +- Makefile.version.aarch64.var | 2 +- Makefile.version.x86_64.var | 2 +- apiserver-config-flow.md | 397 + .../csi_controller_deployment.yaml | 2 + .../multus/kustomization.aarch64.yaml | 4 +- .../multus/kustomization.x86_64.yaml | 4 +- .../multus/release-multus-aarch64.json | 6 +- .../multus/release-multus-x86_64.json | 6 +- .../openshift-dns/dns/configmap.yaml | 7 + .../openshift-dns/dns/daemonset.yaml | 13 + .../dns/hosts-configmap-role.yaml | 16 + .../dns/hosts-configmap-rolebinding.yaml | 13 + assets/components/service-ca/deployment.yaml | 1 - ...rver-operator_00_cr-scc-restricted-v3.yaml | 18 + ...systemauthenticated-scc-restricted-v3.yaml | 16 + ...iserver-operator_00_scc-restricted-v3.yaml | 61 + assets/crd/route.crd.yaml | 4 +- .../kserve/certmanager/certificate.yaml | 24 + .../kserve/certmanager/kustomization.yaml | 6 + .../kserve/configmap/inferenceservice.yaml | 155 +- .../gateway-inference-extension.yaml | 540 + .../kustomization.yaml | 5 + ...er.opendatahub.io_datascienceclusters.yaml | 763 + ...ion.opendatahub.io_dscinitializations.yaml | 311 + .../opendatahub-operator/kustomization.yaml | 6 + .../kserve/crd/full/kustomization.yaml | 15 + ...ving.kserve.io_clusterservingruntimes.yaml | 4 + ...ng.kserve.io_clusterstoragecontainers.yaml | 2 + .../serving.kserve.io_inferencegraphs.yaml | 27 + .../serving.kserve.io_inferenceservices.yaml | 689 + ....kserve.io_llminferenceserviceconfigs.yaml | 19270 +++++++++++++++ ...erving.kserve.io_llminferenceservices.yaml | 19380 ++++++++++++++++ ...> serving.kserve.io_localmodelcaches.yaml} | 22 +- .../serving.kserve.io_localmodelnodes.yaml | 61 + .../serving.kserve.io_servingruntimes.yaml | 4 + .../kserve/crd/kustomization.yaml | 9 +- .../cainjection_conversion_webhook.yaml | 2 +- ...h_validatingwebhook_cainjection_patch.yaml | 2 +- ...svc_mutatingwebhook_cainjection_patch.yaml | 2 +- ...c_validatingwebhook_cainjection_patch.yaml | 2 +- .../kserve/default/kustomization.yaml | 229 +- ...c_validatingwebhook_cainjection_patch.yaml | 8 + ...g_validatingwebhook_cainjection_patch.yaml | 8 + ...e_validatingwebhook_cainjection_patch.yaml | 8 + .../localmodelnode_agent_image_patch.yaml | 12 + .../default/manager_auth_proxy_patch.yaml | 2 + ...e_validationwebhook_cainjection_patch.yaml | 2 +- ...l_validatingwebhook_cainjection_patch.yaml | 2 +- ...erenceservice-config-microshift-patch.yaml | 9 +- .../llmisvc/config-llm-decode-template.yaml | 261 + ...onfig-llm-decode-worker-data-parallel.yaml | 520 + .../llmisvc/config-llm-prefill-template.yaml | 206 + ...nfig-llm-prefill-worker-data-parallel.yaml | 462 + .../llmisvc/config-llm-router-route.yaml | 38 + .../kserve/llmisvc/config-llm-scheduler.yaml | 92 + .../kserve/llmisvc/config-llm-template.yaml | 205 + .../config-llm-worker-data-parallel.yaml | 461 + .../kserve/llmisvc/kustomization.yaml | 15 + .../kserve/localmodelnodes/kustomization.yaml | 5 + .../kserve/localmodelnodes/manager.yaml | 70 + .../kserve/localmodels/kustomization.yaml | 5 + .../kserve/localmodels/manager.yaml | 55 + .../kserve/manager/manager.yaml | 10 +- .../kserve/manager/service.yaml | 15 +- .../llmisvc/istio_gateway_monitor.yaml | 17 + .../monitoring/llmisvc/kustomization.yaml | 13 + .../kserve/monitoring/llmisvc/rbac.yaml | 9 + .../kserve/overlays/odh/kustomization.yaml | 115 +- .../kserve/overlays/odh/llm-svc-scc.yaml | 95 + .../odh}/network-policies.yaml | 0 .../kserve/overlays/odh/params.env | 11 +- .../kserve/overlays/odh/params.yaml | 6 + .../patch-inferenceservice-config.yaml} | 7 +- .../patch-set-resources-manager.yaml} | 0 ...webhook-svc-openshift-cert-injection.yaml} | 0 .../odh/patches/remove-cert-manager.yaml | 13 + .../patches/remove-clusterservingruntime.yaml | 11 + .../odh/patches/remove-local-model.yaml | 75 + .../kserve/overlays/odh/remove-namespace.yaml | 6 - .../overlays/odh/user-cluster-roles.yaml | 4 + .../kserve/rbac/kustomization.yaml | 3 + .../kserve/rbac/localmodel/role.yaml | 26 +- .../kserve/rbac/localmodelnode/role.yaml | 74 + .../rbac/localmodelnode/role_binding.yaml | 12 + .../rbac/localmodelnode/service_account.yaml | 9 + .../ai-model-serving/kserve/rbac/role.yaml | 166 +- .../kserve/webhook/manifests.yaml | 132 +- .../release-ai-model-serving-x86_64.json | 34 +- .../runtimes/kustomization.x86_64.yaml | 51 +- .../runtimes/ovms-kserve.yaml | 2 +- .../ai-model-serving/runtimes/vllm-cuda.yaml | 2 +- .../ai-model-serving/runtimes/vllm-gaudi.yaml | 2 +- .../ai-model-serving/runtimes/vllm-rocm.yaml | 2 +- .../0000_50_olm_00-catalogsources.crd.yaml | 6 +- ..._50_olm_00-clusterserviceversions.crd.yaml | 458 +- .../0000_50_olm_00-installplans.crd.yaml | 2 +- .../0000_50_olm_00-olmconfigs.crd.yaml | 2 +- ...0000_50_olm_00-operatorconditions.crd.yaml | 2 +- .../0000_50_olm_00-operatorgroups.crd.yaml | 2 +- .../0000_50_olm_00-operators.crd.yaml | 2 +- .../0000_50_olm_00-subscriptions.crd.yaml | 172 +- ...50_olm_02-olm-operator.serviceaccount.yaml | 12 + ...000_50_olm_07-olm-operator.deployment.yaml | 2 +- ...50_olm_08-catalog-operator.deployment.yaml | 2 +- .../kustomization.aarch64.yaml | 10 +- .../kustomization.x86_64.yaml | 10 +- .../release-olm-aarch64.json | 8 +- .../release-olm-x86_64.json | 8 +- ...sriovnetwork.openshift.io_ovsnetworks.yaml | 111 + ...vnetwork.openshift.io_sriovibnetworks.yaml | 84 + ...openshift.io_sriovnetworknodepolicies.yaml | 219 + ...k.openshift.io_sriovnetworknodestates.yaml | 375 + ....openshift.io_sriovnetworkpoolconfigs.yaml | 137 + ...iovnetwork.openshift.io_sriovnetworks.yaml | 142 + ...ork.openshift.io_sriovoperatorconfigs.yaml | 120 + assets/optional/sriov/deploy/clusterrole.yaml | 122 + .../sriov/deploy/clusterrolebinding.yaml | 25 + assets/optional/sriov/deploy/namespace.yaml | 9 + assets/optional/sriov/deploy/operator.yaml | 112 + assets/optional/sriov/deploy/role.yaml | 153 + assets/optional/sriov/deploy/rolebinding.yaml | 25 + .../optional/sriov/deploy/serviceaccount.yaml | 13 + .../sriov/deploy/sriovoperatorconfig.yaml | 10 + .../supported-nic-ids_v1_configmap.yaml | 52 + assets/optional/sriov/kustomization.yaml | 19 + .../optional/sriov/release-sriov-aarch64.json | 17 + .../optional/sriov/release-sriov-x86_64.json | 17 + assets/release/release-aarch64.json | 18 +- assets/release/release-x86_64.json | 18 +- .../config/config-openapi-spec.json | 56 + ...hboard-microshift-telemetry.configmap.yaml | 640 +- .../openshift/kubernetes/.go-version | 2 +- .../kubernetes/CHANGELOG/CHANGELOG-1.34.md | 212 +- .../openshift/kubernetes/REBASE.openshift.md | 15 +- .../build/build-image/cross/VERSION | 2 +- .../openshift/kubernetes/build/common.sh | 6 +- .../kubernetes/build/dependencies.yaml | 18 +- .../cluster/addons/addon-manager/Makefile | 2 +- .../openshift/kubernetes/cluster/common.sh | 4 +- .../kubernetes/cluster/gce/config-default.sh | 2 +- .../kubernetes/cluster/gce/config-test.sh | 2 +- .../cluster/gce/gci/configure-helper.sh | 12 +- .../cluster/gce/manifests/etcd.manifest | 36 +- .../kubernetes/cluster/gce/upgrade-aliases.sh | 4 +- .../openshift/kubernetes/cluster/gce/util.sh | 12 +- .../kubernetes/cluster/images/etcd/Makefile | 10 +- .../kubernetes/cmd/kubeadm/app/cmd/certs.go | 6 +- .../kubernetes/cmd/kubeadm/app/cmd/init.go | 40 +- .../kubernetes/cmd/kubeadm/app/cmd/join.go | 37 +- .../cmd/kubeadm/app/cmd/phases/init/data.go | 2 +- .../kubeadm/app/cmd/phases/init/data_test.go | 2 +- .../app/cmd/phases/init/waitcontrolplane.go | 3 +- .../cmd/kubeadm/app/cmd/phases/join/data.go | 1 + .../kubeadm/app/cmd/phases/join/data_test.go | 27 +- .../app/cmd/phases/join/waitcontrolplane.go | 2 +- .../kubernetes/cmd/kubeadm/app/cmd/reset.go | 6 +- .../cmd/kubeadm/app/cmd/upgrade/apply.go | 5 +- .../cmd/kubeadm/app/cmd/upgrade/common.go | 6 +- .../cmd/kubeadm/app/cmd/upgrade/diff.go | 8 +- .../cmd/kubeadm/app/cmd/upgrade/diff_test.go | 2 +- .../cmd/kubeadm/app/cmd/upgrade/node.go | 19 +- .../cmd/kubeadm/app/cmd/util/join.go | 6 +- .../cmd/kubeadm/app/cmd/util/join_test.go | 2 +- .../cmd/kubeadm/app/constants/constants.go | 12 +- .../cmd/kubeadm/app/discovery/discovery.go | 6 +- .../cmd/kubeadm/app/discovery/file/file.go | 11 +- .../cmd/kubeadm/app/discovery/token/token.go | 6 +- .../kubeadm/app/discovery/token/token_test.go | 34 +- .../cmd/kubeadm/app/preflight/checks.go | 7 +- .../cmd/kubeadm/app/util/apiclient/wait.go | 4 +- .../cmd/kubeadm/app/util/config/cluster.go | 23 +- .../kubeadm/app/util/config/cluster_test.go | 29 +- .../cmd/kubeadm/app/util/dryrun/dryrun.go | 8 +- .../kubeadm/app/util/kubeconfig/kubeconfig.go | 12 +- .../app/util/kubeconfig/kubeconfig_test.go | 51 +- .../kubeadm/app/util/pkiutil/pki_helpers.go | 30 +- .../cmd/kubeadm/app/util/staticpod/utils.go | 15 + deps/github.com/openshift/kubernetes/go.mod | 5 +- deps/github.com/openshift/kubernetes/go.sum | 8 +- .../openshift/kubernetes/hack/lib/etcd.sh | 2 +- .../openshift/kubernetes/hack/lib/util.sh | 2 +- .../kubernetes/hack/make-rules/update.sh | 1 - .../hack/update-test-annotations.sh | 1 - .../hack/verify-test-annotations.sh | 1 - .../cmd/k8s-tests-ext/disabled_tests.go | 11 - .../cmd/k8s-tests-ext/k8s-tests.go | 48 +- .../cmd/k8s-tests-ext/labels.go | 6 +- .../openshift-hack/e2e/annotate/annotate.go | 290 - .../e2e/annotate/annotate_test.go | 55 - .../openshift-hack/e2e/annotate/cmd/main.go | 9 - .../generated/zz_generated.annotations.go | 14905 ------------ .../openshift-hack/e2e/annotate/rules.go | 37 - .../openshift-hack/e2e/annotate/rules_test.go | 92 - .../kubernetes/openshift-hack/e2e/include.go | 1 - .../openshift-hack/e2e/kube_e2e_test.go | 7 +- .../images/hyperkube/Dockerfile.rhel | 2 +- .../openshift-hack/test-kubernetes-e2e.sh | 2 +- .../openshift-hack/update-test-annotations.sh | 13 - .../openshift-hack/verify-test-annotations.sh | 28 - .../kubernetes/pkg/api/service/warnings.go | 2 +- .../pkg/api/service/warnings_test.go | 25 +- .../pkg/apis/batch/validation/validation.go | 9 + .../certificates/v1beta1/defaults_test.go | 6 +- .../pkg/controller/controller_utils.go | 65 +- .../pkg/controller/controller_utils_test.go | 71 +- .../controller/daemon/daemon_controller.go | 4 +- .../controller/history/controller_history.go | 18 - .../pkg/controller/job/job_controller.go | 4 +- .../pkg/controller/job/job_controller_test.go | 2 + .../pkg/controller/replicaset/replica_set.go | 4 +- .../controller/statefulset/stateful_set.go | 4 +- .../stateful_set_compatibility_test.go | 149 + .../statefulset/stateful_set_control.go | 56 +- .../statefulset/stateful_set_control_test.go | 3 +- .../compatibility_revision_1.33.0.json | 25 + .../compatibility_revision_1.34.0.json | 25 + .../testdata/compatibility_set_1.33.0.json | 104 + .../testdata/compatibility_set_1.34.0.json | 102 + .../kubernetes/pkg/features/kube_features.go | 14 +- .../cm/dra/plugin/dra_plugin_manager.go | 20 +- .../kubelet/cm/dra/plugin/dra_plugin_test.go | 38 + .../kuberuntime/kuberuntime_container.go | 6 + .../kubernetes/pkg/kubelet/managed/managed.go | 36 + .../pkg/kubelet/managed/managed_test.go | 172 + .../kubernetes/pkg/kubelet/prober/worker.go | 17 +- .../pkg/kubelet/prober/worker_test.go | 85 + .../pkg/proxy/util/localdetector.go | 8 +- .../pkg/proxy/util/localdetector_test.go | 64 + .../kubernetes/pkg/proxy/winkernel/hns.go | 20 +- .../pkg/proxy/winkernel/hns_test.go | 2 + .../kubernetes/pkg/proxy/winkernel/proxier.go | 10 +- .../pkg/proxy/winkernel/proxier_test.go | 197 +- .../pkg/registry/batch/job/strategy.go | 7 +- .../pkg/registry/batch/job/strategy_test.go | 27 + .../api_dispatcher/api_dispatcher_test.go | 10 +- .../backend/api_dispatcher/call_queue_test.go | 22 +- .../tainttoleration/taint_toleration.go | 4 +- .../tainttoleration/taint_toleration_test.go | 6 +- .../framework/preemption/preemption.go | 94 +- .../framework/preemption/preemption_test.go | 67 +- .../kubernetes/pkg/volume/csi/csi_attacher.go | 2 +- .../kubernetes/pkg/volume/plugins.go | 2 +- .../pkg/volume/portworx/portworx.go | 33 +- .../kubernetes/staging/publishing/rules.yaml | 126 +- .../pkg/authorizer/webhook/metrics_test.go | 14 +- .../leaderelection/resourcelock/leaselock.go | 3 + .../resourcelock/leaselock_test.go | 34 +- .../src/k8s.io/client-go/util/cert/cert.go | 4 +- .../allocatortesting/allocator_testing.go | 52 +- .../experimental/allocator_experimental.go | 40 +- .../incubating/allocator_incubating.go | 40 +- .../internal/stable/allocator_stable.go | 40 +- .../pkg/cmd/apiresources/apiresources.go | 3 + .../reference/versioned_feature_list.yaml | 8 +- .../test/conformance/image/Makefile | 2 +- .../node/framework/cgroups/cgroups_linux.go | 24 +- .../e2e/framework/metrics/kubelet_metrics.go | 1 - .../e2e/framework/metrics/metrics_grabber.go | 31 +- .../kubernetes/test/e2e/framework/pv/wait.go | 9 +- .../csimock/mutable_csinode_allocatable.go | 65 +- .../test/e2e/storage/drivers/csi.go | 111 +- .../test/e2e/storage/testsuites/base.go | 1 - .../testsuites/volume_group_snapshottable.go | 11 +- .../storage/utils/volume_group_snapshot.go | 8 +- .../storage-csi/external-attacher/rbac.yaml | 4 +- .../rbac.yaml | 4 +- .../external-provisioner/rbac.yaml | 4 +- .../storage-csi/external-resizer/rbac.yaml | 5 +- .../csi-snapshotter/rbac-csi-snapshotter.yaml | 9 +- ...age.k8s.io_volumegroupsnapshotclasses.yaml | 86 +- ...ge.k8s.io_volumegroupsnapshotcontents.yaml | 339 +- ...t.storage.k8s.io_volumegroupsnapshots.yaml | 223 +- .../csi-hostpath-plugin.yaml | 2 +- .../run_group_snapshot_e2e.sh | 15 +- .../storage-csi/hostpath/README.md | 2 +- .../hostpath/csi-hostpath-plugin.yaml | 34 +- .../hostpath/csi-hostpath-testing.yaml | 2 +- .../mock/csi-mock-driver-attacher.yaml | 2 +- .../mock/csi-mock-driver-resizer.yaml | 2 +- .../mock/csi-mock-driver-snapshotter.yaml | 2 +- .../storage-csi/mock/csi-mock-driver.yaml | 6 +- .../storage-csi/mock/csi-mock-proxy.yaml | 6 +- .../storage-csi/update-hostpath.sh | 15 +- .../test/e2e_node/container_lifecycle_test.go | 106 + .../kubernetes/test/images/nonroot/BASEIMAGE | 10 +- .../test/images/pets/peer-finder/BASEIMAGE | 10 +- .../images/pets/zookeeper-installer/BASEIMAGE | 8 +- .../images/regression-issue-74839/BASEIMAGE | 10 +- .../test/images/resource-consumer/BASEIMAGE | 10 +- .../apimachinery/apply/apply_test.go | 10 +- .../test/integration/auth/auth_test.go | 49 +- .../test/integration/auth/testdata/README.md | 1 + .../auth/testdata/sloppy-san-client-key.pem | 5 + .../auth/testdata/sloppy-san-client.pem | 65 + .../auth/testdata/sloppy-san-root.pem | 78 + .../test/integration/job/job_test.go | 79 + .../scheduler/preemption/misc/main_test.go | 27 + .../preemption/misc/miscpreemption_test.go | 1238 + .../nominatednodename_test.go | 5 +- .../scheduler/preemption/preemption_test.go | 1200 +- .../volume/persistent_volumes_test.go | 21 +- .../kubernetes/test/utils/image/manifest.go | 2 +- .../github.com/MakeNowJust/heredoc/README.md | 52 - .../google/cadvisor/cache/memory/memory.go | 84 +- .../google/cadvisor/manager/container.go | 28 +- .../google/cadvisor/manager/manager.go | 207 +- .../validators/types_unix.go | 7 - .../openshift/kubernetes/vendor/modules.txt | 5 +- docs/user/README.md | 38 +- docs/user/howto_config.md | 16 + etcd/cmd/microshift-etcd/run.go | 4 +- etcd/go.mod | 69 +- etcd/go.sum | 207 +- .../golang-jwt/jwt/v4/MIGRATION_GUIDE.md | 22 - .../github.com/golang-jwt/jwt/v4/README.md | 138 - .../github.com/golang-jwt/jwt/v4/claims.go | 269 - .../github.com/golang-jwt/jwt/v4/errors.go | 112 - .../golang-jwt/jwt/v4/map_claims.go | 151 - .../github.com/golang-jwt/jwt/v4/parser.go | 206 - .../golang-jwt/jwt/v4/parser_option.go | 29 - .../github.com/golang-jwt/jwt/v4/token.go | 143 - .../golang-jwt/jwt/{v4 => v5}/.gitignore | 0 .../golang-jwt/jwt/{v4 => v5}/LICENSE | 0 .../golang-jwt/jwt/v5/MIGRATION_GUIDE.md | 195 + .../github.com/golang-jwt/jwt/v5/README.md | 167 + .../golang-jwt/jwt/{v4 => v5}/SECURITY.md | 4 +- .../jwt/{v4 => v5}/VERSION_HISTORY.md | 16 +- .../github.com/golang-jwt/jwt/v5/claims.go | 16 + .../golang-jwt/jwt/{v4 => v5}/doc.go | 0 .../golang-jwt/jwt/{v4 => v5}/ecdsa.go | 24 +- .../golang-jwt/jwt/{v4 => v5}/ecdsa_utils.go | 0 .../golang-jwt/jwt/{v4 => v5}/ed25519.go | 30 +- .../jwt/{v4 => v5}/ed25519_utils.go | 0 .../github.com/golang-jwt/jwt/v5/errors.go | 49 + .../golang-jwt/jwt/v5/errors_go1_20.go | 47 + .../golang-jwt/jwt/v5/errors_go_other.go | 78 + .../golang-jwt/jwt/{v4 => v5}/hmac.go | 39 +- .../golang-jwt/jwt/v5/map_claims.go | 109 + .../golang-jwt/jwt/{v4 => v5}/none.go | 18 +- .../github.com/golang-jwt/jwt/v5/parser.go | 268 + .../golang-jwt/jwt/v5/parser_option.go | 128 + .../golang-jwt/jwt/v5/registered_claims.go | 63 + .../golang-jwt/jwt/{v4 => v5}/rsa.go | 22 +- .../golang-jwt/jwt/{v4 => v5}/rsa_pss.go | 22 +- .../golang-jwt/jwt/{v4 => v5}/rsa_utils.go | 6 +- .../jwt/{v4 => v5}/signing_method.go | 11 +- .../jwt/{v4 => v5}/staticcheck.conf | 0 .../github.com/golang-jwt/jwt/v5/token.go | 100 + .../golang-jwt/jwt/v5/token_option.go | 5 + .../golang-jwt/jwt/{v4 => v5}/types.go | 48 +- .../github.com/golang-jwt/jwt/v5/validator.go | 316 + .../golang/protobuf/descriptor/descriptor.go | 180 - .../golang/protobuf/jsonpb/decode.go | 531 - .../golang/protobuf/jsonpb/encode.go | 560 - .../github.com/golang/protobuf/jsonpb/json.go | 69 - .../protoc-gen-go/descriptor/descriptor.pb.go | 324 - .../golang/protobuf/ptypes/any/any.pb.go | 62 - .../protobuf/ptypes/duration/duration.pb.go | 63 - .../protobuf/ptypes/timestamp/timestamp.pb.go | 64 - .../protobuf/ptypes/wrappers/wrappers.pb.go | 71 - .../go-grpc-middleware/.gitignore | 204 - .../go-grpc-middleware/.travis.yml | 16 - .../go-grpc-middleware/CHANGELOG.md | 51 - .../go-grpc-middleware/CONTRIBUTING.md | 20 - .../go-grpc-middleware/README.md | 86 - .../go-grpc-middleware/chain.go | 120 - .../grpc-ecosystem/go-grpc-middleware/doc.go | 69 - .../go-grpc-middleware/makefile | 17 - .../{ => providers/prometheus}/LICENSE | 0 .../providers/prometheus/client_metrics.go | 117 + .../providers/prometheus/client_options.go | 77 + .../providers/prometheus/constants.go | 23 + .../providers/prometheus/doc.go | 8 + .../providers/prometheus/options.go | 129 + .../providers/prometheus/reporter.go | 113 + .../providers/prometheus/server_metrics.go | 124 + .../providers/prometheus/server_options.go | 48 + .../go-grpc-middleware/slack.png | Bin 5088 -> 0 bytes .../go-grpc-middleware/v2/COPYRIGHT | 2 + .../v2}/LICENSE | 0 .../v2/interceptors/callmeta.go | 66 + .../v2/interceptors/client.go | 79 + .../go-grpc-middleware/v2/interceptors/doc.go | 12 + .../v2/interceptors/reporter.go | 75 + .../v2/interceptors/server.go | 65 + .../go-grpc-middleware/wrappers.go | 30 - .../go-grpc-prometheus/.gitignore | 201 - .../go-grpc-prometheus/.travis.yml | 25 - .../go-grpc-prometheus/CHANGELOG.md | 24 - .../go-grpc-prometheus/README.md | 247 - .../go-grpc-prometheus/client.go | 39 - .../go-grpc-prometheus/client_metrics.go | 170 - .../go-grpc-prometheus/client_reporter.go | 46 - .../go-grpc-prometheus/makefile | 16 - .../go-grpc-prometheus/metric_options.go | 41 - .../go-grpc-prometheus/server.go | 48 - .../go-grpc-prometheus/server_metrics.go | 185 - .../go-grpc-prometheus/server_reporter.go | 46 - .../grpc-ecosystem/go-grpc-prometheus/util.go | 50 - .../grpc-ecosystem/grpc-gateway/LICENSE.txt | 27 - .../grpc-gateway/internal/BUILD.bazel | 23 - .../grpc-gateway/internal/errors.pb.go | 189 - .../grpc-gateway/internal/errors.proto | 26 - .../grpc-gateway/runtime/BUILD.bazel | 85 - .../grpc-gateway/runtime/context.go | 291 - .../grpc-gateway/runtime/convert.go | 318 - .../grpc-gateway/runtime/doc.go | 5 - .../grpc-gateway/runtime/errors.go | 186 - .../grpc-gateway/runtime/fieldmask.go | 89 - .../grpc-gateway/runtime/handler.go | 212 - .../runtime/marshal_httpbodyproto.go | 43 - .../grpc-gateway/runtime/marshal_json.go | 45 - .../grpc-gateway/runtime/marshal_jsonpb.go | 262 - .../grpc-gateway/runtime/marshal_proto.go | 62 - .../grpc-gateway/runtime/marshaler.go | 55 - .../runtime/marshaler_registry.go | 99 - .../grpc-gateway/runtime/mux.go | 300 - .../grpc-gateway/runtime/pattern.go | 262 - .../grpc-gateway/runtime/proto2_convert.go | 80 - .../grpc-gateway/runtime/proto_errors.go | 106 - .../grpc-gateway/runtime/query.go | 406 - .../grpc-gateway/utilities/BUILD.bazel | 21 - .../grpc-gateway/utilities/doc.go | 2 - .../grpc-gateway/utilities/pattern.go | 22 - .../grpc-gateway/utilities/readerfactory.go | 20 - .../grpc-gateway/utilities/trie.go | 177 - .../protoc-gen-openapiv2/options/BUILD.bazel | 44 + .../options/annotations.pb.go | 269 + .../options/annotations.proto | 51 + .../options/annotations_protoopaque.pb.go | 269 + .../protoc-gen-openapiv2/options/buf.gen.yaml | 7 + .../options/openapiv2.pb.go | 4263 ++++ .../options/openapiv2.proto | 759 + .../options/openapiv2_protoopaque.pb.go | 4055 ++++ .../api/config/v1/types_cluster_version.go | 18 +- .../api/config/v1/types_infrastructure.go | 135 + ..._generated.featuregated-crd-manifests.yaml | 3 + .../v1/zz_generated.swagger_doc_generated.go | 11 +- .../openshift/api/features/features.go | 926 + .../api/features/legacyfeaturegates.go | 119 + .../github.com/openshift/api/features/util.go | 224 + .../operator/v1/types_csi_cluster_driver.go | 1 - .../api/operator/v1/types_ingress.go | 17 + .../v1/zz_generated.swagger_doc_generated.go | 2 +- .../microshift/pkg/config/apiserver.go | 102 + .../openshift/microshift/pkg/config/config.go | 31 +- .../openshift/microshift/pkg/config/dns.go | 82 + .../openshift/microshift/pkg/util/net.go | 6 +- etcd/vendor/go.etcd.io/bbolt/.go-version | 2 +- etcd/vendor/go.etcd.io/bbolt/tx.go | 68 +- .../go.etcd.io/etcd/api/v3/authpb/auth.pb.go | 47 +- .../go.etcd.io/etcd/api/v3/authpb/auth.proto | 2 + .../etcd/api/v3/etcdserverpb/etcdserver.pb.go | 52 +- .../etcd/api/v3/etcdserverpb/etcdserver.proto | 2 + .../etcd/api/v3/etcdserverpb/gw/rpc.pb.gw.go | 3209 +-- .../api/v3/etcdserverpb/raft_internal.pb.go | 192 +- .../api/v3/etcdserverpb/raft_internal.proto | 22 +- .../v3/etcdserverpb/raft_internal_stringer.go | 12 +- .../etcd/api/v3/etcdserverpb/rpc.pb.go | 1291 +- .../etcd/api/v3/etcdserverpb/rpc.proto | 343 +- .../etcd/api/v3/membershippb/membership.pb.go | 53 +- .../etcd/api/v3/membershippb/membership.proto | 15 + .../go.etcd.io/etcd/api/v3/mvccpb/kv.pb.go | 42 +- .../go.etcd.io/etcd/api/v3/mvccpb/kv.proto | 2 + .../etcd/api/v3/v3rpc/rpctypes/error.go | 168 +- .../api/v3/v3rpc/rpctypes/metadatafields.go | 3 + .../go.etcd.io/etcd/api/v3/version/version.go | 31 +- .../etcd/api/v3/versionpb/version.pb.go | 91 + .../etcd/api/v3/versionpb/version.proto | 30 + .../etcd/client/pkg/v3/fileutil/dir_unix.go | 3 +- .../client/pkg/v3/fileutil/dir_windows.go | 3 +- .../etcd/client/pkg/v3/fileutil/fileutil.go | 27 +- .../etcd/client/pkg/v3/fileutil/lock.go | 4 +- .../etcd/client/pkg/v3/fileutil/lock_flock.go | 4 +- .../etcd/client/pkg/v3/fileutil/lock_linux.go | 8 +- .../client/pkg/v3/fileutil/lock_solaris.go | 1 - .../etcd/client/pkg/v3/fileutil/lock_unix.go | 1 - .../client/pkg/v3/fileutil/lock_windows.go | 47 +- .../client/pkg/v3/fileutil/preallocate.go | 6 +- .../pkg/v3/fileutil/preallocate_darwin.go | 4 +- .../pkg/v3/fileutil/preallocate_unix.go | 10 +- .../v3/fileutil/preallocate_unsupported.go | 1 - .../etcd/client/pkg/v3/fileutil/purge.go | 38 +- .../etcd/client/pkg/v3/fileutil/sync.go | 1 - .../client/pkg/v3/fileutil/sync_darwin.go | 1 - .../etcd/client/pkg/v3/fileutil/sync_linux.go | 1 - .../etcd/client/pkg/v3/logutil/log_format.go | 42 + .../etcd/client/pkg/v3/logutil/zap.go | 49 +- .../etcd/client/pkg/v3/logutil/zap_journal.go | 5 +- .../go.etcd.io/etcd/client/pkg/v3/srv/srv.go | 16 +- .../etcd/client/pkg/v3/tlsutil/tlsutil.go | 8 +- .../pkg/v3/transport/keepalive_listener.go | 12 +- .../client/pkg/v3/transport/limit_listen.go | 4 +- .../etcd/client/pkg/v3/transport/listener.go | 190 +- .../client/pkg/v3/transport/listener_opts.go | 14 + .../client/pkg/v3/transport/listener_tls.go | 11 +- .../etcd/client/pkg/v3/transport/sockopt.go | 14 + .../pkg/v3/transport/sockopt_solaris.go | 5 +- .../client/pkg/v3/transport/sockopt_unix.go | 3 +- .../client/pkg/v3/transport/sockopt_wasm.go} | 23 +- .../pkg/v3/transport/sockopt_windows.go | 21 +- .../etcd/client/pkg/v3/transport/tls.go | 3 +- .../etcd/client/pkg/v3/transport/transport.go | 13 +- .../go.etcd.io/etcd/client/pkg/v3/types/id.go | 19 +- .../etcd/client/pkg/v3/types/set.go | 2 +- .../etcd/client/pkg/v3/verify/verify.go | 80 + etcd/vendor/go.etcd.io/etcd/client/v2/json.go | 73 - etcd/vendor/go.etcd.io/etcd/client/v3/OWNERS | 4 + .../go.etcd.io/etcd/client/v3/README.md | 22 +- etcd/vendor/go.etcd.io/etcd/client/v3/auth.go | 3 +- .../go.etcd.io/etcd/client/v3/client.go | 130 +- .../go.etcd.io/etcd/client/v3/cluster.go | 12 +- .../go.etcd.io/etcd/client/v3/compare.go | 12 +- .../etcd/client/v3/concurrency/election.go | 2 +- .../etcd/client/v3/concurrency/key.go | 15 +- .../etcd/client/v3/concurrency/mutex.go | 19 +- .../etcd/client/v3/concurrency/session.go | 29 +- .../etcd/client/v3/concurrency/stm.go | 4 + .../go.etcd.io/etcd/client/v3/config.go | 129 +- .../etcd/client/v3/credentials/credentials.go | 86 +- etcd/vendor/go.etcd.io/etcd/client/v3/ctx.go | 3 +- etcd/vendor/go.etcd.io/etcd/client/v3/doc.go | 5 +- .../client/v3/internal/endpoint/endpoint.go | 26 +- .../client/v3/internal/resolver/resolver.go | 11 +- etcd/vendor/go.etcd.io/etcd/client/v3/kv.go | 20 +- .../vendor/go.etcd.io/etcd/client/v3/lease.go | 27 +- .../go.etcd.io/etcd/client/v3/logger.go | 5 +- .../go.etcd.io/etcd/client/v3/maintenance.go | 159 +- etcd/vendor/go.etcd.io/etcd/client/v3/op.go | 35 +- .../go.etcd.io/etcd/client/v3/options.go | 2 +- .../vendor/go.etcd.io/etcd/client/v3/retry.go | 45 +- .../etcd/client/v3/retry_interceptor.go | 98 +- etcd/vendor/go.etcd.io/etcd/client/v3/sort.go | 6 +- etcd/vendor/go.etcd.io/etcd/client/v3/txn.go | 4 +- .../vendor/go.etcd.io/etcd/client/v3/watch.go | 77 +- .../etcd/pkg/v3/adt/interval_tree.go | 105 +- .../etcd/pkg/v3/contention/contention.go | 17 +- .../go.etcd.io/etcd/pkg/v3/cpuutil/endian.go | 4 +- .../etcd/pkg/v3/featuregate/feature_gate.go | 400 + .../go.etcd.io/etcd/pkg/v3/flags/flag.go | 18 +- .../etcd/pkg/v3/flags/selective_string.go | 9 +- .../go.etcd.io/etcd/pkg/v3/flags/strings.go | 2 +- .../etcd/pkg/v3/flags/unique_strings.go | 5 +- .../go.etcd.io/etcd/pkg/v3/flags/urls.go | 2 +- .../etcd/pkg/v3/httputil/httputil.go | 3 +- .../etcd/pkg/v3/ioutil/pagewriter.go | 12 +- .../go.etcd.io/etcd/pkg/v3/netutil/netutil.go | 13 +- .../go.etcd.io/etcd/pkg/v3/netutil/routes.go | 1 - .../etcd/pkg/v3/netutil/routes_linux.go | 21 +- .../go.etcd.io/etcd/pkg/v3/notify/notify.go | 52 + .../etcd/pkg/v3/runtime/fds_other.go | 1 - .../etcd/pkg/v3/schedule/schedule.go | 54 +- .../go.etcd.io/etcd/pkg/v3/traceutil/trace.go | 43 +- .../go.etcd.io/etcd/pkg/v3/wait/wait.go | 22 +- .../go.etcd.io/etcd/pkg/v3/wait/wait_time.go | 4 +- etcd/vendor/go.etcd.io/etcd/raft/v3/LICENSE | 202 - etcd/vendor/go.etcd.io/etcd/raft/v3/OWNERS | 5 - etcd/vendor/go.etcd.io/etcd/raft/v3/log.go | 406 - .../go.etcd.io/etcd/raft/v3/log_unstable.go | 157 - .../vendor/go.etcd.io/etcd/raft/v3/rawnode.go | 241 - .../go.etcd.io/etcd/server/v3/auth/jwt.go | 19 +- .../go.etcd.io/etcd/server/v3/auth/metrics.go | 13 +- .../go.etcd.io/etcd/server/v3/auth/nop.go | 2 + .../go.etcd.io/etcd/server/v3/auth/options.go | 73 +- .../etcd/server/v3/auth/range_perm_cache.go | 31 +- .../etcd/server/v3/auth/simple_token.go | 9 +- .../go.etcd.io/etcd/server/v3/auth/store.go | 382 +- .../etcd/server/v3/config/config.go | 89 +- .../etcd/server/v3/config/v2_deprecation.go | 58 +- .../go.etcd.io/etcd/server/v3/embed/config.go | 888 +- .../etcd/server/v3/embed/config_logging.go | 46 +- .../v3/embed/config_logging_journal_unix.go | 7 +- .../embed/config_logging_journal_windows.go | 1 - .../etcd/server/v3/embed/config_tracing.go | 20 +- .../go.etcd.io/etcd/server/v3/embed/etcd.go | 350 +- .../go.etcd.io/etcd/server/v3/embed/serve.go | 110 +- .../go.etcd.io/etcd/server/v3/embed/util.go | 10 +- .../etcd/server/v3/etcdserver/adapters.go | 89 + .../server/v3/etcdserver/api/capability.go | 9 +- .../server/v3/etcdserver/api/etcdhttp/base.go | 156 - .../v3/etcdserver/api/etcdhttp/debug.go | 47 + .../v3/etcdserver/api/etcdhttp/health.go | 127 +- .../server/v3/etcdserver/api/etcdhttp/peer.go | 18 +- .../httptypes => etcdhttp/types}/errors.go | 0 .../v3/etcdserver/api/etcdhttp/utils.go | 99 + .../v3/etcdserver/api/etcdhttp/version.go | 65 + .../v3/etcdserver/api/membership/cluster.go | 565 +- .../v3/etcdserver/api/membership/errors.go | 4 +- .../v3/etcdserver/api/membership/member.go | 24 +- .../v3/etcdserver/api/membership/metrics.go | 39 +- .../v3/etcdserver/api/membership/store.go | 335 +- .../v3/etcdserver/api/membership/storev2.go | 224 +- .../v3/etcdserver/api/rafthttp/coder.go | 2 +- .../server/v3/etcdserver/api/rafthttp/doc.go | 2 +- .../server/v3/etcdserver/api/rafthttp/http.go | 34 +- .../v3/etcdserver/api/rafthttp/metrics.go | 219 +- .../v3/etcdserver/api/rafthttp/msg_codec.go | 2 +- .../etcdserver/api/rafthttp/msgappv2_codec.go | 2 +- .../server/v3/etcdserver/api/rafthttp/peer.go | 44 +- .../v3/etcdserver/api/rafthttp/peer_status.go | 4 +- .../v3/etcdserver/api/rafthttp/pipeline.go | 18 +- .../v3/etcdserver/api/rafthttp/remote.go | 6 +- .../api/rafthttp/snapshot_sender.go | 20 +- .../v3/etcdserver/api/rafthttp/stream.go | 33 +- .../v3/etcdserver/api/rafthttp/transport.go | 50 +- .../server/v3/etcdserver/api/rafthttp/util.go | 11 +- .../etcd/server/v3/etcdserver/api/snap/db.go | 7 +- .../server/v3/etcdserver/api/snap/message.go | 2 +- .../v3/etcdserver/api/snap/snappb/snap.pb.go | 9 +- .../v3/etcdserver/api/snap/snappb/snap.proto | 2 + .../v3/etcdserver/api/snap/snapshotter.go | 85 +- .../server/v3/etcdserver/api/v2auth/auth.go | 670 - .../v3/etcdserver/api/v2auth/auth_requests.go | 177 - .../etcdserver/api/v2discovery/discovery.go | 29 +- .../server/v3/etcdserver/api/v2error/error.go | 10 +- .../v3/etcdserver/api/v2http/capability.go | 41 - .../server/v3/etcdserver/api/v2http/client.go | 757 - .../v3/etcdserver/api/v2http/client_auth.go | 604 - .../server/v3/etcdserver/api/v2http/http.go | 82 - .../etcdserver/api/v2http/httptypes/member.go | 69 - .../v3/etcdserver/api/v2http/metrics.go | 98 - .../server/v3/etcdserver/api/v2stats/queue.go | 3 +- .../v3/etcdserver/api/v2stats/server.go | 4 +- .../etcdserver/api/v2store/event_history.go | 1 - .../v3/etcdserver/api/v2store/event_queue.go | 2 +- .../v3/etcdserver/api/v2store/metrics.go | 25 +- .../server/v3/etcdserver/api/v2store/node.go | 5 +- .../v3/etcdserver/api/v2store/node_extern.go | 1 - .../server/v3/etcdserver/api/v2store/stats.go | 2 +- .../server/v3/etcdserver/api/v2store/store.go | 47 +- .../v3/etcdserver/api/v2store/ttl_key_heap.go | 8 +- .../v3/etcdserver/api/v2store/watcher_hub.go | 1 - .../server/v3/etcdserver/api/v2v3/cluster.go | 31 - .../server/v3/etcdserver/api/v2v3/server.go | 130 - .../server/v3/etcdserver/api/v2v3/store.go | 638 - .../server/v3/etcdserver/api/v2v3/watcher.go | 142 - .../v3/etcdserver/api/v3alarm/alarms.go | 61 +- .../v3/etcdserver/api/v3client/v3client.go | 2 +- .../etcdserver/api/v3compactor/compactor.go | 4 +- .../v3/etcdserver/api/v3compactor/periodic.go | 37 +- .../v3/etcdserver/api/v3compactor/revision.go | 9 +- .../etcdserver/api/v3discovery/discovery.go | 509 + .../v3/etcdserver/api/v3election/election.go | 2 +- .../v3electionpb/gw/v3election.pb.gw.go | 365 +- .../v3election/v3electionpb/v3election.pb.go | 73 +- .../v3election/v3electionpb/v3election.proto | 4 +- .../server/v3/etcdserver/api/v3lock/lock.go | 2 +- .../api/v3lock/v3lockpb/gw/v3lock.pb.gw.go | 180 +- .../api/v3lock/v3lockpb/v3lock.pb.go | 46 +- .../api/v3lock/v3lockpb/v3lock.proto | 2 + .../server/v3/etcdserver/api/v3rpc/auth.go | 21 + .../server/v3/etcdserver/api/v3rpc/codec.go | 4 +- .../server/v3/etcdserver/api/v3rpc/grpc.go | 50 +- .../server/v3/etcdserver/api/v3rpc/header.go | 5 +- .../server/v3/etcdserver/api/v3rpc/health.go | 6 +- .../v3/etcdserver/api/v3rpc/interceptor.go | 54 +- .../server/v3/etcdserver/api/v3rpc/key.go | 9 + .../server/v3/etcdserver/api/v3rpc/lease.go | 20 +- .../v3/etcdserver/api/v3rpc/maintenance.go | 133 +- .../server/v3/etcdserver/api/v3rpc/member.go | 2 +- .../server/v3/etcdserver/api/v3rpc/metrics.go | 30 +- .../server/v3/etcdserver/api/v3rpc/quota.go | 13 +- .../server/v3/etcdserver/api/v3rpc/util.go | 82 +- .../server/v3/etcdserver/api/v3rpc/watch.go | 63 +- .../etcd/server/v3/etcdserver/apply.go | 1167 - .../etcd/server/v3/etcdserver/apply/apply.go | 493 + .../v3/etcdserver/{ => apply}/apply_auth.go | 91 +- .../server/v3/etcdserver/apply/corrupt.go | 55 + .../v2stats/stats.go => apply/metrics.go} | 27 +- .../v3/etcdserver/apply/uber_applier.go | 228 + .../etcd/server/v3/etcdserver/apply_v2.go | 165 +- .../etcd/server/v3/etcdserver/bootstrap.go | 742 + .../server/v3/etcdserver/cindex/cindex.go | 90 +- .../etcd/server/v3/etcdserver/cluster_util.go | 140 +- .../etcd/server/v3/etcdserver/corrupt.go | 304 +- .../etcd/server/v3/etcdserver/errors.go | 57 - .../server/v3/etcdserver/errors/errors.go | 54 + .../etcd/server/v3/etcdserver/metrics.go | 109 +- .../etcd/server/v3/etcdserver/raft.go | 424 +- .../etcd/server/v3/etcdserver/server.go | 1450 +- .../server/v3/etcdserver/snapshot_merge.go | 18 +- .../etcd/server/v3/etcdserver/txn/metrics.go | 71 + .../etcd/server/v3/etcdserver/txn/txn.go | 723 + .../etcd/server/v3/etcdserver/txn/util.go | 107 + .../etcd/server/v3/etcdserver/util.go | 86 - .../etcd/server/v3/etcdserver/v2_server.go | 140 - .../etcd/server/v3/etcdserver/v3_server.go | 280 +- .../etcdserver/{api/v2http => version}/doc.go | 6 +- .../{api/membership => version}/downgrade.go | 58 +- .../{api/v2v3/doc.go => version/errors.go} | 13 +- .../server/v3/etcdserver/version/monitor.go | 221 + .../server/v3/etcdserver/version/version.go | 81 + .../etcd/server/v3/etcdserver/zap_raft.go | 31 +- .../etcd/server/v3/features/etcd_features.go | 108 + .../v3/internal/clientv2}/README.md | 17 +- .../v3/internal/clientv2}/auth_role.go | 12 +- .../v3/internal/clientv2}/auth_user.go | 22 +- .../v3/internal/clientv2}/cancelreq.go | 2 +- .../v3/internal/clientv2}/client.go | 20 +- .../v3/internal/clientv2}/cluster_error.go | 0 .../v3/internal/clientv2}/curl.go | 12 +- .../v3/internal/clientv2}/discover.go | 0 .../v2 => server/v3/internal/clientv2}/doc.go | 0 .../v3/internal/clientv2}/keys.go | 22 +- .../v3/internal/clientv2}/members.go | 12 +- .../v3/internal/clientv2}/util.go | 19 +- .../go.etcd.io/etcd/server/v3/lease/lease.go | 135 + .../etcd/server/v3/lease/lease_queue.go | 6 +- .../etcd/server/v3/lease/leasehttp/http.go | 22 +- .../etcd/server/v3/lease/leasepb/lease.pb.go | 10 +- .../etcd/server/v3/lease/leasepb/lease.proto | 2 + .../go.etcd.io/etcd/server/v3/lease/lessor.go | 223 +- .../etcd/server/v3/lease/metrics.go | 3 +- .../etcd/server/v3/mvcc/backend/verify.go | 70 - .../etcd/server/v3/mvcc/revision.go | 67 - .../go.etcd.io/etcd/server/v3/mvcc/util.go | 59 - .../grpcproxy/adapter/auth_client_adapter.go | 4 +- .../v3/proxy/grpcproxy/adapter/chan_stream.go | 17 +- .../adapter/cluster_client_adapter.go | 4 +- .../adapter/election_client_adapter.go | 10 +- .../grpcproxy/adapter/kv_client_adapter.go | 4 +- .../grpcproxy/adapter/lease_client_adapter.go | 10 +- .../grpcproxy/adapter/lock_client_adapter.go | 4 +- .../adapter/maintenance_client_adapter.go | 10 +- .../grpcproxy/adapter/watch_client_adapter.go | 9 +- .../etcd/server/v3/revbump/revbump.go | 10 +- .../v3/{etcdserver => storage}/backend.go | 45 +- .../v3/{mvcc => storage}/backend/backend.go | 109 +- .../v3/{mvcc => storage}/backend/batch_tx.go | 45 +- .../backend/config_default.go | 1 - .../{mvcc => storage}/backend/config_linux.go | 0 .../backend/config_windows.go | 1 - .../v3/{mvcc => storage}/backend/doc.go | 0 .../v3/{mvcc => storage}/backend/hooks.go | 6 +- .../v3/{mvcc => storage}/backend/metrics.go | 0 .../v3/{mvcc => storage}/backend/read_tx.go | 5 +- .../v3/{mvcc => storage}/backend/tx_buffer.go | 43 +- .../etcd/server/v3/storage/backend/verify.go | 117 + .../v3/{ => storage}/datadir/datadir.go | 9 + .../server/v3/{ => storage}/datadir/doc.go | 0 .../etcd/server/v3/storage/hooks.go | 60 + .../etcd/server/v3/storage/metrics.go | 30 + .../etcd/server/v3/{ => storage}/mvcc/doc.go | 0 .../etcd/server/v3/{ => storage}/mvcc/hash.go | 40 +- .../server/v3/{ => storage}/mvcc/index.go | 161 +- .../server/v3/{ => storage}/mvcc/key_index.go | 73 +- .../etcd/server/v3/{ => storage}/mvcc/kv.go | 2 +- .../server/v3/{ => storage}/mvcc/kv_view.go | 0 .../server/v3/{ => storage}/mvcc/kvstore.go | 130 +- .../{ => storage}/mvcc/kvstore_compaction.go | 21 +- .../v3/{ => storage}/mvcc/kvstore_txn.go | 193 +- .../server/v3/{ => storage}/mvcc/metrics.go | 109 +- .../v3/{ => storage}/mvcc/metrics_txn.go | 1 - .../etcd/server/v3/storage/mvcc/revision.go | 126 + .../etcd/server/v3/storage/mvcc/store.go | 60 + .../v3/{ => storage}/mvcc/watchable_store.go | 173 +- .../{ => storage}/mvcc/watchable_store_txn.go | 0 .../server/v3/{ => storage}/mvcc/watcher.go | 0 .../v3/{ => storage}/mvcc/watcher_group.go | 10 +- .../v3/{etcdserver => storage}/quota.go | 61 +- .../etcd/server/v3/storage/schema/actions.go | 93 + .../etcd/server/v3/storage/schema/alarm.go | 105 + .../etcd/server/v3/storage/schema/auth.go | 152 + .../server/v3/storage/schema/auth_roles.go | 105 + .../server/v3/storage/schema/auth_users.go | 108 + .../buckets => storage/schema}/bucket.go | 30 +- .../etcd/server/v3/storage/schema/changes.go | 50 + .../etcd/server/v3/storage/schema/cindex.go | 95 + .../schema}/confstate.go | 22 +- .../etcd/server/v3/storage/schema/lease.go | 84 + .../server/v3/storage/schema/membership.go | 254 + .../server/v3/storage/schema/migration.go | 108 + .../etcd/server/v3/storage/schema/schema.go | 138 + .../etcd/server/v3/storage/schema/version.go | 67 + .../v3/{etcdserver => storage}/storage.go | 123 +- .../go.etcd.io/etcd/server/v3/storage/util.go | 160 + .../server/v3/{ => storage}/wal/decoder.go | 73 +- .../etcd/server/v3/{ => storage}/wal/doc.go | 12 +- .../server/v3/{ => storage}/wal/encoder.go | 8 +- .../v3/{ => storage}/wal/file_pipeline.go | 7 +- .../server/v3/{ => storage}/wal/metrics.go | 0 .../server/v3/{ => storage}/wal/repair.go | 24 +- .../etcd/server/v3/{ => storage}/wal/util.go | 10 +- .../etcd/server/v3/storage/wal/version.go | 288 + .../etcd/server/v3/{ => storage}/wal/wal.go | 180 +- .../v3/{ => storage}/wal/walpb/record.go | 12 +- .../v3/{ => storage}/wal/walpb/record.pb.go | 36 +- .../v3/{ => storage}/wal/walpb/record.proto | 4 +- .../etcd/server/v3/verify/verify.go | 74 +- etcd/vendor/go.etcd.io/raft/v3/.gitignore | 1 + etcd/vendor/go.etcd.io/raft/v3/.go-version | 1 + etcd/vendor/go.etcd.io/raft/v3/.golangci.yaml | 41 + .../{etcd/client/v2 => raft/v3}/LICENSE | 0 etcd/vendor/go.etcd.io/raft/v3/Makefile | 28 + etcd/vendor/go.etcd.io/raft/v3/OWNERS | 11 + .../go.etcd.io/{etcd => }/raft/v3/README.md | 8 +- .../{etcd => }/raft/v3/bootstrap.go | 2 +- .../raft/v3/confchange/confchange.go | 88 +- .../{etcd => }/raft/v3/confchange/restore.go | 8 +- .../go.etcd.io/{etcd => }/raft/v3/design.md | 0 .../go.etcd.io/{etcd => }/raft/v3/doc.go | 100 + etcd/vendor/go.etcd.io/raft/v3/log.go | 574 + .../vendor/go.etcd.io/raft/v3/log_unstable.go | 245 + .../go.etcd.io/{etcd => }/raft/v3/logger.go | 4 +- .../go.etcd.io/{etcd => }/raft/v3/node.go | 180 +- .../{etcd => }/raft/v3/quorum/joint.go | 0 .../{etcd => }/raft/v3/quorum/majority.go | 44 +- .../{etcd => }/raft/v3/quorum/quorum.go | 0 .../raft/v3/quorum/voteresult_string.go | 0 .../go.etcd.io/{etcd => }/raft/v3/raft.go | 971 +- .../{etcd => }/raft/v3/raftpb/confchange.go | 8 +- .../{etcd => }/raft/v3/raftpb/confstate.go | 4 +- .../{etcd => }/raft/v3/raftpb/raft.pb.go | 372 +- .../{etcd => }/raft/v3/raftpb/raft.proto | 79 +- etcd/vendor/go.etcd.io/raft/v3/rawnode.go | 562 + .../{etcd => }/raft/v3/read_only.go | 4 +- etcd/vendor/go.etcd.io/raft/v3/state_trace.go | 339 + .../go.etcd.io/raft/v3/state_trace_nop.go | 50 + .../go.etcd.io/{etcd => }/raft/v3/status.go | 10 +- .../go.etcd.io/{etcd => }/raft/v3/storage.go | 55 +- .../{etcd => }/raft/v3/tracker/inflights.go | 63 +- .../{etcd => }/raft/v3/tracker/progress.go | 169 +- .../{etcd => }/raft/v3/tracker/state.go | 2 +- .../{etcd => }/raft/v3/tracker/tracker.go | 31 +- etcd/vendor/go.etcd.io/raft/v3/types.go | 106 + .../go.etcd.io/{etcd => }/raft/v3/util.go | 160 +- .../otel/semconv/internal/http.go | 338 - .../otel/semconv/v1.4.0/README.md | 3 - .../otel/semconv/v1.4.0/doc.go | 9 - .../otel/semconv/v1.4.0/exception.go | 9 - .../otel/semconv/v1.4.0/http.go | 103 - .../otel/semconv/v1.4.0/resource.go | 895 - .../otel/semconv/v1.4.0/schema.go | 9 - .../otel/semconv/v1.4.0/trace.go | 1367 -- .../vendor/google.golang.org/genproto/LICENSE | 202 - .../grpc/reflection/README.md | 18 + .../grpc/reflection/adapt.go | 57 + .../grpc_reflection_v1/reflection.pb.go | 777 + .../grpc_reflection_v1/reflection_grpc.pb.go | 138 + .../grpc_reflection_v1alpha/reflection.pb.go | 847 + .../reflection_grpc.pb.go | 135 + .../grpc/reflection/internal/internal.go | 436 + .../grpc/reflection/serverreflection.go | 160 + .../vendor/k8s.io/client-go/util/cert/cert.go | 4 +- etcd/vendor/k8s.io/utils/net/multi_listen.go | 6 +- etcd/vendor/modules.txt | 170 +- go.mod | 76 +- go.sum | 83 +- origin/skip.txt | 72 + .../crio.conf.d/10-microshift_amd64.conf | 2 +- .../crio.conf.d/10-microshift_arm64.conf | 2 +- packaging/images/Makefile | 2 +- packaging/images/README.md | 4 +- packaging/microshift/config.yaml | 18 + packaging/rpm/make-rpm.sh | 2 +- packaging/rpm/microshift.spec | 73 +- pkg/admin/prerun/featuregate_lock.go | 215 + pkg/admin/prerun/featuregate_lock_test.go | 482 + pkg/assets/apps.go | 5 +- pkg/assets/crd.go | 2 +- pkg/cmd/run.go | 22 +- pkg/components/controllers.go | 18 +- pkg/components/storage.go | 8 + pkg/config/apiserver.go | 102 + pkg/config/config.go | 31 +- pkg/config/config_test.go | 61 + pkg/config/dns.go | 82 + pkg/controllers/etcd.go | 5 +- pkg/controllers/hostswatcher.go | 280 + pkg/controllers/kube-apiserver.go | 45 +- .../openshift-default-scc-manager.go | 3 + .../microshift_optional_workloads.go | 4 + pkg/util/net.go | 6 +- rebase.log | 846 + scripts/auto-rebase/assets.yaml | 9 + .../auto-rebase/assets_ai_model_serving.yaml | 85 +- scripts/auto-rebase/assets_sriov.yaml | 34 + scripts/auto-rebase/changelog.txt | 5150 +--- scripts/auto-rebase/commits.txt | 68 +- scripts/auto-rebase/last_rebase.sh | 2 +- .../last_rebase_ai_model_serving.sh | 2 +- scripts/auto-rebase/last_rebase_sriov.sh | 2 + .../manifests_patches/020-dns-configmap.patch | 18 + .../manifests_patches/020-dns-daemonset.patch | 31 + .../020-dns-hosts-configmap-role.patch | 22 + .../020-dns-hosts-configmap-rolebinding.patch | 19 + scripts/auto-rebase/presubmit.py | 1 + scripts/auto-rebase/rebase.py | 319 +- scripts/auto-rebase/rebase.sh | 58 +- .../auto-rebase/rebase_ai_model_serving.sh | 9 +- scripts/auto-rebase/rebase_cert_manager.sh | 55 +- scripts/auto-rebase/rebase_job_entrypoint.sh | 6 +- scripts/auto-rebase/rebase_sriov.sh | 453 + scripts/aws/cf-gen.yaml | 9 +- .../setup/01-microshift.sh | 2 +- .../tests/02-wait-for-greenboot.sh | 2 +- scripts/devenv-builder/configure-vm.sh | 2 +- .../create-venv.sh} | 7 +- scripts/pyutils/ghutils.py | 169 + scripts/pyutils/gitutils.py | 140 + scripts/pyutils/requirements.txt | 2 + scripts/release-notes/common.py | 250 + scripts/release-notes/gen_gh_releases.sh | 46 + ...otes.py => gen_gh_releases_from_mirror.py} | 250 +- .../gen_gh_releases_from_rhocp.py | 210 + scripts/release-notes/tag_stable_releases.py | 90 - test/assets/common_versions.sh.template | 29 +- .../greenboot/kustomization.yaml | 2 +- test/assets/observability/otel_config.yaml | 15 +- .../sriov/sriov-network-policy-template.yaml | 17 + test/bin/build_images.sh | 1 + test/bin/build_rpms.sh | 10 +- test/bin/ci_phase_boot_and_test.sh | 4 +- test/bin/ci_phase_iso_build.sh | 18 +- test/bin/common.sh | 13 +- test/bin/common_versions.sh | 30 +- test/bin/common_versions_verify.sh | 30 + test/bin/manage_brew_rpms.sh | 193 +- test/bin/manage_build_cache.sh | 73 +- test/bin/manage_hypervisor_config.sh | 8 + test/bin/manage_loki.sh | 13 +- test/bin/manage_prometheus.sh | 14 +- test/bin/mirror_registry.sh | 5 + test/bin/pyutils/build_bootc_images.py | 18 +- test/bin/pyutils/generate_common_versions.py | 217 +- test/bin/scenario.sh | 119 +- .../group2/build-serialsim.sh.template | 3 +- .../rhel100-bootc-crel-isolated.containerfile | 48 + ...rhel100-bootc-crel-optionals.containerfile | 40 + .../group2/rhel100-bootc-crel.containerfile | 32 + ...-bootc-brew-z1-with-optional.containerfile | 49 + .../group1/rhel100-bootc-source.containerfile | 5 +- ...el100-bootc-source-optionals.containerfile | 33 + .../rhel96-bootc-source-fips.containerfile | 5 +- ...ootc-source-ai-model-serving.containerfile | 4 +- ...cos10-bootc-source-optionals.containerfile | 33 + ...-bootc-brew-ec-with-optional.containerfile | 56 + ...-bootc-brew-rc-with-optional.containerfile | 56 + ...c-brew-zstream-with-optional.containerfile | 56 + .../group1/rhel100-bootc-brew.containerfile} | 7 +- ...-bootc-brew-ec-with-optional.containerfile | 0 ...-bootc-brew-rc-with-optional.containerfile | 0 ...-bootc-brew-y1-with-optional.containerfile | 0 ...-bootc-brew-y2-with-optional.containerfile | 0 ...c-brew-zstream-with-optional.containerfile | 0 ...c-brew-ec-with-optional-fips.containerfile | 5 +- ...-brew-ec-with-optional-tuned.containerfile | 0 ...96-bootc-brew-ec-with-optional.image-bootc | 0 ...c-brew-nightly-with-optional.containerfile | 53 + ...c-brew-rc-with-optional-fips.containerfile | 5 +- ...-brew-rc-with-optional-tuned.containerfile | 0 ...96-bootc-brew-rc-with-optional.image-bootc | 0 ...w-zstream-with-optional-fips.containerfile | 5 +- ...-zstream-with-optional-tuned.containerfile | 0 ...otc-brew-zstream-with-optional.image-bootc | 0 .../group1/rhel96-source-isolated.toml | 6 + .../rhel96-brew-y2-with-optionals.toml | 0 .../rhel96-brew-y1-with-optionals.toml | 0 .../rhel96-brew-ec-with-optionals.toml | 0 .../rhel96-brew-nightly-with-optionals.toml | 71 + .../rhel96-brew-rc-with-optionals.toml | 0 .../rhel96-brew-zstream-with-optionals.toml | 0 .../group3}/rhel96-lrel-optionals-tuned.toml | 0 .../includes/post-containers.cfg | 6 +- test/resources/common.resource | 11 + test/resources/hosts.resource | 44 + test/resources/loki.py | 32 +- test/resources/observability.resource | 26 +- test/resources/oc.resource | 8 +- test/resources/prometheus.py | 26 +- .../periodics/el100-src@optional.sh | 44 + .../el96-crel@el96-src@optional-upgrade.sh | 33 - ...96-crel@el96-src@upgrade-fails-isolated.sh | 34 - .../el96-crel@el96-src@upgrade-fails.sh | 34 - .../el96-crel@el96-src@upgrade-ok-isolated.sh | 33 - .../periodics/el96-crel@optional-sigstore.sh | 41 - .../el96-prel@el96-crel@upgrade-ok.sh | 33 - .../el96-prel@el96-src@upgrade-ok.sh | 27 + ... => el96-src@fault-tests-and-greenboot.sh} | 5 +- .../periodics/el96-src@fault-tests.sh | 16 - ...-src@fips.sh.disabled => el96-src@fips.sh} | 0 ...src@gitops-telemetry-clusterid-systemd.sh} | 8 +- .../periodics/el96-src@greenboot.sh | 16 - ...sh => el96-yminus2@el96-src@upgrade-ok.sh} | 7 +- .../el96-crel@el100-src@upgrade-ok.sh | 33 - .../el96-prel@el100-src@upgrade-ok.sh | 18 +- .../el96-prel@el96-src@upgrade-ok.sh | 18 +- .../presubmits/el96-src@optional.sh | 20 +- .../presubmits/el96-src@standard-suite1.sh | 3 + .../el100-lrel@ginkgo-tests.sh} | 15 +- .../releases/el100-lrel@optional.sh | 33 + .../el100-lrel@standard1.sh} | 9 +- .../el100-lrel@standard2.sh} | 7 +- .../el96-crel@published-images-standard1.sh | 0 .../el96-crel@published-images-standard2.sh | 0 .../el96-lrel@ai-model-serving-online.sh | 18 +- .../releases/el96-lrel@dual-stack.sh | 15 +- ...rel@fips.sh.disabled => el96-lrel@fips.sh} | 9 +- .../releases/el96-lrel@ginkgo-tests.sh | 20 +- .../releases/el96-lrel@ipv6.sh | 31 +- .../releases/el96-lrel@low-latency.sh | 16 +- .../el96-lrel@multi-config-standard1.sh | 118 + .../el96-lrel@multi-config-standard2.sh | 114 + .../releases/el96-lrel@multi-nic.sh | 15 +- .../el96-lrel@nightly-brew-standard1.sh | 27 + .../el96-lrel@nightly-brew-standard2.sh | 25 + .../releases/el96-lrel@optional.sh | 35 +- .../releases/el96-lrel@osconfig.sh | 15 +- .../releases/el96-lrel@router.sh | 15 +- .../releases/el96-lrel@standard1.sh | 15 +- .../releases/el96-lrel@standard2.sh | 15 +- .../releases/el96-lrel@storage.sh | 15 +- .../releases/el96-lrel@telemetry.sh | 16 +- .../releases/el96-lrel@tlsv13-standard1.sh | 15 +- .../releases/el96-lrel@tlsv13-standard2.sh | 15 +- .../releases/el96-y1@el96-lrel@lvms.sh | 48 +- .../releases/el96-y1@el96-lrel@standard1.sh | 33 +- .../releases/el96-y1@el96-lrel@standard2.sh | 33 +- .../releases/el96-y2@el96-lrel@lvms.sh | 51 +- .../releases/el96-y2@el96-lrel@standard1.sh | 18 +- .../releases/el96-y2@el96-lrel@standard2.sh | 18 +- .../releases/el96-z1@el96-lrel@standard1.sh | 37 + .../releases/el96-z1@el96-lrel@standard2.sh | 36 + .../upstream/cos10-src@optional.sh | 44 + .../upstream/cos9-src@optional.sh | 21 +- .../el96-crel@el96-src@optional-upgrade.sh | 32 - .../el96-crel@el96-src@upgrade-fails.sh | 33 - .../periodics/el96-crel@optional-sigstore.sh | 41 - .../el96-prel@el96-crel@upgrade-ok.sh | 33 - .../el96-prel@el96-src@upgrade-ok.sh | 18 + test/scenarios/periodics/el96-src@fips-rpm.sh | 26 + .../periodics/el96-src@fips-rpm.sh.disabled | 22 - ...-src@fips.sh.disabled => el96-src@fips.sh} | 16 +- test/scenarios/periodics/el96-src@optional.sh | 18 +- .../el96-yminus2@el96-src@upgrade-ok.sh | 18 + .../el96-crel@el96-src@upgrade-ok.sh | 32 - .../presubmits/el96-src@low-latency.sh | 3 +- .../presubmits/el96-src@standard-suite1.sh | 3 + test/scenarios/releases/el96-lrel@backups.sh | 15 +- .../releases/el96-lrel@dual-stack.sh | 15 +- .../releases/el96-lrel@ginkgo-multi-config.sh | 112 + .../releases/el96-lrel@ginkgo-tests.sh | 18 +- test/scenarios/releases/el96-lrel@ipv6.sh | 17 +- .../releases/el96-lrel@low-latency.sh | 19 +- .../scenarios/releases/el96-lrel@multi-nic.sh | 15 +- test/scenarios/releases/el96-lrel@optional.sh | 41 +- test/scenarios/releases/el96-lrel@osconfig.sh | 15 +- test/scenarios/releases/el96-lrel@router.sh | 15 +- .../scenarios/releases/el96-lrel@standard1.sh | 15 +- .../scenarios/releases/el96-lrel@standard2.sh | 15 +- test/scenarios/releases/el96-lrel@storage.sh | 15 +- .../releases/el96-lrel@tlsv13-standard1.sh | 17 +- .../releases/el96-lrel@tlsv13-standard2.sh | 17 +- .../releases/el96-yminus1@el96-lrel@lvms.sh | 38 +- .../el96-yminus1@el96-lrel@standard1.sh | 15 +- .../el96-yminus1@el96-lrel@standard2.sh | 15 +- .../releases/el96-yminus2@el96-lrel@lvms.sh | 38 +- .../el96-yminus2@el96-lrel@standard1.sh | 15 +- .../el96-yminus2@el96-lrel@standard2.sh | 21 +- test/suites/ipv6/dualstack.robot | 20 +- test/suites/optional/cert-manager.robot | 67 +- test/suites/optional/gateway-api.robot | 3 +- test/suites/optional/observability.robot | 24 +- test/suites/optional/sriov.robot | 72 + test/suites/standard1/dns.robot | 162 + test/suites/standard1/tls-configuration.robot | 1 - test/suites/standard1/version.robot | 2 + test/suites/standard2/configuration.robot | 1 + test/suites/standard2/feature-gates.robot | 139 + .../validate-custom-certificates.robot | 36 +- test/suites/telemetry/telemetry.robot | 30 +- test/suites/tuned/uncore-cache.robot | 86 + test/suites/tuned/workload-partitioning.robot | 10 - .../github.com/openshift/api/.golangci.yaml | 24 +- vendor/github.com/openshift/api/AGENTS.md | 15 + vendor/github.com/openshift/api/Makefile | 44 +- .../api/config/v1/types_cluster_version.go | 18 +- .../api/config/v1/types_infrastructure.go | 135 + ..._generated.featuregated-crd-manifests.yaml | 3 + .../v1/zz_generated.swagger_doc_generated.go | 11 +- .../openshift/api/envtest-releases.yaml | 13 + vendor/github.com/openshift/api/features.md | 19 +- .../openshift/api/features/features.go | 58 +- .../api/machine/v1beta1/types_awsprovider.go | 51 + .../api/machine/v1beta1/types_gcpprovider.go | 16 + .../machine/v1beta1/zz_generated.deepcopy.go | 52 + .../zz_generated.swagger_doc_generated.go | 21 + .../operator/v1/types_csi_cluster_driver.go | 1 - .../api/operator/v1/types_ingress.go | 17 + .../v1/zz_generated.swagger_doc_generated.go | 2 +- .../openshift/api/route/v1/generated.proto | 4 +- .../openshift/api/route/v1/types.go | 4 +- .../v1/zz_generated.swagger_doc_generated.go | 2 +- .../resourceapply/admissionregistration.go | 48 + .../resource/resourceapply/generic.go | 26 +- .../resource/resourceapply/networking.go | 16 +- .../resource/resourceapply/storage.go | 54 +- .../pkg/route/ingress/ingress.go | 76 +- .../pkg/routecontroller/wellknown.go | 6 + .../leaderelection/resourcelock/leaselock.go | 3 + vendor/k8s.io/client-go/util/cert/cert.go | 4 +- .../experimental/allocator_experimental.go | 40 +- .../incubating/allocator_incubating.go | 40 +- .../internal/stable/allocator_stable.go | 40 +- .../pkg/cmd/apiresources/apiresources.go | 3 + .../kubernetes/pkg/api/service/warnings.go | 2 +- .../pkg/apis/batch/validation/validation.go | 9 + .../pkg/controller/controller_utils.go | 65 +- .../controller/daemon/daemon_controller.go | 4 +- .../controller/history/controller_history.go | 18 - .../pkg/controller/job/job_controller.go | 4 +- .../pkg/controller/replicaset/replica_set.go | 4 +- .../controller/statefulset/stateful_set.go | 4 +- .../statefulset/stateful_set_control.go | 56 +- .../kubernetes/pkg/features/kube_features.go | 14 +- .../cm/dra/plugin/dra_plugin_manager.go | 20 +- .../kuberuntime/kuberuntime_container.go | 6 + .../kubernetes/pkg/kubelet/managed/managed.go | 36 + .../kubernetes/pkg/kubelet/prober/worker.go | 17 +- .../pkg/registry/batch/job/strategy.go | 7 +- .../tainttoleration/taint_toleration.go | 4 +- .../framework/preemption/preemption.go | 94 +- .../kubernetes/pkg/volume/csi/csi_attacher.go | 2 +- .../k8s.io/kubernetes/pkg/volume/plugins.go | 2 +- .../pkg/volume/portworx/portworx.go | 33 +- vendor/k8s.io/utils/net/multi_listen.go | 6 +- vendor/modules.txt | 86 +- 1140 files changed, 100300 insertions(+), 53564 deletions(-) create mode 100644 .claude/.gitignore create mode 100644 .claude/agents/openshift-ci-analyzis.md create mode 100644 .claude/commands/analyze-ci-test-job.md create mode 100644 .claude/commands/analyze-ci-test-scenario.md create mode 100644 .claude/commands/analyze-microshift-start.md create mode 100644 .claude/commands/analyze-sos-report.md create mode 100644 .claude/commands/generate-tests-template.md create mode 100644 .claude/commands/generate-tests.md create mode 100644 .claude/commands/microshift-release-versions.md create mode 100644 .claude/scripts/extract_microshift_version.py create mode 100644 .claude/settings.json delete mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 apiserver-config-flow.md create mode 100644 assets/components/openshift-dns/dns/hosts-configmap-role.yaml create mode 100644 assets/components/openshift-dns/dns/hosts-configmap-rolebinding.yaml create mode 100644 assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-restricted-v3.yaml create mode 100644 assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v3.yaml create mode 100644 assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-restricted-v3.yaml create mode 100644 assets/optional/ai-model-serving/kserve/certmanager/certificate.yaml create mode 100644 assets/optional/ai-model-serving/kserve/certmanager/kustomization.yaml create mode 100644 assets/optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/gateway-inference-extension.yaml create mode 100644 assets/optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/kustomization.yaml create mode 100644 assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/datasciencecluster.opendatahub.io_datascienceclusters.yaml create mode 100644 assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/dscinitialization.opendatahub.io_dscinitializations.yaml create mode 100644 assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/kustomization.yaml create mode 100644 assets/optional/ai-model-serving/kserve/crd/full/kustomization.yaml create mode 100644 assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_llminferenceserviceconfigs.yaml create mode 100644 assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_llminferenceservices.yaml rename assets/optional/ai-model-serving/kserve/crd/full/{serving.kserve.io_clusterlocalmodels.yaml => serving.kserve.io_localmodelcaches.yaml} (85%) create mode 100644 assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_localmodelnodes.yaml create mode 100644 assets/optional/ai-model-serving/kserve/default/llmisvc_validatingwebhook_cainjection_patch.yaml create mode 100644 assets/optional/ai-model-serving/kserve/default/llmisvcconfig_validatingwebhook_cainjection_patch.yaml create mode 100644 assets/optional/ai-model-serving/kserve/default/localmodelcache_validatingwebhook_cainjection_patch.yaml create mode 100644 assets/optional/ai-model-serving/kserve/default/localmodelnode_agent_image_patch.yaml create mode 100644 assets/optional/ai-model-serving/kserve/llmisvc/config-llm-decode-template.yaml create mode 100644 assets/optional/ai-model-serving/kserve/llmisvc/config-llm-decode-worker-data-parallel.yaml create mode 100644 assets/optional/ai-model-serving/kserve/llmisvc/config-llm-prefill-template.yaml create mode 100644 assets/optional/ai-model-serving/kserve/llmisvc/config-llm-prefill-worker-data-parallel.yaml create mode 100644 assets/optional/ai-model-serving/kserve/llmisvc/config-llm-router-route.yaml create mode 100644 assets/optional/ai-model-serving/kserve/llmisvc/config-llm-scheduler.yaml create mode 100644 assets/optional/ai-model-serving/kserve/llmisvc/config-llm-template.yaml create mode 100644 assets/optional/ai-model-serving/kserve/llmisvc/config-llm-worker-data-parallel.yaml create mode 100644 assets/optional/ai-model-serving/kserve/llmisvc/kustomization.yaml create mode 100644 assets/optional/ai-model-serving/kserve/localmodelnodes/kustomization.yaml create mode 100644 assets/optional/ai-model-serving/kserve/localmodelnodes/manager.yaml create mode 100644 assets/optional/ai-model-serving/kserve/localmodels/kustomization.yaml create mode 100644 assets/optional/ai-model-serving/kserve/localmodels/manager.yaml create mode 100644 assets/optional/ai-model-serving/kserve/monitoring/llmisvc/istio_gateway_monitor.yaml create mode 100644 assets/optional/ai-model-serving/kserve/monitoring/llmisvc/kustomization.yaml create mode 100644 assets/optional/ai-model-serving/kserve/monitoring/llmisvc/rbac.yaml create mode 100644 assets/optional/ai-model-serving/kserve/overlays/odh/llm-svc-scc.yaml rename assets/optional/ai-model-serving/kserve/{default => overlays/odh}/network-policies.yaml (100%) rename assets/optional/ai-model-serving/kserve/overlays/odh/{inferenceservice-config-patch.yaml => patches/patch-inferenceservice-config.yaml} (93%) rename assets/optional/ai-model-serving/kserve/overlays/odh/{set-resources-manager-patch.yaml => patches/patch-set-resources-manager.yaml} (100%) rename assets/optional/ai-model-serving/kserve/{default/svc_webhook_cainjection_patch.yaml => overlays/odh/patches/patch-webhook-svc-openshift-cert-injection.yaml} (100%) create mode 100644 assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-cert-manager.yaml create mode 100644 assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-clusterservingruntime.yaml create mode 100644 assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-local-model.yaml delete mode 100644 assets/optional/ai-model-serving/kserve/overlays/odh/remove-namespace.yaml create mode 100644 assets/optional/ai-model-serving/kserve/rbac/localmodelnode/role.yaml create mode 100644 assets/optional/ai-model-serving/kserve/rbac/localmodelnode/role_binding.yaml create mode 100644 assets/optional/ai-model-serving/kserve/rbac/localmodelnode/service_account.yaml create mode 100644 assets/optional/sriov/crd/sriovnetwork.openshift.io_ovsnetworks.yaml create mode 100644 assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovibnetworks.yaml create mode 100644 assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml create mode 100644 assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworknodestates.yaml create mode 100644 assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml create mode 100644 assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworks.yaml create mode 100644 assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml create mode 100644 assets/optional/sriov/deploy/clusterrole.yaml create mode 100644 assets/optional/sriov/deploy/clusterrolebinding.yaml create mode 100644 assets/optional/sriov/deploy/namespace.yaml create mode 100644 assets/optional/sriov/deploy/operator.yaml create mode 100644 assets/optional/sriov/deploy/role.yaml create mode 100644 assets/optional/sriov/deploy/rolebinding.yaml create mode 100644 assets/optional/sriov/deploy/serviceaccount.yaml create mode 100644 assets/optional/sriov/deploy/sriovoperatorconfig.yaml create mode 100644 assets/optional/sriov/deploy/supported-nic-ids_v1_configmap.yaml create mode 100644 assets/optional/sriov/kustomization.yaml create mode 100644 assets/optional/sriov/release-sriov-aarch64.json create mode 100644 assets/optional/sriov/release-sriov-x86_64.json delete mode 120000 deps/github.com/openshift/kubernetes/hack/update-test-annotations.sh delete mode 120000 deps/github.com/openshift/kubernetes/hack/verify-test-annotations.sh delete mode 100644 deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/annotate.go delete mode 100644 deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/annotate_test.go delete mode 100644 deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/cmd/main.go delete mode 100644 deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/generated/zz_generated.annotations.go delete mode 100644 deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/rules.go delete mode 100644 deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/rules_test.go delete mode 100755 deps/github.com/openshift/kubernetes/openshift-hack/update-test-annotations.sh delete mode 100755 deps/github.com/openshift/kubernetes/openshift-hack/verify-test-annotations.sh create mode 100644 deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_compatibility_test.go create mode 100644 deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_revision_1.33.0.json create mode 100644 deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_revision_1.34.0.json create mode 100644 deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_set_1.33.0.json create mode 100644 deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_set_1.34.0.json create mode 100644 deps/github.com/openshift/kubernetes/test/integration/auth/testdata/README.md create mode 100644 deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-client-key.pem create mode 100644 deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-client.pem create mode 100644 deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-root.pem create mode 100644 deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/misc/main_test.go create mode 100644 deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/misc/miscpreemption_test.go delete mode 100644 deps/github.com/openshift/kubernetes/vendor/github.com/MakeNowJust/heredoc/README.md delete mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md delete mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v4/README.md delete mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v4/claims.go delete mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v4/errors.go delete mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v4/map_claims.go delete mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v4/parser.go delete mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v4/parser_option.go delete mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v4/token.go rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/.gitignore (100%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/LICENSE (100%) create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/MIGRATION_GUIDE.md create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/README.md rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/SECURITY.md (59%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/VERSION_HISTORY.md (96%) create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/claims.go rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/doc.go (100%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/ecdsa.go (88%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/ecdsa_utils.go (100%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/ed25519.go (71%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/ed25519_utils.go (100%) create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/errors.go create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/errors_go1_20.go create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/errors_go_other.go rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/hmac.go (57%) create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/map_claims.go rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/none.go (72%) create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/parser.go create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/parser_option.go create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/registered_claims.go rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/rsa.go (84%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/rsa_pss.go (88%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/rsa_utils.go (93%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/signing_method.go (71%) rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/staticcheck.conf (100%) create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/token.go create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/token_option.go rename etcd/vendor/github.com/golang-jwt/jwt/{v4 => v5}/types.go (73%) create mode 100644 etcd/vendor/github.com/golang-jwt/jwt/v5/validator.go delete mode 100644 etcd/vendor/github.com/golang/protobuf/descriptor/descriptor.go delete mode 100644 etcd/vendor/github.com/golang/protobuf/jsonpb/decode.go delete mode 100644 etcd/vendor/github.com/golang/protobuf/jsonpb/encode.go delete mode 100644 etcd/vendor/github.com/golang/protobuf/jsonpb/json.go delete mode 100644 etcd/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go delete mode 100644 etcd/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go delete mode 100644 etcd/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go delete mode 100644 etcd/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go delete mode 100644 etcd/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/.gitignore delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/.travis.yml delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/CHANGELOG.md delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/CONTRIBUTING.md delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/makefile rename etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/{ => providers/prometheus}/LICENSE (100%) create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_metrics.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_options.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/constants.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/doc.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/options.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/reporter.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_metrics.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_options.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/slack.png create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/COPYRIGHT rename etcd/vendor/github.com/grpc-ecosystem/{go-grpc-prometheus => go-grpc-middleware/v2}/LICENSE (100%) create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/callmeta.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/client.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/doc.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/reporter.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/server.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/.gitignore delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/.travis.yml delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/CHANGELOG.md delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_metrics.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/makefile delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/metric_options.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_metrics.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/BUILD.bazel delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.pb.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.proto delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/doc.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_json.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_jsonpb.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_proto.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto2_convert.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/BUILD.bazel delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/doc.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/pattern.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/readerfactory.go delete mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/trie.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/BUILD.bazel create mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations.pb.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations.proto create mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations_protoopaque.pb.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/buf.gen.yaml create mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2.pb.go create mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2.proto create mode 100644 etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2_protoopaque.pb.go create mode 100644 etcd/vendor/github.com/openshift/api/features/features.go create mode 100644 etcd/vendor/github.com/openshift/api/features/legacyfeaturegates.go create mode 100644 etcd/vendor/github.com/openshift/api/features/util.go create mode 100644 etcd/vendor/go.etcd.io/etcd/api/v3/versionpb/version.pb.go create mode 100644 etcd/vendor/go.etcd.io/etcd/api/v3/versionpb/version.proto create mode 100644 etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/log_format.go rename etcd/vendor/{google.golang.org/genproto/protobuf/field_mask/field_mask.go => go.etcd.io/etcd/client/pkg/v3/transport/sockopt_wasm.go} (54%) create mode 100644 etcd/vendor/go.etcd.io/etcd/client/pkg/v3/verify/verify.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/client/v2/json.go create mode 100644 etcd/vendor/go.etcd.io/etcd/client/v3/OWNERS create mode 100644 etcd/vendor/go.etcd.io/etcd/pkg/v3/featuregate/feature_gate.go create mode 100644 etcd/vendor/go.etcd.io/etcd/pkg/v3/notify/notify.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/raft/v3/LICENSE delete mode 100644 etcd/vendor/go.etcd.io/etcd/raft/v3/OWNERS delete mode 100644 etcd/vendor/go.etcd.io/etcd/raft/v3/log.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/raft/v3/log_unstable.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/raft/v3/rawnode.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/adapters.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/base.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/debug.go rename etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/{v2http/httptypes => etcdhttp/types}/errors.go (100%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/utils.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/version.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth_requests.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/capability.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client_auth.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/http.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/member.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/metrics.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/cluster.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/server.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/store.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/watcher.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery/discovery.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/apply.go rename etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/{ => apply}/apply_auth.go (66%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/corrupt.go rename etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/{api/v2stats/stats.go => apply/metrics.go} (53%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/uber_applier.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/bootstrap.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors/errors.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/metrics.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/txn.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/util.go rename etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/{api/v2http => version}/doc.go (81%) rename etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/{api/membership => version}/downgrade.go (60%) rename etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/{api/v2v3/doc.go => version/errors.go} (60%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/monitor.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/version.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/features/etcd_features.go rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/README.md (94%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/auth_role.go (96%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/auth_user.go (94%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/cancelreq.go (81%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/client.go (97%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/cluster_error.go (100%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/curl.go (88%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/discover.go (100%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/doc.go (100%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/keys.go (97%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/members.go (95%) rename etcd/vendor/go.etcd.io/etcd/{client/v2 => server/v3/internal/clientv2}/util.go (80%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/lease/lease.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/verify.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/revision.go delete mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/util.go rename etcd/vendor/go.etcd.io/etcd/server/v3/{etcdserver => storage}/backend.go (69%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/backend.go (88%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/batch_tx.go (95%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/config_default.go (96%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/config_linux.go (100%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/config_windows.go (98%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/doc.go (100%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/hooks.go (88%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/metrics.go (100%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/read_tx.go (98%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc => storage}/backend/tx_buffer.go (83%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/verify.go rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/datadir/datadir.go (84%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/datadir/doc.go (100%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/hooks.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/metrics.go rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/doc.go (100%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/hash.go (76%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/index.go (54%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/key_index.go (83%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/kv.go (99%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/kv_view.go (100%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/kvstore.go (81%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/kvstore_compaction.go (87%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/kvstore_txn.go (80%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/metrics.go (86%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/metrics_txn.go (96%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/revision.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/store.go rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/watchable_store.go (80%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/watchable_store_txn.go (100%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/watcher.go (100%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/mvcc/watcher_group.go (97%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{etcdserver => storage}/quota.go (72%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/actions.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/alarm.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth_roles.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth_users.go rename etcd/vendor/go.etcd.io/etcd/server/v3/{mvcc/buckets => storage/schema}/bucket.go (70%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/changes.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/cindex.go rename etcd/vendor/go.etcd.io/etcd/server/v3/{etcdserver/api/membership => storage/schema}/confstate.go (73%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/lease.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/membership.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/migration.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/schema.go create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/version.go rename etcd/vendor/go.etcd.io/etcd/server/v3/{etcdserver => storage}/storage.go (54%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/util.go rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/decoder.go (66%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/doc.go (85%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/encoder.go (96%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/file_pipeline.go (94%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/metrics.go (100%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/repair.go (83%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/util.go (94%) create mode 100644 etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/version.go rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/wal.go (85%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/walpb/record.go (87%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/walpb/record.pb.go (89%) rename etcd/vendor/go.etcd.io/etcd/server/v3/{ => storage}/wal/walpb/record.proto (87%) create mode 100644 etcd/vendor/go.etcd.io/raft/v3/.gitignore create mode 100644 etcd/vendor/go.etcd.io/raft/v3/.go-version create mode 100644 etcd/vendor/go.etcd.io/raft/v3/.golangci.yaml rename etcd/vendor/go.etcd.io/{etcd/client/v2 => raft/v3}/LICENSE (100%) create mode 100644 etcd/vendor/go.etcd.io/raft/v3/Makefile create mode 100644 etcd/vendor/go.etcd.io/raft/v3/OWNERS rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/README.md (97%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/bootstrap.go (98%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/confchange/confchange.go (87%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/confchange/restore.go (97%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/design.md (100%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/doc.go (79%) create mode 100644 etcd/vendor/go.etcd.io/raft/v3/log.go create mode 100644 etcd/vendor/go.etcd.io/raft/v3/log_unstable.go rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/logger.go (97%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/node.go (79%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/quorum/joint.go (100%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/quorum/majority.go (85%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/quorum/quorum.go (100%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/quorum/voteresult_string.go (100%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/raft.go (63%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/raftpb/confchange.go (95%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/raftpb/confstate.go (94%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/raftpb/raft.pb.go (84%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/raftpb/raft.proto (73%) create mode 100644 etcd/vendor/go.etcd.io/raft/v3/rawnode.go rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/read_only.go (97%) create mode 100644 etcd/vendor/go.etcd.io/raft/v3/state_trace.go create mode 100644 etcd/vendor/go.etcd.io/raft/v3/state_trace_nop.go rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/status.go (92%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/storage.go (78%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/tracker/inflights.go (62%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/tracker/progress.go (57%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/tracker/state.go (95%) rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/tracker/tracker.go (93%) create mode 100644 etcd/vendor/go.etcd.io/raft/v3/types.go rename etcd/vendor/go.etcd.io/{etcd => }/raft/v3/util.go (55%) delete mode 100644 etcd/vendor/go.opentelemetry.io/otel/semconv/internal/http.go delete mode 100644 etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/README.md delete mode 100644 etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/doc.go delete mode 100644 etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/exception.go delete mode 100644 etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/http.go delete mode 100644 etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/resource.go delete mode 100644 etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/schema.go delete mode 100644 etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/trace.go delete mode 100644 etcd/vendor/google.golang.org/genproto/LICENSE create mode 100644 etcd/vendor/google.golang.org/grpc/reflection/README.md create mode 100644 etcd/vendor/google.golang.org/grpc/reflection/adapt.go create mode 100644 etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go create mode 100644 etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go create mode 100644 etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go create mode 100644 etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go create mode 100644 etcd/vendor/google.golang.org/grpc/reflection/internal/internal.go create mode 100644 etcd/vendor/google.golang.org/grpc/reflection/serverreflection.go create mode 100644 pkg/admin/prerun/featuregate_lock.go create mode 100644 pkg/admin/prerun/featuregate_lock_test.go create mode 100644 pkg/controllers/hostswatcher.go create mode 100644 rebase.log create mode 100644 scripts/auto-rebase/assets_sriov.yaml create mode 100755 scripts/auto-rebase/last_rebase_sriov.sh create mode 100644 scripts/auto-rebase/manifests_patches/020-dns-configmap.patch create mode 100644 scripts/auto-rebase/manifests_patches/020-dns-daemonset.patch create mode 100644 scripts/auto-rebase/manifests_patches/020-dns-hosts-configmap-role.patch create mode 100644 scripts/auto-rebase/manifests_patches/020-dns-hosts-configmap-rolebinding.patch create mode 100755 scripts/auto-rebase/rebase_sriov.sh rename scripts/{release-notes/gen_ec_release_notes.sh => pyutils/create-venv.sh} (75%) create mode 100644 scripts/pyutils/ghutils.py create mode 100644 scripts/pyutils/gitutils.py create mode 100644 scripts/pyutils/requirements.txt create mode 100644 scripts/release-notes/common.py create mode 100755 scripts/release-notes/gen_gh_releases.sh rename scripts/release-notes/{gen_ec_release_notes.py => gen_gh_releases_from_mirror.py} (61%) mode change 100644 => 100755 create mode 100755 scripts/release-notes/gen_gh_releases_from_rhocp.py delete mode 100644 scripts/release-notes/tag_stable_releases.py create mode 100644 test/assets/sriov/sriov-network-policy-template.yaml create mode 100644 test/bin/common_versions_verify.sh mode change 100644 => 100755 test/bin/pyutils/generate_common_versions.py create mode 100644 test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel-isolated.containerfile create mode 100644 test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel-optionals.containerfile create mode 100644 test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel.containerfile create mode 100644 test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-z1-with-optional.containerfile create mode 100644 test/image-blueprints-bootc/layer2-presubmit/group2/rhel100-bootc-source-optionals.containerfile create mode 100644 test/image-blueprints-bootc/layer4-upstream/group2/cos10-bootc-source-optionals.containerfile create mode 100644 test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-ec-with-optional.containerfile create mode 100644 test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-rc-with-optional.containerfile create mode 100644 test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-zstream-with-optional.containerfile rename test/image-blueprints-bootc/{layer1-base/group2/rhel96-bootc-brew.containerfile => layer5-release/group1/rhel100-bootc-brew.containerfile} (83%) rename test/image-blueprints-bootc/{layer1-base/group2 => layer5-release/group1}/rhel96-bootc-brew-ec-with-optional.containerfile (100%) rename test/image-blueprints-bootc/{layer1-base/group2 => layer5-release/group1}/rhel96-bootc-brew-rc-with-optional.containerfile (100%) rename test/image-blueprints-bootc/{layer1-base/group2 => layer5-release/group1}/rhel96-bootc-brew-y1-with-optional.containerfile (100%) rename test/image-blueprints-bootc/{layer1-base/group2 => layer5-release/group1}/rhel96-bootc-brew-y2-with-optional.containerfile (100%) rename test/image-blueprints-bootc/{layer1-base/group2 => layer5-release/group1}/rhel96-bootc-brew-zstream-with-optional.containerfile (100%) rename test/image-blueprints-bootc/{layer1-base/group3 => layer5-release/group2}/rhel96-bootc-brew-ec-with-optional-fips.containerfile (70%) rename test/image-blueprints-bootc/{layer1-base/group4 => layer5-release/group2}/rhel96-bootc-brew-ec-with-optional-tuned.containerfile (100%) rename test/image-blueprints-bootc/{layer1-base/group3 => layer5-release/group2}/rhel96-bootc-brew-ec-with-optional.image-bootc (100%) create mode 100644 test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-nightly-with-optional.containerfile rename test/image-blueprints-bootc/{layer1-base/group3 => layer5-release/group2}/rhel96-bootc-brew-rc-with-optional-fips.containerfile (70%) rename test/image-blueprints-bootc/{layer1-base/group4 => layer5-release/group2}/rhel96-bootc-brew-rc-with-optional-tuned.containerfile (100%) rename test/image-blueprints-bootc/{layer1-base/group3 => layer5-release/group2}/rhel96-bootc-brew-rc-with-optional.image-bootc (100%) rename test/image-blueprints-bootc/{layer1-base/group3 => layer5-release/group2}/rhel96-bootc-brew-zstream-with-optional-fips.containerfile (70%) rename test/image-blueprints-bootc/{layer1-base/group4 => layer5-release/group2}/rhel96-bootc-brew-zstream-with-optional-tuned.containerfile (100%) rename test/image-blueprints-bootc/{layer1-base/group3 => layer5-release/group2}/rhel96-bootc-brew-zstream-with-optional.image-bootc (100%) rename test/image-blueprints/{layer1-base/group2 => layer4-release/group1}/rhel96-brew-y2-with-optionals.toml (100%) rename test/image-blueprints/{layer1-base/group3 => layer4-release/group2}/rhel96-brew-y1-with-optionals.toml (100%) rename test/image-blueprints/{layer1-base/group4 => layer4-release/group3}/rhel96-brew-ec-with-optionals.toml (100%) create mode 100644 test/image-blueprints/layer4-release/group3/rhel96-brew-nightly-with-optionals.toml rename test/image-blueprints/{layer1-base/group4 => layer4-release/group3}/rhel96-brew-rc-with-optionals.toml (100%) rename test/image-blueprints/{layer1-base/group4 => layer4-release/group3}/rhel96-brew-zstream-with-optionals.toml (100%) rename test/image-blueprints/{layer2-presubmit/group1 => layer4-release/group3}/rhel96-lrel-optionals-tuned.toml (100%) create mode 100644 test/resources/hosts.resource create mode 100644 test/scenarios-bootc/periodics/el100-src@optional.sh delete mode 100644 test/scenarios-bootc/periodics/el96-crel@el96-src@optional-upgrade.sh delete mode 100644 test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-fails-isolated.sh delete mode 100644 test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-fails.sh delete mode 100644 test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-ok-isolated.sh delete mode 100644 test/scenarios-bootc/periodics/el96-crel@optional-sigstore.sh delete mode 100644 test/scenarios-bootc/periodics/el96-prel@el96-crel@upgrade-ok.sh create mode 100644 test/scenarios-bootc/periodics/el96-prel@el96-src@upgrade-ok.sh rename test/scenarios-bootc/periodics/{el96-src@gitops.sh => el96-src@fault-tests-and-greenboot.sh} (81%) delete mode 100644 test/scenarios-bootc/periodics/el96-src@fault-tests.sh rename test/scenarios-bootc/periodics/{el96-src@fips.sh.disabled => el96-src@fips.sh} (100%) rename test/scenarios-bootc/periodics/{el96-src@telemetry.sh => el96-src@gitops-telemetry-clusterid-systemd.sh} (71%) mode change 100644 => 100755 delete mode 100644 test/scenarios-bootc/periodics/el96-src@greenboot.sh rename test/scenarios-bootc/periodics/{el96-src@osconfig-misc.sh => el96-yminus2@el96-src@upgrade-ok.sh} (63%) delete mode 100644 test/scenarios-bootc/presubmits/el96-crel@el100-src@upgrade-ok.sh rename test/scenarios-bootc/{presubmits/el96-crel@el96-src@upgrade-ok.sh => releases/el100-lrel@ginkgo-tests.sh} (71%) create mode 100644 test/scenarios-bootc/releases/el100-lrel@optional.sh rename test/scenarios-bootc/{periodics/el96-crel@brew-standard1.sh => releases/el100-lrel@standard1.sh} (81%) rename test/scenarios-bootc/{periodics/el96-crel@brew-standard2.sh => releases/el100-lrel@standard2.sh} (85%) rename test/scenarios-bootc/{periodics => releases}/el96-crel@published-images-standard1.sh (100%) rename test/scenarios-bootc/{periodics => releases}/el96-crel@published-images-standard2.sh (100%) rename test/scenarios-bootc/releases/{el96-lrel@fips.sh.disabled => el96-lrel@fips.sh} (81%) create mode 100644 test/scenarios-bootc/releases/el96-lrel@multi-config-standard1.sh create mode 100644 test/scenarios-bootc/releases/el96-lrel@multi-config-standard2.sh create mode 100644 test/scenarios-bootc/releases/el96-lrel@nightly-brew-standard1.sh create mode 100644 test/scenarios-bootc/releases/el96-lrel@nightly-brew-standard2.sh create mode 100644 test/scenarios-bootc/releases/el96-z1@el96-lrel@standard1.sh create mode 100644 test/scenarios-bootc/releases/el96-z1@el96-lrel@standard2.sh create mode 100644 test/scenarios-bootc/upstream/cos10-src@optional.sh delete mode 100644 test/scenarios/periodics/el96-crel@el96-src@optional-upgrade.sh delete mode 100644 test/scenarios/periodics/el96-crel@el96-src@upgrade-fails.sh delete mode 100644 test/scenarios/periodics/el96-crel@optional-sigstore.sh delete mode 100644 test/scenarios/periodics/el96-prel@el96-crel@upgrade-ok.sh create mode 100644 test/scenarios/periodics/el96-prel@el96-src@upgrade-ok.sh create mode 100644 test/scenarios/periodics/el96-src@fips-rpm.sh delete mode 100644 test/scenarios/periodics/el96-src@fips-rpm.sh.disabled rename test/scenarios/periodics/{el96-src@fips.sh.disabled => el96-src@fips.sh} (54%) create mode 100644 test/scenarios/periodics/el96-yminus2@el96-src@upgrade-ok.sh delete mode 100644 test/scenarios/presubmits/el96-crel@el96-src@upgrade-ok.sh create mode 100644 test/scenarios/releases/el96-lrel@ginkgo-multi-config.sh create mode 100644 test/suites/optional/sriov.robot create mode 100644 test/suites/standard1/dns.robot create mode 100644 test/suites/standard2/feature-gates.robot create mode 100644 test/suites/tuned/uncore-cache.robot diff --git a/.claude/.gitignore b/.claude/.gitignore new file mode 100644 index 0000000000..93c0f73fa4 --- /dev/null +++ b/.claude/.gitignore @@ -0,0 +1 @@ +settings.local.json diff --git a/.claude/agents/openshift-ci-analyzis.md b/.claude/agents/openshift-ci-analyzis.md new file mode 100644 index 0000000000..bc69dd9965 --- /dev/null +++ b/.claude/agents/openshift-ci-analyzis.md @@ -0,0 +1,105 @@ +--- +name: openshift-ci-analysis +description: use the @openshift-ci-analysis when the user's prompt is a URL with this domain: https://prow.ci.openshift.org/** +model: sonnet +color: blue +--- + +# Goal: Reduce noise for developers by processing large logs from a CI test pipeline and correctly classifying fatal errors with a false-positive rate of 0.01% and false-negative rate of 0.5%. + +# Audience: Software Engineer + +# Glossary + +- **ci-config**: Top level configuration file specifying build inputs, versions, and test workflows to execute. Periodic tests are suffixed with `__periodic.yaml`. +- **test**: The set of configurations and commands that specify how to execute the test. Can be defined in-line in ci-config, or as individual "steps" (see below). +- **step-registry**: Root directory where all openshift-ci test step configs and commands are stored. +- **step**: Smallest component of the test infrastructure. A step yaml specifies the command or script to execute, environmental variables and default values, and step metadata. Also called "ref" or "step ref". +- **chain**: A yaml configuration specifying 1 or more steps or chains in an array. Steps and chains are exploded and executed serially by index. May override step environment variable values. +- **workflow**: A yaml configuration specifying 1 or more steps, chains, or workflows in an array. Steps, chains, and workflows are exploded and executed serially. May override chain or step environmental variable values. Typically referenced by a test in a ci-config. +- **scenario**: MicroShift integration tests are built on the robotframework test framework. A "scenario" represents the RF suite, the test's environment, the microshift deployment, and the virtual machine on which the entire testing process takes place. Scenarios also include the manner of deployment: rpm-ostree, rpm installation, or bootc container. + +# Job Name and Job ID + +The Job Name and Job ID are encoded in the URL. Use this template to determine the job name and job id: +``` +https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-{MICROSHIFT_VERSION}-{JOB_NAME}/{JOB_ID} +``` + +# Important Files +> IMPORTANT! All files in this list will be downloaded after running the +- `${TMP}/build-log.txt`: Log containing prow job output and most likely place to identify AWS infra related or hypervisor related errors. +- `${STEP}/build-log.txt`: Each step in the CI job is individually logged in a build-log.txt file. +- `./artifacts/${JOB_NAME}/openshift-microshift-infra-sos-aws/artifacts/sosreport-i-"${UNIQUE_ID}"-YYYY-MM-DD-"${UNIQUE_ID_2}".tar.xz`: Compressed archive containing select portions of the test host's filesystem, relevant logs, and system configurations. +- `${JOB_NAME}/${JOB_ID}/artifacts/e2e-aws-ovn-ocp-conformance-arm64/openshift-microshift-e2e-origin-conformance/build-log.txt`: Step-specific build log for origin conformance tests. + +# Important Links + +**Step Diagram URL** (found at the end of the main build-log): +``` +https://steps.ci.openshift.org/job?org=openshift&repo=microshift&branch=release-4.19&test=e2e-aws-tests-bootc-nightly&variant=periodics +``` + +**SOS Report** (contains a cross-section of the test host's filesystem, including the microshift journal and container logs) +``` +https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/pr-logs/pull/openshift_microshift/[0-9]{,4}/${JOB_NAME}/${JOB_ID}/artifacts/e2e-aws-tests/openshift-microshift-infra-sos-aws/artifacts/sosreport-*.tar.xz +``` + +This link provides a diagram of the steps that make up the test. Think about reading this diagram when identifying step failures because not all fatal errors cause the current step to fail but may cause the next step to fail. + +# Common Commands + +Create a temporary working directory to store artifacts for the current job: +```bash +mktemp -d /tmp/openshift-ci-analysis-XXXX +``` + +Fetch the high level summary of the failed prow job: +```bash +curl https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.21-periodics-e2e-aws-ovn-ocp-conformance-serial/1984108354347208704 -o ${TMP}/build-log.txt +``` + +Scan the build log for arbitrary text: +```bash +grep '${SOME_TEXT}' ${GREP_OPTS} ${TMP}/build-log.txt +``` + +Download all prow job artifacts: +```bash +gcloud storage cp -r gs://test-platform-results/logs/periodic-ci-openshift-microshift-release-4.21-periodics-e2e-aws-ovn-ocp-conformance-serial/1984108354347208704/ ${TMP}/ +``` + +# Workflow + +0. Create and use a temporary working directory. Use the mktemp -d command to create this directory, then add the directory to the claude context by executing @add-dir /tmp/NEW_TEMP_DIR. + +1. **Scan for errors**: Start by scanning the top level `build-log.txt` file for errors and determine the step where the error occurred. Record each error with the filepath and line number for later reference. + +2. **Read context**: Iterate over each recorded error, locate the log file and line number, then read 50 lines before and 50 lines after the error. Use this information to characterize the error. Think about whether this error is transient and think about where in the stack the error occurs. Does it occur in the cloud infra, the openshift or prow ci-config, the hypvervisor, or is it a legitimate test failure? If it is a legitimate test failure, determine what stage of the test failed: setup, testing, teardown. + +3. **Analyze the error**: Based on the context of the error, think hard about whether this error caused the test to fail, is a transient error, or is a red herring. + + 3.1 If it is a legitimate test error, analyze the test logs to determine the source of the error. + 3.2 If the source of the error appears to be due to microshift or a workload running on microshift, analyze the sos report's microshift journal and pod logs. + +4. **Produce a report**: Create a concise report of the error. The report MUST specify: + - Where in the pipeline the error occurred + - The specific step the error occurred in + - Whether the test failure was legitimate (i.e., a test failed) or due to an infrastructure failure (i.e., build image was not found, AWS infra failed due to quota, hypervisor failed to create test host VM, etc.) + +# Tips + +1. There are many setup and teardown stages so fatal errors may be buried by log output from the teardown phase. It is not common to find the fatal error at the end of the log. +2. You can quickly determine the failed step from the build-log.txt by reading the last `Running step e2e-aws-tests-bootc-nightly-openshift-microshift-e2e-metal-tests` line before the container logs appear. + +# Output Template + +Use this template for your error analysis reports: + +``` +Error Severity: {1-5} +Stack Layer: {AWS Infra, build phase, deploy phase, test, etc.} +Step Name: {The specific step where the error occurred} +Error: {The exact error, including additional log context if it relates to the failure} +Suggested Remediation: {Based on where the error occurs, think hard about how to correct the error ONLY if it requires fixing. Infrastructure failures may not require code changes.} +``` diff --git a/.claude/commands/analyze-ci-test-job.md b/.claude/commands/analyze-ci-test-job.md new file mode 100644 index 0000000000..52e438e9a1 --- /dev/null +++ b/.claude/commands/analyze-ci-test-job.md @@ -0,0 +1,416 @@ +--- +name: Analyze CI Test Job +argument-hint: +description: Analyze a MicroShift Prow CI Test Job execution +allowed-tools: WebFetch, Bash, Read, Write, Glob, Grep +--- + +## Name +analyze-ci-test-job + +## Synopsis +``` +/analyze-ci-test-job +``` + +## Description +The `analyze-ci-test-job` command fetches comprehensive information from a Prow CI job execution and displays it in both JSON and Markdown formats. + +This command provides: +- Job metadata (status, timing, architecture, image type) +- MicroShift version being tested +- Test scenarios executed and their results +- Build information +- Links to logs and artifacts + +This command is useful for understanding what was tested in a specific job run, identifying failures, and accessing detailed logs and artifacts. + +## Implementation + +This command works by: + +1. **Parsing the job URL** to extract job name, ID, and configuration (architecture, image type, version) +2. **Fetching job metadata** from `finished.json` and `started.json` to get status, timing, and result information +3. **Extracting MicroShift version** using the `extract_microshift_version.py` helper script from build logs +4. **Listing test scenarios** by fetching the scenario-info directory structure from GCS artifacts +5. **Analyzing test results** for each scenario using the `analyze-test-scenario` command to get comprehensive JSON data +6. **Compiling artifacts and logs** by constructing URLs to build logs, test execution logs, and failure diagnostics +7. **Generating a detailed Markdown report** with job overview, version info, scenario results, and artifact links + +The command integrates with the `analyze-test-scenario` command to provide detailed per-scenario analysis and aggregates all information into a human-readable report with proper formatting (status icons, duration calculations, failure summaries). + +## Arguments +- `$1` (job-url): URL to the Prow CI job - **Required** + - Formats accepted: + - Full Prow dashboard URL: `https://prow.ci.openshift.org/view/gs/test-platform-results/logs//` + - GCS web URL: `https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/logs//` + - Job ID only (e.g., "1979744605507162112") - will attempt to infer job type from context + +## Return Value +- **Format**: Markdown +- **Location**: Output directly to the conversation +- **Content**: + - Job overview (status, timing, configuration) + - MicroShift version details + - Test scenario results + - Build information + - Links to logs and artifacts + +## Implementation Steps + +### Step 1: Parse Arguments and Validate Job URL + +**Goal**: Extract the job name, job ID, and job configuration. + +**Actions**: +1. Parse the job URL to extract: + - Job name (e.g., "periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic") + - Job ID (e.g., "1979744605507162112") +2. Determine job configuration from job name: + - Architecture: x86_64 or aarch64 (look for "arm" in job name) + - Image type: bootc or rpm-ostree (look for "bootc" in job name) + - Version: extract from job name (e.g., "4.20") +3. Validate URL format +4. If only job ID provided, ask user for job type or attempt to determine from recent jobs + +**Example Parsing**: +``` +URL: https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic/1979744605507162112 + +Extracted: +- job_name: "periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic" +- job_id: "1979744605507162112" +- version: "4.20" +- arch: "x86_64" +- image_type: "bootc" +``` + +### Step 2: Fetch Job Metadata + +**Goal**: Get job information (status, timing, result). + +**Actions**: +1. Construct the GCS URL for the `finished.json` file: + ``` + https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/logs///finished.json + ``` +2. Fetch the `finished.json` file using curl or WebFetch +3. Parse the JSON to extract: + - Job result (SUCCESS/FAILURE/ABORTED) + - Timestamp (start/end times) + - Duration + - Passed status + - Metadata (repo, revision, etc.) +4. Fetch `started.json` for additional metadata: + ```bash + curl -s "https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/logs///started.json" + ``` + +### Step 3: Extract MicroShift Version + +**Goal**: Determine the exact MicroShift version being tested. + +This command includes a Python script that automates version extraction from test logs. + +**Script Location**: `.claude/scripts/extract_microshift_version.py` + +**Usage**: +```bash +python3 .claude/scripts/extract_microshift_version.py +``` + +**Arguments**: +- `prow_url`: The full Prow CI job URL (e.g., "https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic/1979744605507162112") +- `scenario`: The test scenario name (e.g., "el96-lrel@ipv6") + +**Example**: +```bash +# Extract version for a specific job and scenario +python3 .claude/scripts/extract_microshift_version.py "https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic/1979744605507162112" "el96-lrel@ipv6" +``` + +**Output** (JSON): +```json +{ + "success": true, + "version": "4.20.0-202510161342.p0.g17d1d9a.assembly.4.20.0.el9.x86_64", + "build_type": "zstream", + "url": "https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/logs/...", + "error": null +} +``` + +**Build Types Detected**: +- `"nightly"`: Nightly development builds +- `"ec"`: Engineering Candidate +- `"rc"`: Release Candidate +- `"zstream"`: Stable/zstream release + +### Step 4: List Test Scenarios + +**Goal**: Find all test scenarios executed in this job and list them. + +**Output** (JSON): +```json +{ + "job_id": "1979744605507162112", + "scenarios": [ + "el94-y2@el96-lrel@standard1", + "el96-lrel@standard1", + "el96-lrel@lvm", + "el96-lrel@dual-stack", + "el96-lrel@ipv6" + ], + "total_scenarios": 5 +} +``` + +### Step 5: Analyze Test Results for Each Scenario + +**Goal**: Get detailed test execution results for each scenario. + +**Method**: Use the `analyze-test-scenario` command for each scenario to get comprehensive JSON data. + +**Actions**: +For each scenario found in Step 4: + +1. **Get scenario details** using the analyze-test-scenario command: + ```bash + /microshift-prow-job:analyze-test-scenario + ``` + +2. **Parse the JSON response** which includes: + - Test results summary (total, passed, failed, errors, skipped) + - Individual test case details + - Failure messages and details (if any) + - Scenario configuration (RHEL version, test category) + - Execution timing + - Links to all artifacts + +**Example JSON Response**: +```json +{ + "scenario": { + "name": "el96-lrel@standard1", + "description": "RHEL 9.6 Latest Release - Standard Tests", + "configuration": { + "rhel_version": "9.6", + "release_type": "latest", + "test_category": "Standard Tests" + } + }, + "test_results": { + "status": "passed", + "summary": { + "total": 65, + "passed": 65, + "failed": 0, + "errors": 0, + "skipped": 0 + }, + "execution_time_seconds": 1234.56, + "test_cases": [ + { + "name": "MicroShift boots successfully", + "status": "passed" + } + ], + "failures": [] + }, + "artifacts": { + "junit_xml": "https://...", + "boot_log": "https://...", + "debug_log": "https://..." + } +} +``` + +3. **Extract key information** from each scenario: + - Overall status (passed/failed) + - Test counts + - Failure details (for failed scenarios) + - Execution time + - Test category and configuration + +**Alternative Manual Method** (if analyze-test-scenario command unavailable): +1. Fetch junit.xml directly from artifact URL +2. Parse XML to extract test counts +3. Check boot_and_run.log for execution details +4. Extract scenario metadata from directory structure + +### Step 6: Compile Artifacts and Logs + +**Goal**: Provide links to useful artifacts and logs. + +**Actions**: +1. Compile key artifact URLs: + - Build log: `artifacts//openshift-microshift-infra-iso-build/build-log.txt` + - Test logs for each scenario + - JUnit XML reports + - Any failure logs or sosreports + +2. Categorize artifacts by type: + - Build artifacts + - Test execution logs + - Failure diagnostics + - System information + +### Step 7: Generate Detailed Report + +**Goal**: Create a comprehensive, well-structured report. + +**Report Structure**: +```markdown +# MicroShift CI Job Details + +## Job Overview +- **Job ID**: +- **Job Name**: +- **Status**: ✓ SUCCESS / ✗ FAILURE / ⚠️ ABORTED +- **Architecture**: x86_64 / aarch64 +- **Image Type**: bootc / rpm-ostree +- **Duration**: Xh Ym Zs +- **Started**: YYYY-MM-DD HH:MM:SS UTC +- **Finished**: YYYY-MM-DD HH:MM:SS UTC + +## MicroShift Version +- **Full Version**: +- **Build Type**: nightly / RC / EC / stable +- **Base Version**: X.Y.Z +- **Commit**: +- **Build Timestamp**: YYYY-MM-DD-HHMMSS + +## Test Scenarios + +### Scenario: +- **Description**: +- **Status**: ✓ PASS / ✗ FAIL +- **Tests**: X passed, Y failed, Z skipped +- **Duration**: Xm Ys + +**Failures** (if any): +- Test: + - Error: + - Log: [View]() + +[Repeat for each scenario] + +## Build Information +- **Build Status**: SUCCESS / FAILURE +- **Build Log**: [View]() +- **Build Duration**: Xm Ys + +## Artifacts & Logs +- [Build Log]() +- [Test Execution Logs]() +- [Scenario Details]() +- [Full Artifacts]() + +## Links +- [View on Prow CI]() +- [Browse All Artifacts]() +``` + +### Step 8: Error Handling + +**Goal**: Handle errors gracefully. + +**Common Issues**: +1. **Job not found (404)**: + - Verify job ID is correct + - Check if job is still running (no finished.json yet) + - Provide helpful error message to user + - Handle network errors gracefully + +2. **Artifacts not available**: + - Some jobs may not have all artifacts + - Gracefully handle missing files + - Indicate which artifacts are unavailable in the report + +3. **Invalid job URL**: + - Validate URL format before making requests + - Handle malformed URLs + - Provide examples of valid formats + - Suggest using job ID from create-report command + +4. **Version extraction failures**: + - Handle cases where version cannot be determined + - Provide partial information if available + - Include error message in report + +## Examples + +### Example 1: Successful Job Analysis +``` +/microshift-prow-job:analyze-ci-test-job https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic/1979744605507162112 +``` + +Output: +```markdown +# MicroShift CI Job Details + +## Job Overview +- **Job ID**: 1979744605507162112 +- **Job Name**: periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic +- **Status**: ✓ SUCCESS +- **Architecture**: x86_64 +- **Image Type**: bootc +- **Duration**: 1h 43m 40s +- **Started**: 2025-10-19 03:01:17 UTC +- **Finished**: 2025-10-19 04:44:57 UTC + +## MicroShift Version +- **Full Version**: 4.20.0-0.nightly-2025-10-15-110252-20251017171355-4ad30ab2d +- **Build Type**: nightly +- **Base Version**: 4.20.0 +- **Commit**: 4ad30ab2d +- **Build Date**: 2025-10-15 + +## Test Scenarios + +### Scenario: el96-lrel@standard1 +- **Description**: RHEL 9.6 Latest Release - Standard Tests +- **Status**: ✓ PASS +- **Tests**: 45 passed, 0 failed, 2 skipped + +[Additional sections...] +``` + +### Example 2: Using GCS Web URL +``` +/microshift-prow-job:analyze-ci-test-job https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-release-arm-periodic/1979744608019550208 +``` + +### Example 3: Failed Job Analysis +``` +/microshift-prow-job:analyze-ci-test-job https://prow.ci.openshift.org/view/gs/test-platform-results/logs/some-failing-job/9876543210 +``` + +Output would include failure details: +```markdown +## Job Overview +- **Status**: ✗ FAILURE +... + +## Test Scenarios +... +**Failures**: +- Test: + - Error: + - Log: [View]() +``` + +### Example 4: Job ID Only +``` +/microshift-prow-job:analyze-ci-test-job 1979744605507162112 +``` +(May prompt for additional context or attempt to determine job type from recent jobs) + +## Notes +- This command provides comprehensive analysis including job status, MicroShift version, test scenarios, and detailed results +- Works with MicroShift-specific Prow CI jobs +- Requires internet access to fetch job data from Prow CI +- All times are displayed in UTC +- Duration is calculated from the finished.json timestamp and start time from started.json +- The command is read-only and does not modify any CI job data +- Useful for debugging specific test failures or understanding what was tested diff --git a/.claude/commands/analyze-ci-test-scenario.md b/.claude/commands/analyze-ci-test-scenario.md new file mode 100644 index 0000000000..0935e9e075 --- /dev/null +++ b/.claude/commands/analyze-ci-test-scenario.md @@ -0,0 +1,408 @@ +--- +name: Analyze CI Test Scenario +argument-hint: +description: Analyze MicroShift Test Scenario results +allowed-tools: WebFetch, Bash, Read, Write, Glob, Grep +--- + + +## Name +analyze-ci-test-scenario + +## Synopsis +``` +/analyze-ci-test-scenario +``` + +## Description +The `analyze-ci-test-scenario` command retrieves comprehensive information about a specific test scenario executed within a MicroShift CI job. It returns detailed information containing: +- Scenario configuration (OS version, test type, architecture) +- Test execution results (pass/fail counts, test names) +- MicroShift version tested +- Execution timing +- Links to logs and artifacts +- Test failure details (if any) + +This command is useful for detailed investigation of specific test scenarios and understanding test execution results. + +## Implementation + +This command works by: + +1. **Parsing the job URL** to extract job metadata (ID, name, version, architecture, image type) +2. **Constructing artifact URLs** for the specified scenario in the GCS bucket +3. **Fetching JUnit XML** test results using curl/WebFetch from the scenario's artifact directory +4. **Parsing test results** to extract pass/fail counts, test case names, and failure details +5. **Extracting scenario metadata** from the scenario name (RHEL version, release type, test category) +6. **Compiling artifact links** for all logs and diagnostic files +7. **Generating formatted Markdown output** containing all collected information + +If no scenario name is provided it will prompt to the user what scenario to use. + +The command uses the `.claude/scripts/extract_microshift_version.py` helper script to determine the exact MicroShift version tested in the scenario. + +## Arguments +- `$1` (job-url): URL to the Prow CI job - **Required** + - Formats accepted: + - Full Prow dashboard URL: `https://prow.ci.openshift.org/view/gs/test-platform-results/logs//` + - GCS web URL: `https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/logs//` +- `$2` (scenario-name): Name of the scenario to analyze - **Required** + - Examples: `el96-lrel@standard1`, `el96-lrel@lvm`, `el96-lrel@dual-stack` + - If not provided, the command will list all available scenarios + +## Return Value +- **Format**: Markdown +- **Location**: Output directly to the conversation +- **Content**: Comprehensive scenario information including test results, configuration, and artifacts + +## Implementation Steps + +### Step 1: Parse and Validate Input + +**Goal**: Extract job information and scenario name from the arguments. + +**Actions**: +1. Parse the job URL to extract: + - Job name + - Job ID + - Version (e.g., "4.20") + - Job type (bootc/rpm-ostree, x86_64/aarch64) +2. Validate scenario name format (should match pattern: `el[0-9]+-[a-z0-9]+@.+`) +3. If no scenario name provided, set `list_scenarios = true` flag + +**Example**: +```javascript +// Input +job_url = "https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic/1979744605507162112" +scenario_name = "el96-lrel@standard1" + +// Parsed +job_id = "1979744605507162112" +job_name = "periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic" +version = "4.20" +job_type = "e2e-aws-tests-bootc-release-periodic" +arch = "x86_64" +image_type = "bootc" +``` + +### Step 2: Construct Artifact URLs + +**Goal**: Build URLs to the scenario's artifacts. + +**Actions**: +1. Construct base artifact URL: + ``` + https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/logs///artifacts//openshift-microshift-e2e-metal-tests/artifacts/scenario-info// + ``` +2. Construct specific artifact URLs: + - JUnit XML: `/junit.xml` + - Boot log: `/boot_and_run.log` + - Debug log: `/rf-debug.log` + - Phase logs: `/phase_*/*.log` + +### Step 3: List Available Scenarios (if no scenario specified) + +**Goal**: If no scenario name was provided, list all available scenarios in the job. + +**Actions**: +1. Fetch the scenario-info directory listing: + ``` + https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/logs///artifacts//openshift-microshift-e2e-metal-tests/artifacts/scenario-info/ + ``` +2. Use WebFetch to parse the HTML directory listing +3. Extract all scenario directory names +4. Return formatted list of scenarios + +**Output Format** (if listing scenarios): +``` +# Available Test Scenarios + +Job: periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic +Job ID: 1979744605507162112 + +## Scenarios (11 total) +- el94-y2@el96-lrel@standard1 +- el94-y2@el96-lrel@standard2 +- el96-lrel@ai-model-serving-online +- el96-lrel@dual-stack +- el96-lrel@ginkgo-tests +- el96-lrel@ipv6 +- el96-lrel@low-latency +- el96-lrel@lvm +- el96-lrel@multi-nic +- el96-lrel@standard1 +- el96-lrel@standard2 +``` + +### Step 4: Fetch and Parse JUnit XML + +**Goal**: Get test execution results from JUnit XML. + +**Actions**: +1. Fetch the junit.xml file using curl or WebFetch +2. Parse XML to extract: + - Total test count + - Passed tests count + - Failed tests count + - Skipped tests count + - Error count + - Test execution time + - Individual test case names and statuses + - Failure messages and stack traces (if any) + +**Example Parsing**: +```python +import xml.etree.ElementTree as ET + +root = ET.fromstring(xml_content) +testsuite = root.find('.//testsuite') + +test_results = { + 'total': int(testsuite.get('tests', '0')), + 'passed': 0, + 'failures': int(testsuite.get('failures', '0')), + 'errors': int(testsuite.get('errors', '0')), + 'skipped': int(testsuite.get('skipped', '0')), + 'time': float(testsuite.get('time', '0')), + 'test_cases': [] +} + +for testcase in testsuite.findall('.//testcase'): + name = testcase.get('name') + status = 'passed' + message = None + + if testcase.find('failure') is not None: + status = 'failed' + message = testcase.find('failure').get('message') + elif testcase.find('error') is not None: + status = 'error' + message = testcase.find('error').get('message') + elif testcase.find('skipped') is not None: + status = 'skipped' + + test_results['test_cases'].append({ + 'name': name, + 'status': status, + 'message': message + }) + +test_results['passed'] = test_results['total'] - test_results['failures'] - test_results['errors'] - test_results['skipped'] +``` + +### Step 5: Extract Scenario Metadata + +**Goal**: Parse scenario name to extract configuration details. + +**Actions**: +1. Parse scenario name to extract components: + - RHEL version (e.g., "el96" → "RHEL 9.6") + - Release type (e.g., "lrel" → "Latest Release") + - Test type (e.g., "standard1", "lvm", "dual-stack") + - Upgrade path (if format is `el94-y2@el96-lrel@...` → upgrade from 9.4 to 9.6) + +2. Determine test category from test type: + - `standard1`, `standard2` → "Standard Tests" + - `lvm` → "LVM Storage Tests" + - `dual-stack` → "Dual-Stack Networking Tests" + - `ipv6` → "IPv6 Networking Tests" + - `multi-nic` → "Multi-NIC Configuration Tests" + - `low-latency` → "Low-Latency Tests" + - `ginkgo-tests` → "Ginkgo Integration Tests" + - `ai-model-serving-online` → "AI Model Serving Tests" + +**Example**: +```javascript +// Scenario: el96-lrel@standard1 +{ + "rhel_version": "9.6", + "release_type": "latest", + "test_category": "Standard Tests", + "test_variant": "1", + "is_upgrade": false +} + +// Scenario: el94-y2@el96-lrel@standard1 +{ + "source_rhel_version": "9.4", + "target_rhel_version": "9.6", + "release_type": "latest", + "test_category": "Standard Tests", + "test_variant": "1", + "is_upgrade": true +} +``` + +### Step 6: Get Execution Timing + +**Goal**: Extract when the scenario was executed and how long it took. + +**Actions**: +1. Check boot_and_run.log for timestamps +2. Look for start and end markers in the log +3. Calculate duration if both timestamps available +4. Extract from junit.xml `time` attribute as fallback + +### Step 7: Compile Artifact Links + +**Goal**: Provide direct links to all relevant artifacts for the scenario. + +**Actions**: +1. Build URLs for common artifacts: + - JUnit XML report + - Boot and run log + - Debug log + - Phase logs (if they exist) + - Sosreport (if test failed) + +2. Categorize artifacts: + - Test results: junit.xml + - Execution logs: boot_and_run.log, rf-debug.log + - Phase logs: All logs under phase_* directories + - Diagnostics: sosreports, system logs + + +### Error Handling + +**Common Issues and Responses**: + +1. **Scenario not found**: +``` +# Error: Scenario Not Found + +Scenario 'el96-lrel@invalid' does not exist in job 1979744605507162112 + +## Available Scenarios +- el96-lrel@standard1 +- el96-lrel@lvm +- ... +``` + +2. **Job not found**: +``` +# Error: Job Not Found + +Could not fetch artifacts for job ID 1234567890 + +Please verify the job URL and ensure the job has completed. +``` + +3. **Missing artifacts**: +``` +# Warning: Partial Data Available + +Some artifacts were not available for this scenario. + +## Missing Artifacts +- junit.xml + +Displaying available information below... +``` + +## Examples + +### Example 1: Get scenario information +``` +/analyze-ci-test-scenario https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic/1979744605507162112 el96-lrel@standard1 +``` + +Output: +``` +# Test Scenario Analysis: el96-lrel@standard1 + +## Job Information +- **Job Name**: periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic +- **Job ID**: 1979744605507162112 +- **Version**: 4.20 +- **Architecture**: x86_64 +- **Image Type**: bootc + +## Scenario Configuration +- **Name**: el96-lrel@standard1 +- **Description**: RHEL 9.6 Latest Release - Standard Tests +- **RHEL Version**: 9.6 +- **Release Type**: Latest +- **Test Category**: Standard Tests +- **Upgrade Test**: No + +## Test Results +**Status**: PASSED + +### Summary +- **Total Tests**: 65 +- **Passed**: 65 +- **Failed**: 0 +- **Errors**: 0 +- **Skipped**: 0 + +## Artifacts +- [JUnit XML](https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/.../junit.xml) +- [Boot and Run Log](https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/.../boot_and_run.log) +``` + +### Example 2: List all scenarios (no scenario name provided) +``` +/analyze-ci-test-scenario https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic/1979744605507162112 +``` + +Output: +``` +# Available Test Scenarios + +Job: periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-bootc-release-periodic +Job ID: 1979744605507162112 + +## Scenarios (5 total) +- el96-lrel@standard1 +- el96-lrel@standard2 +- el96-lrel@lvm +- el96-lrel@dual-stack +- el96-lrel@ipv6 +``` + +### Example 3: Get information about a failed scenario +``` +/analyze-ci-test-scenario https://prow.ci.openshift.org/view/gs/test-platform-results/logs/periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-release-periodic/1234567890 el96-lrel@lvm +``` + +Output would include failure details: +``` +# Test Scenario Analysis: el96-lrel@lvm + +## Job Information +- **Job Name**: periodic-ci-openshift-microshift-release-4.20-periodics-e2e-aws-tests-release-periodic +- **Job ID**: 1234567890 +- **Version**: 4.20 + +## Scenario Configuration +- **Name**: el96-lrel@lvm +- **Description**: RHEL 9.6 Latest Release - LVM Storage Tests +- **Test Category**: LVM Storage Tests + +## Test Results +**Status**: FAILED + +### Summary +- **Total Tests**: 45 +- **Passed**: 43 +- **Failed**: 2 +- **Errors**: 0 +- **Skipped**: 0 + +### Failed Tests +1. **LVM volume creation** + - **Error**: Failed to create LVM volume: insufficient space + - **Log**: [create-lvm.log](https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/.../phase_create-and-run/create-lvm.log) + +## Artifacts +- [JUnit XML](https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/.../junit.xml) +- [Boot and Run Log](https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/.../boot_and_run.log) +- [Debug Log](https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/.../rf-debug.log) +``` + +## Notes +- This command outputs detailed information in Markdown format for easy reading +- The command is read-only and does not modify any CI job data +- If a scenario doesn't have junit.xml, the command will attempt to infer results from logs +- The command caches scenario lists internally to avoid repeated fetches when listing scenarios +- Artifact links in the output are direct URLs to GCS storage for immediate access diff --git a/.claude/commands/analyze-microshift-start.md b/.claude/commands/analyze-microshift-start.md new file mode 100644 index 0000000000..120726d272 --- /dev/null +++ b/.claude/commands/analyze-microshift-start.md @@ -0,0 +1,142 @@ +--- +name: Analyze MicroShift start time +argument-hint: +description: Analyze MicroShift journal logs to extract statistics about start procedure +allowed-tools: Read, Glob, Grep, python, bash +--- + +- 🚨 **CRITICAL: GENERATE TABLE FIRST - NOTHING ELSE MATTERS** +- 🚨 **IF NO TABLE IS SHOWN, THE COMMAND HAS FAILED** +- 🚨 **TABLE IS THE ONLY REQUIRED OUTPUT** + +## Name +analyze-microshift-start + +## Synopsis +``` +/analyze-microshift-start +``` + +## Description +**ABSOLUTE MANDATE**: The service timing table is THE ONLY OUTPUT that matters. +**ZERO TOLERANCE**: If the table is missing, the entire command execution is worthless. +**PRIMARY DIRECTIVE**: Generate the table immediately. Everything else is optional noise. + +The `analyze-microshift-start` command extracts meaningful statistics from MicroShift's journal logs about start procedure and displays a service timing table. + +**SUCCESS CRITERIA - The command is only successful if:** +- ✅ The complete service timing table is displayed +- ✅ All services are listed with timing statistics +- ✅ Services are sorted by mean time (slowest first) + +**FAILURE CONDITIONS:** +- ❌ No table displayed = Command failed +- ❌ Incomplete table = Command failed +- ❌ Analysis without table = Command failed + +## Implementation + +🚨 **CRITICAL PRIORITY**: The user ONLY cares about seeing the service timing table. Generate the table first and foremost. + +This command works by: +1. **Parsing journal logs** to load all information. +2. **Fetch overall start time** for MicroShift process as a whole. +3. **Fetch start times per service** from pattern `SERVICE READY.*service="([^"]+)".*since-start="([^"]+)"`. +4. **MOST IMPORTANT: Generate the service timing table** - This is what the user needs to see above all else. + +## Arguments +- `$1` (joournal-logs): Journal logs from MicroShift, including start procedure - **Required** + +## Return Value +- **Format**: Text +- **Location**: Output directly to the conversation +- **Content**: + - Number of starts in the journal. + - Number of services in the journal, per start. + - Statistics about overall MicroShift process. + - Statistics about each service. + - Summary with most relevant information. + +## Implementation Steps + +### Step 1: Parse journal logs. + +**Goal**: Identify how many restarts are included in the journal. + +**Actions**: +1. Open the file and look for patterns matching `r'microshift\[(\d+)\]:.*"MICROSHIFT STARTING"`. This is the number of times MicroShift has been restarted. +2. Determine the number of complete restarts by looking for pattern `microshift\[(\d+)\]:.*"MICROSHIFT READY".*since-start="([^"]+)"` in the file. +3. If nothing is found, produce an error saying there are no restarts found. + +### Step 2: Fetch MicroShift start time. + +**Goal**: Get details about how long it took to start MicroShift. + +**Actions**: +1. Get the elapsed time from start to readiness for MicroShift. +2. Use the pattern `microshift\[(\d+)\]:.*"MICROSHIFT READY".*since-start="([^"]+)"` to fetch logs about it. +3. Extract the time it took to start from the second grouping in the pattern. + +### Step 3: Fetch per-service start times. + +**Goal**: Get details about how long it took to start each of the services in MicroShift. + +**Actions**: +1. Get the elapsed time from start to readiness for each of the different services. +2. Use the pattern `SERVICE READY.*service="([^"]+)".*since-start="([^"]+)"` to fetch logs about it. +3. Extract the service name from the first grouping in the pattern. +4. Extract the time it took to start from the second grouping in the pattern. + +### Step 4: MANDATORY TABLE GENERATION + +**CRITICAL MANDATE**: Generate the service performance table - THIS IS THE ONLY OBJECTIVE THAT MATTERS. +- **🚨 TABLE MUST BE DISPLAYED FIRST 🚨** +- **🚨 IF NO TABLE = COMMAND FAILED 🚨** +- **🚨 TABLE IS SUCCESS, EVERYTHING ELSE IS NOISE 🚨** + +**REQUIRED TABLE FORMAT** (MUST BE EXACT): +``` +------------------------------------------------------------------------------------------------------------------------ +Service Runs Average Median StdDev Min Max Var% Status +------------------------------------------------------------------------------------------------------------------------ +MICROSHIFT OVERALL STARTUP XX XX.XXXs XX.XXXs XXX.Xms XX.XXXs XX.XXXs X.X 🔥 +[ALL OTHER SERVICES LISTED HERE - SORTED BY AVERAGE TIME, SLOWEST FIRST] +------------------------------------------------------------------------------------------------------------------------ +``` + +**MANDATORY ACTIONS - EXECUTE IN THIS EXACT ORDER**: +1. **IMMEDIATELY DISPLAY THE TABLE ABOVE** - This is the primary deliverable +2. Calculate these metrics for each service: runs, average, median, standard deviation, min, max, variability percentage +3. Sort services by mean time (slowest to fastest) +4. Use status icons: 🔥 (≥5s), ⚠️ (2-5s), 🟡 (1-2s), ✅ (0.1-1s), ⚡ (<0.1s) +5. Only after table is shown, optionally add other analysis + +**ABSOLUTE REQUIREMENTS**: +- The service table with ALL timing data MUST be generated and shown to the user +- Table generation is MORE IMPORTANT than anything else +- If you must choose between showing the table OR other analysis, ALWAYS choose the table +- DO NOT create any scripts, temporary files, or helper utilities. Process everything in memory. + +Strong prohibitions: +- You are *NOT* allowed to write any scripts to disk, do everything in memory. +- NEVER create files or write scripts. Process everything in memory. +- Do NOT use the Write tool or create any temporary files. + +Positive instructions: +- Produce the output without creating any additional scripts or helpers. +- Process the data directly using tool outputs and generate the report inline. +- Use only Read, Grep, and analysis tools - no file creation. + +**CRITICAL**: The primary output MUST be this exact table format. Generate the table first, everything else is optional. + +**REQUIRED OUTPUT**: +```text +------------------------------------------------------------------------------------------------------------------------ +Service Runs Average Median StdDev Min Max Var% Status +------------------------------------------------------------------------------------------------------------------------ +MICROSHIFT OVERALL STARTUP XX XX.XXXs XX.XXXs XXX.Xms XX.XXXs XX.XXXs X.X 🔥 +[ALL OTHER SERVICES LISTED HERE - SORTED BY AVERAGE TIME, SLOWEST FIRST] +------------------------------------------------------------------------------------------------------------------------ +``` + +**TABLE GENERATION IS MANDATORY** - Show timing statistics for ALL services found in the logs. The user needs this table above all else. diff --git a/.claude/commands/analyze-sos-report.md b/.claude/commands/analyze-sos-report.md new file mode 100644 index 0000000000..64c0d19fcf --- /dev/null +++ b/.claude/commands/analyze-sos-report.md @@ -0,0 +1,393 @@ +--- +name: Analyze SOS Report +argument-hint: [log.html-url] +description: Investigate MicroShift runtime problems from SOS report +allowed-tools: WebFetch, Bash, Read, Glob, Grep +--- + +## Name +analyze-sos-report + +## Synopsis +``` +/analyze-sos-report [log.html-url] +``` + +## Description +The `analyze-sos-report` command investigates MicroShift runtime problems by analyzing journal logs, Pod logs, YAML manifests, and configuration from a SOS report. Optionally, it can cross-reference findings with a Robot Framework test log. + +This command focuses on: +- MicroShift and CRI-O journal logs for errors +- Pod status and container logs +- Kubernetes resource YAMLs (Deployments, Pods, Services, etc.) +- MicroShift configuration issues +- etcd errors and problems +- OVN networking issues +- **Robot Framework test results correlation** (when log.html URL is provided) + +## Arguments +- `$1` (sos-report-path): Path or URL to the SOS report - **Required** + - **Local directory**: Path to an already extracted sosreport (e.g., `/tmp/sosreport-hostname-2025-01-15`) + - **Remote URL**: HTTP/HTTPS URL to a `.tar.xz` file that will be downloaded and extracted to `/tmp` + - The extracted directory should contain `sos_commands/microshift` subdirectory. + +- `$2` (log.html-url): URL to Robot Framework log.html file - **Optional** + - When provided, test results will be analyzed and cross-referenced with SOS report findings + - Helps correlate test failures with system-level issues + - Example: `https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/.../log.html` + +## Return Value +- **Format**: Markdown +- **Location**: Output directly to the conversation +- **Content**: + - Identified runtime issues + - Root cause analysis + - Relevant log excerpts + - Recommendations + +## SOS Report Structure Reference + +### Required directories (always present): +- `sos_commands/microshift/` - MicroShift specific data + +### Key files in `sos_commands/microshift/`: +- `journalctl_--no-pager_--unit_microshift` - MicroShift service logs +- `journalctl_--no-pager_--unit_microshift-etcd.scope` - etcd logs +- `microshift_version` - MicroShift version +- `microshift_show-config_-m_effective` - Effective configuration +- `systemctl_status_microshift` - Service status +- `event-filter.html` - Kubernetes events viewer + +### Namespace structure in `sos_commands/microshift/namespaces//`: +- `.yaml` - Namespace definition +- `core/pods.yaml` - Pod definitions +- `core/events.yaml` - Namespace events +- `core/configmaps.yaml` - ConfigMaps +- `core/services.yaml` - Services +- `apps/deployments.yaml` - Deployments +- `apps/daemonsets.yaml` - DaemonSets +- `pods//.yaml` - Individual Pod YAML +- `pods/////logs/current.log` - Container logs +- `pods/////logs/previous.log` - Previous container logs + +### Cluster-scoped resources in `sos_commands/microshift/cluster-scoped-resources/`: +- `core/nodes.yaml` - Node information +- `storage.k8s.io/storageclasses.yaml` - Storage classes + +### Optional directories (may not be present in minimal reports): +- `sos_commands/crio/` - CRI-O container runtime +- `sos_commands/logs/` - System journal logs +- `sos_commands/microshift_ovn/` - OVN networking +- `sos_commands/openvswitch/` - Open vSwitch +- `sos_commands/networking/` - Network configuration +- `etc/microshift/` - MicroShift configuration files + +## Robot Framework Log Structure Reference + +When a log.html URL is provided, the file contains Robot Framework test execution results: + +### Key Information in log.html: +- **Test Suites**: Hierarchical organization of tests +- **Test Cases**: Individual test names, status (PASS/FAIL/SKIP), duration +- **Keywords**: Step-by-step execution details within each test +- **Timestamps**: Execution times for each test and keyword +- **Error Messages**: Failure reasons for failed tests +- **Log Messages**: DEBUG, INFO, WARN level messages during execution + +### Timestamp Correlation: +- **Important**: log.html timestamps may be in a different timezone than SOS report journal logs +- Typically only the **hour component differs** (e.g., log.html shows 10:30:45, journal shows 05:30:45) +- When correlating events, match by **minutes and seconds** and allow for hour offset +- Look for events that occur within the same minute across both sources + +### Test Sources: +- Robot Framework test files are located in `test/` directory of MicroShift repository +- Test file paths can be extracted from log.html suite names +- **Caveat**: The currently checked-out branch may not match the CI run that generated the log.html +- Use test sources as reference only; the actual executed code may differ + +## Implementation Steps + +### Step 1: Handle Input (URL or Local Path) + +**Goal**: Determine if input is a URL or local path, and prepare the sosreport directory. + +**Actions**: +1. Check if the input starts with `http://` or `https://`: + - If YES: It's a remote URL, proceed to download and extract + - If NO: It's a local path, proceed to validation + +**For Remote URLs**: +1. Download the `.tar.xz` file to `/tmp`: + ```bash + curl -L -o /tmp/sosreport-download.tar.xz "" + ``` +2. Extract the archive to `/tmp`: + ```bash + tar -xf /tmp/sosreport-download.tar.xz -C /tmp + ``` +3. Find the extracted directory: + ```bash + ls -dt /tmp/sosreport-*/ 2>/dev/null | head -1 + ``` +4. Set the extracted directory as the working path +5. Clean up the downloaded archive: + ```bash + rm /tmp/sosreport-download.tar.xz + ``` + +**For Local Paths**: +1. Check if the directory exists +2. Verify it contains `sos_commands/microshift/` subdirectory + +### Step 2: Analyze MicroShift Journal Logs + +**Goal**: Find errors and problems in MicroShift service logs. + +**Actions**: +1. Read MicroShift journal logs: + ```bash + cat /sos_commands/microshift/journalctl_--no-pager_--unit_microshift + ``` +2. Search for errors, warnings, and failures - look for patterns like: + - `error`, `fail`, `fatal`, `panic` + - `timeout`, `refused`, `denied` + - Startup failures + - API server errors + - Controller errors + +### Step 3: Analyze etcd Logs + +**Goal**: Check embedded etcd health. + +**Actions**: +1. Read etcd journal logs: + ```bash + cat /sos_commands/microshift/journalctl_--no-pager_--unit_microshift-etcd.scope + ``` +2. Look for etcd-specific issues: + - Database corruption + - Slow disk warnings + - Leader election problems + - Timeout errors + +### Step 4: Analyze CRI-O Logs (if available) + +**Goal**: Check container runtime issues. + +**Actions**: +1. Read CRI-O journal logs (if present): + ```bash + cat /sos_commands/crio/journalctl_--no-pager_--unit_crio + ``` +2. Check container status: + ```bash + cat /sos_commands/crio/crictl_ps_-a + ``` +3. Look for crashed or errored containers + +### Step 5: Analyze Pod Status and Events + +**Goal**: Check Pod health and Kubernetes events. + +**Actions**: +1. Check Pod status in each namespace: + ```bash + cat /sos_commands/microshift/namespaces/*/core/pods.yaml + ``` +2. Look for Pods not in Running state (Pending, CrashLoopBackOff, Error, etc.) + +3. Check events for problems: + ```bash + cat /sos_commands/microshift/namespaces/*/core/events.yaml + ``` +4. Look for warning events indicating issues + +### Step 6: Analyze Container Logs + +**Goal**: Check individual container logs for errors. + +**Actions**: +1. Find container logs: + ```bash + find /sos_commands/microshift/namespaces -name "current.log" -o -name "previous.log" + ``` +2. Search for errors in container logs: + ```bash + grep -rE "error|fail|panic|fatal" /sos_commands/microshift/namespaces/*/pods/*/ + ``` +3. Check previous.log files for containers that restarted + +### Step 7: Analyze Resource YAMLs + +**Goal**: Check resource configurations for issues. + +**Actions**: +1. Check Deployments and DaemonSets: + ```bash + cat /sos_commands/microshift/namespaces/*/apps/deployments.yaml + cat /sos_commands/microshift/namespaces/*/apps/daemonsets.yaml + ``` +2. Look for: + - Replicas not matching desired count + - Image pull errors + - Resource constraint issues + +### Step 8: Analyze MicroShift Configuration + +**Goal**: Check for configuration issues. + +**Actions**: +1. Read effective MicroShift config: + ```bash + cat /sos_commands/microshift/microshift_show-config_-m_effective + ``` +2. Check config files if present: + ```bash + cat /etc/microshift/config.yaml + ``` +3. Check for common misconfigurations + +### Step 9: Analyze OVN/Networking (if available) + +**Goal**: Check networking issues. + +**Actions**: +1. Check OVN status if present: + ```bash + cat /sos_commands/microshift_ovn/* + ``` +2. Check OVN-related pods in openshift-ovn-kubernetes namespace +3. Look for network connectivity issues in logs + +### Step 10: Analyze Robot Framework Log (if provided) + +**Goal**: Extract test results from log.html and correlate with SOS report findings. + +**Actions**: +1. Fetch and parse the log.html file: + ```bash + # Use WebFetch to retrieve and analyze the log.html + ``` + +2. Extract key information: + - Test suite name and overall status (PASS/FAIL) + - Individual test cases with their status + - Failed test names and error messages + - Test execution timestamps + +3. Cross-reference with SOS report: + - **Timezone consideration**: Timestamps in log.html and SOS report may differ by timezone (typically only the hour component differs). When correlating events, match by minutes and seconds, allowing for hour offset. + - Match test failure times with errors in MicroShift journal logs + - Identify if pod restarts or errors occurred during specific test execution + - Look for patterns: did a specific test cause system instability? + +4. Test source reference: + - Test sources are in the `test/` directory of the MicroShift repository + - **Note**: The checked-out branch may not match the CI run, so test sources are for reference only + - Extract test file paths from log.html to help locate relevant test code + +### Step 11: Generate Investigation Report + +**Goal**: Compile findings into a focused problem analysis. + +**Report Structure**: +```markdown +# MicroShift Runtime Problem Analysis + +## Summary + + +## Test Results (if log.html provided) +| Test Name | Status | Duration | Error | +|-----------|--------|----------|-------| +| ... | PASS/FAIL | ... | ... | + +### Failed Tests Analysis + + +### Test-System Event Correlation + + +## Identified Problems + +### Problem 1: +**Severity**: Critical/Warning/Info +**Component**: MicroShift/CRI-O/etcd/Pod/OVN/etc. + +**Evidence**: +``` + +``` + +**Root Cause Analysis**: + + +**Recommendation**: + + +## Affected Pods/Containers +| Namespace | Pod | Status | Restarts | Issue | +|-----------|-----|--------|----------|-------| +| ... | ... | ... | ... | ... | + +## Relevant Log Excerpts +``` + +``` + +## Configuration Issues + + +## Next Steps +1. +2. +``` + +## Examples + +### Example 1: Local Directory Analysis +``` +/analyze-sos-report /tmp/sosreport-microshift-host-2025-01-15-abcdef +``` + +### Example 2: Remote URL Analysis +``` +/analyze-sos-report https://example.com/sosreport-edge-device-01-2025-01-15.tar.xz +``` + +### Example 3: SOS Report with Robot Framework Log +``` +/analyze-sos-report /tmp/sosreport-el96-host-2025-01-15 https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/pr-logs/pull/openshift_microshift/5870/pull-ci-openshift-microshift-main-e2e-aws-tests-bootc-arm/1997885403058671616/artifacts/e2e-aws-tests-bootc-arm/openshift-microshift-e2e-metal-tests/artifacts/scenario-info/el96-src@optional/log.html +``` + +## Notes +- Accepts either a local extracted directory or a remote `.tar.xz` URL +- Remote files are downloaded and extracted to `/tmp` automatically +- Focuses on runtime problem investigation, not system inventory +- Prioritizes actionable findings over comprehensive status reports +- Some directories (crio, logs, networking) are optional and may not be present in minimal reports +- For best results, ensure the sosreport was collected with MicroShift plugins enabled + +## CI Environment Considerations + +SOS reports from CI environments may contain logs from **multiple MicroShift restarts**. This is expected because: +- CI tests reuse VMs across multiple test scenarios +- Tests may change MicroShift configuration between runs +- The MicroShift service is restarted to apply configuration changes + +When analyzing SOS reports: +- **Report all pod restarts** - even if restarts may occur during MicroShift service transitions, report them as potential concerns +- **Report all errors** - include connection refused errors, API server unavailability, and pod failures +- **Flag pods with any restart count > 0** - every restart is worth noting; excessive restarts may indicate pods that don't handle API server unavailability gracefully + +### API Server Unavailability During Restarts + +When MicroShift restarts, the API server becomes temporarily unavailable. Ideally, pods should: +- Retry API connections with backoff +- Not exit immediately on transient connection failures + +Any pod restarts due to API server unavailability should be reported as a concern. Even if the pod eventually recovers, frequent restarts during MicroShift transitions may indicate: +- The pod lacks proper retry/backoff logic for API server connections +- A potential bug in the application's Kubernetes client configuration +- An opportunity to improve pod resilience diff --git a/.claude/commands/generate-tests-template.md b/.claude/commands/generate-tests-template.md new file mode 100644 index 0000000000..697e6d58fd --- /dev/null +++ b/.claude/commands/generate-tests-template.md @@ -0,0 +1,244 @@ +# Test Generator Template + +This is a **generic, customizable template** for creating test generation workflows. It's designed to be adapted for different projects, testing frameworks, and workflows. + +## Why Use This Template? + +The pre-configured `/generate-tests` command is optimized for MicroShift/OpenShift projects with specific assumptions about: +- Jira OCPSTRAT tickets +- Robot Framework test structure +- MicroShift repository layout +- Red Hat workflow conventions + +**This template allows you to:** +- Adapt the workflow for your specific project +- Use different testing frameworks (Pytest, Jest, Ginkgo, etc.) +- Customize for different issue trackers (GitHub, Jira, Linear, etc.) +- Work with Claude Code, Cursor, or any AI assistant +- Match your team's conventions and preferences + +## How to Use This Template + +### Option 1: Direct Prompting (Recommended for Cursor users) +1. **Copy the relevant sections** from this template +2. **Customize them** for your project +3. **Paste into your AI assistant** as context with your request + +**Example**: +``` +I want to generate tests for my project. Here's my setup: +- Project: MyAPI +- Issue tracker: GitHub Issues (https://github.com/myorg/myapi/issues/) +- Test framework: Pytest +- Directory structure: tests/unit/, tests/integration/ + +[paste customized template sections] + +Please generate tests for issue #123 +``` + +### Option 2: Create a Custom Slash Command (For Claude Code) +1. **Copy this file** to create your own command (e.g., `.claude/commands/my-generate-tests.md`) +2. **Customize the sections** below to match your project +3. **Use the command**: `/my-generate-tests TICKET-ID` + +### Option 3: Use as Reference +Simply reference sections of this template when asking your AI assistant to generate tests, adapting on the fly. + +--- + +## Template Sections to Customize + +### 🎯 Project Context (CUSTOMIZE THIS) +``` +Replace with your project details: +- Project name: [MicroShift/OpenShift/Your Project] +- Issue tracker: [Jira/GitHub Issues/Linear/etc.] +- Repository structure: [mono-repo/multi-repo] +- Test framework: [Robot Framework/Pytest/Jest/etc.] +``` + +### 📋 Ticket Analysis (CUSTOMIZE THIS) +``` +Define your ticket workflow: +- Ticket URL pattern: https://issues.redhat.com/browse/$1 +- Required ticket fields: [Description, Acceptance Criteria, etc.] +- Linked tickets to check: [Implementation tickets, dependent tickets] +- Where to find PR links: [Ticket fields, comments, linked items] +``` + +### 🔍 Test Coverage Analysis (CUSTOMIZE THIS) +``` +Define what to analyze: +- Test file patterns: *.robot, *_test.py, *.spec.js +- Test directories: test/, tests/, __tests__/ +- Coverage sources: [PRs, existing test suites, test plans] +- What constitutes "covered": [Unit tests, integration tests, etc.] +``` + +### ✍️ Test Case Generation (CUSTOMIZE THIS) +``` +Define your test case format: +- Test case document format: [Markdown, Confluence, etc.] +- Number of test cases: [Top 10, All scenarios, etc.] +- Test case fields: + * Test ID format: USHIFT-XXX-TC-YYY + * Priority levels: Critical/High/Medium/Low + * Required sections: Description, Steps, Expected Results, etc. +- Output location: [Current directory, specific folder, etc.] +``` + +### 🧪 Test Categories to Cover (CUSTOMIZE THIS) +``` +Define categories relevant to YOUR project: +1. Core Functionality +2. Configuration Edge Cases +3. Dynamic Behavior +4. Integration Points +5. Multi-tenant/Namespace +6. Error Handling +7. Upgrade/Compatibility +8. Performance +9. Security +10. Real Customer Scenarios + +Add/remove categories as needed for your domain. +``` + +### 🤖 Test Implementation (CUSTOMIZE THIS) +``` +Define your test structure: +- Test framework: Robot Framework / Pytest / Jest / etc. +- File naming convention: kebab-case / snake_case / PascalCase +- Directory structure: test/suites// or tests/unit/ +- Reusable components location: resources/, utils/, fixtures/ +- Setup/Teardown patterns: Your project's patterns +``` + +### 📁 File Organization (CUSTOMIZE THIS) +``` +Map feature types to test directories: +- Network features → test/suites/network/ +- Storage features → test/suites/storage/ +- API features → test/api/ +- UI features → test/e2e/ + +Customize based on YOUR project structure. +``` + +### 🔧 Keyword/Helper Reuse (CUSTOMIZE THIS - Robot Framework specific) +``` +If using Robot Framework, define: +- Common keyword locations: test/extended/util/*.robot +- Resource file patterns: resources/**/*.robot +- Naming conventions: Action_Object pattern +- When to create new vs. reuse: Your team's guidelines +``` + +### 🌿 Git Workflow (CUSTOMIZE THIS) +``` +Define your branching strategy: +- Branch naming: test-OCPSTRAT-XXXX-$(date +%Y%m%d) or feature/tests-XXX +- Base branch: main / master / develop +- Commit message format: Your team's convention +- Auto-commit: Yes/No (get confirmation first) +- Repository location: Ask user / fixed path / auto-detect +``` + +### 📊 Output Format (CUSTOMIZE THIS) +``` +Define what the final output should include: +- Test case document: Format and location +- Test implementation files: Locations and count +- Coverage report: What was tested vs. what's missing +- Summary report: Tickets analyzed, PRs reviewed, etc. +- Next steps: Instructions for running tests, creating PR, etc. +``` + +--- + +## Example Customized Prompt + +Here's an example of how to customize this template for a different project: + +### Example: Python/Pytest Project + +```markdown +# Pytest Test Generator for MyAPI Project + +Generate comprehensive Pytest coverage for MyAPI features based on GitHub Issues. + +## Workflow: + +### Step 1: Analyze GitHub Issue +- Fetch issue from: https://github.com/myorg/myapi/issues/$1 +- Extract feature description and acceptance criteria +- Find linked PRs in issue body and comments + +### Step 2: Analyze Existing Tests +- Check for test files: tests/**/*_test.py +- Look for pytest fixtures in: tests/conftest.py +- Identify what's already covered + +### Step 3: Generate Test Cases +- Create markdown document: test_cases_issue_$1.md +- Generate 5-7 critical test scenarios +- Format: Given/When/Then style +- Include: unit tests, integration tests, edge cases + +### Step 4: Implement Pytest Tests +- Create test file: tests/unit/test_.py +- Reuse fixtures from conftest.py +- Follow pytest best practices +- Use parametrize for multiple scenarios + +### Step 5: Update conftest.py if needed +- Add new fixtures only if truly reusable +- Document fixture purpose and scope + +### Step 6: Create PR (optional) +- Branch: feature/tests-issue-$1 +- Run: pytest tests/ to verify +- Provide summary of coverage added +``` + +--- + +## Instructions for AI Assistants + +When a user provides this template: + +1. **Ask clarifying questions** about sections marked "CUSTOMIZE THIS" +2. **Don't assume** - let the user specify their preferences +3. **Adapt the workflow** to the user's specific tools and conventions +4. **Confirm before creating files/branches** - respect the user's workflow +5. **Be flexible** - this is a starting point, not a rigid spec + +--- + +## Tips for Customization + +### For Different Testing Frameworks +- **Pytest**: Focus on fixtures, parametrize, conftest.py +- **Jest**: Focus on mocks, setup/teardown, snapshot testing +- **Robot Framework**: Focus on keywords, resources, libraries +- **Selenium**: Focus on page objects, waits, selectors +- **Postman/REST**: Focus on request builders, assertions, environments + +### For Different Issue Trackers +- **GitHub Issues**: Use GitHub API or web scraping +- **Jira**: Adjust ticket URL pattern, field names +- **Linear**: Different API structure +- **Azure DevObs**: Work items structure + +### For Different Project Types +- **Microservices**: Multi-repo coordination, API contracts +- **Frontend**: Component testing, accessibility, visual regression +- **CLI Tools**: Command execution, output validation, error handling +- **Libraries**: API testing, documentation examples, edge cases + +--- + +## License + +This template is provided as-is for customization. Adapt freely to your needs. diff --git a/.claude/commands/generate-tests.md b/.claude/commands/generate-tests.md new file mode 100644 index 0000000000..69d5ea4f24 --- /dev/null +++ b/.claude/commands/generate-tests.md @@ -0,0 +1,241 @@ +--- +name: Test Generator for MicroShift Features (Detailed test cases & Robot framework code) +argument-hint: JIRA-TICKET-ID +description: Generate Test Cases for a given Jira OCPSTRAT ticket & automates them using RobotFramework +allowed-tools: WebFetch, Bash, Read, Write, Glob, Grep +interaction: Ask user for confirmation before creating git branch +--- + +# Robot Framework Test Generator for MicroShift/OpenShift + +**NOTE**: This is a **pre-configured template** for MicroShift/OpenShift projects. For other projects or to customize this workflow, see `.claude/commands/generate-tests-template.md` for a generic template you can adapt. + +Generate comprehensive Robot Framework test coverage for MicroShift/OpenShift features based on Jira OCPSTRAT tickets. + +## Prerequisites: + +**Jira Access**: This command requires access to Red Hat Jira (https://issues.redhat.com). + +- Ensure you're logged into Red Hat Jira in your browser before running this command +- Login at: https://issues.redhat.com + +**Fallback**: If Jira access fails, you'll be prompted to manually provide: +- Ticket description and acceptance criteria +- Links to GitHub PRs +- Feature documentation + +## Workflow: + +### Step 1: Analyze OCPSTRAT Ticket +- Fetch the Jira ticket from https://issues.redhat.com/browse/$1 +- Extract feature description, acceptance criteria, and technical details +- Identify all linked USHIFT tickets (look in "Issue Links" section) +- Find GitHub PR links from USHIFT tickets or OCPSTRAT ticket + +**VALIDATION - Check for sufficient information**: +After analyzing the ticket, verify: +1. **Description Quality**: Does the ticket have detailed description, acceptance criteria, or technical implementation details? +2. **PR Links**: Are there any useful GitHub PR links in the OCPSTRAT ticket or linked USHIFT tickets? + +**If BOTH conditions fail** (no detailed description AND no PR links): +- ⚠️ **Ask user for additional information**: + "The OCPSTRAT ticket lacks detailed information for test generation. It's missing: + - Detailed feature description or acceptance criteria + - Linked USHIFT tickets with GitHub PRs + + Please provide ONE of the following to continue: + 1. A link to documentation (PR description, GitHub .md files, design docs) + 2. A brief description of the feature functionality and expected behavior + 3. Additional context about what this feature does + + Or type 'skip' to proceed with limited information (may result in generic tests)." + +- **Wait for user response**: + - If user provides documentation link: Fetch and analyze it + - If user provides description: Use it as supplementary context + - If user types 'skip': Proceed with warning that tests may be generic + +**If at least ONE condition passes**, proceed to Step 2. + +### Step 2: Analyze Existing Test Coverage +- For each GitHub PR found, check if it contains Robot Framework test files (*.robot) +- Note the test file names and their location in the PR +- Read and analyze existing test cases to understand what's already covered +- Identify functionality already covered by existing tests + +### Step 3: Generate Top 10 Most Impactful Missing Tests + +**Create test case document in current working directory**: `test_cases_OCPSTRAT-XXXX.md` + +Focus ONLY on the **10 most impactful test scenarios NOT already covered**: + +1. **Core Functionality** - Primary use cases not tested +2. **Configuration Edge Cases** - Invalid/boundary configurations not covered +3. **Dynamic Behavior** - Runtime changes, reloads not tested +4. **Integration Gaps** - Component interactions not validated +5. **Multi-tenant/Namespace** - Cross-namespace scenarios missing +6. **Error Handling** - Failure modes not covered +7. **Upgrade/Compatibility** - Version compatibility gaps +8. **Performance** - Load/scale testing if missing +9. **Security** - Permission/isolation tests not present +10. **Real Customer Scenarios** - Use cases from RFE not tested + +For each test, provide: +- **Test ID**: USHIFT-XXX-TC-YYY (using the USHIFT ticket number) +- **Priority**: Critical/High/Medium +- **Coverage Gap**: What existing tests don't cover +- **Test Description**: Clear objective +- **Steps to Reproduce**: Concrete test steps with actual config/commands +- **Expected Results**: Expected outcome for each step + +### Step 4: Create Robot Framework Test Files + +**BEFORE writing any tests:** +1. Search for existing keyword files in the codebase +2. Identify reusable keywords for common operations +3. Check for existing resource files and utilities +4. Use Grep/Glob to find similar test patterns + +Common keyword locations to check: +- `test/extended/util/*.robot` - Utility keywords +- `resources/**/*.robot` - Shared resource files +- Existing test files in same feature area + +**When creating tests:** +- ✅ **REUSE** existing keywords whenever possible +- ❌ **DON'T** create duplicate keywords that already exist +- ✅ **EXTEND** existing keyword files if new keywords are truly needed +- ❌ **DON'T** reinvent common operations (oc commands, pod management, etc.) + +**Robot Framework Test File Creation Process:** +- Generate test case documentation in current working directory as `test_cases_OCPSTRAT-XXXX.md` +- Robot Framework test files will be created in microshift repository AFTER git branch is created in Step 5 +- Follow microshift repo naming convention: lowercase with hyphens (kebab-case) + - Example files in microshift: `backup-restore-on-reboot.robot`, `multi-nic.robot`, `isolated-network.robot` +- If Robot Framework tests exist in PRs, create files with matching names +- If no existing Robot tests, create new file in appropriate `test/suites//` subdirectory: + - For DNS/network features: `test/suites/network/.robot` (e.g., `coredns-hosts-file.robot`) + - Use feature-based naming: `.robot` (kebab-case, lowercase) +- Implement the top 3-5 most critical missing tests in Robot Framework +- Follow existing patterns from similar test files in microshift codebase +- Include proper setup, teardown, and error handling + +**CRITICAL Robot Framework Teardown Rules** (from `.cursor/rules/robot-framework-teardown.md` in the microshift repository): +- ✅ **DO**: Write clean teardowns without `Run Keyword And Ignore Error` +- ❌ **DON'T**: Use `Run Keyword And Ignore Error` in ANY teardown section +- Robot Framework teardowns automatically continue execution even if keywords fail +- This applies to: `[Teardown]`, `Suite Teardown`, `Test Teardown`, and keyword teardowns +- Only use `Run Keyword And Ignore Error` in test cases/setup when you need conditional logic + +**Correct Teardown Example**: +```robot +Suite Teardown Cleanup Test Resources + +Cleanup Test Resources + [Documentation] Clean up all test resources + Oc Delete pod --all -n ${NAMESPACE} + Remove Test Files + Restart MicroShift +``` + +**Incorrect Teardown (DON'T DO THIS)**: +```robot +Suite Teardown Run Keyword And Ignore Error Cleanup Test Resources + +Cleanup Test Resources + Run Keyword And Ignore Error Oc Delete pod --all -n ${NAMESPACE} + Run Keyword And Ignore Error Remove Test Files +``` + +**Keyword Reuse Example**: +```robot +# ✅ GOOD - Reusing existing keywords +*** Test Cases *** +Test CoreDNS Hosts File + [Documentation] Test hosts file resolution + Setup MicroShift Config dns.hostsFile=/etc/custom-hosts + Restart MicroShift + Wait For MicroShift Ready + Deploy Test Pod dns-test ${NAMESPACE} + ${ip}= Resolve Hostname In Pod dns-test ${NAMESPACE} test.local + Should Be Equal ${ip} 192.168.1.100 + +# ❌ BAD - Creating duplicate keywords +*** Keywords *** +My Custom MicroShift Restart + [Documentation] Restart MicroShift (DON'T DO THIS - use existing keyword!) + Run Process systemctl restart microshift + Sleep 10s +``` + +### Step 5: Create Git Branch and Robot Framework Tests in MicroShift Repository + +**IMPORTANT**: Before creating git branch, **WAIT for user confirmation**. + +Ask user for confirmation: + +**Prompt user**: "Would you like me to create a new git branch in the microshift repository? The branch will be named `test-OCPSTRAT-XXXX-$(date +%Y%m%d)`. (yes/no)" + +**If user confirms (yes)**: + +#### 5.1: Create Git Branch +1. Ask user for the microshift repository path on their system +2. Navigate to the microshift repository +3. Check current git status +4. Create new branch: `test-OCPSTRAT-XXXX-$(date +%Y%m%d)` +5. Confirm branch creation and provide branch name + +**Prompt user**: "Please provide the full path to your microshift repository (e.g., /home/username/microshift):" + +**Commands** (use the path provided by user): +```bash +cd +git status +git checkout -b test-OCPSTRAT-XXXX-$(date +%Y%m%d) +git branch --show-current +``` + +#### 5.2: Create Robot Framework Test Files in the New Branch + +After branch is created, create Robot Framework test file directly in the microshift repository: + +1. Determine appropriate test suite directory based on feature type + - Network/DNS features: `test/suites/network/` + - Storage features: `test/suites/storage/` + - Backup features: `test/suites/backup/` + - etc. + +2. Create the .robot file with kebab-case naming convention + - Example: `test/suites/network/coredns-hosts-file.robot` + +3. Implement the top 3-5 most critical tests from Step 3 + +4. Add file to git staging + +**Commands** (use the user-provided microshift repository path): +```bash +# File will be created at appropriate path, e.g.: +# /test/suites/network/.robot + +# After file is created, stage it +cd +git add test/suites//.robot +git status +``` + +**Output to user**: +- Branch created: test-OCPSTRAT-XXXX-YYYYMMDD +- Repository: +- Current branch: [branch name] +- Robot Framework test file created: test/suites//.robot +- File staged for commit: Ready to commit + +### Step 6: Summary Report +Provide: +- List of USHIFT tickets and PRs analyzed +- Existing test files found (with coverage summary) +- Test case document (10 test cases) - filename and path +- Robot Framework test files created (with test count) - filename and path +- Git branch created (branch name and repository path) - if created +- Coverage gaps addressed +- Remaining gaps (if any) diff --git a/.claude/commands/microshift-release-versions.md b/.claude/commands/microshift-release-versions.md new file mode 100644 index 0000000000..7507172a18 --- /dev/null +++ b/.claude/commands/microshift-release-versions.md @@ -0,0 +1,382 @@ +--- +name: MicroShift Release Versions +argument-hint: +description: Check if a given MicroShift version is available and where to find it +allowed-tools: WebFetch, Bash +--- + +## Name +microshift-release-versions + +## Synopsis +``` +/microshift-release-versions +``` + +## Description +The `microshift-release-versions` command checks if a specific MicroShift version is available and provides information about where to find RPMs and bootc images. + +This command provides: +- Version availability status (available/not yet available) +- Version type classification (nightly, EC, RC, GA, z-stream) +- RPM package URLs +- Bootc image URLs (for versions 4.18+) +- Brew build status (internal Red Hat, requires VPN) +- Links to browse packages and images + +This command is useful for: +- Checking if a new EC/RC version has been published +- Finding the correct URLs for RPM repositories +- Locating bootc image pull specs +- Understanding what version type a given version is +- Finding Brew builds for internal testing (VPN required) + +## Arguments +- `$1` (version): The MicroShift version to check - **Required** + - Formats accepted: + - Full version: `4.20.0`, `4.18.26` + - EC version: `4.21.0-ec.3` or `4.21.0~ec.3` + - RC version: `4.20.0-rc.3` or `4.20.0~rc.3` + - Short version: `4.21` (will check latest available) + +## Return Value +- **Format**: Markdown +- **Location**: Output directly to the conversation +- **Content**: + - Version availability status + - Version type (EC, RC, GA, z-stream) + - RPM URLs for both architectures (x86_64, aarch64) + - Bootc image pull specs (if available) + - Links to package catalogs + +## Version Types Reference + +| Type | Version Format | Release Cadence | RPM Source | Image Source | +|------|----------------|-----------------|------------|--------------| +| Nightly | `X.Y.0~0.nightly_YYYY_MM_DD_HHMMSS` | Continuous | Brew | Not available | +| EC | `X.Y.0~ec.N` | Every sprint (3 weeks) | Brew, mirror repo | Mirror repo | +| RC | `X.Y.0~rc.N` | After branch cutoff until GA | Brew, mirror repo | Mirror repo | +| GA | `X.Y.0` | Every 4 months | Brew, rhocp repos | registry.redhat.io | +| Z-stream | `X.Y.Z` | On request | Brew, rhocp repos | registry.redhat.io | + +## Implementation Steps + +### Step 1: Parse Version and Determine Type + +**Goal**: Parse the input version and classify its type. + +**Actions**: +1. Normalize version format (replace `~` with `-` for URL construction) +2. Extract major.minor version (e.g., `4.20` from `4.20.0-rc.3`) +3. Classify version type: + - Contains `nightly` → Nightly build + - Contains `ec` → Engineering Candidate + - Contains `rc` → Release Candidate + - Format `X.Y.0` → GA release + - Format `X.Y.Z` (Z > 0) → Z-stream release + +**Example**: +``` +Input: 4.21.0-ec.3 +Parsed: +- normalized: 4.21.0-ec.3 +- major_minor: 4.21 +- type: EC +- base_version: 4.21.0 +``` + +### Step 2: Check OpenShift Release Status + +**Goal**: Check if OCP payload is Accepted for this version. + +**Actions**: +1. Web Fetch this and look for the version: + ``` + https://openshift-release.apps.ci.l2s4.p1.openshiftapps.com/ + ``` +2. Check if the payload for the version is Accepted. + +**Outcome**: + - If the payload is Accepted continue with next step. + - If the payload is Not Accepted do not run next steps. MicroShift version won't be created if the OCP is not Accepted. + +**Note**: MicroShift packages become available when the corresponding OCP version is marked as "Accepted". + +### Step 3: Check RPM Availability + +**Goal**: Determine if RPM packages are available and provide URLs. + +**Actions**: + +**For EC versions**: +1. Check mirror.openshift.com, EC packages are under `ocp-dev-preview/`, see: + ``` + https://mirror.openshift.com/pub/openshift-v4/x86_64/microshift/ocp-dev-preview//el9/os/Packages/ + https://mirror.openshift.com/pub/openshift-v4/aarch64/microshift/ocp-dev-preview//el9/os/Packages/ + ``` +2. Use WebFetch to verify the directory exists and list packages + +**For RC versions**: +1. Check mirror.openshift.com, RC packages are under `ocp/`, see: + ``` + https://mirror.openshift.com/pub/openshift-v4/x86_64/microshift/ocp//el9/os/Packages/ + https://mirror.openshift.com/pub/openshift-v4/aarch64/microshift/ocp//el9/os/Packages/ + ``` +2. Use WebFetch to verify the directory exists and list packages + +**For GA/Z-stream versions**: +1. Check on brew: + ``` + https://brewweb.engineering.redhat.com/brew/packageinfo?packageID=82827 + ``` + Use this command to check for microshift releases: + ``` + curl -sk "https://brewweb.engineering.redhat.com/brew/search?match=glob&type=build&terms={version}" 2>/dev/null + ``` + +### Step 4: Check Bootc Image Availability + +**Goal**: Find bootc image pull specs for versions 4.18+. + +**Actions**: + +**For EC versions**: +1. Fetch bootc-pullspec.txt: + ``` + https://mirror.openshift.com/pub/openshift-v4/x86_64/microshift/ocp-dev-preview//el9/bootc-pullspec.txt + https://mirror.openshift.com/pub/openshift-v4/aarch64/microshift/ocp-dev-preview//el9/bootc-pullspec.txt + ``` +2. Extract the quay.io pull spec from the file + +**For RC versions**: +1. Fetch bootc-pullspec.txt: + ``` + https://mirror.openshift.com/pub/openshift-v4/x86_64/microshift/ocp//el9/bootc-pullspec.txt + https://mirror.openshift.com/pub/openshift-v4/aarch64/microshift/ocp//el9/bootc-pullspec.txt + ``` + +**For GA/Z-stream versions**: +1. For pre-GA z-stream, check registry.stage.redhat.io: + - Production: `https://catalog.redhat.com/en/software/containers/openshift4/microshift-bootc-rhel9/` + - Use this command to check the catalog: `curl -sk "https://catalog.redhat.com/api/containers/v1/repositories/registry/registry.access.redhat.com/repository/openshift4/microshift-bootc-rhel9/images?page_size=500&page=0" 2>/dev/null` + - if not found try few more pages + - Stage: `https://catalog.stage.redhat.com/en/software/containers/openshift4/microshift-bootc-rhel9/` + - Use this command to check the catalog: `curl -sk "https://catalog.stage.redhat.com/api/containers/v1/repositories/registry/registry.access.redhat.com/repository/openshift4/microshift-bootc-rhel9/images?page_size=500&page=0" 2>/dev/null` + - if not found try few more pages + +### Step 5: List Available Versions (if short version provided) + +**Goal**: If user provides a short version like `4.21`, list all available sub-versions. + +**Actions**: +1. Fetch directory listing from mirror.openshift.com: + ``` + https://mirror.openshift.com/pub/openshift-v4/x86_64/microshift/ocp-dev-preview/ + https://mirror.openshift.com/pub/openshift-v4/x86_64/microshift/ocp/ + ``` +2. Filter for versions matching the major.minor pattern +3. List all available versions with their types + +### Step 6: Generate Report + +**Goal**: Create a comprehensive availability report. + +**Report Structure**: +```markdown +# MicroShift Version Availability: + +## Status +- **Version**: +- **Type**: EC / RC / GA / Z-stream +- **Status**: Available / Not Yet Available +- **OCP Release Status**: Accepted / Pending + +## Brew Builds (VPN Required) +- **Web**: https://brewweb.engineering.redhat.com/brew/packageinfo?packageID=82827 +- **Build**: (if found) +- **Status**: Available / Not Found / VPN Required + +## RPM Packages + +### x86_64 +- **URL**: +- **Status**: Available / Not Found + +### aarch64 +- **URL**: +- **Status**: Available / Not Found + +## Bootc Images (4.18+) + +### x86_64 +- **Pull Spec**: + +### aarch64 +- **Pull Spec**: + +## Catalog Links +- [Red Hat Catalog]() (GA/Z-stream only) +- [Stage Catalog]() (pre-GA Z-stream only) + +## Notes +- +``` + +## Examples + +### Example 1: Check EC Version +``` +/microshift-release-versions 4.21.0-ec.3 +``` + +Output: +```markdown +# MicroShift Version Availability: 4.21.0-ec.3 + +## Status +- **Version**: 4.21.0-ec.3 +- **Type**: Engineering Candidate (EC) +- **Status**: Available +- **OCP Release Status**: Accepted + +## Brew Builds (VPN Required) +- **Web**: https://brewweb.engineering.redhat.com/brew/packageinfo?packageID=82827 +- **Build**: microshift-4.21.0-0.ec.3.el9 +- **Status**: Available + +## RPM Packages + +### x86_64 +- **URL**: https://mirror.openshift.com/pub/openshift-v4/x86_64/microshift/ocp-dev-preview/4.21.0-ec.3/el9/os/Packages/ +- **Status**: Available + +### aarch64 +- **URL**: https://mirror.openshift.com/pub/openshift-v4/aarch64/microshift/ocp-dev-preview/4.21.0-ec.3/el9/os/Packages/ +- **Status**: Available + +## Bootc Images + +### x86_64 +- **Pull Spec**: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:5ec944... + +### aarch64 +- **Pull Spec**: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a255da... +``` + +### Example 2: Check RC Version (Not Yet Available) +``` +/microshift-release-versions 4.21.0-rc.1 +``` + +Output: +```markdown +# MicroShift Version Availability: 4.21.0-rc.1 + +## Status +- **Version**: 4.21.0-rc.1 +- **Type**: Release Candidate (RC) +- **Status**: Not Yet Available + +## Notes +- 4.21 is currently in EC phase (latest: 4.21.0-ec.3) +- RC versions are created after branch cutoff until GA +- Check https://openshift-release.apps.ci.l2s4.p1.openshiftapps.com/ for release status +``` + +### Example 3: Check GA/Z-stream Version +``` +/microshift-release-versions 4.18.26 +``` + +Output: +```markdown +# MicroShift Version Availability: 4.18.26 + +## Status +- **Version**: 4.18.26 +- **Type**: Z-stream +- **Status**: Available + +## RPM Packages +- **Repo**: rhocp-4.18-for-rhel-9-x86_64-rpms +- **Catalog**: https://access.redhat.com/downloads/content/microshift/4.18.26/ + +## Bootc Images +- **Pull Spec**: registry.redhat.io/openshift4/microshift-bootc-rhel9:4.18.26 +- **Catalog**: https://catalog.redhat.com/en/software/containers/openshift4/microshift-bootc-rhel9/ +``` + +### Example 4: List Available Versions for a Release +``` +/microshift-release-versions 4.21 +``` + +Output: +```markdown +# Available MicroShift 4.21 Versions + +## EC Versions (Dev Preview) +- 4.21.0-ec.3 (Accepted) +- 4.21.0-ec.2 (Accepted) +- 4.21.0-ec.1 (Accepted) +- 4.21.0-ec.0 (Accepted) + +## RC Versions +- None available yet (4.21 is still in EC phase) + +## Notes +- RC versions will be available after branch cutoff +- GA expected in approximately X months +``` + +## Reference Information + +### Brew (Internal Red Hat) + +Brew is Red Hat's internal build system. VPN is required to access it, assume VPN is enabled. + +**Web Interface**: +- Browse all MicroShift packages: https://brewweb.engineering.redhat.com/brew/packageinfo?packageID=82827 + +**Build NVR Format**: +- GA/Z-stream: `microshift-4.18.26-.el9` +- EC: `microshift-4.21.0-0.ec.3..el9` +- RC: `microshift-4.21.0-0.rc.1..el9` +- Nightly: `microshift-4.21.0-0.nightly_YYYY_MM_DD_HHMMSS..el9` + +### URL Patterns + +**Mirror repos (EC/RC)**: +- EC RPMs: `https://mirror.openshift.com/pub/openshift-v4/{ARCH}/microshift/ocp-dev-preview/{VERSION}/el9/os/Packages/` +- RC RPMs: `https://mirror.openshift.com/pub/openshift-v4/{ARCH}/microshift/ocp/{VERSION}/el9/os/Packages/` +- EC Bootc: `https://mirror.openshift.com/pub/openshift-v4/{ARCH}/microshift/ocp-dev-preview/{VERSION}/el9/bootc-pullspec.txt` +- RC Bootc: `https://mirror.openshift.com/pub/openshift-v4/{ARCH}/microshift/ocp/{VERSION}/el9/bootc-pullspec.txt` + +**Registry repos (GA/Z-stream)**: +- Production: `registry.redhat.io/openshift4/microshift-bootc-rhel9` +- Stage: `registry.stage.redhat.io/openshift4/microshift-bootc-rhel9` + +**Catalogs**: +- Production: `https://catalog.redhat.com/en/software/containers/openshift4/microshift-bootc-rhel9/` +- Stage: `https://catalog.stage.redhat.com/en/software/containers/openshift4/microshift-bootc-rhel9/` + +### Release Timing + +- **EC versions**: Usually created from a commit on the last Wednesday of every sprint; available on the first Wednesday of the next sprint +- **RC versions**: Created after branch cutoff until GA; several may be created +- **GA versions**: Released every 4 months +- **Z-stream versions**: Created on request from MicroShift team to ART team + +### CI Testing + +Release versions are tested in CI: +- Scenarios: `test/scenarios/releases/` and `test/scenarios-bootc/releases/` +- Latest release version must be **manually updated** in `test/bin/common_versions.sh` when new RC or z-stream is available + +## Notes +- Assume VPN access is enabled by default when looking for Brew resources +- Bootc images are only available for MicroShift 4.18 and later +- MicroShift packages become available when the OCP version is marked as "Accepted" +- For nightly builds, only RPMs are available in Brew (VPN required) +- The command is read-only and does not modify any data +- Use this command to verify availability before updating CI configurations or deployment scripts diff --git a/.claude/scripts/extract_microshift_version.py b/.claude/scripts/extract_microshift_version.py new file mode 100644 index 0000000000..f78a361b13 --- /dev/null +++ b/.claude/scripts/extract_microshift_version.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python3 +""" +Extract MicroShift version from Prow CI journal logs. + +This script fetches the journal log from a Prow CI job and extracts the +exact MicroShift version being tested from the systemd journal output. + +Usage: + python3 extract_microshift_version.py + +Arguments: + prow_url: The Prow CI job URL + e.g.: "https://prow.ci.openshift.org/view/gs/test-platform-results/pr-logs/pull/openshift_microshift/5703/pull-ci-openshift-microshift-main-e2e-aws-tests-bootc-release/1990417342856695808" + scenario: Scenario name + e.g.: "el96-lrel@backups" + +Output: + JSON object with: + { + "version": "4.20.0-202511160032.p0.gb46fe41.assembly.stream.el9", + "build_type": "nightly", + "success": true, + "error": null + } +""" + +import sys +import json +import re +import urllib.request +import urllib.error +import urllib.parse +import ssl +from html.parser import HTMLParser + + +class GCSWebLinkParser(HTMLParser): + """Parse GCSWeb HTML to extract file links.""" + + def __init__(self): + super().__init__() + self.links = [] + + def handle_starttag(self, tag, attrs): + if tag == 'a': + for attr, value in attrs: + if attr == 'href' and value and not value.startswith('?'): + self.links.append(value) + + +def construct_journal_log_dir_url(job_id, version, job_type, pr_number=None, scenario="el96-lrel@ipv6"): + """Construct the URL to the journal log directory for a given job.""" + base_url = "https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results" + + if pr_number: + # PR job URL pattern + job_name = f"pull-ci-openshift-microshift-release-{version}-{job_type}" + path = f"pr-logs/pull/openshift_microshift/{pr_number}/{job_name}/{job_id}" + else: + # Periodic job URL pattern + job_name = f"periodic-ci-openshift-microshift-release-{version}-periodics-{job_type}" + path = f"logs/{job_name}/{job_id}" + + artifact_path = f"artifacts/{job_type}/openshift-microshift-e2e-metal-tests/artifacts/scenario-info/{scenario}/vms/host1/sos" + + return f"{base_url}/{path}/{artifact_path}/" + + +def fetch_url(url): + """Fetch content from the given URL.""" + try: + # Validate URL scheme + if not url.startswith('https://'): + return None, "Invalid URL scheme. Only HTTPS URLs are supported." + + # Create SSL context that doesn't verify certificates + ssl_context = ssl.create_default_context() + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE + + with urllib.request.urlopen(url, timeout=30, context=ssl_context) as response: + content = response.read().decode('utf-8') + return content, None + except urllib.error.URLError as e: + return None, f"Failed to fetch URL: {e}" + except (UnicodeDecodeError, OSError) as e: + return None, f"Error reading URL: {e}" + + +def find_journal_log_file(dir_url): + """Find the journal log file in the directory listing.""" + html_content, error = fetch_url(dir_url) + if error: + return None, error + + # Parse HTML to find links + parser = GCSWebLinkParser() + parser.feed(html_content) + + # Find journal_*.log files + journal_files = [] + for link in parser.links: + # Extract just the filename from the full path + filename = link.split('/')[-1] + # URL-decode the filename + decoded_filename = urllib.parse.unquote(filename) + if decoded_filename.startswith('journal_') and decoded_filename.endswith('.log'): + # Keep the URL-encoded filename for URL construction + journal_files.append(filename) + + if not journal_files: + return None, "No journal log files found in directory" + + # Return the first journal log file (there should typically be only one) + return journal_files[0], None + + +def extract_version_from_journal(log_content): + """ + Extract MicroShift version from journal log content. + + Looks for pattern: "Version" microshift="4.20.0-202511160032.p0.gb46fe41.assembly.stream.el9" + """ + # Pattern to match: "Version" microshift="" + pattern = r'"Version"\s+microshift="([^"]+)"' + + matches = re.findall(pattern, log_content) + if matches: + version_string = matches[-1].strip() + return version_string, None + + return None, "Could not find MicroShift version in journal log" + + +def determine_build_type(version_string): + """ + Determine the build type from the version string. + + Returns one of: "nightly", "ec", "rc", "zstream" + """ + if "nightly" in version_string.lower(): + return "nightly" + elif "-ec." in version_string: + return "ec" + elif "-rc." in version_string: + return "rc" + else: + # Check if it's a date-based build (likely nightly/stream) + if re.search(r'\d{12}\.p\d+\.g[a-f0-9]+', version_string): + return "nightly" + return "zstream" + + +def parse_prow_url(prow_url): + """ + Parse a Prow CI URL to extract job information. + + Supported URL formats: + - PR jobs: https://prow.ci.openshift.org/view/gs/test-platform-results/pr-logs/pull/openshift_microshift/{pr_number}/{job_name}/{job_id} + - Periodic jobs: https://prow.ci.openshift.org/view/gs/test-platform-results/logs/{job_name}/{job_id} + + Returns: + Tuple of (job_id, version, job_type, pr_number) or (None, None, None, None) on error + """ + # Remove the prow.ci.openshift.org prefix and normalize + url_parts = prow_url.replace("https://prow.ci.openshift.org/view/gs/test-platform-results/", "") + + # Split by '/' + parts = url_parts.split('/') + + if len(parts) < 2: + return None, None, None, None, "Invalid URL format" + + # Check if it's a PR job or periodic job + if parts[0] == "pr-logs" and len(parts) >= 6: + # PR job format: pr-logs/pull/openshift_microshift/{pr_number}/{job_name}/{job_id} + pr_number = parts[3] + job_name = parts[4] + job_id = parts[5] + + # Extract version and job_type from job_name + # Format: pull-ci-openshift-microshift-release-{version}-{job_type} + # or: pull-ci-openshift-microshift-release-{version}-{job_type}-{arch} + if job_name.startswith("pull-ci-openshift-microshift-release-"): + name_parts = job_name.replace("pull-ci-openshift-microshift-release-", "").split("-", 1) + if len(name_parts) >= 2: + version = name_parts[0] + job_type = name_parts[1] + return job_id, version, job_type, pr_number, None + + return None, None, None, None, f"Could not parse PR job name: {job_name}" + + elif parts[0] == "logs" and len(parts) >= 3: + # Periodic job format: logs/{job_name}/{job_id} + job_name = parts[1] + job_id = parts[2] + + # Extract version and job_type from job_name + # Format: periodic-ci-openshift-microshift-release-{version}-periodics-{job_type} + if job_name.startswith("periodic-ci-openshift-microshift-release-"): + name_parts = job_name.replace("periodic-ci-openshift-microshift-release-", "") + # Split on "-periodics-" to separate version from job_type + if "-periodics-" in name_parts: + version, job_type = name_parts.split("-periodics-", 1) + return job_id, version, job_type, None, None + + return None, None, None, None, f"Could not parse periodic job name: {job_name}" + + return None, None, None, None, "Unsupported URL format" + + +def main(): + """Main entry point.""" + if len(sys.argv) != 3: + print(json.dumps({ + "success": False, + "error": "Usage: extract_microshift_version.py " + })) + sys.exit(1) + + prow_url = sys.argv[1] + scenario = sys.argv[2] + + # Validate inputs + if not prow_url or not prow_url.strip(): + print(json.dumps({ + "success": False, + "error": "prow_url cannot be empty" + })) + sys.exit(1) + + if not scenario or not scenario.strip(): + print(json.dumps({ + "success": False, + "error": "scenario cannot be empty" + })) + sys.exit(1) + + # Parse the Prow URL + job_id, version, job_type, pr_number, parse_error = parse_prow_url(prow_url) + if parse_error: + print(json.dumps({ + "success": False, + "error": parse_error, + "prow_url": prow_url + })) + sys.exit(1) + + # Construct journal log directory URL + dir_url = construct_journal_log_dir_url(job_id, version, job_type, pr_number, scenario) + + # Find journal log file + journal_file, error = find_journal_log_file(dir_url) + if error: + print(json.dumps({ + "success": False, + "error": error, + "url": dir_url + })) + sys.exit(1) + + # Construct full journal log URL + log_url = dir_url + journal_file + + # Fetch journal log + log_content, error = fetch_url(log_url) + if error: + print(json.dumps({ + "success": False, + "error": error, + "url": log_url + })) + sys.exit(1) + + # Extract version + microshift_version, error = extract_version_from_journal(log_content) + if error: + print(json.dumps({ + "success": False, + "error": error, + "url": log_url + })) + sys.exit(1) + + # Determine build type + build_type = determine_build_type(microshift_version) + + # Output result + result = { + "success": True, + "version": microshift_version, + "build_type": build_type, + "url": log_url, + "error": None + } + + print(json.dumps(result, indent=2)) + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000000..e85447cce0 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,18 @@ +{ + "permissions": { + "allow": [ + "Read(//tmp/**)", + "Bash(mktemp:*)", + "Bash(curl:*)", + "Bash(gcloud storage cp:*)", + "Bash(gh pr view:*)", + "Bash(gh pr diff:*)", + "Bash(tar:*)", + "Bash(gh pr checks:*)", + "WebFetch(domain:prow.ci.openshift.org)", + "Bash(gh issue list:*)" + ], + "deny": [], + "ask": [] + } +} diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 2adb2ac034..0000000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,9 +0,0 @@ - -**Which issue(s) this PR addresses**: - -Closes # diff --git a/Makefile.kube_git.var b/Makefile.kube_git.var index 7e46e0ffcc..2cd526c48b 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.1 -KUBE_GIT_COMMIT=96593f323733d9ffc0fc70257ecad44a56df0ce3 +KUBE_GIT_VERSION=v1.34.2 +KUBE_GIT_COMMIT=9f57f51e3485ccc1cfd01ec94e9a0f5bef38eacb KUBE_GIT_TREE_STATE=clean diff --git a/Makefile.version.aarch64.var b/Makefile.version.aarch64.var index 15f8632e36..083fa0f3d5 100644 --- a/Makefile.version.aarch64.var +++ b/Makefile.version.aarch64.var @@ -1 +1 @@ -OCP_VERSION := 4.21.0-0.nightly-arm64-2025-10-19-182251 +OCP_VERSION := 4.21.0-0.nightly-arm64-2025-12-12-014247 diff --git a/Makefile.version.x86_64.var b/Makefile.version.x86_64.var index 9dd7d6d31a..9497a2795d 100644 --- a/Makefile.version.x86_64.var +++ b/Makefile.version.x86_64.var @@ -1 +1 @@ -OCP_VERSION := 4.21.0-0.nightly-2025-10-19-181151 +OCP_VERSION := 4.21.0-0.nightly-2025-12-10-193741 diff --git a/apiserver-config-flow.md b/apiserver-config-flow.md new file mode 100644 index 0000000000..665a5cd8a2 --- /dev/null +++ b/apiserver-config-flow.md @@ -0,0 +1,397 @@ +# API Server Config Data Flow + +This document traces the data path from the `apiServer` field in `/etc/microshift/config.yaml` down to where the values are ingested by the kube-apiserver. + +## UML Sequence Diagram + +```mermaid +sequenceDiagram + participant ConfigFile as config.yaml + participant ActiveConfig as config.ActiveConfig() + participant FillDefaults as config.fillDefaults() + participant IncorporateSettings as config.incorporateUserSettings() + participant UpdateComputed as config.updateComputedValues() + participant KASRun as KubeAPIServer.Run() + participant KASConfigure as KubeAPIServer.configure() + participant Merge as resourcemerge.MergePrunedProcessConfig() + participant TempFile as Create Temp File + participant NewCmd as kubeapiserver.NewAPIServerCommand() + participant Execute as cmd.ExecuteContext() + participant GetOpenshiftConfig as enablement.GetOpenshiftConfig() + participant ConfigToFlags as openshiftkubeapiserver.ConfigToFlags() + participant ParseFlags as cmd.ParseFlags() + participant KASMain as Run() [kube-apiserver] + + Note over ConfigFile: User configuration in
/etc/microshift/config.yaml

apiServer:
advertiseAddress: "10.43.0.2"
port: 6443
auditLog:
profile: "Default"
tls:
minVersion: "VersionTLS12"
cipherSuites: [...]
featureGates:
featureSet: "CustomNoUpgrade"
customNoUpgrade:
enabled: ["UserNamespacesSupport"] + + ConfigFile->>+ActiveConfig: Read config.yaml
[files.go:120] + + ActiveConfig->>+FillDefaults: Set default values
[config.go:92] + Note right of FillDefaults: Sets default ApiServer values:
- Port: 6443
- URL: "https://localhost:6443"
- AuditLog defaults
- SubjectAltNames + FillDefaults-->>-ActiveConfig: Config with defaults + + ActiveConfig->>+IncorporateSettings: Merge user settings
[config.go:195] + Note right of IncorporateSettings: Merges user-provided values:
- ApiServer.AdvertiseAddress
- ApiServer.AuditLog.*
- ApiServer.TLS.*
- ApiServer.NamedCertificates
- ApiServer.FeatureGates.* + IncorporateSettings-->>-ActiveConfig: Config with user settings + + ActiveConfig->>+UpdateComputed: Compute derived values
[config.go:434] + Note right of UpdateComputed: Computes:
- AdvertiseAddresses (from ServiceNetwork)
- TLS.UpdateValues() - cipher suites
- SkipInterface flag + UpdateComputed-->>-ActiveConfig: Final Config + + ActiveConfig-->>-ConfigFile: *config.Config + + Note over KASRun: MicroShift creates and starts
kube-apiserver controller + + KASRun->>+KASConfigure: configure(ctx, cfg)
[kube-apiserver.go:97] + + Note right of KASConfigure: Uses cfg.ApiServer fields to build
KubeAPIServerConfig overrides:

- advertise-address
- audit-policy-file
- audit-log-*
- tls-cert-file
- tls-private-key-file
- tls-min-version
- tls-cipher-suites
- feature-gates
- service-cluster-ip-range
- disable-admission-plugins
- enable-admission-plugins + + KASConfigure->>+Merge: Merge config layers
[kube-apiserver.go:267] + Note right of Merge: Merges 3 layers:
1. defaultconfig.yaml (embedded)
2. config-overrides.yaml (embedded)
3. Runtime overrides from cfg.ApiServer

Creates KubeAPIServerConfig struct
with all settings merged + Merge-->>-KASConfigure: kasConfigBytes (marshaled YAML) + + KASConfigure-->>-KASRun: Configuration complete + + KASRun->>TempFile: Create temp config file
[kube-apiserver.go:363] + Note right of TempFile: Write kasConfigBytes to:
/tmp/kube-apiserver-config-*.yaml + + KASRun->>+NewCmd: NewAPIServerCommand()
[kube-apiserver.go:391] + Note right of NewCmd: Initialize kube-apiserver command
from kubernetes/cmd/kube-apiserver + NewCmd-->>-KASRun: cmd *cobra.Command + + KASRun->>+Execute: cmd.ExecuteContext(ctx)
[kube-apiserver.go:404] + Note right of Execute: Args:
--openshift-config /tmp/kube-apiserver-config-*.yaml
-v [verbosity] + + Execute->>+GetOpenshiftConfig: Read config file
[intialization.go:27] + Note right of GetOpenshiftConfig: Reads temp config file and
deserializes into
KubeAPIServerConfig struct

Resolves file paths
Sets recommended defaults + GetOpenshiftConfig-->>-Execute: *KubeAPIServerConfig + + Execute->>+ConfigToFlags: Convert to CLI flags
[flags.go:18] + Note right of ConfigToFlags: Converts KubeAPIServerConfig.APIServerArguments
to command-line flags:

Map[string][]string -> []string

Examples:
"advertise-address": ["10.43.0.2"]
-> --advertise-address=10.43.0.2

"feature-gates": ["UserNamespacesSupport=true"]
-> --feature-gates=UserNamespacesSupport=true

Also converts:
- ServingInfo -> tls-* flags
- AuditConfig -> audit-* flags
- AdmissionConfig -> admission-* flags + ConfigToFlags-->>-Execute: []string (CLI flags) + + Execute->>+ParseFlags: Parse merged flags
[server.go:122] + Note right of ParseFlags: Re-parses command flags with
values from OpenShift config

This updates the ServerRunOptions
with all the ApiServer settings + ParseFlags-->>-Execute: Updated options + + Execute->>+KASMain: Run(ctx, completedOptions)
[server.go:153] + Note right of KASMain: Kube-apiserver starts with
all configuration applied:

- TLS settings
- Audit logging
- Feature gates
- Admission plugins
- Serving configuration + + Note over KASMain: Kube-apiserver running with
all config.ApiServer values
applied via command-line flags +``` + +## Key Data Structures + +### 1. MicroShift Config (`pkg/config/apiserver.go`) + +```go +type ApiServer struct { + SubjectAltNames []string + AdvertiseAddress string + NamedCertificates []NamedCertificateEntry + AuditLog AuditLog + TLS TLSConfig + FeatureGates FeatureGates + URL string + Port int + AdvertiseAddresses []string +} +``` + +### 2. KubeAPIServerConfig (`vendor/github.com/openshift/api/kubecontrolplane/v1/types.go`) + +```go +type KubeAPIServerConfig struct { + GenericAPIServerConfig configv1.GenericAPIServerConfig + APIServerArguments map[string]Arguments + ServiceAccountPublicKeyFiles []string + ServicesNodePortRange string + // ... other fields +} +``` + +### 3. APIServerArguments (Key-Value Map) + +```go +APIServerArguments: map[string]Arguments{ + "advertise-address": {cfg.ApiServer.AdvertiseAddress}, + "audit-log-maxage": {strconv.Itoa(cfg.ApiServer.AuditLog.MaxFileAge)}, + "tls-min-version": {cfg.ApiServer.TLS.MinVersion}, + "tls-cipher-suites": cfg.ApiServer.TLS.CipherSuites, + "feature-gates": {"UserNamespacesSupport=true", ...}, + // ... many more +} +``` + +## Configuration Flow Steps + +### Step 1: Config Loading (`pkg/config/files.go`) + +**Function**: `ActiveConfig()` +**Line**: [120-127](file:///home/microshift/microshift/pkg/config/files.go#L120-L127) + +1. Reads `/etc/microshift/config.yaml` +2. Reads YAML files from `/etc/microshift/config.d/*.yaml` +3. Merges all YAML files using JSON patch merge +4. Deserializes into `Config` struct + +### Step 2: Config Initialization (`pkg/config/config.go`) + +**Function**: `fillDefaults()` +**Lines**: [92-190](file:///home/microshift/microshift/pkg/config/config.go#L92-L190) + +Sets default values for `ApiServer`: +```go +c.ApiServer = ApiServer{ + SubjectAltNames: subjectAltNames, + URL: "https://localhost:6443", + Port: 6443, +} +c.ApiServer.AuditLog = AuditLog{ + MaxFileAge: 0, + MaxFiles: 10, + MaxFileSize: 200, + Profile: "Default", +} +``` + +**Function**: `incorporateUserSettings()` +**Lines**: [195-429](file:///home/microshift/microshift/pkg/config/config.go#L195-L429) + +Merges user-provided values: +```go +if u.ApiServer.AdvertiseAddress != "" { + c.ApiServer.AdvertiseAddress = u.ApiServer.AdvertiseAddress +} +if u.ApiServer.AuditLog.Profile != "" { + c.ApiServer.AuditLog.Profile = u.ApiServer.AuditLog.Profile +} +// ... TLS settings +// ... FeatureGates +``` + +**Function**: `updateComputedValues()` +**Lines**: [434-516](file:///home/microshift/microshift/pkg/config/config.go#L434-L516) + +Computes derived values: +- `AdvertiseAddress` (if not set) +- `AdvertiseAddresses` (for dual-stack) +- `TLS.UpdateValues()` - cipher suites normalization + +### Step 3: KubeAPIServer Configuration (`pkg/controllers/kube-apiserver.go`) + +**Function**: `configure()` +**Lines**: [97-297](file:///home/microshift/microshift/pkg/controllers/kube-apiserver.go#L97-L297) + +Creates `KubeAPIServerConfig` overrides: +```go +overrides := &kubecontrolplanev1.KubeAPIServerConfig{ + APIServerArguments: map[string]Arguments{ + "advertise-address": {s.advertiseAddress}, + "audit-policy-file": {...}, + "audit-log-maxage": {strconv.Itoa(cfg.ApiServer.AuditLog.MaxFileAge)}, + "audit-log-maxbackup": {strconv.Itoa(cfg.ApiServer.AuditLog.MaxFiles)}, + "audit-log-maxsize": {strconv.Itoa(cfg.ApiServer.AuditLog.MaxFileSize)}, + "service-cluster-ip-range": {strings.Join(cfg.Network.ServiceNetwork, ",")}, + "disable-admission-plugins": {...}, + "enable-admission-plugins": {}, + "feature-gates": {"UserNamespacesSupport=true", ...}, + }, + GenericAPIServerConfig: configv1.GenericAPIServerConfig{ + ServingInfo: configv1.HTTPServingInfo{ + ServingInfo: configv1.ServingInfo{ + MinTLSVersion: cfg.ApiServer.TLS.MinVersion, + CipherSuites: cfg.ApiServer.TLS.CipherSuites, + NamedCertificates: namedCerts, + }, + }, + }, +} +``` + +**Function**: `resourcemerge.MergePrunedProcessConfig()` +**Lines**: [267-291](file:///home/microshift/microshift/pkg/controllers/kube-apiserver.go#L267-L291) + +Merges three configuration layers: +1. `defaultconfig.yaml` (embedded baseline) +2. `config-overrides.yaml` (embedded OpenShift defaults) +3. Runtime `overrides` (from cfg.ApiServer) + +Result: `kasConfigBytes` - marshaled YAML config + +### Step 4: Starting Kube-APIServer (`pkg/controllers/kube-apiserver.go`) + +**Function**: `Run()` +**Lines**: [315-413](file:///home/microshift/microshift/pkg/controllers/kube-apiserver.go#L315-L413) + +1. **Line 363-381**: Creates temporary config file + ```go + fd, err := os.CreateTemp("", "kube-apiserver-config-*.yaml") + io.Copy(fd, bytes.NewBuffer(s.kasConfigBytes)) + ``` + +2. **Line 391-395**: Creates kube-apiserver command + ```go + cmd := kubeapiserver.NewAPIServerCommand() + cmd.SetArgs([]string{ + "--openshift-config", fd.Name(), + "-v", strconv.Itoa(s.verbosity), + }) + ``` + +3. **Line 404**: Executes command + ```go + errorChannel <- cmd.ExecuteContext(ctx) + ``` + +### Step 5: Kube-APIServer Ingestion (`deps/.../cmd/kube-apiserver/app/server.go`) + +**Function**: `RunE` (cobra command handler) +**Lines**: [96-154](file:///home/microshift/microshift/deps/github.com/openshift/kubernetes/cmd/kube-apiserver/app/server.go#L96-L154) + +1. **Line 110**: Read OpenShift config file + ```go + openshiftConfig, err := enablement.GetOpenshiftConfig(s.OpenShiftConfig) + ``` + +2. **Line 116-119**: Convert to command-line flags + ```go + args, err := openshiftkubeapiserver.ConfigToFlags(openshiftConfig) + // Example: ["--advertise-address=10.43.0.2", "--audit-log-maxage=0", ...] + ``` + +3. **Line 122**: Parse flags to update options + ```go + cmd.ParseFlags(args) + ``` + +4. **Line 153**: Start API server with merged options + ```go + return Run(ctx, completedOptions) + ``` + +### Step 6: Config to Flags Conversion (`deps/.../openshiftkubeapiserver/flags.go`) + +**Function**: `ConfigToFlags()` +**Lines**: [18-46](file:///home/microshift/microshift/deps/github.com/openshift/kubernetes/openshift-kube-apiserver/openshiftkubeapiserver/flags.go#L18-L46) + +Converts `KubeAPIServerConfig` to CLI flags: + +```go +func ConfigToFlags(kubeAPIServerConfig *KubeAPIServerConfig) ([]string, error) { + args := unmaskArgs(kubeAPIServerConfig.APIServerArguments) + + // Extract from APIServerArguments map + // "advertise-address": ["10.43.0.2"] -> --advertise-address=10.43.0.2 + + // Add additional flags from other config fields + configflags.SetIfUnset(args, "bind-address", host) + configflags.SetIfUnset(args, "tls-cipher-suites", + kubeAPIServerConfig.ServingInfo.CipherSuites...) + configflags.SetIfUnset(args, "tls-min-version", + kubeAPIServerConfig.ServingInfo.MinTLSVersion) + + return configflags.ToFlagSlice(args), nil +} +``` + +**Function**: `ToFlagSlice()` +**Lines**: [29-43](file:///home/microshift/microshift/deps/github.com/openshift/kubernetes/vendor/github.com/openshift/apiserver-library-go/pkg/configflags/helpers.go#L29-L43) + +Converts map to flag array: +```go +func ToFlagSlice(args map[string][]string) []string { + var flags []string + for key, values := range args { + for _, value := range values { + flags = append(flags, fmt.Sprintf("--%s=%v", key, value)) + } + } + return flags +} +``` + +### Step 7: OpenShift Config Reading (`deps/.../enablement/intialization.go`) + +**Function**: `GetOpenshiftConfig()` +**Lines**: [27-58](file:///home/microshift/microshift/deps/github.com/openshift/kubernetes/openshift-kube-apiserver/enablement/intialization.go#L27-L58) + +1. Reads temp config file +2. Deserializes YAML into `KubeAPIServerConfig` +3. Resolves file paths (relative to config file location) +4. Applies recommended defaults + +## Example: Feature Gates Flow + +Let's trace the `featureGates` field specifically: + +### 1. User Configuration (`/etc/microshift/config.yaml`) +```yaml +apiServer: + featureGates: + featureSet: "CustomNoUpgrade" + customNoUpgrade: + enabled: ["UserNamespacesSupport"] + disabled: ["SomeOtherGate"] +``` + +### 2. Parsed into Config Struct (`pkg/config/apiserver.go`) +```go +ApiServer.FeatureGates = FeatureGates{ + FeatureSet: "CustomNoUpgrade", + CustomNoUpgrade: CustomNoUpgrade{ + Enabled: []string{"UserNamespacesSupport"}, + Disabled: []string{"SomeOtherGate"}, + }, +} +``` + +### 3. Current State: Hardcoded Feature Gates (`pkg/controllers/kube-apiserver.go` line 224) + +**NOTE**: As of the current implementation, feature gates are hardcoded and the `cfg.ApiServer.FeatureGates` config is not yet used. The implementation would need to add logic to read from `cfg.ApiServer.FeatureGates` and construct the feature-gates argument dynamically. + +Current hardcoded implementation: +```go +APIServerArguments: map[string]Arguments{ + "feature-gates": { + "UserNamespacesSupport=true", + "UserNamespacesPodSecurityStandards=true", + }, +} +``` + +**To implement feature gates from config**, the code would need to: +1. Read `cfg.ApiServer.FeatureGates.FeatureSet` to determine the base feature set +2. Parse `cfg.ApiServer.FeatureGates.CustomNoUpgrade.Enabled` and `.Disabled` lists +3. Construct feature gate strings like `"FeatureName=true"` or `"FeatureName=false"` +4. Add them to the `"feature-gates"` argument in the `APIServerArguments` map + +### 4. Converted to CLI Flags (`deps/.../flags.go`) +```bash +--feature-gates=UserNamespacesSupport=true +--feature-gates=UserNamespacesPodSecurityStandards=true +``` + +### 5. Parsed by Kube-APIServer +The kube-apiserver's flag parser reads these flags and enables the feature gates. + +## Summary + +The data flow is: + +1. **YAML file** → `ActiveConfig()` → **Config struct** +2. **Config struct** → `KubeAPIServer.configure()` → **KubeAPIServerConfig struct** +3. **KubeAPIServerConfig** → Marshaled to **temp YAML file** +4. **Temp YAML file** → `GetOpenshiftConfig()` → **KubeAPIServerConfig struct** (in kube-apiserver process) +5. **KubeAPIServerConfig** → `ConfigToFlags()` → **CLI flags array** +6. **CLI flags** → `cmd.ParseFlags()` → **ServerRunOptions** (internal kube-apiserver state) +7. **ServerRunOptions** → Used to configure and start the actual API server + +The key transformation points are: +- **Config YAML → Config struct**: Standard YAML unmarshaling +- **Config.ApiServer → KubeAPIServerConfig.APIServerArguments**: Manual mapping in `configure()` +- **KubeAPIServerConfig → CLI flags**: `ConfigToFlags()` conversion +- **CLI flags → Runtime config**: Cobra flag parsing in kube-apiserver + +All `apiServer` fields from the MicroShift config eventually become command-line flags that are parsed by the standard Kubernetes kube-apiserver flag parser. + diff --git a/assets/components/csi-snapshot-controller/csi_controller_deployment.yaml b/assets/components/csi-snapshot-controller/csi_controller_deployment.yaml index 2e9317dd56..66b44115ef 100644 --- a/assets/components/csi-snapshot-controller/csi_controller_deployment.yaml +++ b/assets/components/csi-snapshot-controller/csi_controller_deployment.yaml @@ -3,6 +3,8 @@ apiVersion: apps/v1 metadata: name: csi-snapshot-controller namespace: kube-system + labels: + hypershift.openshift.io/managed-by: csi-snapshot-controller-operator spec: serviceName: "csi-snapshot-controller" # Replicas for HyperShift. On standalone OCP it will be adjusted according to nr. of master nodes. diff --git a/assets/components/multus/kustomization.aarch64.yaml b/assets/components/multus/kustomization.aarch64.yaml index f89ea39e85..82ea664142 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:f707cb71fefd09001955c5f2834513e7b428f3909e060c222a804cd42da617df + digest: sha256:3119d0f37bf3c0212395bfebcfaf06cb5fd7d564852353decd8a50529ec7df17 - name: containernetworking-plugins-microshift newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev - digest: sha256:3cbac138a93c08adc56df905e8cd40e7071d79ff3a7cb98b345164198616ae72 + digest: sha256:5315a414015c766eae633b6aeda7f0dcac245c758142679924b13436fe6b77e8 diff --git a/assets/components/multus/kustomization.x86_64.yaml b/assets/components/multus/kustomization.x86_64.yaml index 06f98658aa..4e45b71342 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:71c83815d761876408e1bc4e2c16992fcb66329db8687f1203f9fe7525d3dc4f + digest: sha256:6e0db14df8cb8f36742991f3efa4ee2ae6b7f761c799ac3fd2243cfca516e0e1 - name: containernetworking-plugins-microshift newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev - digest: sha256:26533c159d815a1dd266d5a458ae6582f269d55a8a2572c2426dfd32f89b7d96 + digest: sha256:bc266d54f88ed5aed0e7747e2655eccb96ff51d1108b14418dd2bb22a6c71eef diff --git a/assets/components/multus/release-multus-aarch64.json b/assets/components/multus/release-multus-aarch64.json index aa2121dda4..ebc3635214 100644 --- a/assets/components/multus/release-multus-aarch64.json +++ b/assets/components/multus/release-multus-aarch64.json @@ -1,9 +1,9 @@ { "release": { - "base": "4.21.0-0.nightly-arm64-2025-10-19-182251" + "base": "4.21.0-0.nightly-arm64-2025-12-12-014247" }, "images": { - "multus-cni-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f707cb71fefd09001955c5f2834513e7b428f3909e060c222a804cd42da617df", - "containernetworking-plugins-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:3cbac138a93c08adc56df905e8cd40e7071d79ff3a7cb98b345164198616ae72" + "multus-cni-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:3119d0f37bf3c0212395bfebcfaf06cb5fd7d564852353decd8a50529ec7df17", + "containernetworking-plugins-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:5315a414015c766eae633b6aeda7f0dcac245c758142679924b13436fe6b77e8" } } diff --git a/assets/components/multus/release-multus-x86_64.json b/assets/components/multus/release-multus-x86_64.json index 396f998902..c85411437c 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.21.0-0.nightly-2025-10-19-181151" + "base": "4.21.0-0.nightly-2025-12-10-193741" }, "images": { - "multus-cni-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:71c83815d761876408e1bc4e2c16992fcb66329db8687f1203f9fe7525d3dc4f", - "containernetworking-plugins-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:26533c159d815a1dd266d5a458ae6582f269d55a8a2572c2426dfd32f89b7d96" + "multus-cni-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:6e0db14df8cb8f36742991f3efa4ee2ae6b7f761c799ac3fd2243cfca516e0e1", + "containernetworking-plugins-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:bc266d54f88ed5aed0e7747e2655eccb96ff51d1108b14418dd2bb22a6c71eef" } } diff --git a/assets/components/openshift-dns/dns/configmap.yaml b/assets/components/openshift-dns/dns/configmap.yaml index 9cd48dbe0d..2b4194e991 100644 --- a/assets/components/openshift-dns/dns/configmap.yaml +++ b/assets/components/openshift-dns/dns/configmap.yaml @@ -22,6 +22,13 @@ data: cache 900 { denial 9984 30 } + + {{- if .HostsEnabled }} + hosts /tmp/hosts/hosts { + fallthrough + } + {{- end }} + reload } hostname.bind:5353 { diff --git a/assets/components/openshift-dns/dns/daemonset.yaml b/assets/components/openshift-dns/dns/daemonset.yaml index 630fa3f931..590fc3daad 100644 --- a/assets/components/openshift-dns/dns/daemonset.yaml +++ b/assets/components/openshift-dns/dns/daemonset.yaml @@ -24,6 +24,11 @@ spec: readOnly: true - mountPath: /tmp name: tmp-dir + {{- if .HostsEnabled }} + - mountPath: /tmp/hosts + name: hosts + readOnly: true + {{- end }} ports: - containerPort: 5353 name: dns @@ -95,6 +100,14 @@ spec: secret: defaultMode: 420 secretName: dns-default-metrics-tls + {{- if .HostsEnabled }} + - name: hosts + configMap: + name: hosts-file + items: + - key: hosts + path: hosts + {{- end }} - name: tmp-dir emptyDir: {} nodeSelector: diff --git a/assets/components/openshift-dns/dns/hosts-configmap-role.yaml b/assets/components/openshift-dns/dns/hosts-configmap-role.yaml new file mode 100644 index 0000000000..e23d64663a --- /dev/null +++ b/assets/components/openshift-dns/dns/hosts-configmap-role.yaml @@ -0,0 +1,16 @@ +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: hosts-configmap-reader + namespace: openshift-dns +rules: +- apiGroups: + - "" + resources: + - configmaps + resourceNames: + - hosts-file + verbs: + - get + - list + - watch diff --git a/assets/components/openshift-dns/dns/hosts-configmap-rolebinding.yaml b/assets/components/openshift-dns/dns/hosts-configmap-rolebinding.yaml new file mode 100644 index 0000000000..e5acd3916e --- /dev/null +++ b/assets/components/openshift-dns/dns/hosts-configmap-rolebinding.yaml @@ -0,0 +1,13 @@ +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: hosts-configmap-reader + namespace: openshift-dns +subjects: +- kind: ServiceAccount + name: dns + namespace: openshift-dns +roleRef: + kind: Role + name: hosts-configmap-reader + apiGroup: rbac.authorization.k8s.io diff --git a/assets/components/service-ca/deployment.yaml b/assets/components/service-ca/deployment.yaml index 21bf96457a..fc27a300fb 100644 --- a/assets/components/service-ca/deployment.yaml +++ b/assets/components/service-ca/deployment.yaml @@ -28,7 +28,6 @@ spec: - name: service-ca-controller image: '{{ .ReleaseImage.service_ca_operator }}' imagePullPolicy: IfNotPresent - terminationMessagePolicy: FallbackTo command: ["service-ca-operator", "controller"] ports: - containerPort: 8443 diff --git a/assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-restricted-v3.yaml b/assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-restricted-v3.yaml new file mode 100644 index 0000000000..ddb798dba0 --- /dev/null +++ b/assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-restricted-v3.yaml @@ -0,0 +1,18 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + annotations: + include.release.openshift.io/ibm-cloud-managed: "true" + include.release.openshift.io/self-managed-high-availability: "true" + include.release.openshift.io/single-node-developer: "true" + rbac.authorization.kubernetes.io/autoupdate: "true" + name: system:openshift:scc:restricted-v3 +rules: +- apiGroups: + - security.openshift.io + resourceNames: + - restricted-v3 + resources: + - securitycontextconstraints + verbs: + - use diff --git a/assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v3.yaml b/assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v3.yaml new file mode 100644 index 0000000000..579239cf1a --- /dev/null +++ b/assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v3.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + annotations: + include.release.openshift.io/ibm-cloud-managed: "true" + include.release.openshift.io/self-managed-high-availability: "true" + include.release.openshift.io/single-node-developer: "true" + name: system:openshift:scc:restricted-v3 +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:openshift:scc:restricted-v3 +subjects: +- apiGroup: rbac.authorization.k8s.io + kind: Group + name: system:authenticated diff --git a/assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-restricted-v3.yaml b/assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-restricted-v3.yaml new file mode 100644 index 0000000000..3685755954 --- /dev/null +++ b/assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-restricted-v3.yaml @@ -0,0 +1,61 @@ +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +allowedCapabilities: +- NET_BIND_SERVICE +apiVersion: security.openshift.io/v1 +defaultAddCapabilities: +fsGroup: + type: MustRunAs + ranges: + - min: 1000 + max: 65534 +groups: [] +kind: SecurityContextConstraints +metadata: + annotations: + include.release.openshift.io/ibm-cloud-managed: "true" + include.release.openshift.io/self-managed-high-availability: "true" + include.release.openshift.io/single-node-developer: "true" + kubernetes.io/description: restricted-v3 denies access to all host features and requires + pods to be run with user namespace (and may not be root within that user namespace), + and SELinux context that are allocated to the namespace. This is the most restrictive SCC. + On top of the legacy 'restricted' SCC, it also requires to drop ALL capabilities + and does not allow privilege escalation binaries. It will also default the seccomp + profile to runtime/default if unset, otherwise this seccomp profile is required. + On top of the legacy 'restricted-v2' SCC, it requires a pod runs in a user namespace. + Because of this, the pod to be any non-root UID within the user namespace (between 1000-65534), and + it will still be unprivileged outside of the user namespace. + name: restricted-v3 +priority: +readOnlyRootFilesystem: false +requiredDropCapabilities: +- ALL +runAsUser: + type: MustRunAsRange + uidRangeMin: 1000 + uidRangeMax: 65534 +seLinuxContext: + type: MustRunAs +seccompProfiles: +- runtime/default +supplementalGroups: + type: MustRunAs + ranges: + - min: 1000 + max: 65534 +users: [] +userNamespaceLevel: RequirePodLevel +volumes: +- configMap +- csi +- downwardAPI +- emptyDir +- ephemeral +- persistentVolumeClaim +- projected +- secret diff --git a/assets/crd/route.crd.yaml b/assets/crd/route.crd.yaml index cca8d723f5..b0c3b33e7d 100644 --- a/assets/crd/route.crd.yaml +++ b/assets/crd/route.crd.yaml @@ -540,10 +540,12 @@ spec: type: string termination: description: |- - termination indicates termination type. + termination indicates the TLS termination type. * edge - TLS termination is done by the router and http is used to communicate with the backend (default) + * passthrough - Traffic is sent straight to the destination without the router providing TLS termination + * reencrypt - TLS termination is done by the router and https is used to communicate with the backend Note: passthrough termination is incompatible with httpHeader actions diff --git a/assets/optional/ai-model-serving/kserve/certmanager/certificate.yaml b/assets/optional/ai-model-serving/kserve/certmanager/certificate.yaml new file mode 100644 index 0000000000..aa7b2c55c9 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/certmanager/certificate.yaml @@ -0,0 +1,24 @@ +# The following manifests contain a self-signed issuer CR and a certificate CR. +# More document can be found at https://docs.cert-manager.io +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer + namespace: kserve +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml + namespace: kserve +spec: + # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize + commonName: $(webhookServiceName).$(kserveNamespace).svc + dnsNames: + - $(webhookServiceName).$(kserveNamespace).svc + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: kserve-webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize diff --git a/assets/optional/ai-model-serving/kserve/certmanager/kustomization.yaml b/assets/optional/ai-model-serving/kserve/certmanager/kustomization.yaml new file mode 100644 index 0000000000..1a95b92a2e --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/certmanager/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- certificate.yaml + diff --git a/assets/optional/ai-model-serving/kserve/configmap/inferenceservice.yaml b/assets/optional/ai-model-serving/kserve/configmap/inferenceservice.yaml index 495e21dc4a..cfa5b092dc 100644 --- a/assets/optional/ai-model-serving/kserve/configmap/inferenceservice.yaml +++ b/assets/optional/ai-model-serving/kserve/configmap/inferenceservice.yaml @@ -42,24 +42,23 @@ data: } } # ====================================== ISVC CONFIGURATION ====================================== - # Example + # Example - setting custom annotation inferenceService: |- - { - "serviceAnnotationDisallowedList": [ - "my.custom.annotation/1" - ], - "serviceLabelDisallowedList": [ - "my.custom.label.1" - ] + { + "serviceAnnotationDisallowedList": [ + "my.custom.annotation/1" + ], + "serviceLabelDisallowedList": [ + "my.custom.label.1" + ] } - # Example of isvc configuration + # Example - setting custom annotation inferenceService: |- { # ServiceAnnotationDisallowedList is a list of annotations that are not allowed to be propagated to Knative # revisions, which prevents the reconciliation loop to be triggered if the annotations is # configured here are used. # Default values are: - # "autoscaling.knative.dev/initial-scale", # "autoscaling.knative.dev/min-scale", # "autoscaling.knative.dev/max-scale", # "internal.serving.kserve.io/storage-initializer-sourceuri", @@ -73,7 +72,68 @@ data: "serviceLabelDisallowedList": [ "my.custom.label.1" ] + } + # Example - setting custom resource + inferenceService: |- + { + "resource": { + "cpuLimit": "1", + "memoryLimit": "2Gi", + "cpuRequest": "1", + "memoryRequest": "2Gi" + } + } + # Example - setting custom resource + inferenceService: |- + { + # resource contains the default resource configuration for the inference service. + # you can override this configuration by specifying the resources in the inference service yaml. + # If you want to unbound the resource (limits and requests), you can set the value to null or "" + # or just remove the specific field from the config. + "resource": { + # cpuLimit is the limits.cpu to set for the inference service. + "cpuLimit": "1", + + # memoryLimit is the limits.memory to set for the inference service. + "memoryLimit": "2Gi", + + # cpuRequest is the requests.cpu to set for the inference service. + "cpuRequest": "1", + + # memoryRequest is the requests.memory to set for the inference service. + "memoryRequest": "2Gi" + } + } + # ====================================== MultiNode CONFIGURATION ====================================== + # Example + multiNode: |- + { + "customGPUResourceTypeList": [ + "custom.com/gpu" + ] + } + # Example of multinode configuration + multiNode: |- + { + # CustomGPUResourceTypeList is a list of custom GPU resource types intended to identify the GPU type of a resource, + # not to restrict the user from using a specific GPU type. + # The MultiNode runtime pod will dynamically add GPU resources based on the registered GPU types. + "customGPUResourceTypeList": [ + "custom.com/gpu" + ] } + # ====================================== OTelCollector CONFIGURATION ====================================== + # Example + opentelemetryCollector: |- + { + # scrapeInterval is the interval at which the OpenTelemetry Collector will scrape the metrics. + "scrapeInterval": "5s", + # metricScalerEndpoint is the endpoint from which the KEDA's ScaledObject will scrape the metrics. + "metricScalerEndpoint": "keda-otel-scaler.keda.svc:4318", + # metricReceiverEndpoint is the endpoint from which the OpenTelemetry Collector will scrape the metrics. + "metricReceiverEndpoint": "keda-otel-scaler.keda.svc:4317" + } + # ====================================== STORAGE INITIALIZER CONFIGURATION ====================================== # Example storageInitializer: |- @@ -117,7 +177,7 @@ data: # if pvc volume is provided in storageuri then the pvc volume is directly mounted to /mnt/models in the user container. # rather than symlink it to a shared volume. For more info see https://github.com/kserve/kserve/issues/2737 "enableDirectPvcVolumeMount": true, - + # enableModelcar enabled allows you to directly access an OCI container image by # using a source URL with an "oci://" schema. "enableModelcar": false, @@ -222,7 +282,9 @@ data: # ====================================== INGRESS CONFIGURATION ====================================== # Example ingress: |- - { + { + "enableGatewayApi": false, + "kserveIngressGateway": "kserve/kserve-ingress-gateway", "ingressGateway" : "knative-serving/knative-ingress-gateway", "localGateway" : "knative-serving/knative-local-gateway", "localGatewayService" : "knative-local-gateway.istio-system.svc.cluster.local", @@ -235,7 +297,17 @@ data: "disableIngressCreation": false } ingress: |- - { + { + # enableGatewayApi specifies whether to use Gateway API instead of Ingress to serve external traffic. + "enableGatewayApi": false, + + # KServe implements [Gateway API](https://gateway-api.sigs.k8s.io/) to serve external traffic. + # By default, KServe configures a default gateway to serve external traffic. + # But, KServe can be configured to use a custom gateway by modifying this configuration. + # The gateway should be specified in format / + # NOTE: This configuration only applicable for raw deployment. + "kserveIngressGateway": "kserve/kserve-ingress-gateway", + # ingressGateway specifies the ingress gateway to serve external traffic. # The gateway should be specified in format / # NOTE: This configuration only applicable for serverless deployment with Istio configured as network layer. @@ -414,7 +486,9 @@ data: "cpuLimit": "1", "headers": { "propagate": [] - } + }, + "imagePullPolicy": "IfNotPresent", + "imagePullSecrets": ["docker-secret"] } # router is the implementation of inference graph. router: |- @@ -444,6 +518,13 @@ data: "*Trace-Id*" ] } + + # imagePullPolicy specifies when the router image should be pulled from registry. + "imagePullPolicy": "IfNotPresent", + + # # imagePullSecrets specifies the list of secrets to be used for pulling the router image from registry. + # https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + "imagePullSecrets": ["docker-secret"] } # ====================================== DEPLOYMENT CONFIGURATION ====================================== @@ -462,7 +543,7 @@ data: # ModelMesh https://kserve.github.io/website/master/admin/modelmesh/ "defaultDeploymentMode": "Serverless" } - + # ====================================== SERVICE CONFIGURATION ====================================== # Example service: |- @@ -507,7 +588,14 @@ data: # defaultJobImage specifies the default image used for the download job. "defaultJobImage" : "kserve/storage-initializer:latest", # Kubernetes modifies the filesystem group ID on the attached volume. - "FSGroup": 1000 + "fsGroup": 1000, + # TTL for the download job after it is finished. + "jobTTLSecondsAfterFinished": 3600, + # The frequency at which the local model agent reconciles the local models + # This is to detect if models are missing from local disk + "reconcilationFrequencyInSecs": 60, + # This is to disable localmodel pv and pvc management for namespaces without isvcs + "disableVolumeManagement": false } explainers: |- @@ -528,9 +616,10 @@ data: "caBundleConfigMapName": "", "caBundleVolumeMountPath": "/etc/ssl/custom-certs", "enableDirectPvcVolumeMount": true, - "enableModelcar": false, + "enableModelcar": true, "cpuModelcar": "10m", - "memoryModelcar": "15Mi" + "memoryModelcar": "15Mi", + "uidModelcar": 1010 } credentials: |- @@ -555,7 +644,9 @@ data: } ingress: |- - { + { + "enableGatewayApi": false, + "kserveIngressGateway": "kserve/kserve-ingress-gateway", "ingressGateway" : "knative-serving/knative-ingress-gateway", "localGateway" : "knative-serving/knative-local-gateway", "localGatewayService" : "knative-local-gateway.istio-system.svc.cluster.local", @@ -603,7 +694,8 @@ data: "memoryRequest": "100Mi", "memoryLimit": "1Gi", "cpuRequest": "100m", - "cpuLimit": "1" + "cpuLimit": "1", + "imagePullPolicy": "IfNotPresent" } deploy: |- @@ -622,9 +714,9 @@ data: "enabled": false, "jobNamespace": "kserve-localmodel-jobs", "defaultJobImage" : "kserve/storage-initializer:latest", - "FSGroup": 1000 + "fsGroup": 1000 } - + security: |- { "autoMountServiceAccountToken": true @@ -633,4 +725,21 @@ data: service: |- { "serviceClusterIPNone": true - } \ No newline at end of file + } + + inferenceService: |- + { + "resource": { + "cpuLimit": "1", + "memoryLimit": "2Gi", + "cpuRequest": "1", + "memoryRequest": "2Gi" + } + } + + opentelemetryCollector: |- + { + "scrapeInterval": "5s", + "metricReceiverEndpoint": "keda-otel-scaler.keda.svc:4317", + "metricScalerEndpoint": "keda-otel-scaler.keda.svc:4318" + } diff --git a/assets/optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/gateway-inference-extension.yaml b/assets/optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/gateway-inference-extension.yaml new file mode 100644 index 0000000000..0fbcd4c4cd --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/gateway-inference-extension.yaml @@ -0,0 +1,540 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: inferencemodels.inference.networking.x-k8s.io +spec: + group: inference.networking.x-k8s.io + names: + kind: InferenceModel + listKind: InferenceModelList + plural: inferencemodels + singular: inferencemodel + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.modelName + name: Model Name + type: string + - jsonPath: .spec.poolRef.name + name: Inference Pool + type: string + - jsonPath: .spec.criticality + name: Criticality + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha2 + schema: + openAPIV3Schema: + description: InferenceModel is the Schema for the InferenceModels API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + InferenceModelSpec represents the desired state of a specific model use case. This resource is + managed by the "Inference Workload Owner" persona. + + The Inference Workload Owner persona is someone that trains, verifies, and + leverages a large language model from a model frontend, drives the lifecycle + and rollout of new versions of those models, and defines the specific + performance and latency goals for the model. These workloads are + expected to operate within an InferencePool sharing compute capacity with other + InferenceModels, defined by the Inference Platform Admin. + + InferenceModel's modelName (not the ObjectMeta name) is unique for a given InferencePool, + if the name is reused, an error will be shown on the status of a + InferenceModel that attempted to reuse. The oldest InferenceModel, based on + creation timestamp, will be selected to remain valid. In the event of a race + condition, one will be selected at random. + properties: + criticality: + description: |- + Criticality defines how important it is to serve the model compared to other models referencing the same pool. + Criticality impacts how traffic is handled in resource constrained situations. It handles this by + queuing or rejecting requests of lower criticality. InferenceModels of an equivalent Criticality will + fairly share resources over throughput of tokens. In the future, the metric used to calculate fairness, + and the proportionality of fairness will be configurable. + + Default values for this field will not be set, to allow for future additions of new field that may 'one of' with this field. + Any implementations that may consume this field may treat an unset value as the 'Standard' range. + enum: + - Critical + - Standard + - Sheddable + type: string + modelName: + description: |- + ModelName is the name of the model as it will be set in the "model" parameter for an incoming request. + ModelNames must be unique for a referencing InferencePool + (names can be reused for a different pool in the same cluster). + The modelName with the oldest creation timestamp is retained, and the incoming + InferenceModel's Ready status is set to false with a corresponding reason. + In the rare case of a race condition, one Model will be selected randomly to be considered valid, and the other rejected. + Names can be reserved without an underlying model configured in the pool. + This can be done by specifying a target model and setting the weight to zero, + an error will be returned specifying that no valid target model is found. + maxLength: 256 + type: string + x-kubernetes-validations: + - message: modelName is immutable + rule: self == oldSelf + poolRef: + description: PoolRef is a reference to the inference pool, the pool + must exist in the same namespace. + properties: + group: + default: inference.networking.x-k8s.io + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: InferencePool + description: Kind is kind of the referent. For example "InferencePool". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + required: + - name + type: object + targetModels: + description: |- + TargetModels allow multiple versions of a model for traffic splitting. + If not specified, the target model name is defaulted to the modelName parameter. + modelName is often in reference to a LoRA adapter. + items: + description: |- + TargetModel represents a deployed model or a LoRA adapter. The + Name field is expected to match the name of the LoRA adapter + (or base model) as it is registered within the model server. Inference + Gateway assumes that the model exists on the model server and it's the + responsibility of the user to validate a correct match. Should a model fail + to exist at request time, the error is processed by the Inference Gateway + and emitted on the appropriate InferenceModel object. + properties: + name: + description: Name is the name of the adapter or base model, + as expected by the ModelServer. + maxLength: 253 + type: string + weight: + description: |- + Weight is used to determine the proportion of traffic that should be + sent to this model when multiple target models are specified. + + Weight defines the proportion of requests forwarded to the specified + model. This is computed as weight/(sum of all weights in this + TargetModels list). For non-zero values, there may be some epsilon from + the exact proportion defined here depending on the precision an + implementation supports. Weight is not a percentage and the sum of + weights does not need to equal 100. + + If a weight is set for any targetModel, it must be set for all targetModels. + Conversely weights are optional, so long as ALL targetModels do not specify a weight. + format: int32 + maximum: 1000000 + minimum: 1 + type: integer + required: + - name + type: object + maxItems: 10 + type: array + x-kubernetes-validations: + - message: Weights should be set for all models, or none of the models. + rule: self.all(model, has(model.weight)) || self.all(model, !has(model.weight)) + required: + - modelName + - poolRef + type: object + status: + description: InferenceModelStatus defines the observed state of InferenceModel + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Ready + description: |- + Conditions track the state of the InferenceModel. + + Known condition types are: + + * "Accepted" + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: inferencepools.inference.networking.x-k8s.io +spec: + group: inference.networking.x-k8s.io + names: + kind: InferencePool + listKind: InferencePoolList + plural: inferencepools + singular: inferencepool + scope: Namespaced + versions: + - name: v1alpha2 + schema: + openAPIV3Schema: + description: InferencePool is the Schema for the InferencePools API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: InferencePoolSpec defines the desired state of InferencePool + properties: + extensionRef: + description: Extension configures an endpoint picker as an extension + service. + properties: + failureMode: + default: FailClose + description: |- + Configures how the gateway handles the case when the extension is not responsive. + Defaults to failClose. + enum: + - FailOpen + - FailClose + type: string + group: + default: "" + description: |- + Group is the group of the referent. + The default value is "", representing the Core API group. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + description: |- + Kind is the Kubernetes resource kind of the referent. For example + "Service". + + Defaults to "Service" when not specified. + + ExternalName services can refer to CNAME DNS records that may live + outside of the cluster and as such are difficult to reason about in + terms of conformance. They also may not be safe to forward to (see + CVE-2021-25740 for more information). Implementations MUST NOT + support ExternalName Services. + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + portNumber: + description: |- + The port number on the service running the extension. When unspecified, + implementations SHOULD infer a default value of 9002 when the Kind is + Service. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + selector: + additionalProperties: + description: |- + LabelValue is the value of a label. This is used for validation + of maps. This matches the Kubernetes label validation rules: + * must be 63 characters or less (can be empty), + * unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]), + * could contain dashes (-), underscores (_), dots (.), and alphanumerics between. + + Valid values include: + + * MyValue + * my.name + * 123-my-value + maxLength: 63 + minLength: 0 + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + description: |- + Selector defines a map of labels to watch model server pods + that should be included in the InferencePool. + In some cases, implementations may translate this field to a Service selector, so this matches the simple + map used for Service selectors instead of the full Kubernetes LabelSelector type. + If sepecified, it will be applied to match the model server pods in the same namespace as the InferencePool. + Cross namesoace selector is not supported. + type: object + targetPortNumber: + description: |- + TargetPortNumber defines the port number to access the selected model servers. + The number must be in the range 1 to 65535. + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - extensionRef + - selector + - targetPortNumber + type: object + status: + default: + parent: + - conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + parentRef: + kind: Status + name: default + description: Status defines the observed state of InferencePool. + properties: + parent: + description: |- + Parents is a list of parent resources (usually Gateways) that are + associated with the InferencePool, and the status of the InferencePool with respect to + each parent. + + A maximum of 32 Gateways will be represented in this list. When the list contains + `kind: Status, name: default`, it indicates that the InferencePool is not + associated with any Gateway and a controller must perform the following: + + - Remove the parent when setting the "Accepted" condition. + - Add the parent when the controller will no longer manage the InferencePool + and no other parents exist. + items: + description: PoolStatus defines the observed state of InferencePool + from a Gateway. + properties: + conditions: + default: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Accepted + description: |- + Conditions track the state of the InferencePool. + + Known condition types are: + + * "Accepted" + * "ResolvedRefs" + items: + description: Condition contains details for one aspect of + the current state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, + Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + parentRef: + description: GatewayRef indicates the gateway that observed + state of InferencePool. + properties: + group: + default: gateway.networking.k8s.io + description: Group is the group of the referent. + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + description: Kind is kind of the referent. For example "Gateway". + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + description: Name is the name of the referent. + maxLength: 253 + minLength: 1 + type: string + namespace: + description: |- + Namespace is the namespace of the referent. If not present, + the namespace of the referent is assumed to be the same as + the namespace of the referring object. + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + required: + - name + type: object + required: + - parentRef + type: object + maxItems: 32 + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/assets/optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/kustomization.yaml b/assets/optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/kustomization.yaml new file mode 100644 index 0000000000..47ac561c56 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - gateway-inference-extension.yaml diff --git a/assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/datasciencecluster.opendatahub.io_datascienceclusters.yaml b/assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/datasciencecluster.opendatahub.io_datascienceclusters.yaml new file mode 100644 index 0000000000..41d1c76d65 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/datasciencecluster.opendatahub.io_datascienceclusters.yaml @@ -0,0 +1,763 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: datascienceclusters.datasciencecluster.opendatahub.io +spec: + group: datasciencecluster.opendatahub.io + names: + kind: DataScienceCluster + listKind: DataScienceClusterList + plural: datascienceclusters + shortNames: + - dsc + singular: datasciencecluster + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: DataScienceCluster is the Schema for the datascienceclusters + API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: DataScienceClusterSpec defines the desired state of the cluster. + properties: + components: + description: Override and fine tune specific component configurations. + properties: + codeflare: + description: |- + CodeFlare component configuration. + If CodeFlare Operator has been installed in the cluster, it should be uninstalled first before enabled component. + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + dashboard: + description: Dashboard component configuration. + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + datasciencepipelines: + description: |- + DataServicePipeline component configuration. + Require OpenShift Pipelines Operator to be installed before enable component + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + kserve: + description: |- + Kserve component configuration. + Require OpenShift Serverless and OpenShift Service Mesh Operators to be installed before enable component + Does not support enabled ModelMeshServing at the same time + properties: + defaultDeploymentMode: + description: |- + Configures the default deployment mode for Kserve. This can be set to 'Serverless' or 'RawDeployment'. + The value specified in this field will be used to set the default deployment mode in the 'inferenceservice-config' configmap for Kserve. + This field is optional. If no default deployment mode is specified, Kserve will use Serverless mode. + enum: + - Serverless + - RawDeployment + pattern: ^(Serverless|RawDeployment)$ + type: string + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + serving: + description: |- + Serving configures the KNative-Serving stack used for model serving. A Service + Mesh (Istio) is prerequisite, since it is used as networking layer. + properties: + ingressGateway: + description: |- + IngressGateway allows to customize some parameters for the Istio Ingress Gateway + that is bound to KNative-Serving. + properties: + certificate: + description: |- + Certificate specifies configuration of the TLS certificate securing communication + for the gateway. + properties: + secretName: + description: |- + SecretName specifies the name of the Kubernetes Secret resource that contains a + TLS certificate secure HTTP communications for the KNative network. + type: string + type: + default: OpenshiftDefaultIngress + description: |- + Type specifies if the TLS certificate should be generated automatically, or if the certificate + is provided by the user. Allowed values are: + * SelfSigned: A certificate is going to be generated using an own private key. + * Provided: Pre-existence of the TLS Secret (see SecretName) with a valid certificate is assumed. + * OpenshiftDefaultIngress: Default ingress certificate configured for OpenShift + enum: + - SelfSigned + - Provided + - OpenshiftDefaultIngress + type: string + type: object + domain: + description: |- + Domain specifies the host name for intercepting incoming requests. + Most likely, you will want to use a wildcard name, like *.example.com. + If not set, the domain of the OpenShift Ingress is used. + If you choose to generate a certificate, this is the domain used for the certificate request. + type: string + type: object + managementState: + default: Managed + enum: + - Managed + - Unmanaged + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + name: + default: knative-serving + description: |- + Name specifies the name of the KNativeServing resource that is going to be + created to instruct the KNative Operator to deploy KNative serving components. + This resource is created in the "knative-serving" namespace. + type: string + type: object + type: object + kueue: + description: Kueue component configuration. + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + modelmeshserving: + description: |- + ModelMeshServing component configuration. + Does not support enabled Kserve at the same time + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + modelregistry: + description: ModelRegistry component configuration. + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + registriesNamespace: + default: odh-model-registries + description: Namespace for model registries to be installed, + configurable only once when model registry is enabled, defaults + to "odh-model-registries" + maxLength: 63 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$ + type: string + type: object + x-kubernetes-validations: + - message: RegistriesNamespace is immutable when model registry + is Managed + rule: (self.managementState != 'Managed') || (oldSelf.registriesNamespace + == '') || (oldSelf.managementState != 'Managed')|| (self.registriesNamespace + == oldSelf.registriesNamespace) + ray: + description: Ray component configuration. + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + trainingoperator: + description: Training Operator component configuration. + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + trustyai: + description: TrustyAI component configuration. + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + workbenches: + description: Workbenches component configuration. + properties: + devFlags: + description: Add developer fields + properties: + manifests: + description: List of custom manifests for the given component + items: + properties: + contextDir: + default: manifests + description: contextDir is the relative path to + the folder containing manifests in a repository, + default value "manifests" + type: string + sourcePath: + default: "" + description: 'sourcePath is the subpath within contextDir + where kustomize builds start. Examples include + any sub-folder or path: `base`, `overlays/dev`, + `default`, `odh` etc.' + type: string + uri: + default: "" + description: uri is the URI point to a git repo + with tag/branch. e.g. https://github.com/org/repo/tarball/ + type: string + type: object + type: array + type: object + managementState: + description: |- + Set to one of the following values: + + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so + + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + type: object + type: object + status: + description: DataScienceClusterStatus defines the observed state of DataScienceCluster. + properties: + components: + description: Expose component's specific status + properties: + modelregistry: + description: ModelRegistry component status + properties: + registriesNamespace: + type: string + type: object + type: object + conditions: + description: Conditions describes the state of the DataScienceCluster + resource. + items: + description: |- + Condition represents the state of the operator's + reconciliation functionality. + properties: + lastHeartbeatTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + description: ConditionType is the state of the operator's reconciliation + functionality. + type: string + required: + - status + - type + type: object + type: array + errorMessage: + type: string + installedComponents: + additionalProperties: + type: boolean + description: List of components with status if installed or not + type: object + phase: + description: |- + Phase describes the Phase of DataScienceCluster reconciliation state + This is used by OLM UI to provide status information to the user + type: string + relatedObjects: + description: |- + RelatedObjects is a list of objects created and maintained by this operator. + Object references will be added to this list after they have been created AND found in the cluster. + items: + description: ObjectReference contains enough information to let + you inspect or modify the referred object. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: array + release: + description: Version and release type + properties: + name: + type: string + version: + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/dscinitialization.opendatahub.io_dscinitializations.yaml b/assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/dscinitialization.opendatahub.io_dscinitializations.yaml new file mode 100644 index 0000000000..894772ea9a --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/dscinitialization.opendatahub.io_dscinitializations.yaml @@ -0,0 +1,311 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.1 + name: dscinitializations.dscinitialization.opendatahub.io +spec: + group: dscinitialization.opendatahub.io + names: + kind: DSCInitialization + listKind: DSCInitializationList + plural: dscinitializations + shortNames: + - dsci + singular: dscinitialization + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: Current Phase + jsonPath: .status.phase + name: Phase + type: string + - jsonPath: .metadata.creationTimestamp + name: Created At + type: string + name: v1 + schema: + openAPIV3Schema: + description: DSCInitialization is the Schema for the dscinitializations API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: DSCInitializationSpec defines the desired state of DSCInitialization. + properties: + applicationsNamespace: + default: opendatahub + description: Namespace for applications to be installed, non-configurable, + default to "opendatahub" + maxLength: 63 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$ + type: string + x-kubernetes-validations: + - message: ApplicationsNamespace is immutable + rule: self == oldSelf + devFlags: + description: |- + Internal development useful field to test customizations. + This is not recommended to be used in production environment. + properties: + logLevel: + description: Override Zap log level. Can be "debug", "info", "error" + or a number (more verbose). + type: string + logmode: + default: production + description: '## DEPRECATED ##: Ignored, use LogLevel instead' + enum: + - devel + - development + - prod + - production + - default + type: string + manifestsUri: + description: Custom manifests uri for odh-manifests + type: string + type: object + monitoring: + description: Enable monitoring on specified namespace + properties: + managementState: + description: |- + Set to one of the following values: + - "Managed" : the operator is actively managing the component and trying to keep it active. + It will only upgrade the component if it is safe to do so. + - "Removed" : the operator is actively managing the component and will not install it, + or if it is installed, the operator will try to remove it. + enum: + - Managed + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + namespace: + default: opendatahub + description: Namespace for monitoring if it is enabled + maxLength: 63 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$ + type: string + type: object + serviceMesh: + description: |- + Configures Service Mesh as networking layer for Data Science Clusters components. + The Service Mesh is a mandatory prerequisite for single model serving (KServe) and + you should review this configuration if you are planning to use KServe. + For other components, it enhances user experience; e.g. it provides unified + authentication giving a Single Sign On experience. + properties: + auth: + description: |- + Auth holds configuration of authentication and authorization services + used by Service Mesh in Opendatahub. + properties: + audiences: + default: + - https://kubernetes.default.svc + description: |- + Audiences is a list of the identifiers that the resource server presented + with the token identifies as. Audience-aware token authenticators will verify + that the token was intended for at least one of the audiences in this list. + If no audiences are provided, the audience will default to the audience of the + Kubernetes apiserver (kubernetes.default.svc). + items: + type: string + type: array + namespace: + description: |- + Namespace where it is deployed. If not provided, the default is to + use '-auth-provider' suffix on the ApplicationsNamespace of the DSCI. + maxLength: 63 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$ + type: string + type: object + controlPlane: + description: ControlPlane holds configuration of Service Mesh + used by Opendatahub. + properties: + metricsCollection: + default: Istio + description: |- + MetricsCollection specifies if metrics from components on the Mesh namespace + should be collected. Setting the value to "Istio" will collect metrics from the + control plane and any proxies on the Mesh namespace (like gateway pods). Setting + to "None" will disable metrics collection. + enum: + - Istio + - None + type: string + name: + default: data-science-smcp + description: Name is a name Service Mesh Control Plane. Defaults + to "data-science-smcp". + type: string + namespace: + default: istio-system + description: Namespace is a namespace where Service Mesh is + deployed. Defaults to "istio-system". + maxLength: 63 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?)?$ + type: string + type: object + managementState: + default: Removed + enum: + - Managed + - Unmanaged + - Removed + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + type: object + trustedCABundle: + description: |- + When set to `Managed`, adds odh-trusted-ca-bundle Configmap to all namespaces that includes + cluster-wide Trusted CA Bundle in .data["ca-bundle.crt"]. + Additionally, this fields allows admins to add custom CA bundles to the configmap using the .CustomCABundle field. + properties: + customCABundle: + default: "" + description: |- + A custom CA bundle that will be available for all components in the + Data Science Cluster(DSC). This bundle will be stored in odh-trusted-ca-bundle + ConfigMap .data.odh-ca-bundle.crt . + type: string + managementState: + default: Removed + description: managementState indicates whether and how the operator + should manage customized CA bundle + enum: + - Managed + - Removed + - Unmanaged + pattern: ^(Managed|Unmanaged|Force|Removed)$ + type: string + required: + - customCABundle + - managementState + type: object + required: + - applicationsNamespace + type: object + status: + description: DSCInitializationStatus defines the observed state of DSCInitialization. + properties: + conditions: + description: Conditions describes the state of the DSCInitializationStatus + resource + items: + description: |- + Condition represents the state of the operator's + reconciliation functionality. + properties: + lastHeartbeatTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + description: ConditionType is the state of the operator's reconciliation + functionality. + type: string + required: + - status + - type + type: object + type: array + errorMessage: + type: string + phase: + description: |- + Phase describes the Phase of DSCInitializationStatus + This is used by OLM UI to provide status information to the user + type: string + relatedObjects: + description: |- + RelatedObjects is a list of objects created and maintained by this operator. + Object references will be added to this list after they have been created AND found in the cluster + items: + description: ObjectReference contains enough information to let + you inspect or modify the referred object. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: array + release: + description: Version and release type + properties: + name: + type: string + version: + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/kustomization.yaml b/assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/kustomization.yaml new file mode 100644 index 0000000000..1742a6c251 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - dscinitialization.opendatahub.io_dscinitializations.yaml + - datasciencecluster.opendatahub.io_datascienceclusters.yaml diff --git a/assets/optional/ai-model-serving/kserve/crd/full/kustomization.yaml b/assets/optional/ai-model-serving/kserve/crd/full/kustomization.yaml new file mode 100644 index 0000000000..a48d970d0b --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/crd/full/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - serving.kserve.io_inferenceservices.yaml + - serving.kserve.io_trainedmodels.yaml + - serving.kserve.io_clusterservingruntimes.yaml + - serving.kserve.io_servingruntimes.yaml + - serving.kserve.io_inferencegraphs.yaml + - serving.kserve.io_clusterstoragecontainers.yaml + - serving.kserve.io_localmodelcaches.yaml + - serving.kserve.io_localmodelnodegroups.yaml + - serving.kserve.io_localmodelnodes.yaml + - serving.kserve.io_llminferenceserviceconfigs.yaml + - serving.kserve.io_llminferenceservices.yaml diff --git a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterservingruntimes.yaml b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterservingruntimes.yaml index 556950f31b..70e2860cc4 100644 --- a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterservingruntimes.yaml +++ b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterservingruntimes.yaml @@ -793,6 +793,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -2772,6 +2774,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: diff --git a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterstoragecontainers.yaml b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterstoragecontainers.yaml index e48c266037..8f799c5cdc 100644 --- a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterstoragecontainers.yaml +++ b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterstoragecontainers.yaml @@ -261,6 +261,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: diff --git a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferencegraphs.yaml b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferencegraphs.yaml index 30d0ecf981..a8d0690fe2 100644 --- a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferencegraphs.yaml +++ b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferencegraphs.yaml @@ -478,9 +478,17 @@ spec: type: object type: object maxReplicas: + format: int32 type: integer minReplicas: + format: int32 type: integer + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object nodes: additionalProperties: properties: @@ -561,10 +569,29 @@ spec: - rps type: string scaleTarget: + format: int32 type: integer + serviceAccountName: + type: string timeout: format: int64 type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array required: - nodes type: object diff --git a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferenceservices.yaml b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferenceservices.yaml index 8d8ec79557..fd438f9b65 100644 --- a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferenceservices.yaml +++ b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferenceservices.yaml @@ -735,6 +735,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -1189,6 +1191,162 @@ spec: workingDir: type: string type: object + autoScaling: + properties: + metrics: + items: + properties: + external: + properties: + authenticationRef: + properties: + authModes: + type: string + authenticationRef: + properties: + name: + type: string + required: + - name + type: object + required: + - authenticationRef + type: object + metric: + properties: + backend: + enum: + - prometheus + - graphite + type: string + namespace: + type: string + query: + type: string + serverAddress: + type: string + type: object + target: + properties: + averageUtilization: + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Utilization + - Value + - AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - metric + - target + type: object + podmetric: + properties: + metric: + properties: + backend: + enum: + - opentelemetry + type: string + metricNames: + items: + type: string + type: array + operationOverTime: + type: string + query: + type: string + serverAddress: + type: string + type: object + target: + properties: + averageUtilization: + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Utilization + - Value + - AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - metric + - target + type: object + resource: + properties: + name: + enum: + - cpu + - memory + type: string + target: + properties: + averageUtilization: + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Utilization + - Value + - AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - name + - target + type: object + type: + enum: + - Resource + - External + - PodMetric + type: string + required: + - type + type: object + type: array + type: object automountServiceAccountToken: type: boolean batcher: @@ -1440,6 +1598,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -2194,6 +2354,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -2646,6 +2808,10 @@ spec: type: object logger: properties: + metadataAnnotations: + items: + type: string + type: array metadataHeaders: items: type: string @@ -2660,8 +2826,10 @@ spec: type: string type: object maxReplicas: + format: int32 type: integer minReplicas: + format: int32 type: integer nodeName: type: string @@ -2715,6 +2883,39 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object restartPolicy: type: string runtimeClassName: @@ -2726,7 +2927,14 @@ spec: - concurrency - rps type: string + scaleMetricType: + enum: + - Utilization + - Value + - AverageValue + type: string scaleTarget: + format: int32 type: integer schedulerName: type: string @@ -2766,6 +2974,8 @@ spec: runAsUser: format: int64 type: integer + seLinuxChangePolicy: + type: string seLinuxOptions: properties: level: @@ -4139,6 +4349,162 @@ spec: additionalProperties: type: string type: object + autoScaling: + properties: + metrics: + items: + properties: + external: + properties: + authenticationRef: + properties: + authModes: + type: string + authenticationRef: + properties: + name: + type: string + required: + - name + type: object + required: + - authenticationRef + type: object + metric: + properties: + backend: + enum: + - prometheus + - graphite + type: string + namespace: + type: string + query: + type: string + serverAddress: + type: string + type: object + target: + properties: + averageUtilization: + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Utilization + - Value + - AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - metric + - target + type: object + podmetric: + properties: + metric: + properties: + backend: + enum: + - opentelemetry + type: string + metricNames: + items: + type: string + type: array + operationOverTime: + type: string + query: + type: string + serverAddress: + type: string + type: object + target: + properties: + averageUtilization: + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Utilization + - Value + - AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - metric + - target + type: object + resource: + properties: + name: + enum: + - cpu + - memory + type: string + target: + properties: + averageUtilization: + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Utilization + - Value + - AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - name + - target + type: object + type: + enum: + - Resource + - External + - PodMetric + type: string + required: + - type + type: object + type: array + type: object automountServiceAccountToken: type: boolean batcher: @@ -4390,6 +4756,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -5134,6 +5502,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -5831,6 +6201,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -6514,6 +6886,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -6970,6 +7344,10 @@ spec: type: object logger: properties: + metadataAnnotations: + items: + type: string + type: array metadataHeaders: items: type: string @@ -6984,8 +7362,10 @@ spec: type: string type: object maxReplicas: + format: int32 type: integer minReplicas: + format: int32 type: integer model: properties: @@ -7220,6 +7600,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -7925,6 +8307,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -8625,6 +9009,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -9312,6 +9698,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -10006,6 +10394,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -10485,6 +10875,39 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object restartPolicy: type: string runtimeClassName: @@ -10496,7 +10919,14 @@ spec: - concurrency - rps type: string + scaleMetricType: + enum: + - Utilization + - Value + - AverageValue + type: string scaleTarget: + format: int32 type: integer schedulerName: type: string @@ -10536,6 +10966,8 @@ spec: runAsUser: format: int64 type: integer + seLinuxChangePolicy: + type: string seLinuxOptions: properties: level: @@ -10830,6 +11262,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -11519,6 +11953,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -12286,6 +12722,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -14201,6 +14639,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -14908,6 +15348,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -15623,6 +16065,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -16125,6 +16569,39 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object restartPolicy: type: string runtimeClassName: @@ -16167,6 +16644,8 @@ spec: runAsUser: format: int64 type: integer + seLinuxChangePolicy: + type: string seLinuxOptions: properties: level: @@ -17324,6 +17803,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -18227,6 +18708,162 @@ spec: additionalProperties: type: string type: object + autoScaling: + properties: + metrics: + items: + properties: + external: + properties: + authenticationRef: + properties: + authModes: + type: string + authenticationRef: + properties: + name: + type: string + required: + - name + type: object + required: + - authenticationRef + type: object + metric: + properties: + backend: + enum: + - prometheus + - graphite + type: string + namespace: + type: string + query: + type: string + serverAddress: + type: string + type: object + target: + properties: + averageUtilization: + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Utilization + - Value + - AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - metric + - target + type: object + podmetric: + properties: + metric: + properties: + backend: + enum: + - opentelemetry + type: string + metricNames: + items: + type: string + type: array + operationOverTime: + type: string + query: + type: string + serverAddress: + type: string + type: object + target: + properties: + averageUtilization: + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Utilization + - Value + - AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - metric + - target + type: object + resource: + properties: + name: + enum: + - cpu + - memory + type: string + target: + properties: + averageUtilization: + format: int32 + type: integer + averageValue: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: + enum: + - Utilization + - Value + - AverageValue + type: string + value: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + required: + - name + - target + type: object + type: + enum: + - Resource + - External + - PodMetric + type: string + required: + - type + type: object + type: array + type: object automountServiceAccountToken: type: boolean batcher: @@ -18478,6 +19115,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -19232,6 +19871,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -19684,6 +20325,10 @@ spec: type: object logger: properties: + metadataAnnotations: + items: + type: string + type: array metadataHeaders: items: type: string @@ -19698,8 +20343,10 @@ spec: type: string type: object maxReplicas: + format: int32 type: integer minReplicas: + format: int32 type: integer nodeName: type: string @@ -19753,6 +20400,39 @@ spec: x-kubernetes-list-map-keys: - name x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object restartPolicy: type: string runtimeClassName: @@ -19764,7 +20444,14 @@ spec: - concurrency - rps type: string + scaleMetricType: + enum: + - Utilization + - Value + - AverageValue + type: string scaleTarget: + format: int32 type: integer schedulerName: type: string @@ -19804,6 +20491,8 @@ spec: runAsUser: format: int64 type: integer + seLinuxChangePolicy: + type: string seLinuxOptions: properties: level: diff --git a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_llminferenceserviceconfigs.yaml b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_llminferenceserviceconfigs.yaml new file mode 100644 index 0000000000..ca879e9ab6 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_llminferenceserviceconfigs.yaml @@ -0,0 +1,19270 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.2 + name: llminferenceserviceconfigs.serving.kserve.io +spec: + group: serving.kserve.io + names: + kind: LLMInferenceServiceConfig + listKind: LLMInferenceServiceConfigList + plural: llminferenceserviceconfigs + singular: llminferenceserviceconfig + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + baseRefs: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + model: + properties: + criticality: + enum: + - Critical + - Standard + - Sheddable + type: string + lora: + properties: + adapters: + x-kubernetes-preserve-unknown-fields: true + type: object + name: + type: string + uri: + type: string + required: + - uri + type: object + parallelism: + properties: + data: + format: int32 + minimum: 1 + type: integer + dataLocal: + format: int32 + minimum: 1 + type: integer + dataRPCPort: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + expert: + type: boolean + pipeline: + format: int32 + minimum: 1 + type: integer + tensor: + format: int32 + minimum: 1 + type: integer + type: object + prefill: + properties: + parallelism: + properties: + data: + format: int32 + minimum: 1 + type: integer + dataLocal: + format: int32 + minimum: 1 + type: integer + dataRPCPort: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + expert: + type: boolean + pipeline: + format: int32 + minimum: 1 + type: integer + tensor: + format: int32 + minimum: 1 + type: integer + type: object + replicas: + format: int32 + minimum: 0 + type: integer + template: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + worker: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: object + replicas: + format: int32 + minimum: 0 + type: integer + router: + properties: + gateway: + properties: + refs: + items: + properties: + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + type: object + type: array + type: object + ingress: + properties: + refs: + items: + properties: + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + type: object + type: array + type: object + route: + properties: + http: + properties: + refs: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + spec: + properties: + hostnames: + items: + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + items: + properties: + group: + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + items: + properties: + backendRefs: + items: + properties: + filters: + items: + properties: + extensionRef: + properties: + group: + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + properties: + add: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + properties: + backendRef: + properties: + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + fraction: + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal to denominator + rule: self.numerator <= self.denominator + percent: + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + properties: + hostname: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + properties: + replaceFullPath: + maxLength: 1024 + type: string + replacePrefixMatch: + maxLength: 1024 + type: string + type: + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + enum: + - http + - https + type: string + statusCode: + default: 302 + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + properties: + add: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + properties: + hostname: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + properties: + replaceFullPath: + maxLength: 1024 + type: string + replacePrefixMatch: + maxLength: 1024 + type: string + type: + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 16 + type: array + filters: + items: + properties: + extensionRef: + properties: + group: + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + properties: + add: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + properties: + backendRef: + properties: + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + fraction: + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal to denominator + rule: self.numerator <= self.denominator + percent: + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + properties: + hostname: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + properties: + replaceFullPath: + maxLength: 1024 + type: string + replacePrefixMatch: + maxLength: 1024 + type: string + type: + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + enum: + - http + - https + type: string + statusCode: + default: 302 + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + properties: + add: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + properties: + hostname: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + properties: + replaceFullPath: + maxLength: 1024 + type: string + replacePrefixMatch: + maxLength: 1024 + type: string + type: + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + matches: + default: + - path: + type: PathPrefix + value: / + items: + properties: + headers: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + enum: + - Exact + - RegularExpression + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + properties: + type: + default: PathPrefix + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + maxLength: 1024 + type: string + type: object + queryParams: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + enum: + - Exact + - RegularExpression + type: string + value: + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 64 + type: array + name: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + retry: + properties: + attempts: + type: integer + backoff: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + codes: + items: + maximum: 599 + minimum: 400 + type: integer + type: array + type: object + sessionPersistence: + properties: + absoluteTimeout: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + cookieConfig: + properties: + lifetimeType: + default: Session + enum: + - Permanent + - Session + type: string + type: object + idleTimeout: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + sessionName: + maxLength: 128 + type: string + type: + default: Cookie + enum: + - Cookie + - Header + type: string + type: object + x-kubernetes-validations: + - message: AbsoluteTimeout must be specified when cookie lifetimeType is Permanent + rule: '!has(self.cookieConfig) || !has(self.cookieConfig.lifetimeType) || self.cookieConfig.lifetimeType != ''Permanent'' || has(self.absoluteTimeout)' + timeouts: + properties: + backendRequest: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + request: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request timeout + rule: '!(has(self.request) && has(self.backendRequest) && duration(self.request) != duration(''0s'') && duration(self.backendRequest) > duration(self.request))' + type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less than 128 + rule: '(self.size() > 0 ? self[0].matches.size() : 0) + (self.size() > 1 ? self[1].matches.size() : 0) + (self.size() > 2 ? self[2].matches.size() : 0) + (self.size() > 3 ? self[3].matches.size() : 0) + (self.size() > 4 ? self[4].matches.size() : 0) + (self.size() > 5 ? self[5].matches.size() : 0) + (self.size() > 6 ? self[6].matches.size() : 0) + (self.size() > 7 ? self[7].matches.size() : 0) + (self.size() > 8 ? self[8].matches.size() : 0) + (self.size() > 9 ? self[9].matches.size() : 0) + (self.size() > 10 ? self[10].matches.size() : 0) + (self.size() > 11 ? self[11].matches.size() : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' + type: object + type: object + type: object + scheduler: + properties: + pool: + properties: + ref: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + spec: + properties: + extensionRef: + properties: + failureMode: + default: FailClose + enum: + - FailOpen + - FailClose + type: string + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + portNumber: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + selector: + additionalProperties: + maxLength: 63 + minLength: 0 + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: object + targetPortNumber: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - extensionRef + - selector + - targetPortNumber + type: object + type: object + template: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: object + type: object + template: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + worker: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: object + type: object + served: true + storage: true diff --git a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_llminferenceservices.yaml b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_llminferenceservices.yaml new file mode 100644 index 0000000000..c2e524232a --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_llminferenceservices.yaml @@ -0,0 +1,19380 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.2 + name: llminferenceservices.serving.kserve.io +spec: + group: serving.kserve.io + names: + kind: LLMInferenceService + listKind: LLMInferenceServiceList + plural: llminferenceservices + shortNames: + - llmisvc + singular: llminferenceservice + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.url + name: URL + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].reason + name: Reason + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.addresses[*].url + name: URLs + priority: 1 + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + baseRefs: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + model: + properties: + criticality: + enum: + - Critical + - Standard + - Sheddable + type: string + lora: + properties: + adapters: + x-kubernetes-preserve-unknown-fields: true + type: object + name: + type: string + uri: + type: string + required: + - uri + type: object + parallelism: + properties: + data: + format: int32 + minimum: 1 + type: integer + dataLocal: + format: int32 + minimum: 1 + type: integer + dataRPCPort: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + expert: + type: boolean + pipeline: + format: int32 + minimum: 1 + type: integer + tensor: + format: int32 + minimum: 1 + type: integer + type: object + prefill: + properties: + parallelism: + properties: + data: + format: int32 + minimum: 1 + type: integer + dataLocal: + format: int32 + minimum: 1 + type: integer + dataRPCPort: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + expert: + type: boolean + pipeline: + format: int32 + minimum: 1 + type: integer + tensor: + format: int32 + minimum: 1 + type: integer + type: object + replicas: + format: int32 + minimum: 0 + type: integer + template: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + worker: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: object + replicas: + format: int32 + minimum: 0 + type: integer + router: + properties: + gateway: + properties: + refs: + items: + properties: + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + type: object + type: array + type: object + ingress: + properties: + refs: + items: + properties: + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + type: object + type: array + type: object + route: + properties: + http: + properties: + refs: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + spec: + properties: + hostnames: + items: + maxLength: 253 + minLength: 1 + pattern: ^(\*\.)?[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + maxItems: 16 + type: array + parentRefs: + items: + properties: + group: + default: gateway.networking.k8s.io + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Gateway + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + sectionName: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + required: + - name + type: object + maxItems: 32 + type: array + rules: + default: + - matches: + - path: + type: PathPrefix + value: / + items: + properties: + backendRefs: + items: + properties: + filters: + items: + properties: + extensionRef: + properties: + group: + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + properties: + add: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + properties: + backendRef: + properties: + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + fraction: + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal to denominator + rule: self.numerator <= self.denominator + percent: + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + properties: + hostname: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + properties: + replaceFullPath: + maxLength: 1024 + type: string + replacePrefixMatch: + maxLength: 1024 + type: string + type: + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + enum: + - http + - https + type: string + statusCode: + default: 302 + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + properties: + add: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + properties: + hostname: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + properties: + replaceFullPath: + maxLength: 1024 + type: string + replacePrefixMatch: + maxLength: 1024 + type: string + type: + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + weight: + default: 1 + format: int32 + maximum: 1000000 + minimum: 0 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + maxItems: 16 + type: array + filters: + items: + properties: + extensionRef: + properties: + group: + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + required: + - group + - kind + - name + type: object + requestHeaderModifier: + properties: + add: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + requestMirror: + properties: + backendRef: + properties: + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + namespace: + maxLength: 63 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + x-kubernetes-validations: + - message: Must have port for Service reference + rule: '(size(self.group) == 0 && self.kind == ''Service'') ? has(self.port) : true' + fraction: + properties: + denominator: + default: 100 + format: int32 + minimum: 1 + type: integer + numerator: + format: int32 + minimum: 0 + type: integer + required: + - numerator + type: object + x-kubernetes-validations: + - message: numerator must be less than or equal to denominator + rule: self.numerator <= self.denominator + percent: + format: int32 + maximum: 100 + minimum: 0 + type: integer + required: + - backendRef + type: object + requestRedirect: + properties: + hostname: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + properties: + replaceFullPath: + maxLength: 1024 + type: string + replacePrefixMatch: + maxLength: 1024 + type: string + type: + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + port: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + scheme: + enum: + - http + - https + type: string + statusCode: + default: 302 + enum: + - 301 + - 302 + type: integer + type: object + responseHeaderModifier: + properties: + add: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + remove: + items: + type: string + maxItems: 16 + type: array + x-kubernetes-list-type: set + set: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: + enum: + - RequestHeaderModifier + - ResponseHeaderModifier + - RequestMirror + - RequestRedirect + - URLRewrite + - ExtensionRef + type: string + urlRewrite: + properties: + hostname: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + path: + properties: + replaceFullPath: + maxLength: 1024 + type: string + replacePrefixMatch: + maxLength: 1024 + type: string + type: + enum: + - ReplaceFullPath + - ReplacePrefixMatch + type: string + required: + - type + type: object + x-kubernetes-validations: + - message: replaceFullPath must be specified when type is set to 'ReplaceFullPath' + rule: 'self.type == ''ReplaceFullPath'' ? has(self.replaceFullPath) : true' + - message: type must be 'ReplaceFullPath' when replaceFullPath is set + rule: 'has(self.replaceFullPath) ? self.type == ''ReplaceFullPath'' : true' + - message: replacePrefixMatch must be specified when type is set to 'ReplacePrefixMatch' + rule: 'self.type == ''ReplacePrefixMatch'' ? has(self.replacePrefixMatch) : true' + - message: type must be 'ReplacePrefixMatch' when replacePrefixMatch is set + rule: 'has(self.replacePrefixMatch) ? self.type == ''ReplacePrefixMatch'' : true' + type: object + required: + - type + type: object + x-kubernetes-validations: + - message: filter.requestHeaderModifier must be nil if the filter.type is not RequestHeaderModifier + rule: '!(has(self.requestHeaderModifier) && self.type != ''RequestHeaderModifier'')' + - message: filter.requestHeaderModifier must be specified for RequestHeaderModifier filter.type + rule: '!(!has(self.requestHeaderModifier) && self.type == ''RequestHeaderModifier'')' + - message: filter.responseHeaderModifier must be nil if the filter.type is not ResponseHeaderModifier + rule: '!(has(self.responseHeaderModifier) && self.type != ''ResponseHeaderModifier'')' + - message: filter.responseHeaderModifier must be specified for ResponseHeaderModifier filter.type + rule: '!(!has(self.responseHeaderModifier) && self.type == ''ResponseHeaderModifier'')' + - message: filter.requestMirror must be nil if the filter.type is not RequestMirror + rule: '!(has(self.requestMirror) && self.type != ''RequestMirror'')' + - message: filter.requestMirror must be specified for RequestMirror filter.type + rule: '!(!has(self.requestMirror) && self.type == ''RequestMirror'')' + - message: filter.requestRedirect must be nil if the filter.type is not RequestRedirect + rule: '!(has(self.requestRedirect) && self.type != ''RequestRedirect'')' + - message: filter.requestRedirect must be specified for RequestRedirect filter.type + rule: '!(!has(self.requestRedirect) && self.type == ''RequestRedirect'')' + - message: filter.urlRewrite must be nil if the filter.type is not URLRewrite + rule: '!(has(self.urlRewrite) && self.type != ''URLRewrite'')' + - message: filter.urlRewrite must be specified for URLRewrite filter.type + rule: '!(!has(self.urlRewrite) && self.type == ''URLRewrite'')' + - message: filter.extensionRef must be nil if the filter.type is not ExtensionRef + rule: '!(has(self.extensionRef) && self.type != ''ExtensionRef'')' + - message: filter.extensionRef must be specified for ExtensionRef filter.type + rule: '!(!has(self.extensionRef) && self.type == ''ExtensionRef'')' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: May specify either httpRouteFilterRequestRedirect or httpRouteFilterRequestRewrite, but not both + rule: '!(self.exists(f, f.type == ''RequestRedirect'') && self.exists(f, f.type == ''URLRewrite''))' + - message: RequestHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'RequestHeaderModifier').size() <= 1 + - message: ResponseHeaderModifier filter cannot be repeated + rule: self.filter(f, f.type == 'ResponseHeaderModifier').size() <= 1 + - message: RequestRedirect filter cannot be repeated + rule: self.filter(f, f.type == 'RequestRedirect').size() <= 1 + - message: URLRewrite filter cannot be repeated + rule: self.filter(f, f.type == 'URLRewrite').size() <= 1 + matches: + default: + - path: + type: PathPrefix + value: / + items: + properties: + headers: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + enum: + - Exact + - RegularExpression + type: string + value: + maxLength: 4096 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + method: + enum: + - GET + - HEAD + - POST + - PUT + - DELETE + - CONNECT + - OPTIONS + - TRACE + - PATCH + type: string + path: + default: + type: PathPrefix + value: / + properties: + type: + default: PathPrefix + enum: + - Exact + - PathPrefix + - RegularExpression + type: string + value: + default: / + maxLength: 1024 + type: string + type: object + x-kubernetes-validations: + - message: value must be an absolute path and start with '/' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.startsWith(''/'') : true' + - message: must not contain '//' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''//'') : true' + - message: must not contain '/./' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/./'') : true' + - message: must not contain '/../' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''/../'') : true' + - message: must not contain '%2f' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2f'') : true' + - message: must not contain '%2F' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''%2F'') : true' + - message: must not contain '#' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.contains(''#'') : true' + - message: must not end with '/..' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/..'') : true' + - message: must not end with '/.' when type one of ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? !self.value.endsWith(''/.'') : true' + - message: type must be one of ['Exact', 'PathPrefix', 'RegularExpression'] + rule: self.type in ['Exact','PathPrefix'] || self.type == 'RegularExpression' + - message: must only contain valid characters (matching ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$) for types ['Exact', 'PathPrefix'] + rule: '(self.type in [''Exact'',''PathPrefix'']) ? self.value.matches(r"""^(?:[-A-Za-z0-9/._~!$&''()*+,;=:@]|[%][0-9a-fA-F]{2})+$""") : true' + queryParams: + items: + properties: + name: + maxLength: 256 + minLength: 1 + pattern: ^[A-Za-z0-9!#$%&'*+\-.^_\x60|~]+$ + type: string + type: + default: Exact + enum: + - Exact + - RegularExpression + type: string + value: + maxLength: 1024 + minLength: 1 + type: string + required: + - name + - value + type: object + maxItems: 16 + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + maxItems: 64 + type: array + name: + maxLength: 253 + minLength: 1 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + retry: + properties: + attempts: + type: integer + backoff: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + codes: + items: + maximum: 599 + minimum: 400 + type: integer + type: array + type: object + sessionPersistence: + properties: + absoluteTimeout: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + cookieConfig: + properties: + lifetimeType: + default: Session + enum: + - Permanent + - Session + type: string + type: object + idleTimeout: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + sessionName: + maxLength: 128 + type: string + type: + default: Cookie + enum: + - Cookie + - Header + type: string + type: object + x-kubernetes-validations: + - message: AbsoluteTimeout must be specified when cookie lifetimeType is Permanent + rule: '!has(self.cookieConfig) || !has(self.cookieConfig.lifetimeType) || self.cookieConfig.lifetimeType != ''Permanent'' || has(self.absoluteTimeout)' + timeouts: + properties: + backendRequest: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + request: + pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$ + type: string + type: object + x-kubernetes-validations: + - message: backendRequest timeout cannot be longer than request timeout + rule: '!(has(self.request) && has(self.backendRequest) && duration(self.request) != duration(''0s'') && duration(self.backendRequest) > duration(self.request))' + type: object + x-kubernetes-validations: + - message: RequestRedirect filter must not be used together with backendRefs + rule: '(has(self.backendRefs) && size(self.backendRefs) > 0) ? (!has(self.filters) || self.filters.all(f, !has(f.requestRedirect))): true' + - message: When using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.filters) && self.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' && has(f.urlRewrite.path.replacePrefixMatch))) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, when using RequestRedirect filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.requestRedirect) && has(f.requestRedirect.path) && f.requestRedirect.path.type == ''ReplacePrefixMatch'' && has(f.requestRedirect.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + - message: Within backendRefs, When using URLRewrite filter with path.replacePrefixMatch, exactly one PathPrefix match must be specified + rule: '(has(self.backendRefs) && self.backendRefs.exists_one(b, (has(b.filters) && b.filters.exists_one(f, has(f.urlRewrite) && has(f.urlRewrite.path) && f.urlRewrite.path.type == ''ReplacePrefixMatch'' && has(f.urlRewrite.path.replacePrefixMatch))) )) ? ((size(self.matches) != 1 || !has(self.matches[0].path) || self.matches[0].path.type != ''PathPrefix'') ? false : true) : true' + maxItems: 16 + type: array + x-kubernetes-validations: + - message: While 16 rules and 64 matches per rule are allowed, the total number of matches across all rules in a route must be less than 128 + rule: '(self.size() > 0 ? self[0].matches.size() : 0) + (self.size() > 1 ? self[1].matches.size() : 0) + (self.size() > 2 ? self[2].matches.size() : 0) + (self.size() > 3 ? self[3].matches.size() : 0) + (self.size() > 4 ? self[4].matches.size() : 0) + (self.size() > 5 ? self[5].matches.size() : 0) + (self.size() > 6 ? self[6].matches.size() : 0) + (self.size() > 7 ? self[7].matches.size() : 0) + (self.size() > 8 ? self[8].matches.size() : 0) + (self.size() > 9 ? self[9].matches.size() : 0) + (self.size() > 10 ? self[10].matches.size() : 0) + (self.size() > 11 ? self[11].matches.size() : 0) + (self.size() > 12 ? self[12].matches.size() : 0) + (self.size() > 13 ? self[13].matches.size() : 0) + (self.size() > 14 ? self[14].matches.size() : 0) + (self.size() > 15 ? self[15].matches.size() : 0) <= 128' + type: object + type: object + type: object + scheduler: + properties: + pool: + properties: + ref: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + spec: + properties: + extensionRef: + properties: + failureMode: + default: FailClose + enum: + - FailOpen + - FailClose + type: string + group: + default: "" + maxLength: 253 + pattern: ^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$ + type: string + kind: + default: Service + maxLength: 63 + minLength: 1 + pattern: ^[a-zA-Z]([-a-zA-Z0-9]*[a-zA-Z0-9])?$ + type: string + name: + maxLength: 253 + minLength: 1 + type: string + portNumber: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - name + type: object + selector: + additionalProperties: + maxLength: 63 + minLength: 0 + pattern: ^(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])?$ + type: string + type: object + targetPortNumber: + format: int32 + maximum: 65535 + minimum: 1 + type: integer + required: + - extensionRef + - selector + - targetPortNumber + type: object + type: object + template: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: object + type: object + template: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + worker: + properties: + activeDeadlineSeconds: + format: int64 + type: integer + affinity: + properties: + nodeAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + preference: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + properties: + nodeSelectorTerms: + items: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + properties: + preferredDuringSchedulingIgnoredDuringExecution: + items: + properties: + podAffinityTerm: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + weight: + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + automountServiceAccountToken: + type: boolean + containers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + dnsConfig: + properties: + nameservers: + items: + type: string + type: array + x-kubernetes-list-type: atomic + options: + items: + properties: + name: + type: string + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + searches: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + dnsPolicy: + type: string + enableServiceLinks: + type: boolean + ephemeralContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + targetContainerName: + type: string + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + hostAliases: + items: + properties: + hostnames: + items: + type: string + type: array + x-kubernetes-list-type: atomic + ip: + type: string + required: + - ip + type: object + type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map + hostIPC: + type: boolean + hostNetwork: + type: boolean + hostPID: + type: boolean + hostUsers: + type: boolean + hostname: + type: string + imagePullSecrets: + items: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + initContainers: + items: + properties: + args: + items: + type: string + type: array + x-kubernetes-list-type: atomic + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + env: + items: + properties: + name: + type: string + value: + type: string + valueFrom: + properties: + configMapKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + secretKeyRef: + properties: + key: + type: string + name: + default: "" + type: string + optional: + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + envFrom: + items: + properties: + configMapRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array + x-kubernetes-list-type: atomic + image: + type: string + imagePullPolicy: + type: string + lifecycle: + properties: + postStart: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + sleep: + properties: + seconds: + format: int64 + type: integer + required: + - seconds + type: object + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + stopSignal: + type: string + type: object + livenessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + name: + type: string + ports: + items: + properties: + containerPort: + format: int32 + type: integer + hostIP: + type: string + hostPort: + format: int32 + type: integer + name: + type: string + protocol: + default: TCP + type: string + required: + - containerPort + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resizePolicy: + items: + properties: + resourceName: + type: string + restartPolicy: + type: string + required: + - resourceName + - restartPolicy + type: object + type: array + x-kubernetes-list-type: atomic + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + securityContext: + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + capabilities: + properties: + add: + items: + type: string + type: array + x-kubernetes-list-type: atomic + drop: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + startupProbe: + properties: + exec: + properties: + command: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + failureThreshold: + format: int32 + type: integer + grpc: + properties: + port: + format: int32 + type: integer + service: + default: "" + type: string + required: + - port + type: object + httpGet: + properties: + host: + type: string + httpHeaders: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + path: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + scheme: + type: string + required: + - port + type: object + initialDelaySeconds: + format: int32 + type: integer + periodSeconds: + format: int32 + type: integer + successThreshold: + format: int32 + type: integer + tcpSocket: + properties: + host: + type: string + port: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - port + type: object + terminationGracePeriodSeconds: + format: int64 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + stdin: + type: boolean + stdinOnce: + type: boolean + terminationMessagePath: + type: string + terminationMessagePolicy: + type: string + tty: + type: boolean + volumeDevices: + items: + properties: + devicePath: + type: string + name: + type: string + required: + - devicePath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map + volumeMounts: + items: + properties: + mountPath: + type: string + mountPropagation: + type: string + name: + type: string + readOnly: + type: boolean + recursiveReadOnly: + type: string + subPath: + type: string + subPathExpr: + type: string + required: + - mountPath + - name + type: object + type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map + workingDir: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + nodeName: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + x-kubernetes-map-type: atomic + os: + properties: + name: + type: string + required: + - name + type: object + overhead: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + preemptionPolicy: + type: string + priority: + format: int32 + type: integer + priorityClassName: + type: string + readinessGates: + items: + properties: + conditionType: + type: string + required: + - conditionType + type: object + type: array + x-kubernetes-list-type: atomic + resourceClaims: + items: + properties: + name: + type: string + resourceClaimName: + type: string + resourceClaimTemplateName: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + resources: + properties: + claims: + items: + properties: + name: + type: string + request: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + restartPolicy: + type: string + runtimeClassName: + type: string + schedulerName: + type: string + schedulingGates: + items: + properties: + name: + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + securityContext: + properties: + appArmorProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + fsGroup: + format: int64 + type: integer + fsGroupChangePolicy: + type: string + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxChangePolicy: + type: string + seLinuxOptions: + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + properties: + localhostProfile: + type: string + type: + type: string + required: + - type + type: object + supplementalGroups: + items: + format: int64 + type: integer + type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + type: string + sysctls: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-list-type: atomic + windowsOptions: + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object + serviceAccount: + type: string + serviceAccountName: + type: string + setHostnameAsFQDN: + type: boolean + shareProcessNamespace: + type: boolean + subdomain: + type: string + terminationGracePeriodSeconds: + format: int64 + type: integer + tolerations: + items: + properties: + effect: + type: string + key: + type: string + operator: + type: string + tolerationSeconds: + format: int64 + type: integer + value: + type: string + type: object + type: array + x-kubernetes-list-type: atomic + topologySpreadConstraints: + items: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + items: + type: string + type: array + x-kubernetes-list-type: atomic + maxSkew: + format: int32 + type: integer + minDomains: + format: int32 + type: integer + nodeAffinityPolicy: + type: string + nodeTaintsPolicy: + type: string + topologyKey: + type: string + whenUnsatisfiable: + type: string + required: + - maxSkew + - topologyKey + - whenUnsatisfiable + type: object + type: array + x-kubernetes-list-map-keys: + - topologyKey + - whenUnsatisfiable + x-kubernetes-list-type: map + volumes: + items: + properties: + awsElasticBlockStore: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + azureDisk: + properties: + cachingMode: + type: string + diskName: + type: string + diskURI: + type: string + fsType: + default: ext4 + type: string + kind: + type: string + readOnly: + default: false + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + properties: + readOnly: + type: boolean + secretName: + type: string + shareName: + type: string + required: + - secretName + - shareName + type: object + cephfs: + properties: + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + path: + type: string + readOnly: + type: boolean + secretFile: + type: string + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + type: string + required: + - monitors + type: object + cinder: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeID: + type: string + required: + - volumeID + type: object + configMap: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + csi: + properties: + driver: + type: string + fsType: + type: string + nodePublishSecretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + readOnly: + type: boolean + volumeAttributes: + additionalProperties: + type: string + type: object + required: + - driver + type: object + downwardAPI: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + emptyDir: + properties: + medium: + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + ephemeral: + properties: + volumeClaimTemplate: + properties: + metadata: + type: object + spec: + properties: + accessModes: + items: + type: string + type: array + x-kubernetes-list-type: atomic + dataSource: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + properties: + apiGroup: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + resources: + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + type: object + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + type: string + volumeAttributesClassName: + type: string + volumeMode: + type: string + volumeName: + type: string + type: object + required: + - spec + type: object + type: object + fc: + properties: + fsType: + type: string + lun: + format: int32 + type: integer + readOnly: + type: boolean + targetWWNs: + items: + type: string + type: array + x-kubernetes-list-type: atomic + wwids: + items: + type: string + type: array + x-kubernetes-list-type: atomic + type: object + flexVolume: + properties: + driver: + type: string + fsType: + type: string + options: + additionalProperties: + type: string + type: object + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + required: + - driver + type: object + flocker: + properties: + datasetName: + type: string + datasetUUID: + type: string + type: object + gcePersistentDisk: + properties: + fsType: + type: string + partition: + format: int32 + type: integer + pdName: + type: string + readOnly: + type: boolean + required: + - pdName + type: object + gitRepo: + properties: + directory: + type: string + repository: + type: string + revision: + type: string + required: + - repository + type: object + glusterfs: + properties: + endpoints: + type: string + path: + type: string + readOnly: + type: boolean + required: + - endpoints + - path + type: object + hostPath: + properties: + path: + type: string + type: + type: string + required: + - path + type: object + image: + properties: + pullPolicy: + type: string + reference: + type: string + type: object + iscsi: + properties: + chapAuthDiscovery: + type: boolean + chapAuthSession: + type: boolean + fsType: + type: string + initiatorName: + type: string + iqn: + type: string + iscsiInterface: + default: default + type: string + lun: + format: int32 + type: integer + portals: + items: + type: string + type: array + x-kubernetes-list-type: atomic + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + targetPortal: + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + type: string + nfs: + properties: + path: + type: string + readOnly: + type: boolean + server: + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + properties: + claimName: + type: string + readOnly: + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + properties: + fsType: + type: string + pdID: + type: string + required: + - pdID + type: object + portworxVolume: + properties: + fsType: + type: string + readOnly: + type: boolean + volumeID: + type: string + required: + - volumeID + type: object + projected: + properties: + defaultMode: + format: int32 + type: integer + sources: + items: + properties: + clusterTrustBundle: + properties: + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + type: object + type: object + x-kubernetes-map-type: atomic + name: + type: string + optional: + type: boolean + path: + type: string + signerName: + type: string + required: + - path + type: object + configMap: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + downwardAPI: + properties: + items: + items: + properties: + fieldRef: + properties: + apiVersion: + type: string + fieldPath: + type: string + required: + - fieldPath + type: object + x-kubernetes-map-type: atomic + mode: + format: int32 + type: integer + path: + type: string + resourceFieldRef: + properties: + containerName: + type: string + divisor: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + type: string + required: + - resource + type: object + x-kubernetes-map-type: atomic + required: + - path + type: object + type: array + x-kubernetes-list-type: atomic + type: object + secret: + properties: + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + name: + default: "" + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + serviceAccountToken: + properties: + audience: + type: string + expirationSeconds: + format: int64 + type: integer + path: + type: string + required: + - path + type: object + type: object + type: array + x-kubernetes-list-type: atomic + type: object + quobyte: + properties: + group: + type: string + readOnly: + type: boolean + registry: + type: string + tenant: + type: string + user: + type: string + volume: + type: string + required: + - registry + - volume + type: object + rbd: + properties: + fsType: + type: string + image: + type: string + keyring: + default: /etc/ceph/keyring + type: string + monitors: + items: + type: string + type: array + x-kubernetes-list-type: atomic + pool: + default: rbd + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + user: + default: admin + type: string + required: + - image + - monitors + type: object + scaleIO: + properties: + fsType: + default: xfs + type: string + gateway: + type: string + protectionDomain: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + sslEnabled: + type: boolean + storageMode: + default: ThinProvisioned + type: string + storagePool: + type: string + system: + type: string + volumeName: + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + properties: + defaultMode: + format: int32 + type: integer + items: + items: + properties: + key: + type: string + mode: + format: int32 + type: integer + path: + type: string + required: + - key + - path + type: object + type: array + x-kubernetes-list-type: atomic + optional: + type: boolean + secretName: + type: string + type: object + storageos: + properties: + fsType: + type: string + readOnly: + type: boolean + secretRef: + properties: + name: + default: "" + type: string + type: object + x-kubernetes-map-type: atomic + volumeName: + type: string + volumeNamespace: + type: string + type: object + vsphereVolume: + properties: + fsType: + type: string + storagePolicyID: + type: string + storagePolicyName: + type: string + volumePath: + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + type: object + type: object + status: + properties: + address: + properties: + CACerts: + type: string + audience: + type: string + name: + type: string + url: + type: string + type: object + addresses: + items: + properties: + CACerts: + type: string + audience: + type: string + name: + type: string + url: + type: string + type: object + type: array + annotations: + additionalProperties: + type: string + type: object + conditions: + items: + properties: + lastTransitionTime: + type: string + message: + type: string + reason: + type: string + severity: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + observedGeneration: + format: int64 + type: integer + url: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterlocalmodels.yaml b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_localmodelcaches.yaml similarity index 85% rename from assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterlocalmodels.yaml rename to assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_localmodelcaches.yaml index 2e5afd4b91..ab92f72ab7 100644 --- a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterlocalmodels.yaml +++ b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_localmodelcaches.yaml @@ -4,14 +4,14 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.16.2 - name: clusterlocalmodels.serving.kserve.io + name: localmodelcaches.serving.kserve.io spec: group: serving.kserve.io names: - kind: ClusterLocalModel - listKind: ClusterLocalModelList - plural: clusterlocalmodels - singular: clusterlocalmodel + kind: LocalModelCache + listKind: LocalModelCacheList + plural: localmodelcaches + singular: localmodelcache scope: Cluster versions: - name: v1alpha1 @@ -32,8 +32,11 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - nodeGroup: - type: string + nodeGroups: + items: + type: string + minItems: 1 + type: array sourceModelUri: type: string x-kubernetes-validations: @@ -41,7 +44,7 @@ spec: rule: self == oldSelf required: - modelSize - - nodeGroup + - nodeGroups - sourceModelUri type: object status: @@ -73,9 +76,6 @@ spec: - NodeDownloading - NodeDownloaded - NodeDownloadError - - NodeDeleting - - NodeDeletionError - - NodeDeleted type: string type: object type: object diff --git a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_localmodelnodes.yaml b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_localmodelnodes.yaml new file mode 100644 index 0000000000..f130f6e7a3 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_localmodelnodes.yaml @@ -0,0 +1,61 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.2 + name: localmodelnodes.serving.kserve.io +spec: + group: serving.kserve.io + names: + kind: LocalModelNode + listKind: LocalModelNodeList + plural: localmodelnodes + singular: localmodelnode + scope: Cluster + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + localModels: + items: + properties: + modelName: + type: string + sourceModelUri: + type: string + required: + - modelName + - sourceModelUri + type: object + type: array + required: + - localModels + type: object + status: + properties: + modelStatus: + additionalProperties: + enum: + - "" + - ModelDownloadPending + - ModelDownloading + - ModelDownloaded + - ModelDownloadError + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_servingruntimes.yaml b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_servingruntimes.yaml index b5f5e6bc55..5a88508dbd 100644 --- a/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_servingruntimes.yaml +++ b/assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_servingruntimes.yaml @@ -793,6 +793,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: @@ -2772,6 +2774,8 @@ spec: - port type: object type: object + stopSignal: + type: string type: object livenessProbe: properties: diff --git a/assets/optional/ai-model-serving/kserve/crd/kustomization.yaml b/assets/optional/ai-model-serving/kserve/crd/kustomization.yaml index a7e42d9789..4958a515d3 100644 --- a/assets/optional/ai-model-serving/kserve/crd/kustomization.yaml +++ b/assets/optional/ai-model-serving/kserve/crd/kustomization.yaml @@ -13,14 +13,15 @@ kind: Kustomization resources: - full/serving.kserve.io_inferenceservices.yaml - full/serving.kserve.io_trainedmodels.yaml -# - serving.kserve.io_clusterservingruntimes.yaml # Not supported in ODH -# - full/serving.kserve.io_clusterservingruntimes.yaml +- full/serving.kserve.io_clusterservingruntimes.yaml - full/serving.kserve.io_servingruntimes.yaml - full/serving.kserve.io_inferencegraphs.yaml - full/serving.kserve.io_clusterstoragecontainers.yaml -- full/serving.kserve.io_clusterlocalmodels.yaml +- full/serving.kserve.io_localmodelcaches.yaml - full/serving.kserve.io_localmodelnodegroups.yaml - +- full/serving.kserve.io_localmodelnodes.yaml +- full/serving.kserve.io_llminferenceserviceconfigs.yaml +- full/serving.kserve.io_llminferenceservices.yaml patches: # Fix for https://github.com/kubernetes/kubernetes/issues/91395 diff --git a/assets/optional/ai-model-serving/kserve/default/cainjection_conversion_webhook.yaml b/assets/optional/ai-model-serving/kserve/default/cainjection_conversion_webhook.yaml index 92f5d3114b..af5dadeb06 100644 --- a/assets/optional/ai-model-serving/kserve/default/cainjection_conversion_webhook.yaml +++ b/assets/optional/ai-model-serving/kserve/default/cainjection_conversion_webhook.yaml @@ -4,5 +4,5 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - service.beta.openshift.io/inject-cabundle: "true" + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert name: inferenceservices.serving.kserve.io diff --git a/assets/optional/ai-model-serving/kserve/default/inferencegraph_validatingwebhook_cainjection_patch.yaml b/assets/optional/ai-model-serving/kserve/default/inferencegraph_validatingwebhook_cainjection_patch.yaml index a39d282a96..5e94b5d330 100644 --- a/assets/optional/ai-model-serving/kserve/default/inferencegraph_validatingwebhook_cainjection_patch.yaml +++ b/assets/optional/ai-model-serving/kserve/default/inferencegraph_validatingwebhook_cainjection_patch.yaml @@ -3,6 +3,6 @@ kind: ValidatingWebhookConfiguration metadata: name: inferencegraph.serving.kserve.io annotations: - service.beta.openshift.io/inject-cabundle: "true" + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert webhooks: - name: inferencegraph.kserve-webhook-server.validator diff --git a/assets/optional/ai-model-serving/kserve/default/isvc_mutatingwebhook_cainjection_patch.yaml b/assets/optional/ai-model-serving/kserve/default/isvc_mutatingwebhook_cainjection_patch.yaml index e91ee9f50a..cff6c92acd 100644 --- a/assets/optional/ai-model-serving/kserve/default/isvc_mutatingwebhook_cainjection_patch.yaml +++ b/assets/optional/ai-model-serving/kserve/default/isvc_mutatingwebhook_cainjection_patch.yaml @@ -3,6 +3,6 @@ kind: MutatingWebhookConfiguration metadata: name: inferenceservice.serving.kserve.io annotations: - service.beta.openshift.io/inject-cabundle: "true" + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert webhooks: - name: inferenceservice.kserve-webhook-server.defaulter diff --git a/assets/optional/ai-model-serving/kserve/default/isvc_validatingwebhook_cainjection_patch.yaml b/assets/optional/ai-model-serving/kserve/default/isvc_validatingwebhook_cainjection_patch.yaml index f0f0d437ab..946b7e5ca5 100644 --- a/assets/optional/ai-model-serving/kserve/default/isvc_validatingwebhook_cainjection_patch.yaml +++ b/assets/optional/ai-model-serving/kserve/default/isvc_validatingwebhook_cainjection_patch.yaml @@ -3,6 +3,6 @@ kind: ValidatingWebhookConfiguration metadata: name: inferenceservice.serving.kserve.io annotations: - service.beta.openshift.io/inject-cabundle: "true" + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert webhooks: - name: inferenceservice.kserve-webhook-server.validator diff --git a/assets/optional/ai-model-serving/kserve/default/kustomization.yaml b/assets/optional/ai-model-serving/kserve/default/kustomization.yaml index f57fd23675..42f0652543 100644 --- a/assets/optional/ai-model-serving/kserve/default/kustomization.yaml +++ b/assets/optional/ai-model-serving/kserve/default/kustomization.yaml @@ -17,9 +17,9 @@ resources: - ../rbac - ../manager - ../webhook -# - ../certmanager # not needed, because ODH is using OpenShift's serving certificates for WebHooks -# - ../localmodels # This is commented out for 2.16 -- network-policies.yaml # ODH specific +- ../certmanager +- ../localmodels +- ../localmodelnodes generatorOptions: disableNameSuffixHash: true @@ -53,16 +53,31 @@ replacements: select: kind: ValidatingWebhookConfiguration name: inferencegraph.serving.kserve.io -# - fieldPaths: -# - webhooks.*.clientConfig.service.name -# select: -# kind: ValidatingWebhookConfiguration -# name: clusterservingruntime.serving.kserve.io + - fieldPaths: + - webhooks.*.clientConfig.service.name + select: + kind: ValidatingWebhookConfiguration + name: clusterservingruntime.serving.kserve.io - fieldPaths: - webhooks.*.clientConfig.service.name select: kind: ValidatingWebhookConfiguration name: servingruntime.serving.kserve.io + - fieldPaths: + - webhooks.*.clientConfig.service.name + select: + kind: ValidatingWebhookConfiguration + name: localmodelcache.serving.kserve.io + - fieldPaths: + - webhooks.*.clientConfig.service.name + select: + kind: ValidatingWebhookConfiguration + name: llminferenceservice.serving.kserve.io + - fieldPaths: + - webhooks.*.clientConfig.service.name + select: + kind: ValidatingWebhookConfiguration + name: llminferenceserviceconfig.serving.kserve.io - fieldPaths: - spec.commonName - spec.dnsNames.0 @@ -73,6 +88,7 @@ replacements: kind: Certificate name: serving-cert namespace: kserve +# Replace the namespace with the namespace of the controller manager. - source: fieldPath: metadata.namespace kind: Deployment @@ -99,82 +115,105 @@ replacements: select: kind: ValidatingWebhookConfiguration name: inferencegraph.serving.kserve.io -# - fieldPaths: -# - webhooks.*.clientConfig.service.namespace -# select: -# kind: ValidatingWebhookConfiguration -# name: clusterservingruntime.serving.kserve.io - fieldPaths: - webhooks.*.clientConfig.service.namespace + select: + kind: ValidatingWebhookConfiguration + name: clusterservingruntime.serving.kserve.io + - fieldPaths: + - webhooks.*.clientConfig.service.namespace + select: + kind: ValidatingWebhookConfiguration + name: servingruntime.serving.kserve.io + - fieldPaths: + - webhooks.*.clientConfig.service.namespace + select: + kind: ValidatingWebhookConfiguration + name: localmodelcache.serving.kserve.io + - fieldPaths: + - webhooks.*.clientConfig.service.namespace + select: + kind: ValidatingWebhookConfiguration + name: llminferenceservice.serving.kserve.io + - fieldPaths: + - webhooks.*.clientConfig.service.namespace + select: + kind: ValidatingWebhookConfiguration + name: llminferenceserviceconfig.serving.kserve.io + - fieldPaths: + - spec.commonName + - spec.dnsNames.0 + options: + delimiter: '.' + index: 1 + select: + kind: Certificate + name: serving-cert + namespace: kserve + - fieldPaths: + - metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + select: + kind: CustomResourceDefinition + name: inferenceservices.serving.kserve.io + - fieldPaths: + - metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + select: + kind: MutatingWebhookConfiguration + name: inferenceservice.serving.kserve.io + - fieldPaths: + - metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + select: + kind: ValidatingWebhookConfiguration + name: inferenceservice.serving.kserve.io + - fieldPaths: + - metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + select: + kind: ValidatingWebhookConfiguration + name: trainedmodel.serving.kserve.io + - fieldPaths: + - metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + select: + kind: ValidatingWebhookConfiguration + name: inferencegraph.serving.kserve.io + - fieldPaths: + - metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + select: + kind: ValidatingWebhookConfiguration + name: clusterservingruntime.serving.kserve.io + - fieldPaths: + - metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 select: kind: ValidatingWebhookConfiguration name: servingruntime.serving.kserve.io -# - fieldPaths: -# - spec.commonName -# - spec.dnsNames.0 -# options: -# delimiter: '.' -# index: 1 -# select: -# kind: Certificate -# name: serving-cert -# namespace: kserve -# - fieldPaths: -# - metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# select: -# kind: CustomResourceDefinition -# name: inferenceservices.serving.kserve.io -# - fieldPaths: -# - metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# select: -# kind: MutatingWebhookConfiguration -# name: inferenceservice.serving.kserve.io -# - fieldPaths: -# - metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# select: -# kind: ValidatingWebhookConfiguration -# name: inferenceservice.serving.kserve.io -# - fieldPaths: -# - metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# select: -# kind: ValidatingWebhookConfiguration -# name: trainedmodel.serving.kserve.io -# - fieldPaths: -# - metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# select: -# kind: ValidatingWebhookConfiguration -# name: inferencegraph.serving.kserve.io -# - fieldPaths: -# - metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# select: -# kind: ValidatingWebhookConfiguration -# name: clusterservingruntime.serving.kserve.io -# - fieldPaths: -# - metadata.annotations.[cert-manager.io/inject-ca-from] -# options: -# delimiter: '/' -# index: 0 -# select: -# kind: ValidatingWebhookConfiguration -# name: servingruntime.serving.kserve.io + - fieldPaths: + - metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + select: + kind: ValidatingWebhookConfiguration + name: localmodelcache.serving.kserve.io # Protect the /metrics endpoint by putting it behind auth. # Only one of manager_auth_proxy_patch.yaml and @@ -187,34 +226,18 @@ replacements: #- manager_prometheus_metrics_patch.yaml patches: - path: manager_image_patch.yaml -#- path: manager_auth_proxy_patch.yaml +# FIXME(upstream): auth_proxy_overlay? +# - path: manager_auth_proxy_patch.yaml - path: isvc_mutatingwebhook_cainjection_patch.yaml - path: isvc_validatingwebhook_cainjection_patch.yaml - path: inferencegraph_validatingwebhook_cainjection_patch.yaml - path: trainedmodel_validatingwebhook_cainjection_patch.yaml -#- path: clusterservingruntime_validatingwebhook_cainjection_patch.yaml +- path: clusterservingruntime_validatingwebhook_cainjection_patch.yaml - path: servingruntime_validationwebhook_cainjection_patch.yaml -- path: svc_webhook_cainjection_patch.yaml +- path: localmodelcache_validatingwebhook_cainjection_patch.yaml +- path: llmisvc_validatingwebhook_cainjection_patch.yaml +- path: llmisvcconfig_validatingwebhook_cainjection_patch.yaml - path: manager_resources_patch.yaml - path: cainjection_conversion_webhook.yaml -# - path: localmodel_manager_image_patch.yaml -# Since OpenShift serving-certificates are being used, -# remove CA bundle placeholders -# - patch: |- -# - op: remove -# path: "/spec/conversion/webhook/clientConfig/caBundle" -# target: -# kind: CustomResourceDefinition -# name: inferenceservices.serving.kserve.io -# - patch: |- -# - op: remove -# path: "/webhooks/0/clientConfig/caBundle" -# - op: remove -# path: "/webhooks/1/clientConfig/caBundle" -# target: -# kind: MutatingWebhookConfiguration -# - patch: |- -# - op: remove -# path: "/webhooks/0/clientConfig/caBundle" -# target: -# kind: ValidatingWebhookConfiguration +- path: localmodel_manager_image_patch.yaml +- path: localmodelnode_agent_image_patch.yaml diff --git a/assets/optional/ai-model-serving/kserve/default/llmisvc_validatingwebhook_cainjection_patch.yaml b/assets/optional/ai-model-serving/kserve/default/llmisvc_validatingwebhook_cainjection_patch.yaml new file mode 100644 index 0000000000..9df4eadc2b --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/default/llmisvc_validatingwebhook_cainjection_patch.yaml @@ -0,0 +1,8 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: llminferenceservice.serving.kserve.io + annotations: + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert +webhooks: + - name: llminferenceservice.kserve-webhook-server.validator \ No newline at end of file diff --git a/assets/optional/ai-model-serving/kserve/default/llmisvcconfig_validatingwebhook_cainjection_patch.yaml b/assets/optional/ai-model-serving/kserve/default/llmisvcconfig_validatingwebhook_cainjection_patch.yaml new file mode 100644 index 0000000000..bf0d0cdcef --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/default/llmisvcconfig_validatingwebhook_cainjection_patch.yaml @@ -0,0 +1,8 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: llminferenceserviceconfig.serving.kserve.io + annotations: + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert +webhooks: + - name: llminferenceserviceconfig.kserve-webhook-server.validator \ No newline at end of file diff --git a/assets/optional/ai-model-serving/kserve/default/localmodelcache_validatingwebhook_cainjection_patch.yaml b/assets/optional/ai-model-serving/kserve/default/localmodelcache_validatingwebhook_cainjection_patch.yaml new file mode 100644 index 0000000000..4bfaca56a2 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/default/localmodelcache_validatingwebhook_cainjection_patch.yaml @@ -0,0 +1,8 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: localmodelcache.serving.kserve.io + annotations: + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert +webhooks: + - name: localmodelcache.kserve-webhook-server.validator diff --git a/assets/optional/ai-model-serving/kserve/default/localmodelnode_agent_image_patch.yaml b/assets/optional/ai-model-serving/kserve/default/localmodelnode_agent_image_patch.yaml new file mode 100644 index 0000000000..64a4f53954 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/default/localmodelnode_agent_image_patch.yaml @@ -0,0 +1,12 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: kserve-localmodelnode-agent + namespace: kserve +spec: + template: + spec: + containers: + # Change the value of image field below to your controller image URL + - image: kserve/kserve-localmodelnode-agent:latest + name: manager diff --git a/assets/optional/ai-model-serving/kserve/default/manager_auth_proxy_patch.yaml b/assets/optional/ai-model-serving/kserve/default/manager_auth_proxy_patch.yaml index 61f7af61ae..b0f5d03de7 100644 --- a/assets/optional/ai-model-serving/kserve/default/manager_auth_proxy_patch.yaml +++ b/assets/optional/ai-model-serving/kserve/default/manager_auth_proxy_patch.yaml @@ -30,4 +30,6 @@ spec: name: https - name: manager args: + # When changing args, also update manager.yaml because the following + # list of args will fully override the arguments in manager.yaml. - "--metrics-addr=127.0.0.1:8080" diff --git a/assets/optional/ai-model-serving/kserve/default/servingruntime_validationwebhook_cainjection_patch.yaml b/assets/optional/ai-model-serving/kserve/default/servingruntime_validationwebhook_cainjection_patch.yaml index c7335123f5..ac87c8516b 100644 --- a/assets/optional/ai-model-serving/kserve/default/servingruntime_validationwebhook_cainjection_patch.yaml +++ b/assets/optional/ai-model-serving/kserve/default/servingruntime_validationwebhook_cainjection_patch.yaml @@ -3,6 +3,6 @@ kind: ValidatingWebhookConfiguration metadata: name: servingruntime.serving.kserve.io annotations: - service.beta.openshift.io/inject-cabundle: "true" + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert webhooks: - name: servingruntime.kserve-webhook-server.validator diff --git a/assets/optional/ai-model-serving/kserve/default/trainedmodel_validatingwebhook_cainjection_patch.yaml b/assets/optional/ai-model-serving/kserve/default/trainedmodel_validatingwebhook_cainjection_patch.yaml index ce021eae54..abad6f07fa 100644 --- a/assets/optional/ai-model-serving/kserve/default/trainedmodel_validatingwebhook_cainjection_patch.yaml +++ b/assets/optional/ai-model-serving/kserve/default/trainedmodel_validatingwebhook_cainjection_patch.yaml @@ -3,6 +3,6 @@ kind: ValidatingWebhookConfiguration metadata: name: trainedmodel.serving.kserve.io annotations: - service.beta.openshift.io/inject-cabundle: "true" + cert-manager.io/inject-ca-from: $(kserveNamespace)/serving-cert webhooks: - name: trainedmodel.kserve-webhook-server.validator diff --git a/assets/optional/ai-model-serving/kserve/inferenceservice-config-microshift-patch.yaml b/assets/optional/ai-model-serving/kserve/inferenceservice-config-microshift-patch.yaml index e58d90c467..d779334936 100644 --- a/assets/optional/ai-model-serving/kserve/inferenceservice-config-microshift-patch.yaml +++ b/assets/optional/ai-model-serving/kserve/inferenceservice-config-microshift-patch.yaml @@ -1,5 +1,5 @@ # This is a MicroShift specific kserve configuration. -# For RHOAI kserve configuration see: assets/optional/ai-model-serving/kserve/overlays/odh/inferenceservice-config-patch.yaml +# For RHOAI kserve configuration see: assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-inferenceservice-config.yaml # For upstream kserve configuration and description of the config see: assets/optional/ai-model-serving/kserve/configmap/inferenceservice.yaml # # The difference compared to RHOAI's kserve configuration is the 'deploy' section setting: @@ -25,14 +25,18 @@ data: { "image" : "$(kserve-storage-initializer)", "memoryRequest": "100Mi", - "memoryLimit": "1Gi", + "memoryLimit": "24Gi", "cpuRequest": "100m", "cpuLimit": "1", "enableDirectPvcVolumeMount": true, + "cpuModelcar": "10m", + "memoryModelcar": "15Mi", "enableModelcar": true } ingress: |- { + "enableGatewayApi": false, + "kserveIngressGateway": "openshift-ingress/openshift-ai-inference", "ingressGateway" : "knative-serving/knative-ingress-gateway", "knativeLocalGatewayService" : "knative-local-gateway.istio-system.svc.cluster.local", "ingressService" : "istio-ingressgateway.istio-system.svc.cluster.local", @@ -96,7 +100,6 @@ data: inferenceService: |- { "serviceAnnotationDisallowedList": [ - "autoscaling.knative.dev/initial-scale", "autoscaling.knative.dev/min-scale", "autoscaling.knative.dev/max-scale", "internal.serving.kserve.io/storage-initializer-sourceuri", diff --git a/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-decode-template.yaml b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-decode-template.yaml new file mode 100644 index 0000000000..0602ecfaad --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-decode-template.yaml @@ -0,0 +1,261 @@ +apiVersion: serving.kserve.io/v1alpha1 +kind: LLMInferenceServiceConfig +metadata: + name: kserve-config-llm-decode-template +spec: + template: + containers: + - image: ghcr.io/llm-d/llm-d-dev:v0.2.2 + imagePullPolicy: IfNotPresent + name: main + ports: + - containerPort: 8001 + protocol: TCP + command: + - "/bin/bash" + - "-c" + args: + - |- + if [ "$KSERVE_INFER_ROCE" = "true" ]; then + echo "Trying to infer RoCE configs ... " + grep -H . /sys/class/infiniband/*/ports/*/gids/* 2>/dev/null + grep -H . /sys/class/infiniband/*/ports/*/gid_attrs/types/* 2>/dev/null + + cat /proc/driver/nvidia/params + + KSERVE_INFER_IB_GID_INDEX_GREP=${KSERVE_INFER_IB_GID_INDEX_GREP:-"RoCE v2"} + + echo "[Infer RoCE] Discovering active HCAs ..." + active_hcas=() + # Loop through all mlx5 devices found in sysfs + for hca_dir in /sys/class/infiniband/mlx5_*; do + # Ensure it's a directory before proceeding + if [ -d "$hca_dir" ]; then + hca_name=$(basename "$hca_dir") + port_state_file="$hca_dir/ports/1/state" # Assume port 1 + type_file="$hca_dir/ports/1/gid_attrs/types/*" + + echo "[Infer RoCE] Check if the port state file ${port_state_file} exists and contains 'ACTIVE'" + if [ -f "$port_state_file" ] && grep -q "ACTIVE" "$port_state_file" && grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" ${type_file} 2>/dev/null; then + echo "[Infer RoCE] Found active HCA: $hca_name" + active_hcas+=("$hca_name") + else + echo "[Infer RoCE] Skipping inactive or down HCA: $hca_name" + fi + fi + done + + ucx_hcas=() + for hca in "${active_hcas[@]}"; do + ucx_hcas+=("${hca}:1") + done + + # Check if we found any active HCAs + if [ ${#active_hcas[@]} -gt 0 ]; then + # Join the array elements with a comma + hcas=$(IFS=,; echo "${active_hcas[*]}") + echo "[Infer RoCE] Setting active HCAs: ${hcas}" + export NCCL_IB_HCA=${NCCL_IB_HCA:-${hcas}} + export NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST:-${ucx_hcas}} + export UCX_NET_DEVICES=${UCX_NET_DEVICES:-${ucx_hcas}} + + echo "[Infer RoCE] NCCL_IB_HCA=${NCCL_IB_HCA}" + echo "[Infer RoCE] NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST}" + else + echo "[Infer RoCE] WARNING: No active RoCE HCAs found. NCCL_IB_HCA will not be set." + fi + + if [ ${#active_hcas[@]} -gt 0 ]; then + echo "[Infer RoCE] Finding GID_INDEX for each active HCA (SR-IOV compatible)..." + + # For SR-IOV environments, find the most common IPv4 RoCE v2 GID index across all HCAs + declare -A gid_index_count + declare -A hca_gid_index + + for hca_name in "${active_hcas[@]}"; do + echo "[Infer RoCE] Processing HCA: ${hca_name}" + + # Find all RoCE v2 IPv4 GIDs for this HCA and count by index + for tpath in /sys/class/infiniband/${hca_name}/ports/1/gid_attrs/types/*; do + if grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" "$tpath" 2>/dev/null; then + idx=$(basename "$tpath") + gid_file="/sys/class/infiniband/${hca_name}/ports/1/gids/${idx}" + # Check for IPv4 GID (contains ffff:) + if [ -f "$gid_file" ] && grep -q "ffff:" "$gid_file"; then + gid_value=$(cat "$gid_file" 2>/dev/null || echo "") + echo "[Infer RoCE] Found IPv4 RoCE v2 GID for ${hca_name}: index=${idx}, gid=${gid_value}" + hca_gid_index["${hca_name}"]="${idx}" + gid_index_count["${idx}"]=$((${gid_index_count["${idx}"]} + 1)) + break # Use first found IPv4 GID per HCA + fi + fi + done + done + + # Find the most common GID index (most likely to be consistent across nodes) + best_gid_index="" + max_count=0 + for idx in "${!gid_index_count[@]}"; do + count=${gid_index_count["${idx}"]} + echo "[Infer RoCE] GID_INDEX ${idx} found on ${count} HCAs" + if [ $count -gt $max_count ]; then + max_count=$count + best_gid_index="$idx" + fi + done + + # Use deterministic fallback if counts are equal - prefer lower index number + if [ ${#gid_index_count[@]} -gt 1 ]; then + echo "[Infer RoCE] Multiple GID indices found, selecting most common: ${best_gid_index}" + # If there's a tie, prefer index 3 as it's most common in SR-IOV setups + if [ -n "${gid_index_count['3']}" ] && [ "${gid_index_count['3']}" -eq "$max_count" ]; then + best_gid_index="3" + echo "[Infer RoCE] Using deterministic fallback: GID_INDEX=3 (SR-IOV standard)" + fi + fi + + # Check if GID_INDEX is already set via environment variables + if [ -n "${NCCL_IB_GID_INDEX}" ]; then + echo "[Infer RoCE] Using pre-configured NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX} from environment" + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + echo "[Infer RoCE] Using hardcoded GID_INDEX=${NCCL_IB_GID_INDEX} for NCCL, NVSHMEM, and UCX" + elif [ -n "$best_gid_index" ]; then + echo "[Infer RoCE] Selected GID_INDEX: ${best_gid_index} (found on ${max_count} HCAs)" + + export NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX:-$best_gid_index} + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$best_gid_index} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$best_gid_index} + + echo "[Infer RoCE] Exported GID_INDEX=${best_gid_index} for NCCL, NVSHMEM, and UCX" + else + echo "[Infer RoCE] ERROR: No valid IPv4 ${KSERVE_INFER_IB_GID_INDEX_GREP} GID_INDEX found on any HCA." + fi + else + echo "[Infer RoCE] No active HCAs found, skipping GID_INDEX inference." + fi + fi + + eval "vllm serve /mnt/models \ + --served-model-name "{{ .Spec.Model.Name }}" \ + --port 8001 \ + --disable-log-requests \ + ${VLLM_ADDITIONAL_ARGS} \ + --enable-ssl-refresh \ + --ssl-certfile /etc/ssl/certs/tls.crt \ + --ssl-keyfile /etc/ssl/certs/tls.key" + env: + - name: HOME + value: /home + - name: VLLM_LOGGING_LEVEL + value: INFO + - name: HF_HUB_CACHE + value: /models + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + livenessProbe: + httpGet: + path: /health + port: 8001 + scheme: HTTPS + initialDelaySeconds: 120 + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8001 + scheme: HTTPS + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 60 + volumeMounts: + - mountPath: /home + name: home + - mountPath: /dev/shm + name: dshm + - mountPath: /models + name: model-cache + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + initContainers: + - name: llm-d-routing-sidecar + imagePullPolicy: IfNotPresent + image: ghcr.io/llm-d/llm-d-routing-sidecar:v0.2.0 + restartPolicy: Always + ports: + - containerPort: 8000 + protocol: TCP + resources: { } + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: + - ALL + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + livenessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 10 + args: + - "--port=8000" + - "--vllm-port=8001" + - "--connector=nixlv2" + - "--secure-proxy=true" + - "--cert-path=/etc/ssl/certs" + - "--decoder-use-tls=true" + - "--decoder-tls-insecure-skip-verify=true" + - "--prefiller-use-tls=true" + - "--prefiller-tls-insecure-skip-verify=true" + - "--enable-ssrf-protection=true" + volumeMounts: + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + env: + - name: INFERENCE_POOL_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: { } + name: home + - emptyDir: + medium: Memory + sizeLimit: 1Gi + name: dshm + - emptyDir: { } + name: model-cache + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" diff --git a/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-decode-worker-data-parallel.yaml b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-decode-worker-data-parallel.yaml new file mode 100644 index 0000000000..975544973a --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-decode-worker-data-parallel.yaml @@ -0,0 +1,520 @@ +apiVersion: serving.kserve.io/v1alpha1 +kind: LLMInferenceServiceConfig +metadata: + name: kserve-config-llm-decode-worker-data-parallel +spec: + template: + initContainers: + - name: llm-d-routing-sidecar + imagePullPolicy: IfNotPresent + image: ghcr.io/llm-d/llm-d-routing-sidecar:v0.2.0 + restartPolicy: Always + ports: + - containerPort: 8000 + protocol: TCP + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + livenessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 10 + args: + - "--port=8000" + - "--vllm-port=8001" + - "--connector=nixlv2" + - "--secure-proxy=true" + - "--cert-path=/etc/ssl/certs" + - "--decoder-use-tls=true" + - "--decoder-tls-insecure-skip-verify=true" + - "--prefiller-use-tls=true" + - "--prefiller-tls-insecure-skip-verify=true" + - "--enable-ssrf-protection=true" + volumeMounts: + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + env: + - name: INFERENCE_POOL_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + containers: + - image: ghcr.io/llm-d/llm-d-dev:v0.2.2 + imagePullPolicy: IfNotPresent + name: main + ports: + - containerPort: 8001 + protocol: TCP + command: + - "/bin/bash" + - "-c" + args: + - |- + # In some versions, ZMQ bind doesn't resolve the address through DNS + # Retry DP_ADDRESS resolution (configurable attempts, default 30) + RESOLVE_ATTEMPTS=${DP_ADDRESS_RESOLVE_ATTEMPTS:-30} + for ((i=1; i<=RESOLVE_ATTEMPTS; i++)); do + DP_ADDRESS=$(getent hosts ${LWS_LEADER_ADDRESS} | cut -d' ' -f1) + if [ -n "$DP_ADDRESS" ]; then + echo "DP_ADDRESS=${DP_ADDRESS} (resolved on attempt $i)" + break + else + echo "DP_ADDRESS resolution failed on attempt $i, retrying..." + sleep 1 + fi + done + + if [ -z "$DP_ADDRESS" ]; then + echo "WARNING: Failed to resolve DP_ADDRESS after ${RESOLVE_ATTEMPTS} attempts, falling back to LWS_LEADER_ADDRESS" + DP_ADDRESS=${LWS_LEADER_ADDRESS} + echo "DP_ADDRESS=${DP_ADDRESS} (fallback)" + fi + + if [ "$KSERVE_INFER_ROCE" = "true" ]; then + echo "Trying to infer RoCE configs ... " + grep -H . /sys/class/infiniband/*/ports/*/gids/* 2>/dev/null + grep -H . /sys/class/infiniband/*/ports/*/gid_attrs/types/* 2>/dev/null + + cat /proc/driver/nvidia/params + + KSERVE_INFER_IB_GID_INDEX_GREP=${KSERVE_INFER_IB_GID_INDEX_GREP:-"RoCE v2"} + + echo "[Infer RoCE] Discovering active HCAs ..." + active_hcas=() + # Loop through all mlx5 devices found in sysfs + for hca_dir in /sys/class/infiniband/mlx5_*; do + # Ensure it's a directory before proceeding + if [ -d "$hca_dir" ]; then + hca_name=$(basename "$hca_dir") + port_state_file="$hca_dir/ports/1/state" # Assume port 1 + type_file="$hca_dir/ports/1/gid_attrs/types/*" + + echo "[Infer RoCE] Check if the port state file ${port_state_file} exists and contains 'ACTIVE'" + if [ -f "$port_state_file" ] && grep -q "ACTIVE" "$port_state_file" && grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" ${type_file} 2>/dev/null; then + echo "[Infer RoCE] Found active HCA: $hca_name" + active_hcas+=("$hca_name") + else + echo "[Infer RoCE] Skipping inactive or down HCA: $hca_name" + fi + fi + done + + ucx_hcas=() + for hca in "${active_hcas[@]}"; do + ucx_hcas+=("${hca}:1") + done + + # Check if we found any active HCAs + if [ ${#active_hcas[@]} -gt 0 ]; then + # Join the array elements with a comma + hcas=$(IFS=,; echo "${active_hcas[*]}") + echo "[Infer RoCE] Setting active HCAs: ${hcas}" + export NCCL_IB_HCA=${NCCL_IB_HCA:-${hcas}} + export NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST:-${ucx_hcas}} + export UCX_NET_DEVICES=${UCX_NET_DEVICES:-${ucx_hcas}} + + echo "[Infer RoCE] NCCL_IB_HCA=${NCCL_IB_HCA}" + echo "[Infer RoCE] NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST}" + else + echo "[Infer RoCE] WARNING: No active RoCE HCAs found. NCCL_IB_HCA will not be set." + fi + + if [ ${#active_hcas[@]} -gt 0 ]; then + echo "[Infer RoCE] Finding GID_INDEX for each active HCA (SR-IOV compatible)..." + + # For SR-IOV environments, find the most common IPv4 RoCE v2 GID index across all HCAs + declare -A gid_index_count + declare -A hca_gid_index + + for hca_name in "${active_hcas[@]}"; do + echo "[Infer RoCE] Processing HCA: ${hca_name}" + + # Find all RoCE v2 IPv4 GIDs for this HCA and count by index + for tpath in /sys/class/infiniband/${hca_name}/ports/1/gid_attrs/types/*; do + if grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" "$tpath" 2>/dev/null; then + idx=$(basename "$tpath") + gid_file="/sys/class/infiniband/${hca_name}/ports/1/gids/${idx}" + # Check for IPv4 GID (contains ffff:) + if [ -f "$gid_file" ] && grep -q "ffff:" "$gid_file"; then + gid_value=$(cat "$gid_file" 2>/dev/null || echo "") + echo "[Infer RoCE] Found IPv4 RoCE v2 GID for ${hca_name}: index=${idx}, gid=${gid_value}" + hca_gid_index["${hca_name}"]="${idx}" + gid_index_count["${idx}"]=$((${gid_index_count["${idx}"]} + 1)) + break # Use first found IPv4 GID per HCA + fi + fi + done + done + + # Find the most common GID index (most likely to be consistent across nodes) + best_gid_index="" + max_count=0 + for idx in "${!gid_index_count[@]}"; do + count=${gid_index_count["${idx}"]} + echo "[Infer RoCE] GID_INDEX ${idx} found on ${count} HCAs" + if [ $count -gt $max_count ]; then + max_count=$count + best_gid_index="$idx" + fi + done + + # Use deterministic fallback if counts are equal - prefer lower index number + if [ ${#gid_index_count[@]} -gt 1 ]; then + echo "[Infer RoCE] Multiple GID indices found, selecting most common: ${best_gid_index}" + # If there's a tie, prefer index 3 as it's most common in SR-IOV setups + if [ -n "${gid_index_count['3']}" ] && [ "${gid_index_count['3']}" -eq "$max_count" ]; then + best_gid_index="3" + echo "[Infer RoCE] Using deterministic fallback: GID_INDEX=3 (SR-IOV standard)" + fi + fi + + # Check if GID_INDEX is already set via environment variables + if [ -n "${NCCL_IB_GID_INDEX}" ]; then + echo "[Infer RoCE] Using pre-configured NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX} from environment" + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + echo "[Infer RoCE] Using hardcoded GID_INDEX=${NCCL_IB_GID_INDEX} for NCCL, NVSHMEM, and UCX" + elif [ -n "$best_gid_index" ]; then + echo "[Infer RoCE] Selected GID_INDEX: ${best_gid_index} (found on ${max_count} HCAs)" + + export NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX:-$best_gid_index} + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$best_gid_index} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$best_gid_index} + + echo "[Infer RoCE] Exported GID_INDEX=${best_gid_index} for NCCL, NVSHMEM, and UCX" + else + echo "[Infer RoCE] ERROR: No valid IPv4 ${KSERVE_INFER_IB_GID_INDEX_GREP} GID_INDEX found on any HCA." + fi + else + echo "[Infer RoCE] No active HCAs found, skipping GID_INDEX inference." + fi + fi + + START_RANK=0 + eval "vllm serve \ + /mnt/models \ + --served-model-name "{{ .Spec.Model.Name }}" \ + --port 8001 \ + --api-server-count ${VLLM_API_SERVER_COUNT:-8} \ + --disable-log-requests \ + {{- if .Spec.Parallelism.Expert -}}--enable-expert-parallel{{- end }} \ + {{- if .Spec.Parallelism.Tensor -}}--tensor-parallel-size {{ .Spec.Parallelism.Tensor }}{{- end }} \ + --data-parallel-size {{ or .Spec.Parallelism.Data 1 }} \ + --data-parallel-size-local {{ or .Spec.Parallelism.DataLocal 1 }} \ + --data-parallel-address ${DP_ADDRESS} \ + --data-parallel-rpc-port {{ if .Spec.Parallelism.DataRPCPort }}{{ .Spec.Parallelism.DataRPCPort }}{{ else }}5555{{- end }} \ + --data-parallel-start-rank $START_RANK \ + ${VLLM_ADDITIONAL_ARGS} \ + --trust-remote-code \ + --enable-ssl-refresh \ + --ssl-certfile \ + /etc/ssl/certs/tls.crt \ + --ssl-keyfile \ + /etc/ssl/certs/tls.key" + env: + - name: HOME + value: /home + - name: VLLM_LOGGING_LEVEL + value: INFO + - name: HF_HUB_CACHE + value: /models + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + add: + - "IPC_LOCK" + - "SYS_RAWIO" + - "NET_RAW" + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + livenessProbe: + httpGet: + path: /health + port: 8001 + scheme: HTTPS + initialDelaySeconds: 300 + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8001 + scheme: HTTPS + initialDelaySeconds: 200 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 60 + volumeMounts: + - mountPath: /home + name: home + - mountPath: /dev/shm + name: dshm + - mountPath: /models + name: model-cache + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: { } + name: home + - emptyDir: + medium: Memory + sizeLimit: 8Gi + name: dshm + - emptyDir: { } + name: model-cache + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" + worker: + containers: + - image: ghcr.io/llm-d/llm-d-dev:v0.2.2 + imagePullPolicy: IfNotPresent + name: main + ports: + - containerPort: 8001 + protocol: TCP + command: + - "/bin/bash" + - "-c" + args: + - |- + # In some versions, ZMQ bind doesn't resolve the address through DNS + # Retry DP_ADDRESS resolution (configurable attempts, default 30) + RESOLVE_ATTEMPTS=${DP_ADDRESS_RESOLVE_ATTEMPTS:-30} + for ((i=1; i<=RESOLVE_ATTEMPTS; i++)); do + DP_ADDRESS=$(getent hosts ${LWS_LEADER_ADDRESS} | cut -d' ' -f1) + if [ -n "$DP_ADDRESS" ]; then + echo "DP_ADDRESS=${DP_ADDRESS} (resolved on attempt $i)" + break + else + echo "DP_ADDRESS resolution failed on attempt $i, retrying..." + sleep 1 + fi + done + + if [ -z "$DP_ADDRESS" ]; then + echo "WARNING: Failed to resolve DP_ADDRESS after ${RESOLVE_ATTEMPTS} attempts, falling back to LWS_LEADER_ADDRESS" + DP_ADDRESS=${LWS_LEADER_ADDRESS} + echo "DP_ADDRESS=${DP_ADDRESS} (fallback)" + fi + + if [ "$KSERVE_INFER_ROCE" = "true" ]; then + echo "Trying to infer RoCE configs ... " + grep -H . /sys/class/infiniband/*/ports/*/gids/* 2>/dev/null + grep -H . /sys/class/infiniband/*/ports/*/gid_attrs/types/* 2>/dev/null + + cat /proc/driver/nvidia/params + + KSERVE_INFER_IB_GID_INDEX_GREP=${KSERVE_INFER_IB_GID_INDEX_GREP:-"RoCE v2"} + + echo "[Infer RoCE] Discovering active HCAs ..." + active_hcas=() + # Loop through all mlx5 devices found in sysfs + for hca_dir in /sys/class/infiniband/mlx5_*; do + # Ensure it's a directory before proceeding + if [ -d "$hca_dir" ]; then + hca_name=$(basename "$hca_dir") + port_state_file="$hca_dir/ports/1/state" # Assume port 1 + type_file="$hca_dir/ports/1/gid_attrs/types/*" + + echo "[Infer RoCE] Check if the port state file ${port_state_file} exists and contains 'ACTIVE'" + if [ -f "$port_state_file" ] && grep -q "ACTIVE" "$port_state_file" && grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" ${type_file} 2>/dev/null; then + echo "[Infer RoCE] Found active HCA: $hca_name" + active_hcas+=("$hca_name") + else + echo "[Infer RoCE] Skipping inactive or down HCA: $hca_name" + fi + fi + done + + ucx_hcas=() + for hca in "${active_hcas[@]}"; do + ucx_hcas+=("${hca}:1") + done + + # Check if we found any active HCAs + if [ ${#active_hcas[@]} -gt 0 ]; then + # Join the array elements with a comma + hcas=$(IFS=,; echo "${active_hcas[*]}") + echo "[Infer RoCE] Setting active HCAs: ${hcas}" + export NCCL_IB_HCA=${NCCL_IB_HCA:-${hcas}} + export NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST:-${ucx_hcas}} + export UCX_NET_DEVICES=${UCX_NET_DEVICES:-${ucx_hcas}} + + echo "[Infer RoCE] NCCL_IB_HCA=${NCCL_IB_HCA}" + echo "[Infer RoCE] NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST}" + else + echo "[Infer RoCE] WARNING: No active RoCE HCAs found. NCCL_IB_HCA will not be set." + fi + + if [ ${#active_hcas[@]} -gt 0 ]; then + echo "[Infer RoCE] Finding GID_INDEX for each active HCA (SR-IOV compatible)..." + + # For SR-IOV environments, find the most common IPv4 RoCE v2 GID index across all HCAs + declare -A gid_index_count + declare -A hca_gid_index + + for hca_name in "${active_hcas[@]}"; do + echo "[Infer RoCE] Processing HCA: ${hca_name}" + + # Find all RoCE v2 IPv4 GIDs for this HCA and count by index + for tpath in /sys/class/infiniband/${hca_name}/ports/1/gid_attrs/types/*; do + if grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" "$tpath" 2>/dev/null; then + idx=$(basename "$tpath") + gid_file="/sys/class/infiniband/${hca_name}/ports/1/gids/${idx}" + # Check for IPv4 GID (contains ffff:) + if [ -f "$gid_file" ] && grep -q "ffff:" "$gid_file"; then + gid_value=$(cat "$gid_file" 2>/dev/null || echo "") + echo "[Infer RoCE] Found IPv4 RoCE v2 GID for ${hca_name}: index=${idx}, gid=${gid_value}" + hca_gid_index["${hca_name}"]="${idx}" + gid_index_count["${idx}"]=$((${gid_index_count["${idx}"]} + 1)) + break # Use first found IPv4 GID per HCA + fi + fi + done + done + + # Find the most common GID index (most likely to be consistent across nodes) + best_gid_index="" + max_count=0 + for idx in "${!gid_index_count[@]}"; do + count=${gid_index_count["${idx}"]} + echo "[Infer RoCE] GID_INDEX ${idx} found on ${count} HCAs" + if [ $count -gt $max_count ]; then + max_count=$count + best_gid_index="$idx" + fi + done + + # Use deterministic fallback if counts are equal - prefer lower index number + if [ ${#gid_index_count[@]} -gt 1 ]; then + echo "[Infer RoCE] Multiple GID indices found, selecting most common: ${best_gid_index}" + # If there's a tie, prefer index 3 as it's most common in SR-IOV setups + if [ -n "${gid_index_count['3']}" ] && [ "${gid_index_count['3']}" -eq "$max_count" ]; then + best_gid_index="3" + echo "[Infer RoCE] Using deterministic fallback: GID_INDEX=3 (SR-IOV standard)" + fi + fi + + # Check if GID_INDEX is already set via environment variables + if [ -n "${NCCL_IB_GID_INDEX}" ]; then + echo "[Infer RoCE] Using pre-configured NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX} from environment" + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + echo "[Infer RoCE] Using hardcoded GID_INDEX=${NCCL_IB_GID_INDEX} for NCCL, NVSHMEM, and UCX" + elif [ -n "$best_gid_index" ]; then + echo "[Infer RoCE] Selected GID_INDEX: ${best_gid_index} (found on ${max_count} HCAs)" + + export NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX:-$best_gid_index} + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$best_gid_index} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$best_gid_index} + + echo "[Infer RoCE] Exported GID_INDEX=${best_gid_index} for NCCL, NVSHMEM, and UCX" + else + echo "[Infer RoCE] ERROR: No valid IPv4 ${KSERVE_INFER_IB_GID_INDEX_GREP} GID_INDEX found on any HCA." + fi + else + echo "[Infer RoCE] No active HCAs found, skipping GID_INDEX inference." + fi + fi + + START_RANK=$(( ${LWS_WORKER_INDEX:-0} * {{ or .Spec.Parallelism.DataLocal 1 }} )) + eval "vllm serve \ + /mnt/models \ + --served-model-name "{{ .Spec.Model.Name }}" \ + --port 8001 \ + --disable-log-requests \ + {{- if .Spec.Parallelism.Expert }}--enable-expert-parallel{{- end }} \ + {{- if .Spec.Parallelism.Tensor }}--tensor-parallel-size {{ .Spec.Parallelism.Tensor }}{{- end }} \ + --data-parallel-size {{ or .Spec.Parallelism.Data 1 }} \ + --data-parallel-size-local {{ or .Spec.Parallelism.DataLocal 1 }} \ + --data-parallel-address ${DP_ADDRESS} \ + --data-parallel-rpc-port {{ if .Spec.Parallelism.DataRPCPort }}{{ .Spec.Parallelism.DataRPCPort }}{{ else }}5555{{- end }} \ + --data-parallel-start-rank $START_RANK \ + ${VLLM_ADDITIONAL_ARGS} \ + --trust-remote-code \ + --headless \ + --enable-ssl-refresh \ + --ssl-certfile \ + /etc/ssl/certs/tls.crt \ + --ssl-keyfile \ + /etc/ssl/certs/tls.key" + env: + - name: HOME + value: /home + - name: VLLM_LOGGING_LEVEL + value: INFO + - name: HF_HUB_CACHE + value: /models + - name: VLLM_RANDOMIZE_DP_DUMMY_INPUTS + value: "1" + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + add: + - "IPC_LOCK" + - "SYS_RAWIO" + - "NET_RAW" + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - mountPath: /home + name: home + - mountPath: /dev/shm + name: dshm + - mountPath: /models + name: model-cache + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: { } + name: home + - emptyDir: + medium: Memory + sizeLimit: 8Gi + name: dshm + - emptyDir: { } + name: model-cache + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" diff --git a/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-prefill-template.yaml b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-prefill-template.yaml new file mode 100644 index 0000000000..16ef6425e6 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-prefill-template.yaml @@ -0,0 +1,206 @@ +apiVersion: serving.kserve.io/v1alpha1 +kind: LLMInferenceServiceConfig +metadata: + name: kserve-config-llm-prefill-template +spec: + prefill: + template: + containers: + - image: ghcr.io/llm-d/llm-d-dev:v0.2.2 + imagePullPolicy: IfNotPresent + name: main + ports: + - containerPort: 8000 + protocol: TCP + command: + - "/bin/bash" + - "-c" + args: + - |- + if [ "$KSERVE_INFER_ROCE" = "true" ]; then + echo "Trying to infer RoCE configs ... " + grep -H . /sys/class/infiniband/*/ports/*/gids/* 2>/dev/null + grep -H . /sys/class/infiniband/*/ports/*/gid_attrs/types/* 2>/dev/null + + cat /proc/driver/nvidia/params + + KSERVE_INFER_IB_GID_INDEX_GREP=${KSERVE_INFER_IB_GID_INDEX_GREP:-"RoCE v2"} + + echo "[Infer RoCE] Discovering active HCAs ..." + active_hcas=() + # Loop through all mlx5 devices found in sysfs + for hca_dir in /sys/class/infiniband/mlx5_*; do + # Ensure it's a directory before proceeding + if [ -d "$hca_dir" ]; then + hca_name=$(basename "$hca_dir") + port_state_file="$hca_dir/ports/1/state" # Assume port 1 + type_file="$hca_dir/ports/1/gid_attrs/types/*" + + echo "[Infer RoCE] Check if the port state file ${port_state_file} exists and contains 'ACTIVE'" + if [ -f "$port_state_file" ] && grep -q "ACTIVE" "$port_state_file" && grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" ${type_file} 2>/dev/null; then + echo "[Infer RoCE] Found active HCA: $hca_name" + active_hcas+=("$hca_name") + else + echo "[Infer RoCE] Skipping inactive or down HCA: $hca_name" + fi + fi + done + + ucx_hcas=() + for hca in "${active_hcas[@]}"; do + ucx_hcas+=("${hca}:1") + done + + # Check if we found any active HCAs + if [ ${#active_hcas[@]} -gt 0 ]; then + # Join the array elements with a comma + hcas=$(IFS=,; echo "${active_hcas[*]}") + echo "[Infer RoCE] Setting active HCAs: ${hcas}" + export NCCL_IB_HCA=${NCCL_IB_HCA:-${hcas}} + export NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST:-${ucx_hcas}} + export UCX_NET_DEVICES=${UCX_NET_DEVICES:-${ucx_hcas}} + + echo "[Infer RoCE] NCCL_IB_HCA=${NCCL_IB_HCA}" + echo "[Infer RoCE] NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST}" + else + echo "[Infer RoCE] WARNING: No active RoCE HCAs found. NCCL_IB_HCA will not be set." + fi + + if [ ${#active_hcas[@]} -gt 0 ]; then + echo "[Infer RoCE] Finding GID_INDEX for each active HCA (SR-IOV compatible)..." + + # For SR-IOV environments, find the most common IPv4 RoCE v2 GID index across all HCAs + declare -A gid_index_count + declare -A hca_gid_index + + for hca_name in "${active_hcas[@]}"; do + echo "[Infer RoCE] Processing HCA: ${hca_name}" + + # Find all RoCE v2 IPv4 GIDs for this HCA and count by index + for tpath in /sys/class/infiniband/${hca_name}/ports/1/gid_attrs/types/*; do + if grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" "$tpath" 2>/dev/null; then + idx=$(basename "$tpath") + gid_file="/sys/class/infiniband/${hca_name}/ports/1/gids/${idx}" + # Check for IPv4 GID (contains ffff:) + if [ -f "$gid_file" ] && grep -q "ffff:" "$gid_file"; then + gid_value=$(cat "$gid_file" 2>/dev/null || echo "") + echo "[Infer RoCE] Found IPv4 RoCE v2 GID for ${hca_name}: index=${idx}, gid=${gid_value}" + hca_gid_index["${hca_name}"]="${idx}" + gid_index_count["${idx}"]=$((${gid_index_count["${idx}"]} + 1)) + break # Use first found IPv4 GID per HCA + fi + fi + done + done + + # Find the most common GID index (most likely to be consistent across nodes) + best_gid_index="" + max_count=0 + for idx in "${!gid_index_count[@]}"; do + count=${gid_index_count["${idx}"]} + echo "[Infer RoCE] GID_INDEX ${idx} found on ${count} HCAs" + if [ $count -gt $max_count ]; then + max_count=$count + best_gid_index="$idx" + fi + done + + # Use deterministic fallback if counts are equal - prefer lower index number + if [ ${#gid_index_count[@]} -gt 1 ]; then + echo "[Infer RoCE] Multiple GID indices found, selecting most common: ${best_gid_index}" + # If there's a tie, prefer index 3 as it's most common in SR-IOV setups + if [ -n "${gid_index_count['3']}" ] && [ "${gid_index_count['3']}" -eq "$max_count" ]; then + best_gid_index="3" + echo "[Infer RoCE] Using deterministic fallback: GID_INDEX=3 (SR-IOV standard)" + fi + fi + + # Check if GID_INDEX is already set via environment variables + if [ -n "${NCCL_IB_GID_INDEX}" ]; then + echo "[Infer RoCE] Using pre-configured NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX} from environment" + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + echo "[Infer RoCE] Using hardcoded GID_INDEX=${NCCL_IB_GID_INDEX} for NCCL, NVSHMEM, and UCX" + elif [ -n "$best_gid_index" ]; then + echo "[Infer RoCE] Selected GID_INDEX: ${best_gid_index} (found on ${max_count} HCAs)" + + export NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX:-$best_gid_index} + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$best_gid_index} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$best_gid_index} + + echo "[Infer RoCE] Exported GID_INDEX=${best_gid_index} for NCCL, NVSHMEM, and UCX" + else + echo "[Infer RoCE] ERROR: No valid IPv4 ${KSERVE_INFER_IB_GID_INDEX_GREP} GID_INDEX found on any HCA." + fi + else + echo "[Infer RoCE] No active HCAs found, skipping GID_INDEX inference." + fi + fi + + eval "vllm serve /mnt/models \ + --served-model-name "{{ .Spec.Model.Name }}" \ + --port "8000" \ + --disable-log-requests \ + ${VLLM_ADDITIONAL_ARGS} \ + --enable-ssl-refresh \ + --ssl-certfile /etc/ssl/certs/tls.crt \ + --ssl-keyfile /etc/ssl/certs/tls.key" + env: + - name: HOME + value: /home + - name: VLLM_LOGGING_LEVEL + value: INFO + - name: HF_HUB_CACHE + value: /models + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + livenessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 120 + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 60 + volumeMounts: + - mountPath: /home + name: home + - mountPath: /dev/shm + name: dshm + - mountPath: /models + name: model-cache + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: { } + name: home + - emptyDir: + medium: Memory + sizeLimit: 1Gi + name: dshm + - emptyDir: { } + name: model-cache + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" diff --git a/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-prefill-worker-data-parallel.yaml b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-prefill-worker-data-parallel.yaml new file mode 100644 index 0000000000..557f116797 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-prefill-worker-data-parallel.yaml @@ -0,0 +1,462 @@ +apiVersion: serving.kserve.io/v1alpha1 +kind: LLMInferenceServiceConfig +metadata: + name: kserve-config-llm-prefill-worker-data-parallel +spec: + prefill: + template: + containers: + - image: ghcr.io/llm-d/llm-d-dev:v0.2.2 + imagePullPolicy: IfNotPresent + name: main + ports: + - containerPort: 8000 + protocol: TCP + command: + - "/bin/bash" + - "-c" + args: + - |- + # In some versions, ZMQ bind doesn't resolve the address through DNS + # Retry DP_ADDRESS resolution (configurable attempts, default 30) + RESOLVE_ATTEMPTS=${DP_ADDRESS_RESOLVE_ATTEMPTS:-30} + for ((i=1; i<=RESOLVE_ATTEMPTS; i++)); do + DP_ADDRESS=$(getent hosts ${LWS_LEADER_ADDRESS} | cut -d' ' -f1) + if [ -n "$DP_ADDRESS" ]; then + echo "DP_ADDRESS=${DP_ADDRESS} (resolved on attempt $i)" + break + else + echo "DP_ADDRESS resolution failed on attempt $i, retrying..." + sleep 1 + fi + done + + if [ -z "$DP_ADDRESS" ]; then + echo "WARNING: Failed to resolve DP_ADDRESS after ${RESOLVE_ATTEMPTS} attempts, falling back to LWS_LEADER_ADDRESS" + DP_ADDRESS=${LWS_LEADER_ADDRESS} + echo "DP_ADDRESS=${DP_ADDRESS} (fallback)" + fi + + if [ "$KSERVE_INFER_ROCE" = "true" ]; then + echo "Trying to infer RoCE configs ... " + grep -H . /sys/class/infiniband/*/ports/*/gids/* 2>/dev/null + grep -H . /sys/class/infiniband/*/ports/*/gid_attrs/types/* 2>/dev/null + + cat /proc/driver/nvidia/params + + KSERVE_INFER_IB_GID_INDEX_GREP=${KSERVE_INFER_IB_GID_INDEX_GREP:-"RoCE v2"} + + echo "[Infer RoCE] Discovering active HCAs ..." + active_hcas=() + # Loop through all mlx5 devices found in sysfs + for hca_dir in /sys/class/infiniband/mlx5_*; do + # Ensure it's a directory before proceeding + if [ -d "$hca_dir" ]; then + hca_name=$(basename "$hca_dir") + port_state_file="$hca_dir/ports/1/state" # Assume port 1 + type_file="$hca_dir/ports/1/gid_attrs/types/*" + + echo "[Infer RoCE] Check if the port state file ${port_state_file} exists and contains 'ACTIVE'" + if [ -f "$port_state_file" ] && grep -q "ACTIVE" "$port_state_file" && grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" ${type_file} 2>/dev/null; then + echo "[Infer RoCE] Found active HCA: $hca_name" + active_hcas+=("$hca_name") + else + echo "[Infer RoCE] Skipping inactive or down HCA: $hca_name" + fi + fi + done + + ucx_hcas=() + for hca in "${active_hcas[@]}"; do + ucx_hcas+=("${hca}:1") + done + + # Check if we found any active HCAs + if [ ${#active_hcas[@]} -gt 0 ]; then + # Join the array elements with a comma + hcas=$(IFS=,; echo "${active_hcas[*]}") + echo "[Infer RoCE] Setting active HCAs: ${hcas}" + export NCCL_IB_HCA=${NCCL_IB_HCA:-${hcas}} + export NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST:-${ucx_hcas}} + export UCX_NET_DEVICES=${UCX_NET_DEVICES:-${ucx_hcas}} + + echo "[Infer RoCE] NCCL_IB_HCA=${NCCL_IB_HCA}" + echo "[Infer RoCE] NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST}" + else + echo "[Infer RoCE] WARNING: No active RoCE HCAs found. NCCL_IB_HCA will not be set." + fi + + if [ ${#active_hcas[@]} -gt 0 ]; then + echo "[Infer RoCE] Finding GID_INDEX for each active HCA (SR-IOV compatible)..." + + # For SR-IOV environments, find the most common IPv4 RoCE v2 GID index across all HCAs + declare -A gid_index_count + declare -A hca_gid_index + + for hca_name in "${active_hcas[@]}"; do + echo "[Infer RoCE] Processing HCA: ${hca_name}" + + # Find all RoCE v2 IPv4 GIDs for this HCA and count by index + for tpath in /sys/class/infiniband/${hca_name}/ports/1/gid_attrs/types/*; do + if grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" "$tpath" 2>/dev/null; then + idx=$(basename "$tpath") + gid_file="/sys/class/infiniband/${hca_name}/ports/1/gids/${idx}" + # Check for IPv4 GID (contains ffff:) + if [ -f "$gid_file" ] && grep -q "ffff:" "$gid_file"; then + gid_value=$(cat "$gid_file" 2>/dev/null || echo "") + echo "[Infer RoCE] Found IPv4 RoCE v2 GID for ${hca_name}: index=${idx}, gid=${gid_value}" + hca_gid_index["${hca_name}"]="${idx}" + gid_index_count["${idx}"]=$((${gid_index_count["${idx}"]} + 1)) + break # Use first found IPv4 GID per HCA + fi + fi + done + done + + # Find the most common GID index (most likely to be consistent across nodes) + best_gid_index="" + max_count=0 + for idx in "${!gid_index_count[@]}"; do + count=${gid_index_count["${idx}"]} + echo "[Infer RoCE] GID_INDEX ${idx} found on ${count} HCAs" + if [ $count -gt $max_count ]; then + max_count=$count + best_gid_index="$idx" + fi + done + + # Use deterministic fallback if counts are equal - prefer lower index number + if [ ${#gid_index_count[@]} -gt 1 ]; then + echo "[Infer RoCE] Multiple GID indices found, selecting most common: ${best_gid_index}" + # If there's a tie, prefer index 3 as it's most common in SR-IOV setups + if [ -n "${gid_index_count['3']}" ] && [ "${gid_index_count['3']}" -eq "$max_count" ]; then + best_gid_index="3" + echo "[Infer RoCE] Using deterministic fallback: GID_INDEX=3 (SR-IOV standard)" + fi + fi + + # Check if GID_INDEX is already set via environment variables + if [ -n "${NCCL_IB_GID_INDEX}" ]; then + echo "[Infer RoCE] Using pre-configured NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX} from environment" + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + echo "[Infer RoCE] Using hardcoded GID_INDEX=${NCCL_IB_GID_INDEX} for NCCL, NVSHMEM, and UCX" + elif [ -n "$best_gid_index" ]; then + echo "[Infer RoCE] Selected GID_INDEX: ${best_gid_index} (found on ${max_count} HCAs)" + + export NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX:-$best_gid_index} + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$best_gid_index} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$best_gid_index} + + echo "[Infer RoCE] Exported GID_INDEX=${best_gid_index} for NCCL, NVSHMEM, and UCX" + else + echo "[Infer RoCE] ERROR: No valid IPv4 ${KSERVE_INFER_IB_GID_INDEX_GREP} GID_INDEX found on any HCA." + fi + else + echo "[Infer RoCE] No active HCAs found, skipping GID_INDEX inference." + fi + fi + + START_RANK=0 + eval "vllm serve \ + /mnt/models \ + --served-model-name "{{ .Spec.Model.Name }}" \ + --port 8000 \ + --api-server-count ${VLLM_API_SERVER_COUNT:-8} \ + --disable-log-requests \ + {{- if .Spec.Prefill.Parallelism.Expert -}}--enable-expert-parallel{{- end }} \ + {{- if .Spec.Prefill.Parallelism.Tensor -}}--tensor-parallel-size {{ .Spec.Prefill.Parallelism.Tensor }}{{- end }} \ + --data-parallel-size {{ or .Spec.Prefill.Parallelism.Data 1 }} \ + --data-parallel-size-local {{ or .Spec.Prefill.Parallelism.DataLocal 1 }} \ + --data-parallel-address ${DP_ADDRESS} \ + --data-parallel-rpc-port {{ if .Spec.Prefill.Parallelism.DataRPCPort }}{{ .Spec.Prefill.Parallelism.DataRPCPort }}{{ else }}5555{{- end }} \ + --data-parallel-start-rank $START_RANK \ + ${VLLM_ADDITIONAL_ARGS} \ + --trust-remote-code \ + --enable-ssl-refresh \ + --ssl-certfile \ + /etc/ssl/certs/tls.crt \ + --ssl-keyfile \ + /etc/ssl/certs/tls.key" + env: + - name: HOME + value: /home + - name: VLLM_LOGGING_LEVEL + value: INFO + - name: HF_HUB_CACHE + value: /models + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + add: + - "IPC_LOCK" + - "SYS_RAWIO" + - "NET_RAW" + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + livenessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 300 + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 200 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 60 + volumeMounts: + - mountPath: /home + name: home + - mountPath: /dev/shm + name: dshm + - mountPath: /models + name: model-cache + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: { } + name: home + - emptyDir: + medium: Memory + sizeLimit: 8Gi + name: dshm + - emptyDir: { } + name: model-cache + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" + worker: + containers: + - image: ghcr.io/llm-d/llm-d-dev:v0.2.2 + imagePullPolicy: IfNotPresent + name: main + ports: + - containerPort: 8000 + protocol: TCP + command: + - "/bin/bash" + - "-c" + args: + - |- + # In some versions, ZMQ bind doesn't resolve the address through DNS + # Retry DP_ADDRESS resolution (configurable attempts, default 30) + RESOLVE_ATTEMPTS=${DP_ADDRESS_RESOLVE_ATTEMPTS:-30} + for ((i=1; i<=RESOLVE_ATTEMPTS; i++)); do + DP_ADDRESS=$(getent hosts ${LWS_LEADER_ADDRESS} | cut -d' ' -f1) + if [ -n "$DP_ADDRESS" ]; then + echo "DP_ADDRESS=${DP_ADDRESS} (resolved on attempt $i)" + break + else + echo "DP_ADDRESS resolution failed on attempt $i, retrying..." + sleep 1 + fi + done + + if [ -z "$DP_ADDRESS" ]; then + echo "WARNING: Failed to resolve DP_ADDRESS after ${RESOLVE_ATTEMPTS} attempts, falling back to LWS_LEADER_ADDRESS" + DP_ADDRESS=${LWS_LEADER_ADDRESS} + echo "DP_ADDRESS=${DP_ADDRESS} (fallback)" + fi + + if [ "$KSERVE_INFER_ROCE" = "true" ]; then + echo "Trying to infer RoCE configs ... " + grep -H . /sys/class/infiniband/*/ports/*/gids/* 2>/dev/null + grep -H . /sys/class/infiniband/*/ports/*/gid_attrs/types/* 2>/dev/null + + cat /proc/driver/nvidia/params + + KSERVE_INFER_IB_GID_INDEX_GREP=${KSERVE_INFER_IB_GID_INDEX_GREP:-"RoCE v2"} + + echo "[Infer RoCE] Discovering active HCAs ..." + active_hcas=() + # Loop through all mlx5 devices found in sysfs + for hca_dir in /sys/class/infiniband/mlx5_*; do + # Ensure it's a directory before proceeding + if [ -d "$hca_dir" ]; then + hca_name=$(basename "$hca_dir") + port_state_file="$hca_dir/ports/1/state" # Assume port 1 + type_file="$hca_dir/ports/1/gid_attrs/types/*" + + echo "[Infer RoCE] Check if the port state file ${port_state_file} exists and contains 'ACTIVE'" + if [ -f "$port_state_file" ] && grep -q "ACTIVE" "$port_state_file" && grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" ${type_file} 2>/dev/null; then + echo "[Infer RoCE] Found active HCA: $hca_name" + active_hcas+=("$hca_name") + else + echo "[Infer RoCE] Skipping inactive or down HCA: $hca_name" + fi + fi + done + + ucx_hcas=() + for hca in "${active_hcas[@]}"; do + ucx_hcas+=("${hca}:1") + done + + # Check if we found any active HCAs + if [ ${#active_hcas[@]} -gt 0 ]; then + # Join the array elements with a comma + hcas=$(IFS=,; echo "${active_hcas[*]}") + echo "[Infer RoCE] Setting active HCAs: ${hcas}" + export NCCL_IB_HCA=${NCCL_IB_HCA:-${hcas}} + export NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST:-${ucx_hcas}} + export UCX_NET_DEVICES=${UCX_NET_DEVICES:-${ucx_hcas}} + + echo "[Infer RoCE] NCCL_IB_HCA=${NCCL_IB_HCA}" + echo "[Infer RoCE] NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST}" + else + echo "[Infer RoCE] WARNING: No active RoCE HCAs found. NCCL_IB_HCA will not be set." + fi + + if [ ${#active_hcas[@]} -gt 0 ]; then + echo "[Infer RoCE] Finding GID_INDEX for each active HCA (SR-IOV compatible)..." + + # For SR-IOV environments, find the most common IPv4 RoCE v2 GID index across all HCAs + declare -A gid_index_count + declare -A hca_gid_index + + for hca_name in "${active_hcas[@]}"; do + echo "[Infer RoCE] Processing HCA: ${hca_name}" + + # Find all RoCE v2 IPv4 GIDs for this HCA and count by index + for tpath in /sys/class/infiniband/${hca_name}/ports/1/gid_attrs/types/*; do + if grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" "$tpath" 2>/dev/null; then + idx=$(basename "$tpath") + gid_file="/sys/class/infiniband/${hca_name}/ports/1/gids/${idx}" + # Check for IPv4 GID (contains ffff:) + if [ -f "$gid_file" ] && grep -q "ffff:" "$gid_file"; then + gid_value=$(cat "$gid_file" 2>/dev/null || echo "") + echo "[Infer RoCE] Found IPv4 RoCE v2 GID for ${hca_name}: index=${idx}, gid=${gid_value}" + hca_gid_index["${hca_name}"]="${idx}" + gid_index_count["${idx}"]=$((${gid_index_count["${idx}"]} + 1)) + break # Use first found IPv4 GID per HCA + fi + fi + done + done + + # Find the most common GID index (most likely to be consistent across nodes) + best_gid_index="" + max_count=0 + for idx in "${!gid_index_count[@]}"; do + count=${gid_index_count["${idx}"]} + echo "[Infer RoCE] GID_INDEX ${idx} found on ${count} HCAs" + if [ $count -gt $max_count ]; then + max_count=$count + best_gid_index="$idx" + fi + done + + # Use deterministic fallback if counts are equal - prefer lower index number + if [ ${#gid_index_count[@]} -gt 1 ]; then + echo "[Infer RoCE] Multiple GID indices found, selecting most common: ${best_gid_index}" + # If there's a tie, prefer index 3 as it's most common in SR-IOV setups + if [ -n "${gid_index_count['3']}" ] && [ "${gid_index_count['3']}" -eq "$max_count" ]; then + best_gid_index="3" + echo "[Infer RoCE] Using deterministic fallback: GID_INDEX=3 (SR-IOV standard)" + fi + fi + + # Check if GID_INDEX is already set via environment variables + if [ -n "${NCCL_IB_GID_INDEX}" ]; then + echo "[Infer RoCE] Using pre-configured NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX} from environment" + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + echo "[Infer RoCE] Using hardcoded GID_INDEX=${NCCL_IB_GID_INDEX} for NCCL, NVSHMEM, and UCX" + elif [ -n "$best_gid_index" ]; then + echo "[Infer RoCE] Selected GID_INDEX: ${best_gid_index} (found on ${max_count} HCAs)" + + export NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX:-$best_gid_index} + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$best_gid_index} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$best_gid_index} + + echo "[Infer RoCE] Exported GID_INDEX=${best_gid_index} for NCCL, NVSHMEM, and UCX" + else + echo "[Infer RoCE] ERROR: No valid IPv4 ${KSERVE_INFER_IB_GID_INDEX_GREP} GID_INDEX found on any HCA." + fi + else + echo "[Infer RoCE] No active HCAs found, skipping GID_INDEX inference." + fi + fi + + START_RANK=$(( ${LWS_WORKER_INDEX:-0} * {{ or .Spec.Prefill.Parallelism.DataLocal 1 }} )) + eval "vllm serve \ + /mnt/models \ + --served-model-name "{{ .Spec.Model.Name }}" \ + --port 8000 \ + --disable-log-requests \ + {{- if .Spec.Prefill.Parallelism.Expert }}--enable-expert-parallel{{- end }} \ + {{- if .Spec.Prefill.Parallelism.Tensor }}--tensor-parallel-size {{ .Spec.Prefill.Parallelism.Tensor }}{{- end }} \ + --data-parallel-size {{ or .Spec.Prefill.Parallelism.Data 1 }} \ + --data-parallel-size-local {{ or .Spec.Prefill.Parallelism.DataLocal 1 }} \ + --data-parallel-address ${DP_ADDRESS} \ + --data-parallel-rpc-port {{ if .Spec.Prefill.Parallelism.DataRPCPort }}{{ .Spec.Prefill.Parallelism.DataRPCPort }}{{ else }}5555{{- end }} \ + --data-parallel-start-rank $START_RANK \ + ${VLLM_ADDITIONAL_ARGS} \ + --trust-remote-code \ + --headless \ + --enable-ssl-refresh \ + --ssl-certfile \ + /etc/ssl/certs/tls.crt \ + --ssl-keyfile \ + /etc/ssl/certs/tls.key" + env: + - name: HOME + value: /home + - name: VLLM_LOGGING_LEVEL + value: INFO + - name: HF_HUB_CACHE + value: /models + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + add: + - "IPC_LOCK" + - "SYS_RAWIO" + - "NET_RAW" + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - mountPath: /home + name: home + - mountPath: /dev/shm + name: dshm + - mountPath: /models + name: model-cache + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: { } + name: home + - emptyDir: + medium: Memory + sizeLimit: 8Gi + name: dshm + - emptyDir: { } + name: model-cache + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" diff --git a/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-router-route.yaml b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-router-route.yaml new file mode 100644 index 0000000000..39646092b2 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-router-route.yaml @@ -0,0 +1,38 @@ +apiVersion: serving.kserve.io/v1alpha1 +kind: LLMInferenceServiceConfig +metadata: + name: kserve-config-llm-router-route +spec: + router: + route: + http: + spec: + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: |- + {{ .GlobalConfig.IngressGatewayName }} + namespace: |- + {{ .GlobalConfig.IngressGatewayNamespace }} + rules: + - backendRefs: + - group: inference.networking.x-k8s.io + kind: InferencePool + name: |- + {{ ChildName .ObjectMeta.Name `-inference-pool` }} + port: 8000 + weight: 1 + matches: + - path: + type: PathPrefix + value: |- + /{{ .ObjectMeta.Namespace }}/{{ .ObjectMeta.Name }} + filters: + - type: URLRewrite + urlRewrite: + path: + type: ReplacePrefixMatch + replacePrefixMatch: / + timeouts: + backendRequest: 0s + request: 0s diff --git a/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-scheduler.yaml b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-scheduler.yaml new file mode 100644 index 0000000000..1f5965d2e2 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-scheduler.yaml @@ -0,0 +1,92 @@ +apiVersion: serving.kserve.io/v1alpha1 +kind: LLMInferenceServiceConfig +metadata: + name: kserve-config-llm-scheduler +spec: + router: + scheduler: + pool: + spec: + extensionRef: + failureMode: FailOpen + kind: Service + name: |- + {{ ChildName .ObjectMeta.Name `-epp-service` }} + selector: { } + targetPortNumber: 8000 + template: + containers: + - name: main + ports: + - containerPort: 9002 + name: grpc + protocol: TCP + - containerPort: 9003 + name: grpc-health + protocol: TCP + - containerPort: 9090 + name: metrics + protocol: TCP + image: ghcr.io/llm-d/llm-d-inference-scheduler:v0.2.0 + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + grpc: + port: 9003 + service: envoy.service.ext_proc.v3.ExternalProcessor + initialDelaySeconds: 5 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + readinessProbe: + failureThreshold: 3 + grpc: + port: 9003 + service: envoy.service.ext_proc.v3.ExternalProcessor + initialDelaySeconds: 30 + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + args: + - --poolName + - "{{ ChildName .ObjectMeta.Name `-inference-pool` }}" + - --poolNamespace + - "{{ .ObjectMeta.Namespace }}" + - --zap-encoder + - json + - --grpcPort + - "9002" + - --grpcHealthPort + - "9003" + - --secureServing + - --modelServerMetricsScheme + - "https" + - --modelServerMetricsHttpsInsecureSkipVerify + - --certPath + - "/etc/ssl/certs" + resources: + requests: + cpu: 256m + memory: 500Mi + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + volumeMounts: + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + volumes: + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" + dnsPolicy: ClusterFirst + restartPolicy: Always + terminationGracePeriodSeconds: 30 diff --git a/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-template.yaml b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-template.yaml new file mode 100644 index 0000000000..8e8f1f595e --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-template.yaml @@ -0,0 +1,205 @@ +apiVersion: serving.kserve.io/v1alpha1 +kind: LLMInferenceServiceConfig +metadata: + name: kserve-config-llm-template +spec: + template: + containers: + - image: ghcr.io/llm-d/llm-d-dev:v0.2.2 + imagePullPolicy: IfNotPresent + name: main + ports: + - containerPort: 8000 + protocol: TCP + command: + - "/bin/bash" + - "-c" + args: + - |- + if [ "$KSERVE_INFER_ROCE" = "true" ]; then + echo "Trying to infer RoCE configs ... " + grep -H . /sys/class/infiniband/*/ports/*/gids/* 2>/dev/null + grep -H . /sys/class/infiniband/*/ports/*/gid_attrs/types/* 2>/dev/null + + cat /proc/driver/nvidia/params + + KSERVE_INFER_IB_GID_INDEX_GREP=${KSERVE_INFER_IB_GID_INDEX_GREP:-"RoCE v2"} + + echo "[Infer RoCE] Discovering active HCAs ..." + active_hcas=() + # Loop through all mlx5 devices found in sysfs + for hca_dir in /sys/class/infiniband/mlx5_*; do + # Ensure it's a directory before proceeding + if [ -d "$hca_dir" ]; then + hca_name=$(basename "$hca_dir") + port_state_file="$hca_dir/ports/1/state" # Assume port 1 + type_file="$hca_dir/ports/1/gid_attrs/types/*" + + echo "[Infer RoCE] Check if the port state file ${port_state_file} exists and contains 'ACTIVE'" + if [ -f "$port_state_file" ] && grep -q "ACTIVE" "$port_state_file" && grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" ${type_file} 2>/dev/null; then + echo "[Infer RoCE] Found active HCA: $hca_name" + active_hcas+=("$hca_name") + else + echo "[Infer RoCE] Skipping inactive or down HCA: $hca_name" + fi + fi + done + + ucx_hcas=() + for hca in "${active_hcas[@]}"; do + ucx_hcas+=("${hca}:1") + done + + # Check if we found any active HCAs + if [ ${#active_hcas[@]} -gt 0 ]; then + # Join the array elements with a comma + hcas=$(IFS=,; echo "${active_hcas[*]}") + echo "[Infer RoCE] Setting active HCAs: ${hcas}" + export NCCL_IB_HCA=${NCCL_IB_HCA:-${hcas}} + export NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST:-${ucx_hcas}} + export UCX_NET_DEVICES=${UCX_NET_DEVICES:-${ucx_hcas}} + + echo "[Infer RoCE] NCCL_IB_HCA=${NCCL_IB_HCA}" + echo "[Infer RoCE] NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST}" + else + echo "[Infer RoCE] WARNING: No active RoCE HCAs found. NCCL_IB_HCA will not be set." + fi + + if [ ${#active_hcas[@]} -gt 0 ]; then + echo "[Infer RoCE] Finding GID_INDEX for each active HCA (SR-IOV compatible)..." + + # For SR-IOV environments, find the most common IPv4 RoCE v2 GID index across all HCAs + declare -A gid_index_count + declare -A hca_gid_index + + for hca_name in "${active_hcas[@]}"; do + echo "[Infer RoCE] Processing HCA: ${hca_name}" + + # Find all RoCE v2 IPv4 GIDs for this HCA and count by index + for tpath in /sys/class/infiniband/${hca_name}/ports/1/gid_attrs/types/*; do + if grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" "$tpath" 2>/dev/null; then + idx=$(basename "$tpath") + gid_file="/sys/class/infiniband/${hca_name}/ports/1/gids/${idx}" + # Check for IPv4 GID (contains ffff:) + if [ -f "$gid_file" ] && grep -q "ffff:" "$gid_file"; then + gid_value=$(cat "$gid_file" 2>/dev/null || echo "") + echo "[Infer RoCE] Found IPv4 RoCE v2 GID for ${hca_name}: index=${idx}, gid=${gid_value}" + hca_gid_index["${hca_name}"]="${idx}" + gid_index_count["${idx}"]=$((${gid_index_count["${idx}"]} + 1)) + break # Use first found IPv4 GID per HCA + fi + fi + done + done + + # Find the most common GID index (most likely to be consistent across nodes) + best_gid_index="" + max_count=0 + for idx in "${!gid_index_count[@]}"; do + count=${gid_index_count["${idx}"]} + echo "[Infer RoCE] GID_INDEX ${idx} found on ${count} HCAs" + if [ $count -gt $max_count ]; then + max_count=$count + best_gid_index="$idx" + fi + done + + # Use deterministic fallback if counts are equal - prefer lower index number + if [ ${#gid_index_count[@]} -gt 1 ]; then + echo "[Infer RoCE] Multiple GID indices found, selecting most common: ${best_gid_index}" + # If there's a tie, prefer index 3 as it's most common in SR-IOV setups + if [ -n "${gid_index_count['3']}" ] && [ "${gid_index_count['3']}" -eq "$max_count" ]; then + best_gid_index="3" + echo "[Infer RoCE] Using deterministic fallback: GID_INDEX=3 (SR-IOV standard)" + fi + fi + + # Check if GID_INDEX is already set via environment variables + if [ -n "${NCCL_IB_GID_INDEX}" ]; then + echo "[Infer RoCE] Using pre-configured NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX} from environment" + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + echo "[Infer RoCE] Using hardcoded GID_INDEX=${NCCL_IB_GID_INDEX} for NCCL, NVSHMEM, and UCX" + elif [ -n "$best_gid_index" ]; then + echo "[Infer RoCE] Selected GID_INDEX: ${best_gid_index} (found on ${max_count} HCAs)" + + export NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX:-$best_gid_index} + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$best_gid_index} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$best_gid_index} + + echo "[Infer RoCE] Exported GID_INDEX=${best_gid_index} for NCCL, NVSHMEM, and UCX" + else + echo "[Infer RoCE] ERROR: No valid IPv4 ${KSERVE_INFER_IB_GID_INDEX_GREP} GID_INDEX found on any HCA." + fi + else + echo "[Infer RoCE] No active HCAs found, skipping GID_INDEX inference." + fi + fi + + eval "vllm serve /mnt/models \ + --served-model-name "{{ .Spec.Model.Name }}" \ + --port 8000 \ + --disable-log-requests \ + ${VLLM_ADDITIONAL_ARGS} \ + --enable-ssl-refresh \ + --ssl-certfile /etc/ssl/certs/tls.crt \ + --ssl-keyfile /etc/ssl/certs/tls.key" + env: + - name: HOME + value: /home + - name: VLLM_LOGGING_LEVEL + value: INFO + - name: HF_HUB_CACHE + value: /models + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + livenessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 120 + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 60 + volumeMounts: + - mountPath: /home + name: home + - mountPath: /dev/shm + name: dshm + - mountPath: /models + name: model-cache + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: { } + name: home + - emptyDir: + medium: Memory + sizeLimit: 1Gi + name: dshm + - emptyDir: { } + name: model-cache + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" diff --git a/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-worker-data-parallel.yaml b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-worker-data-parallel.yaml new file mode 100644 index 0000000000..82e0d83beb --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/llmisvc/config-llm-worker-data-parallel.yaml @@ -0,0 +1,461 @@ +apiVersion: serving.kserve.io/v1alpha1 +kind: LLMInferenceServiceConfig +metadata: + name: kserve-config-llm-worker-data-parallel +spec: + template: + containers: + - image: ghcr.io/llm-d/llm-d-dev:v0.2.2 + imagePullPolicy: IfNotPresent + name: main + ports: + - containerPort: 8000 + protocol: TCP + command: + - "/bin/bash" + - "-c" + args: + - |- + # In some versions, ZMQ bind doesn't resolve the address through DNS + # Retry DP_ADDRESS resolution (configurable attempts, default 30) + RESOLVE_ATTEMPTS=${DP_ADDRESS_RESOLVE_ATTEMPTS:-30} + for ((i=1; i<=RESOLVE_ATTEMPTS; i++)); do + DP_ADDRESS=$(getent hosts ${LWS_LEADER_ADDRESS} | cut -d' ' -f1) + if [ -n "$DP_ADDRESS" ]; then + echo "DP_ADDRESS=${DP_ADDRESS} (resolved on attempt $i)" + break + else + echo "DP_ADDRESS resolution failed on attempt $i, retrying..." + sleep 1 + fi + done + + if [ -z "$DP_ADDRESS" ]; then + echo "WARNING: Failed to resolve DP_ADDRESS after ${RESOLVE_ATTEMPTS} attempts, falling back to LWS_LEADER_ADDRESS" + DP_ADDRESS=${LWS_LEADER_ADDRESS} + echo "DP_ADDRESS=${DP_ADDRESS} (fallback)" + fi + + if [ "$KSERVE_INFER_ROCE" = "true" ]; then + echo "Trying to infer RoCE configs ... " + grep -H . /sys/class/infiniband/*/ports/*/gids/* 2>/dev/null + grep -H . /sys/class/infiniband/*/ports/*/gid_attrs/types/* 2>/dev/null + + cat /proc/driver/nvidia/params + + KSERVE_INFER_IB_GID_INDEX_GREP=${KSERVE_INFER_IB_GID_INDEX_GREP:-"RoCE v2"} + + echo "[Infer RoCE] Discovering active HCAs ..." + active_hcas=() + # Loop through all mlx5 devices found in sysfs + for hca_dir in /sys/class/infiniband/mlx5_*; do + # Ensure it's a directory before proceeding + if [ -d "$hca_dir" ]; then + hca_name=$(basename "$hca_dir") + port_state_file="$hca_dir/ports/1/state" # Assume port 1 + type_file="$hca_dir/ports/1/gid_attrs/types/*" + + echo "[Infer RoCE] Check if the port state file ${port_state_file} exists and contains 'ACTIVE'" + if [ -f "$port_state_file" ] && grep -q "ACTIVE" "$port_state_file" && grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" ${type_file} 2>/dev/null; then + echo "[Infer RoCE] Found active HCA: $hca_name" + active_hcas+=("$hca_name") + else + echo "[Infer RoCE] Skipping inactive or down HCA: $hca_name" + fi + fi + done + + ucx_hcas=() + for hca in "${active_hcas[@]}"; do + ucx_hcas+=("${hca}:1") + done + + # Check if we found any active HCAs + if [ ${#active_hcas[@]} -gt 0 ]; then + # Join the array elements with a comma + hcas=$(IFS=,; echo "${active_hcas[*]}") + echo "[Infer RoCE] Setting active HCAs: ${hcas}" + export NCCL_IB_HCA=${NCCL_IB_HCA:-${hcas}} + export NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST:-${ucx_hcas}} + export UCX_NET_DEVICES=${UCX_NET_DEVICES:-${ucx_hcas}} + + echo "[Infer RoCE] NCCL_IB_HCA=${NCCL_IB_HCA}" + echo "[Infer RoCE] NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST}" + else + echo "[Infer RoCE] WARNING: No active RoCE HCAs found. NCCL_IB_HCA will not be set." + fi + + if [ ${#active_hcas[@]} -gt 0 ]; then + echo "[Infer RoCE] Finding GID_INDEX for each active HCA (SR-IOV compatible)..." + + # For SR-IOV environments, find the most common IPv4 RoCE v2 GID index across all HCAs + declare -A gid_index_count + declare -A hca_gid_index + + for hca_name in "${active_hcas[@]}"; do + echo "[Infer RoCE] Processing HCA: ${hca_name}" + + # Find all RoCE v2 IPv4 GIDs for this HCA and count by index + for tpath in /sys/class/infiniband/${hca_name}/ports/1/gid_attrs/types/*; do + if grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" "$tpath" 2>/dev/null; then + idx=$(basename "$tpath") + gid_file="/sys/class/infiniband/${hca_name}/ports/1/gids/${idx}" + # Check for IPv4 GID (contains ffff:) + if [ -f "$gid_file" ] && grep -q "ffff:" "$gid_file"; then + gid_value=$(cat "$gid_file" 2>/dev/null || echo "") + echo "[Infer RoCE] Found IPv4 RoCE v2 GID for ${hca_name}: index=${idx}, gid=${gid_value}" + hca_gid_index["${hca_name}"]="${idx}" + gid_index_count["${idx}"]=$((${gid_index_count["${idx}"]} + 1)) + break # Use first found IPv4 GID per HCA + fi + fi + done + done + + # Find the most common GID index (most likely to be consistent across nodes) + best_gid_index="" + max_count=0 + for idx in "${!gid_index_count[@]}"; do + count=${gid_index_count["${idx}"]} + echo "[Infer RoCE] GID_INDEX ${idx} found on ${count} HCAs" + if [ $count -gt $max_count ]; then + max_count=$count + best_gid_index="$idx" + fi + done + + # Use deterministic fallback if counts are equal - prefer lower index number + if [ ${#gid_index_count[@]} -gt 1 ]; then + echo "[Infer RoCE] Multiple GID indices found, selecting most common: ${best_gid_index}" + # If there's a tie, prefer index 3 as it's most common in SR-IOV setups + if [ -n "${gid_index_count['3']}" ] && [ "${gid_index_count['3']}" -eq "$max_count" ]; then + best_gid_index="3" + echo "[Infer RoCE] Using deterministic fallback: GID_INDEX=3 (SR-IOV standard)" + fi + fi + + # Check if GID_INDEX is already set via environment variables + if [ -n "${NCCL_IB_GID_INDEX}" ]; then + echo "[Infer RoCE] Using pre-configured NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX} from environment" + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + echo "[Infer RoCE] Using hardcoded GID_INDEX=${NCCL_IB_GID_INDEX} for NCCL, NVSHMEM, and UCX" + elif [ -n "$best_gid_index" ]; then + echo "[Infer RoCE] Selected GID_INDEX: ${best_gid_index} (found on ${max_count} HCAs)" + + export NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX:-$best_gid_index} + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$best_gid_index} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$best_gid_index} + + echo "[Infer RoCE] Exported GID_INDEX=${best_gid_index} for NCCL, NVSHMEM, and UCX" + else + echo "[Infer RoCE] ERROR: No valid IPv4 ${KSERVE_INFER_IB_GID_INDEX_GREP} GID_INDEX found on any HCA." + fi + else + echo "[Infer RoCE] No active HCAs found, skipping GID_INDEX inference." + fi + fi + + START_RANK=0 + eval "vllm serve \ + /mnt/models \ + --served-model-name "{{ .Spec.Model.Name }}" \ + --port 8000 \ + --api-server-count ${VLLM_API_SERVER_COUNT:-8} \ + --disable-log-requests \ + {{- if .Spec.Parallelism.Expert -}}--enable-expert-parallel{{- end }} \ + {{- if .Spec.Parallelism.Tensor -}}--tensor-parallel-size {{ .Spec.Parallelism.Tensor }}{{- end }} \ + --data-parallel-size {{ or .Spec.Parallelism.Data 1 }} \ + --data-parallel-size-local {{ or .Spec.Parallelism.DataLocal 1 }} \ + --data-parallel-address ${DP_ADDRESS} \ + --data-parallel-rpc-port {{ if .Spec.Parallelism.DataRPCPort }}{{ .Spec.Parallelism.DataRPCPort }}{{ else }}5555{{- end }} \ + --data-parallel-start-rank $START_RANK \ + ${VLLM_ADDITIONAL_ARGS} \ + --trust-remote-code \ + --enable-ssl-refresh \ + --ssl-certfile \ + /etc/ssl/certs/tls.crt \ + --ssl-keyfile \ + /etc/ssl/certs/tls.key" + env: + - name: HOME + value: /home + - name: VLLM_LOGGING_LEVEL + value: INFO + - name: HF_HUB_CACHE + value: /models + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + add: + - "IPC_LOCK" + - "SYS_RAWIO" + - "NET_RAW" + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + livenessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 300 + periodSeconds: 10 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + httpGet: + path: /health + port: 8000 + scheme: HTTPS + initialDelaySeconds: 200 + periodSeconds: 30 + timeoutSeconds: 5 + failureThreshold: 60 + volumeMounts: + - mountPath: /home + name: home + - mountPath: /dev/shm + name: dshm + - mountPath: /models + name: model-cache + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: { } + name: home + - emptyDir: + medium: Memory + sizeLimit: 8Gi + name: dshm + - emptyDir: { } + name: model-cache + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" + worker: + containers: + - image: ghcr.io/llm-d/llm-d-dev:v0.2.2 + imagePullPolicy: IfNotPresent + name: main + ports: + - containerPort: 8000 + protocol: TCP + command: + - "/bin/bash" + - "-c" + args: + - |- + # In some versions, ZMQ bind doesn't resolve the address through DNS + # Retry DP_ADDRESS resolution (configurable attempts, default 30) + RESOLVE_ATTEMPTS=${DP_ADDRESS_RESOLVE_ATTEMPTS:-30} + for ((i=1; i<=RESOLVE_ATTEMPTS; i++)); do + DP_ADDRESS=$(getent hosts ${LWS_LEADER_ADDRESS} | cut -d' ' -f1) + if [ -n "$DP_ADDRESS" ]; then + echo "DP_ADDRESS=${DP_ADDRESS} (resolved on attempt $i)" + break + else + echo "DP_ADDRESS resolution failed on attempt $i, retrying..." + sleep 1 + fi + done + + if [ -z "$DP_ADDRESS" ]; then + echo "WARNING: Failed to resolve DP_ADDRESS after ${RESOLVE_ATTEMPTS} attempts, falling back to LWS_LEADER_ADDRESS" + DP_ADDRESS=${LWS_LEADER_ADDRESS} + echo "DP_ADDRESS=${DP_ADDRESS} (fallback)" + fi + + if [ "$KSERVE_INFER_ROCE" = "true" ]; then + echo "Trying to infer RoCE configs ... " + grep -H . /sys/class/infiniband/*/ports/*/gids/* 2>/dev/null + grep -H . /sys/class/infiniband/*/ports/*/gid_attrs/types/* 2>/dev/null + + cat /proc/driver/nvidia/params + + KSERVE_INFER_IB_GID_INDEX_GREP=${KSERVE_INFER_IB_GID_INDEX_GREP:-"RoCE v2"} + + echo "[Infer RoCE] Discovering active HCAs ..." + active_hcas=() + # Loop through all mlx5 devices found in sysfs + for hca_dir in /sys/class/infiniband/mlx5_*; do + # Ensure it's a directory before proceeding + if [ -d "$hca_dir" ]; then + hca_name=$(basename "$hca_dir") + port_state_file="$hca_dir/ports/1/state" # Assume port 1 + type_file="$hca_dir/ports/1/gid_attrs/types/*" + + echo "[Infer RoCE] Check if the port state file ${port_state_file} exists and contains 'ACTIVE'" + if [ -f "$port_state_file" ] && grep -q "ACTIVE" "$port_state_file" && grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" ${type_file} 2>/dev/null; then + echo "[Infer RoCE] Found active HCA: $hca_name" + active_hcas+=("$hca_name") + else + echo "[Infer RoCE] Skipping inactive or down HCA: $hca_name" + fi + fi + done + + ucx_hcas=() + for hca in "${active_hcas[@]}"; do + ucx_hcas+=("${hca}:1") + done + + # Check if we found any active HCAs + if [ ${#active_hcas[@]} -gt 0 ]; then + # Join the array elements with a comma + hcas=$(IFS=,; echo "${active_hcas[*]}") + echo "[Infer RoCE] Setting active HCAs: ${hcas}" + export NCCL_IB_HCA=${NCCL_IB_HCA:-${hcas}} + export NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST:-${ucx_hcas}} + export UCX_NET_DEVICES=${UCX_NET_DEVICES:-${ucx_hcas}} + + echo "[Infer RoCE] NCCL_IB_HCA=${NCCL_IB_HCA}" + echo "[Infer RoCE] NVSHMEM_HCA_LIST=${NVSHMEM_HCA_LIST}" + else + echo "[Infer RoCE] WARNING: No active RoCE HCAs found. NCCL_IB_HCA will not be set." + fi + + if [ ${#active_hcas[@]} -gt 0 ]; then + echo "[Infer RoCE] Finding GID_INDEX for each active HCA (SR-IOV compatible)..." + + # For SR-IOV environments, find the most common IPv4 RoCE v2 GID index across all HCAs + declare -A gid_index_count + declare -A hca_gid_index + + for hca_name in "${active_hcas[@]}"; do + echo "[Infer RoCE] Processing HCA: ${hca_name}" + + # Find all RoCE v2 IPv4 GIDs for this HCA and count by index + for tpath in /sys/class/infiniband/${hca_name}/ports/1/gid_attrs/types/*; do + if grep -q "${KSERVE_INFER_IB_GID_INDEX_GREP}" "$tpath" 2>/dev/null; then + idx=$(basename "$tpath") + gid_file="/sys/class/infiniband/${hca_name}/ports/1/gids/${idx}" + # Check for IPv4 GID (contains ffff:) + if [ -f "$gid_file" ] && grep -q "ffff:" "$gid_file"; then + gid_value=$(cat "$gid_file" 2>/dev/null || echo "") + echo "[Infer RoCE] Found IPv4 RoCE v2 GID for ${hca_name}: index=${idx}, gid=${gid_value}" + hca_gid_index["${hca_name}"]="${idx}" + gid_index_count["${idx}"]=$((${gid_index_count["${idx}"]} + 1)) + break # Use first found IPv4 GID per HCA + fi + fi + done + done + + # Find the most common GID index (most likely to be consistent across nodes) + best_gid_index="" + max_count=0 + for idx in "${!gid_index_count[@]}"; do + count=${gid_index_count["${idx}"]} + echo "[Infer RoCE] GID_INDEX ${idx} found on ${count} HCAs" + if [ $count -gt $max_count ]; then + max_count=$count + best_gid_index="$idx" + fi + done + + # Use deterministic fallback if counts are equal - prefer lower index number + if [ ${#gid_index_count[@]} -gt 1 ]; then + echo "[Infer RoCE] Multiple GID indices found, selecting most common: ${best_gid_index}" + # If there's a tie, prefer index 3 as it's most common in SR-IOV setups + if [ -n "${gid_index_count['3']}" ] && [ "${gid_index_count['3']}" -eq "$max_count" ]; then + best_gid_index="3" + echo "[Infer RoCE] Using deterministic fallback: GID_INDEX=3 (SR-IOV standard)" + fi + fi + + # Check if GID_INDEX is already set via environment variables + if [ -n "${NCCL_IB_GID_INDEX}" ]; then + echo "[Infer RoCE] Using pre-configured NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX} from environment" + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$NCCL_IB_GID_INDEX} + echo "[Infer RoCE] Using hardcoded GID_INDEX=${NCCL_IB_GID_INDEX} for NCCL, NVSHMEM, and UCX" + elif [ -n "$best_gid_index" ]; then + echo "[Infer RoCE] Selected GID_INDEX: ${best_gid_index} (found on ${max_count} HCAs)" + + export NCCL_IB_GID_INDEX=${NCCL_IB_GID_INDEX:-$best_gid_index} + export NVSHMEM_IB_GID_INDEX=${NVSHMEM_IB_GID_INDEX:-$best_gid_index} + export UCX_IB_GID_INDEX=${UCX_IB_GID_INDEX:-$best_gid_index} + + echo "[Infer RoCE] Exported GID_INDEX=${best_gid_index} for NCCL, NVSHMEM, and UCX" + else + echo "[Infer RoCE] ERROR: No valid IPv4 ${KSERVE_INFER_IB_GID_INDEX_GREP} GID_INDEX found on any HCA." + fi + else + echo "[Infer RoCE] No active HCAs found, skipping GID_INDEX inference." + fi + fi + + START_RANK=$(( ${LWS_WORKER_INDEX:-0} * {{ or .Spec.Parallelism.DataLocal 1 }} )) + eval "vllm serve \ + /mnt/models \ + --served-model-name "{{ .Spec.Model.Name }}" \ + --port 8000 \ + --disable-log-requests \ + {{- if .Spec.Parallelism.Expert }}--enable-expert-parallel{{- end }} \ + {{- if .Spec.Parallelism.Tensor }}--tensor-parallel-size {{ .Spec.Parallelism.Tensor }}{{- end }} \ + --data-parallel-size {{ or .Spec.Parallelism.Data 1 }} \ + --data-parallel-size-local {{ or .Spec.Parallelism.DataLocal 1 }} \ + --data-parallel-address ${DP_ADDRESS} \ + --data-parallel-rpc-port {{ if .Spec.Parallelism.DataRPCPort }}{{ .Spec.Parallelism.DataRPCPort }}{{ else }}5555{{- end }} \ + --data-parallel-start-rank $START_RANK \ + ${VLLM_ADDITIONAL_ARGS} \ + --trust-remote-code \ + --headless \ + --enable-ssl-refresh \ + --ssl-certfile \ + /etc/ssl/certs/tls.crt \ + --ssl-keyfile \ + /etc/ssl/certs/tls.key" + env: + - name: HOME + value: /home + - name: VLLM_LOGGING_LEVEL + value: INFO + - name: HF_HUB_CACHE + value: /models + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + capabilities: + add: + - "IPC_LOCK" + - "SYS_RAWIO" + - "NET_RAW" + drop: + - ALL + seccompProfile: + type: RuntimeDefault + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: FallbackToLogsOnError + volumeMounts: + - mountPath: /home + name: home + - mountPath: /dev/shm + name: dshm + - mountPath: /models + name: model-cache + - mountPath: /etc/ssl/certs + name: tls-certs + readOnly: true + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: { } + name: home + - emptyDir: + medium: Memory + sizeLimit: 8Gi + name: dshm + - emptyDir: { } + name: model-cache + - name: tls-certs + secret: + secretName: "{{ ChildName .ObjectMeta.Name `-kserve-self-signed-certs` }}" diff --git a/assets/optional/ai-model-serving/kserve/llmisvc/kustomization.yaml b/assets/optional/ai-model-serving/kserve/llmisvc/kustomization.yaml new file mode 100644 index 0000000000..cf9d6b27f5 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/llmisvc/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: kserve + +resources: + - ../crd/external/gateway-inference-extension + - config-llm-decode-template.yaml + - config-llm-decode-worker-data-parallel.yaml + - config-llm-prefill-template.yaml + - config-llm-prefill-worker-data-parallel.yaml + - config-llm-router-route.yaml + - config-llm-scheduler.yaml + - config-llm-template.yaml + - config-llm-worker-data-parallel.yaml diff --git a/assets/optional/ai-model-serving/kserve/localmodelnodes/kustomization.yaml b/assets/optional/ai-model-serving/kserve/localmodelnodes/kustomization.yaml new file mode 100644 index 0000000000..dfce22e6c5 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/localmodelnodes/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- manager.yaml diff --git a/assets/optional/ai-model-serving/kserve/localmodelnodes/manager.yaml b/assets/optional/ai-model-serving/kserve/localmodelnodes/manager.yaml new file mode 100644 index 0000000000..3eee059ed2 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/localmodelnodes/manager.yaml @@ -0,0 +1,70 @@ +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: kserve-localmodelnode-agent + namespace: kserve + labels: + app.kubernetes.io/name: kserve-localmodelnode-agent + control-plane: kserve-localmodelnode-agent + controller-tools.k8s.io: "1.0" +spec: + selector: + matchLabels: + control-plane: kserve-localmodelnode-agent + controller-tools.k8s.io: "1.0" + template: + metadata: + labels: + app.kubernetes.io/name: kserve-localmodelnode-agent + control-plane: kserve-localmodelnode-agent + controller-tools.k8s.io: "1.0" + annotations: + kubectl.kubernetes.io/default-container: manager + spec: + nodeSelector: + kserve/localmodel: worker + serviceAccountName: kserve-localmodelnode-agent + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - command: + - /manager + image: ko://github.com/kserve/kserve/cmd/localmodelnode + imagePullPolicy: Always + name: manager + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + volumeMounts: + - mountPath: /mnt/models + name: models + readOnly: false + resources: + limits: + cpu: 100m + memory: 300Mi + requests: + cpu: 100m + memory: 200Mi + volumes: + - name: models + hostPath: + path: /models + type: DirectoryOrCreate + terminationGracePeriodSeconds: 10 diff --git a/assets/optional/ai-model-serving/kserve/localmodels/kustomization.yaml b/assets/optional/ai-model-serving/kserve/localmodels/kustomization.yaml new file mode 100644 index 0000000000..dfce22e6c5 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/localmodels/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- manager.yaml diff --git a/assets/optional/ai-model-serving/kserve/localmodels/manager.yaml b/assets/optional/ai-model-serving/kserve/localmodels/manager.yaml new file mode 100644 index 0000000000..6379ddaa88 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/localmodels/manager.yaml @@ -0,0 +1,55 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kserve-localmodel-controller-manager + namespace: kserve + labels: + app.kubernetes.io/name: kserve-localmodel-controller-manager + control-plane: kserve-localmodel-controller-manager + controller-tools.k8s.io: "1.0" +spec: + selector: + matchLabels: + control-plane: kserve-localmodel-controller-manager + controller-tools.k8s.io: "1.0" + template: + metadata: + labels: + app.kubernetes.io/name: kserve-localmodel-controller-manager + control-plane: kserve-localmodel-controller-manager + controller-tools.k8s.io: "1.0" + annotations: + kubectl.kubernetes.io/default-container: manager + spec: + serviceAccountName: kserve-localmodel-controller-manager + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - command: + - /manager + image: ko://github.com/kserve/kserve/cmd/localmodel + imagePullPolicy: Always + name: manager + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + resources: + limits: + cpu: 100m + memory: 300Mi + requests: + cpu: 100m + memory: 200Mi + terminationGracePeriodSeconds: 10 diff --git a/assets/optional/ai-model-serving/kserve/manager/manager.yaml b/assets/optional/ai-model-serving/kserve/manager/manager.yaml index de1d4a87c8..9ceceb27c3 100644 --- a/assets/optional/ai-model-serving/kserve/manager/manager.yaml +++ b/assets/optional/ai-model-serving/kserve/manager/manager.yaml @@ -24,10 +24,14 @@ spec: serviceAccountName: kserve-controller-manager securityContext: runAsNonRoot: true + seccompProfile: + type: RuntimeDefault containers: - command: - /manager args: + # When changing arguments, make sure to review the args in manager_auth_proxy_patch.yaml + # and update as needed. - "--leader-elect" image: ko://github.com/kserve/kserve/cmd/manager imagePullPolicy: Always @@ -49,14 +53,14 @@ spec: value: kserve-webhook-server-cert livenessProbe: failureThreshold: 5 - initialDelaySeconds: 10 + initialDelaySeconds: 30 httpGet: path: /healthz port: 8081 timeoutSeconds: 5 readinessProbe: - initialDelaySeconds: 10 - failureThreshold: 10 + initialDelaySeconds: 30 + failureThreshold: 5 periodSeconds: 5 httpGet: path: /readyz diff --git a/assets/optional/ai-model-serving/kserve/manager/service.yaml b/assets/optional/ai-model-serving/kserve/manager/service.yaml index 51010718fe..1b53629cc9 100644 --- a/assets/optional/ai-model-serving/kserve/manager/service.yaml +++ b/assets/optional/ai-model-serving/kserve/manager/service.yaml @@ -1,13 +1,4 @@ apiVersion: v1 -kind: Namespace -metadata: - labels: - control-plane: kserve-controller-manager - controller-tools.k8s.io: "1.0" - istio-injection: disabled - name: kserve ---- -apiVersion: v1 kind: Service metadata: name: kserve-controller-manager-service @@ -20,6 +11,6 @@ spec: control-plane: kserve-controller-manager controller-tools.k8s.io: "1.0" ports: - - port: 8443 - targetPort: https - protocol: TCP + - port: 8443 + targetPort: https + protocol: TCP diff --git a/assets/optional/ai-model-serving/kserve/monitoring/llmisvc/istio_gateway_monitor.yaml b/assets/optional/ai-model-serving/kserve/monitoring/llmisvc/istio_gateway_monitor.yaml new file mode 100644 index 0000000000..aded426af3 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/monitoring/llmisvc/istio_gateway_monitor.yaml @@ -0,0 +1,17 @@ +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: kserve-llm-isvc-gateway + labels: + app.kubernetes.io/name: kserve-llm-isvc-gateway-monitoring +spec: + selector: + matchLabels: + serving.kserve.io/gateway: kserve-ingress-gateway + endpoints: + - targetPort: 15020 + metricRelabelings: + - sourceLabels: [ __name__ ] + action: replace + replacement: "kserve_$1" + targetLabel: __name__ diff --git a/assets/optional/ai-model-serving/kserve/monitoring/llmisvc/kustomization.yaml b/assets/optional/ai-model-serving/kserve/monitoring/llmisvc/kustomization.yaml new file mode 100644 index 0000000000..a51bcf6ff3 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/monitoring/llmisvc/kustomization.yaml @@ -0,0 +1,13 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +namespace: kserve + +labels: +- pairs: + app.kubernetes.io/component: llm-monitoring + app.kubernetes.io/part-of: kserve + +resources: + - rbac.yaml +# - istio_gateway_monitor.yaml diff --git a/assets/optional/ai-model-serving/kserve/monitoring/llmisvc/rbac.yaml b/assets/optional/ai-model-serving/kserve/monitoring/llmisvc/rbac.yaml new file mode 100644 index 0000000000..94ed2c437a --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/monitoring/llmisvc/rbac.yaml @@ -0,0 +1,9 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kserve-metrics-reader-cluster-role +rules: +- nonResourceURLs: + - /metrics + verbs: + - get diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/kustomization.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/kustomization.yaml index 5ae94a2307..cef82dd511 100644 --- a/assets/optional/ai-model-serving/kserve/overlays/odh/kustomization.yaml +++ b/assets/optional/ai-model-serving/kserve/overlays/odh/kustomization.yaml @@ -3,26 +3,117 @@ kind: Kustomization resources: - ../../default +- ../../llmisvc +- ../../monitoring/llmisvc +- llm-svc-scc.yaml +- network-policies.yaml - user-cluster-roles.yaml namespace: opendatahub patches: -- path: remove-namespace.yaml -- path: inferenceservice-config-patch.yaml -- path: set-resources-manager-patch.yaml +- path: patches/remove-clusterservingruntime.yaml +- path: patches/remove-cert-manager.yaml +- path: patches/remove-local-model.yaml +- path: patches/patch-webhook-svc-openshift-cert-injection.yaml +- path: patches/patch-inferenceservice-config.yaml +- path: patches/patch-set-resources-manager.yaml +- target: + kind: MutatingWebhookConfiguration + patch: | + - op: remove + path: /metadata/annotations/cert-manager.io~1inject-ca-from + - op: add + path: /metadata/annotations/service.beta.openshift.io~1inject-cabundle + value: "true" +- target: + kind: CustomResourceDefinition + name: inferenceservices.serving.kserve.io + patch: | + - op: remove + path: /metadata/annotations/cert-manager.io~1inject-ca-from + - op: add + path: /metadata/annotations/service.beta.openshift.io~1inject-cabundle + value: "true" +- target: + kind: ValidatingWebhookConfiguration + patch: | + - op: remove + path: /metadata/annotations/cert-manager.io~1inject-ca-from + - op: add + path: /metadata/annotations/service.beta.openshift.io~1inject-cabundle + value: "true" +- target: + kind: LLMInferenceServiceConfig + name: kserve-config-llm-scheduler + patch: |- + - op: replace + path: /spec/router/scheduler/template/containers/0/image + value: "$(kserve-llm-d-inference-scheduler)" +- target: + kind: LLMInferenceServiceConfig + name: kserve-config-llm-decode-template + patch: |- + - op: replace + path: /spec/template/initContainers/0/image + value: "$(kserve-llm-d-routing-sidecar)" +- target: + kind: LLMInferenceServiceConfig + name: kserve-config-llm-decode-worker-data-parallel + patch: |- + - op: replace + path: /spec/template/initContainers/0/image + value: "$(kserve-llm-d-routing-sidecar)" replacements: - source: kind: ConfigMap name: kserve-parameters - fieldpath: data.kserve-controller + fieldPath: data.kserve-controller targets: - select: kind: Deployment name: kserve-controller-manager fieldPaths: - spec.template.spec.containers.[name=manager].image +- source: + kind: ConfigMap + name: kserve-parameters + fieldPath: data.kserve-llm-d + targets: + - select: + kind: LLMInferenceServiceConfig + name: kserve-config-llm-decode-template + fieldPaths: + - spec.template.containers.[name=main].image + - select: + kind: LLMInferenceServiceConfig + name: kserve-config-llm-decode-worker-data-parallel + fieldPaths: + - spec.template.containers.[name=main].image + - spec.worker.containers.[name=main].image + - select: + kind: LLMInferenceServiceConfig + name: kserve-config-llm-prefill-template + fieldPaths: + - spec.prefill.template.containers.[name=main].image + - select: + kind: LLMInferenceServiceConfig + name: kserve-config-llm-prefill-worker-data-parallel + fieldPaths: + - spec.prefill.template.containers.[name=main].image + - spec.prefill.worker.containers.[name=main].image + - select: + kind: LLMInferenceServiceConfig + name: kserve-config-llm-template + fieldPaths: + - spec.template.containers.[name=main].image + - select: + kind: LLMInferenceServiceConfig + name: kserve-config-llm-worker-data-parallel + fieldPaths: + - spec.template.containers.[name=main].image + - spec.worker.containers.[name=main].image configMapGenerator: - envs: @@ -61,6 +152,20 @@ vars: apiVersion: v1 kind: ConfigMap name: kserve-parameters +- fieldref: + fieldpath: data.kserve-llm-d-inference-scheduler + name: kserve-llm-d-inference-scheduler + objref: + apiVersion: v1 + kind: ConfigMap + name: kserve-parameters +- fieldref: + fieldpath: data.kserve-llm-d-routing-sidecar + name: kserve-llm-d-routing-sidecar + objref: + apiVersion: v1 + kind: ConfigMap + name: kserve-parameters configurations: - - params.yaml +- params.yaml diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/llm-svc-scc.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/llm-svc-scc.yaml new file mode 100644 index 0000000000..4685e21d42 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/overlays/odh/llm-svc-scc.yaml @@ -0,0 +1,95 @@ +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: openshift-ai-llminferenceservice-scc +priority: 10 +allowHostDirVolumePlugin: false +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +runAsUser: + type: MustRunAsRange +seLinuxContext: + type: MustRunAs +fsGroup: + type: RunAsAny +supplementalGroups: + type: RunAsAny +allowedCapabilities: + - "IPC_LOCK" + - "SYS_RAWIO" + - "NET_BIND_SERVICE" + - "NET_RAW" +requiredDropCapabilities: +- ALL +seccompProfiles: +- runtime/default +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: openshift-ai-llminferenceservice-scc +rules: + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - openshift-ai-llminferenceservice-scc + verbs: + - use +--- +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: openshift-ai-llminferenceservice-multi-node-scc +priority: 11 +allowHostDirVolumePlugin: true +allowHostIPC: false +allowHostNetwork: false +allowHostPID: false +allowHostPorts: false +allowPrivilegeEscalation: false +allowPrivilegedContainer: false +volumes: + - hostPath + - configMap + - downwardAPI + - emptyDir + - persistentVolumeClaim + - projected + - secret +runAsUser: + type: MustRunAsRange +seLinuxContext: + type: MustRunAs +fsGroup: + type: RunAsAny +supplementalGroups: + type: RunAsAny +allowedCapabilities: + - "IPC_LOCK" + - "SYS_RAWIO" + - "NET_BIND_SERVICE" + - "NET_RAW" +requiredDropCapabilities: + - ALL +seccompProfiles: + - runtime/default +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: openshift-ai-llminferenceservice-multi-node-scc +rules: + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + resourceNames: + - openshift-ai-llminferenceservice-multi-node-scc + verbs: + - use diff --git a/assets/optional/ai-model-serving/kserve/default/network-policies.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/network-policies.yaml similarity index 100% rename from assets/optional/ai-model-serving/kserve/default/network-policies.yaml rename to assets/optional/ai-model-serving/kserve/overlays/odh/network-policies.yaml diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/params.env b/assets/optional/ai-model-serving/kserve/overlays/odh/params.env index 8231db7d23..fffc4e5724 100644 --- a/assets/optional/ai-model-serving/kserve/overlays/odh/params.env +++ b/assets/optional/ai-model-serving/kserve/overlays/odh/params.env @@ -1,5 +1,8 @@ -kserve-controller=quay.io/modh/kserve-controller@sha256:67672b25f5e4c2ba5457d29f0c5ae5b7e0ec3b635bf58a79892306ddda30ac2a -kserve-agent=quay.io/modh/kserve-agent@sha256:26967e2807991a1fbd3f69dfb46ffe451edb610bc9ea24c64ca835e0135d5a96 -kserve-router=quay.io/modh/kserve-router@sha256:8e73a4b58e1218115236f920ffe2671fb9a2166498ea17b885862df142be9036 -kserve-storage-initializer=quay.io/modh/kserve-storage-initializer@sha256:87272d0875618b3768f72cefc70169fea17be8f7513dab0ad74dd6205d0ce3f8 +kserve-controller=quay.io/opendatahub/kserve-controller:stable-2.x +kserve-agent=quay.io/opendatahub/kserve-agent:stable-2.x +kserve-router=quay.io/opendatahub/kserve-router:stable-2.x +kserve-storage-initializer=quay.io/opendatahub/kserve-storage-initializer:stable-2.x +kserve-llm-d=ghcr.io/llm-d/llm-d-dev:sha-b3f0b0d +kserve-llm-d-inference-scheduler=quay.io/opendatahub/llm-d-inference-scheduler:odh-v2.33 +kserve-llm-d-routing-sidecar=quay.io/opendatahub/llm-d-routing-sidecar:odh-v2.33 oauth-proxy=registry.redhat.io/openshift4/ose-oauth-proxy@sha256:bd49cfc8452b3d96467cc222db9487e120abc6cc5ba81349c6b3703706f36a08 diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/params.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/params.yaml index dc7f5878cc..e42d35f869 100644 --- a/assets/optional/ai-model-serving/kserve/overlays/odh/params.yaml +++ b/assets/optional/ai-model-serving/kserve/overlays/odh/params.yaml @@ -3,3 +3,9 @@ varReference: kind: Deployment - path: data kind: ConfigMap + - path: spec/router/scheduler/template/containers/image + kind: LLMInferenceServiceConfig + - path: spec/worker/initContainers/image + kind: LLMInferenceServiceConfig + - path: spec/template/initContainers/image + kind: LLMInferenceServiceConfig \ No newline at end of file diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/inferenceservice-config-patch.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-inferenceservice-config.yaml similarity index 93% rename from assets/optional/ai-model-serving/kserve/overlays/odh/inferenceservice-config-patch.yaml rename to assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-inferenceservice-config.yaml index 6a232d7583..887ea13f15 100644 --- a/assets/optional/ai-model-serving/kserve/overlays/odh/inferenceservice-config-patch.yaml +++ b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-inferenceservice-config.yaml @@ -17,14 +17,18 @@ data: { "image" : "$(kserve-storage-initializer)", "memoryRequest": "100Mi", - "memoryLimit": "1Gi", + "memoryLimit": "24Gi", "cpuRequest": "100m", "cpuLimit": "1", "enableDirectPvcVolumeMount": true, + "cpuModelcar": "10m", + "memoryModelcar": "15Mi", "enableModelcar": true } ingress: |- { + "enableGatewayApi": false, + "kserveIngressGateway": "openshift-ingress/openshift-ai-inference", "ingressGateway" : "knative-serving/knative-ingress-gateway", "knativeLocalGatewayService" : "knative-local-gateway.istio-system.svc.cluster.local", "ingressService" : "istio-ingressgateway.istio-system.svc.cluster.local", @@ -88,7 +92,6 @@ data: inferenceService: |- { "serviceAnnotationDisallowedList": [ - "autoscaling.knative.dev/initial-scale", "autoscaling.knative.dev/min-scale", "autoscaling.knative.dev/max-scale", "internal.serving.kserve.io/storage-initializer-sourceuri", diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/set-resources-manager-patch.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-set-resources-manager.yaml similarity index 100% rename from assets/optional/ai-model-serving/kserve/overlays/odh/set-resources-manager-patch.yaml rename to assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-set-resources-manager.yaml diff --git a/assets/optional/ai-model-serving/kserve/default/svc_webhook_cainjection_patch.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-webhook-svc-openshift-cert-injection.yaml similarity index 100% rename from assets/optional/ai-model-serving/kserve/default/svc_webhook_cainjection_patch.yaml rename to assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-webhook-svc-openshift-cert-injection.yaml diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-cert-manager.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-cert-manager.yaml new file mode 100644 index 0000000000..367d365c27 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-cert-manager.yaml @@ -0,0 +1,13 @@ +$patch: delete +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: selfsigned-issuer + namespace: kserve +--- +$patch: delete +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: serving-cert + namespace: kserve \ No newline at end of file diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-clusterservingruntime.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-clusterservingruntime.yaml new file mode 100644 index 0000000000..9ef9a2b7e7 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-clusterservingruntime.yaml @@ -0,0 +1,11 @@ +$patch: delete +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: clusterservingruntime.serving.kserve.io +--- +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterservingruntimes.serving.kserve.io diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-local-model.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-local-model.yaml new file mode 100644 index 0000000000..7ac0a9a7f0 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/overlays/odh/patches/remove-local-model.yaml @@ -0,0 +1,75 @@ +$patch: delete +apiVersion: apps/v1 +kind: Deployment +metadata: + name: kserve-localmodel-controller-manager + namespace: kserve +--- +$patch: delete +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: kserve-localmodelnode-agent + namespace: kserve +--- +$patch: delete +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: localmodelcache.serving.kserve.io +--- +$patch: delete +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kserve-localmodelnode-agent-role +--- +$patch: delete +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kserve-localmodelnode-agent-rolebinding +--- +$patch: delete +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kserve-localmodelnode-agent + namespace: kserve +--- +$patch: delete +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kserve-localmodel-manager-role +--- +$patch: delete +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kserve-localmodel-manager-rolebinding +--- +$patch: delete +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kserve-localmodel-controller-manager + namespace: kserve +--- +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: localmodelcaches.serving.kserve.io +--- +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: localmodelnodes.serving.kserve.io +--- +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: localmodelnodegroups.serving.kserve.io diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/remove-namespace.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/remove-namespace.yaml deleted file mode 100644 index bdca3de124..0000000000 --- a/assets/optional/ai-model-serving/kserve/overlays/odh/remove-namespace.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# Remove namespace resource as namespace will already exist. -$patch: delete -apiVersion: v1 -kind: Namespace -metadata: - name: kserve diff --git a/assets/optional/ai-model-serving/kserve/overlays/odh/user-cluster-roles.yaml b/assets/optional/ai-model-serving/kserve/overlays/odh/user-cluster-roles.yaml index b7a8853ec7..1868df6a5b 100644 --- a/assets/optional/ai-model-serving/kserve/overlays/odh/user-cluster-roles.yaml +++ b/assets/optional/ai-model-serving/kserve/overlays/odh/user-cluster-roles.yaml @@ -24,6 +24,7 @@ rules: - serving.kserve.io resources: - inferenceservices + - llminferenceservices - servingruntimes verbs: - create @@ -51,6 +52,9 @@ rules: - inferenceservices - inferenceservices/status - inferenceservices/finalizers + - llminferenceservices + - llminferenceservices/status + - llminferenceservices/finalizers verbs: - get - list diff --git a/assets/optional/ai-model-serving/kserve/rbac/kustomization.yaml b/assets/optional/ai-model-serving/kserve/rbac/kustomization.yaml index 6e872b04bf..fa63957160 100644 --- a/assets/optional/ai-model-serving/kserve/rbac/kustomization.yaml +++ b/assets/optional/ai-model-serving/kserve/rbac/kustomization.yaml @@ -16,3 +16,6 @@ resources: - localmodel/role_binding.yaml - localmodel/role.yaml - localmodel/service_account.yaml +- localmodelnode/role_binding.yaml +- localmodelnode/role.yaml +- localmodelnode/service_account.yaml diff --git a/assets/optional/ai-model-serving/kserve/rbac/localmodel/role.yaml b/assets/optional/ai-model-serving/kserve/rbac/localmodel/role.yaml index 63dfab9bb7..bf1887886b 100644 --- a/assets/optional/ai-model-serving/kserve/rbac/localmodel/role.yaml +++ b/assets/optional/ai-model-serving/kserve/rbac/localmodel/role.yaml @@ -32,34 +32,25 @@ rules: - persistentvolumes verbs: - create - - delete - get - list - patch - update - watch - apiGroups: - - batch + - serving.kserve.io resources: - - jobs + - inferenceservices + - localmodelnodegroups verbs: - - create - - delete - get - list - - patch - - update - watch -- apiGroups: - - batch - resources: - - jobs/status - verbs: - - get - apiGroups: - serving.kserve.io resources: - - clusterlocalmodels + - localmodelcaches + - localmodelnodes verbs: - create - delete @@ -71,7 +62,7 @@ rules: - apiGroups: - serving.kserve.io resources: - - clusterlocalmodels/status + - localmodelcaches/status verbs: - get - patch @@ -79,10 +70,7 @@ rules: - apiGroups: - serving.kserve.io resources: - - clusterstoragecontainers - - inferenceservices - - localmodelnodegroups + - localmodelnodes/status verbs: - get - - list - watch diff --git a/assets/optional/ai-model-serving/kserve/rbac/localmodelnode/role.yaml b/assets/optional/ai-model-serving/kserve/rbac/localmodelnode/role.yaml new file mode 100644 index 0000000000..9ea5ff6c30 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/rbac/localmodelnode/role.yaml @@ -0,0 +1,74 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kserve-localmodelnode-agent-role +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get +- apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - nodes/status + verbs: + - get + - watch +- apiGroups: + - batch + resources: + - jobs + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - batch + resources: + - jobs/status + verbs: + - get +- apiGroups: + - serving.kserve.io + resources: + - clusterstoragecontainers + - localmodelnodegroups + verbs: + - get + - list + - watch +- apiGroups: + - serving.kserve.io + resources: + - localmodelnodes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - serving.kserve.io + resources: + - localmodelnodes/status + verbs: + - get + - patch + - update diff --git a/assets/optional/ai-model-serving/kserve/rbac/localmodelnode/role_binding.yaml b/assets/optional/ai-model-serving/kserve/rbac/localmodelnode/role_binding.yaml new file mode 100644 index 0000000000..de5102d0b2 --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/rbac/localmodelnode/role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kserve-localmodelnode-agent-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: kserve-localmodelnode-agent-role +subjects: +- kind: ServiceAccount + name: kserve-localmodelnode-agent + namespace: kserve \ No newline at end of file diff --git a/assets/optional/ai-model-serving/kserve/rbac/localmodelnode/service_account.yaml b/assets/optional/ai-model-serving/kserve/rbac/localmodelnode/service_account.yaml new file mode 100644 index 0000000000..a3df97b37b --- /dev/null +++ b/assets/optional/ai-model-serving/kserve/rbac/localmodelnode/service_account.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/instance: kserve-localmodelnode-agent + app.kubernetes.io/managed-by: kserve-localmodelnode-agent + app.kubernetes.io/name: kserve-localmodelnode-agent + name: kserve-localmodelnode-agent + namespace: kserve diff --git a/assets/optional/ai-model-serving/kserve/rbac/role.yaml b/assets/optional/ai-model-serving/kserve/rbac/role.yaml index 1371ff8b70..a89ba73a17 100644 --- a/assets/optional/ai-model-serving/kserve/rbac/role.yaml +++ b/assets/optional/ai-model-serving/kserve/rbac/role.yaml @@ -4,6 +4,10 @@ kind: ClusterRole metadata: name: kserve-manager-role rules: +- nonResourceURLs: + - /metrics + verbs: + - get - apiGroups: - "" resources: @@ -16,6 +20,8 @@ rules: - "" resources: - events + - secrets + - serviceaccounts - services verbs: - create @@ -35,25 +41,41 @@ rules: - list - watch - apiGroups: - - "" + - admissionregistration.k8s.io resources: - - secrets + - mutatingwebhookconfigurations + - validatingwebhookconfigurations verbs: + - create + - delete - get + - list + - patch + - update + - watch - apiGroups: - - "" + - apps resources: - - serviceaccounts + - deployments verbs: - create - delete - get + - list - patch + - update + - watch - apiGroups: - - admissionregistration.k8s.io + - authentication.k8s.io resources: - - mutatingwebhookconfigurations - - validatingwebhookconfigurations + - subjectaccessreviews + - tokenreviews + verbs: + - create +- apiGroups: + - autoscaling + resources: + - horizontalpodautoscalers verbs: - create - delete @@ -63,9 +85,19 @@ rules: - update - watch - apiGroups: - - apps + - discovery.k8s.io resources: - - deployments + - endpointslices + verbs: + - get + - list + - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - gatewayclasses + - gateways + - httproutes verbs: - create - delete @@ -75,9 +107,56 @@ rules: - update - watch - apiGroups: - - autoscaling + - inference.networking.x-k8s.io resources: - - horizontalpodautoscalers + - inferencemodels + - inferencepools + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - keda.sh + resources: + - scaledobjects + - scaledobjects/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - keda.sh + resources: + - scaledobjects/status + verbs: + - get + - patch + - update +- apiGroups: + - leaderworkerset.x-k8s.io + resources: + - leaderworkersets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - monitoring.coreos.com + resources: + - podmonitors + - servicemonitors verbs: - create - delete @@ -89,6 +168,7 @@ rules: - apiGroups: - networking.istio.io resources: + - destinationrules - virtualservices - virtualservices/finalizers verbs: @@ -120,13 +200,26 @@ rules: - update - watch - apiGroups: - - operator.knative.dev + - opentelemetry.io resources: - - knativeservings + - opentelemetrycollectors + - opentelemetrycollectors/finalizers verbs: + - create + - delete - get - list + - patch + - update - watch +- apiGroups: + - opentelemetry.io + resources: + - opentelemetrycollectors/status + verbs: + - get + - patch + - update - apiGroups: - rbac.authorization.k8s.io resourceNames: @@ -138,6 +231,20 @@ rules: - get - patch - update +- apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterrolebindings + - rolebindings + - roles + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - route.openshift.io resources: @@ -156,6 +263,14 @@ rules: - routes/status verbs: - get +- apiGroups: + - security.openshift.io + resourceNames: + - openshift-ai-llminferenceservice-scc + resources: + - securitycontextconstraints + verbs: + - use - apiGroups: - serving.knative.dev resources: @@ -177,13 +292,6 @@ rules: - get - patch - update -- apiGroups: - - serving.kserve.io - resources: - - clusterlocalmodels - verbs: - - get - - list - apiGroups: - serving.kserve.io resources: @@ -194,6 +302,8 @@ rules: - inferencegraphs/finalizers - inferenceservices - inferenceservices/finalizers + - llminferenceserviceconfigs + - llminferenceservices - servingruntimes - servingruntimes/finalizers - trainedmodels @@ -211,9 +321,25 @@ rules: - clusterservingruntimes/status - inferencegraphs/status - inferenceservices/status + - llminferenceservices/status - servingruntimes/status - trainedmodels/status verbs: - get - patch - update +- apiGroups: + - serving.kserve.io + resources: + - llminferenceserviceconfigs/finalizers + - llminferenceservices/finalizers + verbs: + - update +- apiGroups: + - serving.kserve.io + resources: + - localmodelcaches + verbs: + - get + - list + - watch diff --git a/assets/optional/ai-model-serving/kserve/webhook/manifests.yaml b/assets/optional/ai-model-serving/kserve/webhook/manifests.yaml index 85265a00dd..b1a53ecdf2 100644 --- a/assets/optional/ai-model-serving/kserve/webhook/manifests.yaml +++ b/assets/optional/ai-model-serving/kserve/webhook/manifests.yaml @@ -132,32 +132,32 @@ webhooks: resources: - inferencegraphs --- -#apiVersion: admissionregistration.k8s.io/v1 -#kind: ValidatingWebhookConfiguration -#metadata: -# creationTimestamp: null -# name: clusterservingruntime.serving.kserve.io -#webhooks: -# - clientConfig: -# service: -# name: $(webhookServiceName) -# namespace: $(kserveNamespace) -# path: /validate-serving-kserve-io-v1alpha1-clusterservingruntime -# failurePolicy: Fail -# name: clusterservingruntime.kserve-webhook-server.validator -# sideEffects: None -# admissionReviewVersions: ["v1beta1"] -# rules: -# - apiGroups: -# - serving.kserve.io -# apiVersions: -# - v1alpha1 -# operations: -# - CREATE -# - UPDATE -# resources: -# - clusterservingruntimes -#--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: clusterservingruntime.serving.kserve.io +webhooks: + - clientConfig: + service: + name: $(webhookServiceName) + namespace: $(kserveNamespace) + path: /validate-serving-kserve-io-v1alpha1-clusterservingruntime + failurePolicy: Fail + name: clusterservingruntime.kserve-webhook-server.validator + sideEffects: None + admissionReviewVersions: ["v1beta1"] + rules: + - apiGroups: + - serving.kserve.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - clusterservingruntimes +--- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: @@ -183,3 +183,83 @@ webhooks: - UPDATE resources: - servingruntimes +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: localmodelcache.serving.kserve.io +webhooks: + - clientConfig: + service: + name: $(webhookServiceName) + namespace: $(kserveNamespace) + path: /validate-serving-kserve-io-v1alpha1-localmodelcache + failurePolicy: Fail + name: localmodelcache.kserve-webhook-server.validator + sideEffects: None + admissionReviewVersions: ["v1beta1"] + rules: + - apiGroups: + - serving.kserve.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - localmodelcaches +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: llminferenceservice.serving.kserve.io +webhooks: + - clientConfig: + service: + name: $(webhookServiceName) + namespace: $(kserveNamespace) + path: /validate-serving-kserve-io-v1alpha1-llminferenceservice + failurePolicy: Fail + name: llminferenceservice.kserve-webhook-server.validator + sideEffects: None + admissionReviewVersions: [ "v1", "v1beta1" ] + rules: + - apiGroups: + - serving.kserve.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - llminferenceservices +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: llminferenceserviceconfig.serving.kserve.io +webhooks: + - clientConfig: + service: + name: $(webhookServiceName) + namespace: $(kserveNamespace) + path: /validate-serving-kserve-io-v1alpha1-llminferenceserviceconfig + failurePolicy: Fail + name: llminferenceserviceconfig.kserve-webhook-server.validator + sideEffects: None + admissionReviewVersions: [ "v1", "v1beta1" ] + rules: + - apiGroups: + - serving.kserve.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - llminferenceserviceconfigs diff --git a/assets/optional/ai-model-serving/release-ai-model-serving-x86_64.json b/assets/optional/ai-model-serving/release-ai-model-serving-x86_64.json index 3a787b8d51..4e924e5ecc 100644 --- a/assets/optional/ai-model-serving/release-ai-model-serving-x86_64.json +++ b/assets/optional/ai-model-serving/release-ai-model-serving-x86_64.json @@ -1,24 +1,26 @@ { "release": { - "base": "2.22.2" + "base": "2.25.0" }, "images": { - "caikit-tgis-image": "quay.io/modh/caikit-tgis-serving@sha256:d8294f446afefc6cbba0df882bba12cdad142f79b29bda46227a6328128d7fb6", - "caikit-standalone-image": "quay.io/modh/caikit-nlp@sha256:c867652a543eacd8288d08e9d38d8d25468c04fb838eebf450906293890b040d", - "tgis-image": "quay.io/modh/text-generation-inference@sha256:e923ebb8e6b8bbc28144d3f143c8453a4c526bc1852952209976cc27a311883b", - "ovms-image": "quay.io/modh/openvino_model_server@sha256:eee2857ddd5cc2df9ea7373ae7c6ae814d77bd631db5c52b91edad18ac6c73c8", - "vllm-cuda-image": "quay.io/modh/vllm@sha256:56aa86c6ed6ba6cc9557a8583ff9d4ee535193f6cda030bd1268064bc70120e3", - "guardrails-detector-huggingface-runtime-image": "quay.io/modh/odh-trustyai-hf-detector-runtime-rhel9@sha256:86316078a2d70ed2d754d683f0daedb76e632dd2b0588afa7713ce2a2a593e2f", - "vllm-cpu-image": "quay.io/modh/vllm@sha256:40e3b271035a750fb185cedb241a108ba0c11de90793d88983aaf805e5357f45", - "vllm-gaudi-image": "quay.io/modh/vllm@sha256:6025bfb31163b7db86d7f0a844da068c88babf4e970c5244492e82bdbaf8dcbe", - "vllm-ppc64le-image": "quay.io/opendatahub/vllm:fast-ppc64le", - "vllm-rocm-image": "quay.io/modh/vllm@sha256:2a90ded5cab4c03d4937c81cf0587cb0109c589e37058a50099139ab62a0666c", - "vllm-s390x-image": "quay.io/opendatahub/vllm:fast-s390x", "ray-tls-generator-image": "registry.redhat.io/ubi9/ubi-minimal:latest", - "kserve-controller": "quay.io/modh/kserve-controller@sha256:67672b25f5e4c2ba5457d29f0c5ae5b7e0ec3b635bf58a79892306ddda30ac2a", - "kserve-agent": "quay.io/modh/kserve-agent@sha256:26967e2807991a1fbd3f69dfb46ffe451edb610bc9ea24c64ca835e0135d5a96", - "kserve-router": "quay.io/modh/kserve-router@sha256:8e73a4b58e1218115236f920ffe2671fb9a2166498ea17b885862df142be9036", - "kserve-storage-initializer": "quay.io/modh/kserve-storage-initializer@sha256:87272d0875618b3768f72cefc70169fea17be8f7513dab0ad74dd6205d0ce3f8", + "caikit-tgis-image": "quay.io/opendatahub/caikit-tgis-serving:fast", + "caikit-standalone-image": "quay.io/opendatahub/caikit-nlp:fast", + "tgis-image": "quay.io/modh/text-generation-inference@sha256:8419f73485c75b4eb0095d31879cc1a94e2be38a0ece08bc7923cef9cdd9444a", + "ovms-image": "quay.io/opendatahub/openvino_model_server:2025.1-release", + "vllm-cuda-image": "quay.io/opendatahub/vllm:fast", + "vllm-cpu-image": "quay.io/opendatahub/vllm:fast-cpu", + "vllm-gaudi-image": "quay.io/opendatahub/vllm:fast-gaudi", + "vllm-rocm-image": "quay.io/opendatahub/vllm:fast-rocm", + "vllm-spyre-image": "registry.redhat.io/rhaiis/vllm-spyre-rhel9@sha256:f36864ec0d7a18a3143296ba2e624eca1fa6ba0af87a7196b325384785bbcf4b", + "guardrails-detector-huggingface-runtime-image": "quay.io/trustyai/guardrails-detector-huggingface-runtime:latest", + "kserve-controller": "quay.io/opendatahub/kserve-controller:stable-2.x", + "kserve-agent": "quay.io/opendatahub/kserve-agent:stable-2.x", + "kserve-router": "quay.io/opendatahub/kserve-router:stable-2.x", + "kserve-storage-initializer": "quay.io/opendatahub/kserve-storage-initializer:stable-2.x", + "kserve-llm-d": "ghcr.io/llm-d/llm-d-dev:sha-b3f0b0d", + "kserve-llm-d-inference-scheduler": "quay.io/opendatahub/llm-d-inference-scheduler:odh-v2.33", + "kserve-llm-d-routing-sidecar": "quay.io/opendatahub/llm-d-routing-sidecar:odh-v2.33", "oauth-proxy": "registry.redhat.io/openshift4/ose-oauth-proxy@sha256:bd49cfc8452b3d96467cc222db9487e120abc6cc5ba81349c6b3703706f36a08" } } diff --git a/assets/optional/ai-model-serving/runtimes/kustomization.x86_64.yaml b/assets/optional/ai-model-serving/runtimes/kustomization.x86_64.yaml index d6d4165f75..210fb0d3ae 100644 --- a/assets/optional/ai-model-serving/runtimes/kustomization.x86_64.yaml +++ b/assets/optional/ai-model-serving/runtimes/kustomization.x86_64.yaml @@ -1,38 +1,35 @@ images: + - name: ray-tls-generator-image + newName: registry.redhat.io/ubi9/ubi-minimal:latest + digest: registry.redhat.io/ubi9/ubi-minimal:latest - name: caikit-tgis-image - newName: quay.io/modh/caikit-tgis-serving - digest: sha256:d8294f446afefc6cbba0df882bba12cdad142f79b29bda46227a6328128d7fb6 + newName: quay.io/opendatahub/caikit-tgis-serving:fast + digest: quay.io/opendatahub/caikit-tgis-serving:fast - name: caikit-standalone-image - newName: quay.io/modh/caikit-nlp - digest: sha256:c867652a543eacd8288d08e9d38d8d25468c04fb838eebf450906293890b040d + newName: quay.io/opendatahub/caikit-nlp:fast + digest: quay.io/opendatahub/caikit-nlp:fast - name: tgis-image newName: quay.io/modh/text-generation-inference - digest: sha256:e923ebb8e6b8bbc28144d3f143c8453a4c526bc1852952209976cc27a311883b + digest: sha256:8419f73485c75b4eb0095d31879cc1a94e2be38a0ece08bc7923cef9cdd9444a - name: ovms-image - newName: quay.io/modh/openvino_model_server - digest: sha256:eee2857ddd5cc2df9ea7373ae7c6ae814d77bd631db5c52b91edad18ac6c73c8 + newName: quay.io/opendatahub/openvino_model_server:2025.1-release + digest: quay.io/opendatahub/openvino_model_server:2025.1-release - name: vllm-cuda-image - newName: quay.io/modh/vllm - digest: sha256:56aa86c6ed6ba6cc9557a8583ff9d4ee535193f6cda030bd1268064bc70120e3 - - name: guardrails-detector-huggingface-runtime-image - newName: quay.io/modh/odh-trustyai-hf-detector-runtime-rhel9 - digest: sha256:86316078a2d70ed2d754d683f0daedb76e632dd2b0588afa7713ce2a2a593e2f + newName: quay.io/opendatahub/vllm:fast + digest: quay.io/opendatahub/vllm:fast - name: vllm-cpu-image - newName: quay.io/modh/vllm - digest: sha256:40e3b271035a750fb185cedb241a108ba0c11de90793d88983aaf805e5357f45 + newName: quay.io/opendatahub/vllm:fast-cpu + digest: quay.io/opendatahub/vllm:fast-cpu - name: vllm-gaudi-image - newName: quay.io/modh/vllm - digest: sha256:6025bfb31163b7db86d7f0a844da068c88babf4e970c5244492e82bdbaf8dcbe - - name: vllm-ppc64le-image - newName: quay.io/opendatahub/vllm:fast-ppc64le - digest: quay.io/opendatahub/vllm:fast-ppc64le + newName: quay.io/opendatahub/vllm:fast-gaudi + digest: quay.io/opendatahub/vllm:fast-gaudi - name: vllm-rocm-image - newName: quay.io/modh/vllm - digest: sha256:2a90ded5cab4c03d4937c81cf0587cb0109c589e37058a50099139ab62a0666c - - name: vllm-s390x-image - newName: quay.io/opendatahub/vllm:fast-s390x - digest: quay.io/opendatahub/vllm:fast-s390x - - name: ray-tls-generator-image - newName: registry.redhat.io/ubi9/ubi-minimal:latest - digest: registry.redhat.io/ubi9/ubi-minimal:latest + newName: quay.io/opendatahub/vllm:fast-rocm + digest: quay.io/opendatahub/vllm:fast-rocm + - name: vllm-spyre-image + newName: registry.redhat.io/rhaiis/vllm-spyre-rhel9 + digest: sha256:f36864ec0d7a18a3143296ba2e624eca1fa6ba0af87a7196b325384785bbcf4b + - name: guardrails-detector-huggingface-runtime-image + newName: quay.io/trustyai/guardrails-detector-huggingface-runtime:latest + digest: quay.io/trustyai/guardrails-detector-huggingface-runtime:latest diff --git a/assets/optional/ai-model-serving/runtimes/ovms-kserve.yaml b/assets/optional/ai-model-serving/runtimes/ovms-kserve.yaml index 278ed3e85d..c2601b4449 100644 --- a/assets/optional/ai-model-serving/runtimes/ovms-kserve.yaml +++ b/assets/optional/ai-model-serving/runtimes/ovms-kserve.yaml @@ -4,7 +4,7 @@ metadata: annotations: openshift.io/display-name: OpenVINO Model Server opendatahub.io/recommended-accelerators: '["nvidia.com/gpu"]' - opendatahub.io/runtime-version: 'v2025.1' + opendatahub.io/runtime-version: 'v2025.2.1' name: kserve-ovms labels: opendatahub.io/dashboard: 'true' diff --git a/assets/optional/ai-model-serving/runtimes/vllm-cuda.yaml b/assets/optional/ai-model-serving/runtimes/vllm-cuda.yaml index de0960f325..98bb9037a2 100644 --- a/assets/optional/ai-model-serving/runtimes/vllm-cuda.yaml +++ b/assets/optional/ai-model-serving/runtimes/vllm-cuda.yaml @@ -5,7 +5,7 @@ metadata: annotations: openshift.io/display-name: vLLM NVIDIA GPU ServingRuntime for KServe opendatahub.io/recommended-accelerators: '["nvidia.com/gpu"]' - opendatahub.io/runtime-version: 'v0.9.1.0' + opendatahub.io/runtime-version: 'v0.10.1.1' labels: opendatahub.io/dashboard: "true" spec: diff --git a/assets/optional/ai-model-serving/runtimes/vllm-gaudi.yaml b/assets/optional/ai-model-serving/runtimes/vllm-gaudi.yaml index 90081ba36e..d9ae5def1f 100644 --- a/assets/optional/ai-model-serving/runtimes/vllm-gaudi.yaml +++ b/assets/optional/ai-model-serving/runtimes/vllm-gaudi.yaml @@ -5,7 +5,7 @@ metadata: annotations: openshift.io/display-name: vLLM Intel Gaudi Accelerator ServingRuntime for KServe opendatahub.io/recommended-accelerators: '["habana.ai/gaudi"]' - opendatahub.io/runtime-version: 'v0.7.2' + opendatahub.io/runtime-version: 'v0.8.5' labels: opendatahub.io/dashboard: 'true' spec: diff --git a/assets/optional/ai-model-serving/runtimes/vllm-rocm.yaml b/assets/optional/ai-model-serving/runtimes/vllm-rocm.yaml index 1c45c0f7dc..8ac4e1d435 100644 --- a/assets/optional/ai-model-serving/runtimes/vllm-rocm.yaml +++ b/assets/optional/ai-model-serving/runtimes/vllm-rocm.yaml @@ -5,7 +5,7 @@ metadata: annotations: openshift.io/display-name: vLLM AMD GPU ServingRuntime for KServe opendatahub.io/recommended-accelerators: '["amd.com/gpu"]' - opendatahub.io/runtime-version: 'v0.8.4.3' + opendatahub.io/runtime-version: 'v0.10.1.1' labels: opendatahub.io/dashboard: 'true' spec: 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 1ce841df79..e0bde39811 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.18.0 + controller-gen.kubebuilder.io/version: v0.19.0 include.release.openshift.io/ibm-cloud-managed: "true" include.release.openshift.io/self-managed-high-availability: "true" capability.openshift.io/name: "OperatorLifecycleManager" @@ -635,8 +635,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. type: array items: 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 63c9bdc6f0..563474fa48 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.18.0 + controller-gen.kubebuilder.io/version: v0.19.0 include.release.openshift.io/ibm-cloud-managed: "true" include.release.openshift.io/self-managed-high-availability: "true" capability.openshift.io/name: "OperatorLifecycleManager" @@ -1386,8 +1386,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. type: array items: @@ -1771,7 +1771,9 @@ spec: - name properties: name: - description: Name of the environment variable. Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -1826,6 +1828,42 @@ spec: description: Path of the field to select in the specified API version. type: string x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + type: object + required: + - key + - path + - volumeName + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + default: false + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing the env file. + type: string + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -1876,8 +1914,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -1904,7 +1942,9 @@ spec: type: boolean x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -2548,7 +2588,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -2601,10 +2641,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -2616,6 +2656,57 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + type: array + items: + description: ContainerRestartRule describes how a container exit is handled. + type: object + required: + - action + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container exits. + type: object + required: + - operator + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + type: array + items: + type: integer + format: int32 + x-kubernetes-list-type: set + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -3217,7 +3308,9 @@ spec: - name properties: name: - description: Name of the environment variable. Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -3272,6 +3365,42 @@ spec: description: Path of the field to select in the specified API version. type: string x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + type: object + required: + - key + - path + - volumeName + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + default: false + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing the env file. + type: string + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -3322,8 +3451,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -3350,7 +3479,9 @@ spec: type: boolean x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -3973,7 +4104,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -4027,9 +4158,51 @@ spec: description: |- Restart policy for the container to manage the restart behavior of each container within a pod. - This may only be set for init containers. You cannot set this field on - ephemeral containers. + You cannot set this field on ephemeral containers. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. You cannot set this field on + ephemeral containers. + type: array + items: + description: ContainerRestartRule describes how a container exit is handled. + type: object + required: + - action + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container exits. + type: object + required: + - operator + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + type: array + items: + type: integer + format: int32 + x-kubernetes-list-type: set + x-kubernetes-list-type: atomic securityContext: description: |- Optional: SecurityContext defines the security options the ephemeral container should be run with. @@ -4544,7 +4717,9 @@ spec: hostNetwork: description: |- Host networking requested for this pod. Use the host's network namespace. - If this option is set, the ports that will be used must be specified. + When using HostNetwork you should specify ports so the scheduler is aware. + When `hostNetwork` is true, specified `hostPort` fields in port definitions must match `containerPort`, + and unspecified `hostPort` fields in port definitions are defaulted to match `containerPort`. Default to false. type: boolean hostPID: @@ -4569,6 +4744,19 @@ spec: Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value. type: string + hostnameOverride: + description: |- + HostnameOverride specifies an explicit override for the pod's hostname as perceived by the pod. + This field only specifies the pod's hostname and does not affect its DNS records. + When this field is set to a non-empty string: + - It takes precedence over the values set in `hostname` and `subdomain`. + - The Pod's hostname will be set to this value. + - `setHostnameAsFQDN` must be nil or set to false. + - `hostNetwork` must be set to false. + + This field must be a valid DNS subdomain as defined in RFC 1123 and contain at most 64 characters. + Requires the HostnameOverride feature gate to be enabled. + type: string imagePullSecrets: description: |- ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. @@ -4656,7 +4844,9 @@ spec: - name properties: name: - description: Name of the environment variable. Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -4711,6 +4901,42 @@ spec: description: Path of the field to select in the specified API version. type: string x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + type: object + required: + - key + - path + - volumeName + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + default: false + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing the env file. + type: string + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -4761,8 +4987,8 @@ spec: envFrom: description: |- List of sources to populate environment variables in the container. - The keys defined within a source must be a C_IDENTIFIER. All invalid keys - will be reported as an event when the container is starting. When a key exists in multiple + The keys defined within a source may consist of any printable ASCII characters except '='. + When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated. @@ -4789,7 +5015,9 @@ spec: type: boolean x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -5433,7 +5661,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -5486,10 +5714,10 @@ spec: restartPolicy: description: |- RestartPolicy defines the restart behavior of individual containers in a pod. - This field may only be set for init containers, and the only allowed value is "Always". - For non-init containers or when this field is not specified, + This overrides the pod-level restart policy. When this field is not specified, the restart behavior is defined by the Pod's restart policy and the container type. - Setting the RestartPolicy as "Always" for the init container will have the following effect: + Additionally, setting the RestartPolicy as "Always" for the init container will + have the following effect: this init container will be continually restarted on exit until all regular containers have terminated. Once all regular containers have completed, all init containers with restartPolicy "Always" @@ -5501,6 +5729,57 @@ spec: init container is started, or after any startupProbe has successfully completed. type: string + restartPolicyRules: + description: |- + Represents a list of rules to be checked to determine if the + container should be restarted on exit. The rules are evaluated in + order. Once a rule matches a container exit condition, the remaining + rules are ignored. If no rule matches the container exit condition, + the Container-level restart policy determines the whether the container + is restarted or not. Constraints on the rules: + - At most 20 rules are allowed. + - Rules can have the same action. + - Identical rules are not forbidden in validations. + When rules are specified, container MUST set RestartPolicy explicitly + even it if matches the Pod's RestartPolicy. + type: array + items: + description: ContainerRestartRule describes how a container exit is handled. + type: object + required: + - action + properties: + action: + description: |- + Specifies the action taken on a container exit if the requirements + are satisfied. The only possible value is "Restart" to restart the + container. + type: string + exitCodes: + description: Represents the exit codes to check on container exits. + type: object + required: + - operator + properties: + operator: + description: |- + Represents the relationship between the container exit code(s) and the + specified values. Possible values are: + - In: the requirement is satisfied if the container exit code is in the + set of specified values. + - NotIn: the requirement is satisfied if the container exit code is + not in the set of specified values. + type: string + values: + description: |- + Specifies the set of values to check for container exit codes. + At most 255 elements are allowed. + type: array + items: + type: integer + format: int32 + x-kubernetes-list-type: set + x-kubernetes-list-type: atomic securityContext: description: |- SecurityContext defines the security options the container should be run with. @@ -6010,6 +6289,7 @@ spec: - spec.hostPID - spec.hostIPC - spec.hostUsers + - spec.resources - spec.securityContext.appArmorProfile - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile @@ -6161,7 +6441,7 @@ spec: description: |- Resources is the total amount of CPU and Memory resources required by all containers in the pod. It supports specifying Requests and Limits for - "cpu" and "memory" resource names only. ResourceClaims are not supported. + "cpu", "memory" and "hugepages-" resource names only. ResourceClaims are not supported. This field enables fine-grained control over resource allocation for the entire pod, allowing resource sharing among containers in a pod. @@ -6175,7 +6455,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -7409,15 +7689,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -7586,16 +7864,13 @@ spec: description: |- glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. - More info: https://examples.k8s.io/volumes/glusterfs/README.md type: object required: - endpoints - path properties: endpoints: - description: |- - endpoints is the endpoint name that details Glusterfs topology. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod + description: endpoints is the endpoint name that details Glusterfs topology. type: string path: description: |- @@ -7670,7 +7945,7 @@ spec: description: |- iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. - More info: https://examples.k8s.io/volumes/iscsi/README.md + More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi type: object required: - iqn @@ -8063,6 +8338,110 @@ spec: type: string x-kubernetes-map-type: atomic x-kubernetes-list-type: atomic + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + type: object + required: + - keyType + - signerName + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + type: integer + format: int32 + signerName: + description: Kubelet's generated CSRs will be addressed to this signer. + type: string secret: description: secret information about the secret data to project type: object @@ -8189,7 +8568,6 @@ spec: description: |- rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. - More info: https://examples.k8s.io/volumes/rbd/README.md type: object required: - image 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 3fd8618308..08f6701336 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.18.0 + controller-gen.kubebuilder.io/version: v0.19.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 d050561f88..ec2291246b 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.18.0 + controller-gen.kubebuilder.io/version: v0.19.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 8b57b2927c..2f5a208669 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.18.0 + controller-gen.kubebuilder.io/version: v0.19.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 72847359aa..acf2160ddc 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.18.0 + controller-gen.kubebuilder.io/version: v0.19.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 5a0e2ba520..c571a3264a 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.18.0 + controller-gen.kubebuilder.io/version: v0.19.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 b093a12ef5..87ce80f720 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.18.0 + controller-gen.kubebuilder.io/version: v0.19.0 include.release.openshift.io/ibm-cloud-managed: "true" include.release.openshift.io/self-managed-high-availability: "true" capability.openshift.io/name: "OperatorLifecycleManager" @@ -622,8 +622,8 @@ spec: most preferred is the one with the greatest sum of weights, i.e. for each node that meets all of the scheduling requirements (resource request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the node(s) with the highest sum are the most preferred. type: array items: @@ -972,7 +972,9 @@ spec: - name properties: name: - description: Name of the environment variable. Must be a C_IDENTIFIER. + description: |- + Name of the environment variable. + May consist of any printable ASCII characters except '='. type: string value: description: |- @@ -1027,6 +1029,42 @@ spec: description: Path of the field to select in the specified API version. type: string x-kubernetes-map-type: atomic + fileKeyRef: + description: |- + FileKeyRef selects a key of the env file. + Requires the EnvFiles feature gate to be enabled. + type: object + required: + - key + - path + - volumeName + properties: + key: + description: |- + The key within the env file. An invalid key will prevent the pod from starting. + The keys defined within a source may consist of any printable ASCII characters except '='. + During Alpha stage of the EnvFiles feature gate, the key size is limited to 128 characters. + type: string + optional: + description: |- + Specify whether the file or its key must be defined. If the file or key + does not exist, then the env var is not published. + If optional is set to true and the specified key does not exist, + the environment variable will not be set in the Pod's containers. + + If optional is set to false and the specified key does not exist, + an error will be returned during Pod creation. + type: boolean + default: false + path: + description: |- + The path within the volume from which to select the file. + Must be relative and may not contain the '..' path or start with '..'. + type: string + volumeName: + description: The name of the volume mount containing the env file. + type: string + x-kubernetes-map-type: atomic resourceFieldRef: description: |- Selects a resource of the container: only resources limits and requests @@ -1102,7 +1140,9 @@ spec: type: boolean x-kubernetes-map-type: atomic prefix: - description: Optional text to prepend to the name of each environment variable. Must be a C_IDENTIFIER. + description: |- + Optional text to prepend to the name of each environment variable. + May consist of any printable ASCII characters except '='. type: string secretRef: description: The Secret to select from @@ -1141,7 +1181,7 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1991,15 +2031,13 @@ spec: volumeAttributesClassName may be used to set the VolumeAttributesClass used by this claim. If specified, the CSI driver will create or update the volume with the attributes defined in the corresponding VolumeAttributesClass. This has a different purpose than storageClassName, - it can be changed after the claim is created. An empty string value means that no VolumeAttributesClass - will be applied to the claim but it's not allowed to reset this field to empty string once it is set. - If unspecified and the PersistentVolumeClaim is unbound, the default VolumeAttributesClass - will be set by the persistentvolume controller if it exists. + it can be changed after the claim is created. An empty string or nil value indicates that no + VolumeAttributesClass will be applied to the claim. If the claim enters an Infeasible error state, + this field can be reset to its previous value (including nil) to cancel the modification. If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ - (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -2168,16 +2206,13 @@ spec: description: |- glusterfs represents a Glusterfs mount on the host that shares a pod's lifetime. Deprecated: Glusterfs is deprecated and the in-tree glusterfs type is no longer supported. - More info: https://examples.k8s.io/volumes/glusterfs/README.md type: object required: - endpoints - path properties: endpoints: - description: |- - endpoints is the endpoint name that details Glusterfs topology. - More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod + description: endpoints is the endpoint name that details Glusterfs topology. type: string path: description: |- @@ -2252,7 +2287,7 @@ spec: description: |- iscsi represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. - More info: https://examples.k8s.io/volumes/iscsi/README.md + More info: https://kubernetes.io/docs/concepts/storage/volumes/#iscsi type: object required: - iqn @@ -2645,6 +2680,110 @@ spec: type: string x-kubernetes-map-type: atomic x-kubernetes-list-type: atomic + podCertificate: + description: |- + Projects an auto-rotating credential bundle (private key and certificate + chain) that the pod can use either as a TLS client or server. + + Kubelet generates a private key and uses it to send a + PodCertificateRequest to the named signer. Once the signer approves the + request and issues a certificate chain, Kubelet writes the key and + certificate chain to the pod filesystem. The pod does not start until + certificates have been issued for each podCertificate projected volume + source in its spec. + + Kubelet will begin trying to rotate the certificate at the time indicated + by the signer using the PodCertificateRequest.Status.BeginRefreshAt + timestamp. + + Kubelet can write a single file, indicated by the credentialBundlePath + field, or separate files, indicated by the keyPath and + certificateChainPath fields. + + The credential bundle is a single file in PEM format. The first PEM + entry is the private key (in PKCS#8 format), and the remaining PEM + entries are the certificate chain issued by the signer (typically, + signers will return their certificate chain in leaf-to-root order). + + Prefer using the credential bundle format, since your application code + can read it atomically. If you use keyPath and certificateChainPath, + your application must make two separate file reads. If these coincide + with a certificate rotation, it is possible that the private key and leaf + certificate you read may not correspond to each other. Your application + will need to check for this condition, and re-read until they are + consistent. + + The named signer controls chooses the format of the certificate it + issues; consult the signer implementation's documentation to learn how to + use the certificates it issues. + type: object + required: + - keyType + - signerName + properties: + certificateChainPath: + description: |- + Write the certificate chain at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + credentialBundlePath: + description: |- + Write the credential bundle at this path in the projected volume. + + The credential bundle is a single file that contains multiple PEM blocks. + The first PEM block is a PRIVATE KEY block, containing a PKCS#8 private + key. + + The remaining blocks are CERTIFICATE blocks, containing the issued + certificate chain from the signer (leaf and any intermediates). + + Using credentialBundlePath lets your Pod's application code make a single + atomic read that retrieves a consistent key and certificate chain. If you + project them to separate files, your application code will need to + additionally check that the leaf certificate was issued to the key. + type: string + keyPath: + description: |- + Write the key at this path in the projected volume. + + Most applications should use credentialBundlePath. When using keyPath + and certificateChainPath, your application needs to check that the key + and leaf certificate are consistent, because it is possible to read the + files mid-rotation. + type: string + keyType: + description: |- + The type of keypair Kubelet will generate for the pod. + + Valid values are "RSA3072", "RSA4096", "ECDSAP256", "ECDSAP384", + "ECDSAP521", and "ED25519". + type: string + maxExpirationSeconds: + description: |- + maxExpirationSeconds is the maximum lifetime permitted for the + certificate. + + Kubelet copies this value verbatim into the PodCertificateRequests it + generates for this projection. + + If omitted, kube-apiserver will set it to 86400(24 hours). kube-apiserver + will reject values shorter than 3600 (1 hour). The maximum allowable + value is 7862400 (91 days). + + The signer implementation is then free to issue a certificate with any + lifetime *shorter* than MaxExpirationSeconds, but no shorter than 3600 + seconds (1 hour). This constraint is enforced by kube-apiserver. + `kubernetes.io` signers will never issue certificates with a lifetime + longer than 24 hours. + type: integer + format: int32 + signerName: + description: Kubelet's generated CSRs will be addressed to this signer. + type: string secret: description: secret information about the secret data to project type: object @@ -2771,7 +2910,6 @@ spec: description: |- rbd represents a Rados Block Device mount on the host that shares a pod's lifetime. Deprecated: RBD is deprecated and the in-tree rbd type is no longer supported. - More info: https://examples.k8s.io/volumes/rbd/README.md type: object required: - image diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_02-olm-operator.serviceaccount.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_02-olm-operator.serviceaccount.yaml index 8e9ea5f101..febe778850 100644 --- a/assets/optional/operator-lifecycle-manager/0000_50_olm_02-olm-operator.serviceaccount.yaml +++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_02-olm-operator.serviceaccount.yaml @@ -24,6 +24,18 @@ rules: verbs: ["watch", "list", "get", "create", "update", "patch", "delete", "deletecollection", "escalate", "bind"] - nonResourceURLs: ["*"] verbs: ["*"] + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create - apiGroups: - security.openshift.io resources: diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_07-olm-operator.deployment.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_07-olm-operator.deployment.yaml index e9ad66d461..a6ba1bfc02 100644 --- a/assets/optional/operator-lifecycle-manager/0000_50_olm_07-olm-operator.deployment.yaml +++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_07-olm-operator.deployment.yaml @@ -34,7 +34,7 @@ spec: secretName: olm-operator-serving-cert - name: profile-collector-cert secret: - secretName: pprof-cert + secretName: olm-operator-serving-cert - name: tmpfs emptyDir: {} containers: diff --git a/assets/optional/operator-lifecycle-manager/0000_50_olm_08-catalog-operator.deployment.yaml b/assets/optional/operator-lifecycle-manager/0000_50_olm_08-catalog-operator.deployment.yaml index ef3c9c95e7..db08341cc7 100644 --- a/assets/optional/operator-lifecycle-manager/0000_50_olm_08-catalog-operator.deployment.yaml +++ b/assets/optional/operator-lifecycle-manager/0000_50_olm_08-catalog-operator.deployment.yaml @@ -34,7 +34,7 @@ spec: secretName: catalog-operator-serving-cert - name: profile-collector-cert secret: - secretName: pprof-cert + secretName: catalog-operator-serving-cert - name: tmpfs emptyDir: {} containers: diff --git a/assets/optional/operator-lifecycle-manager/kustomization.aarch64.yaml b/assets/optional/operator-lifecycle-manager/kustomization.aarch64.yaml index c298acfb03..37900948cb 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:8a7594e9f71021a699d69d3de0af93506ead8c0ed2c5193b65bc20e2c6190ccb + digest: sha256:3c2782471ebec4abc6afd022de2785c3acf79102111a4d5b5fb3e4f700091a4c - name: quay.io/operator-framework/configmap-operator-registry newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev - digest: sha256:3ebeebf84baeced6f8c27c87bd6bd3d963a8c5b247e7c69397836f399610d1ed + digest: sha256:92bcb72a221712e9d063ca5d8ac131b168593436a0f74a74a0a314e7eadcc944 - name: quay.io/openshift/origin-kube-rbac-proxy newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev - digest: sha256:aaf25c001f1ca459d0c1d8ae9636bf81b2701be9bca1ef8a863ffff05811cb31 + digest: sha256:d4ba33fcc9731eccfbdedcf77a4a53ccff1883d93ce3a3ab6c0014eb26a30e09 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:3ebeebf84baeced6f8c27c87bd6bd3d963a8c5b247e7c69397836f399610d1ed + value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:92bcb72a221712e9d063ca5d8ac131b168593436a0f74a74a0a314e7eadcc944 - 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:8a7594e9f71021a699d69d3de0af93506ead8c0ed2c5193b65bc20e2c6190ccb + value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:3c2782471ebec4abc6afd022de2785c3acf79102111a4d5b5fb3e4f700091a4c 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 59b7dc7f3b..253f592778 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:926010feefc5c7835f6fd4fcb4fdbed75a3284bb4b269c7f671d7fcafa85c3a3 + digest: sha256:c4ae8e6acc0e9449ebe3e3592038abc9077bf61bec5774c306ed090eb90e8378 - name: quay.io/operator-framework/configmap-operator-registry newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev - digest: sha256:b52ca59c7d2caac0c58c1bb63b1541cd8bb6f036d0be4224b1c38d4a990d230d + digest: sha256:7bf2e132136e444b3ace65cd83763cd1824e89b37b73c39d4e1b3c62bcd76d4e - name: quay.io/openshift/origin-kube-rbac-proxy newName: quay.io/openshift-release-dev/ocp-v4.0-art-dev - digest: sha256:34eb149d564a29d9376b8176b5e06be7ba12ca80083f9422d337a6225142ccd9 + digest: sha256:bbeddc00892d4caa3fcfd5926f1ca953594473f892bf65e1e468bd3aecd15b56 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:b52ca59c7d2caac0c58c1bb63b1541cd8bb6f036d0be4224b1c38d4a990d230d + value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:7bf2e132136e444b3ace65cd83763cd1824e89b37b73c39d4e1b3c62bcd76d4e - 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:926010feefc5c7835f6fd4fcb4fdbed75a3284bb4b269c7f671d7fcafa85c3a3 + value: quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:c4ae8e6acc0e9449ebe3e3592038abc9077bf61bec5774c306ed090eb90e8378 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 a75b774998..d1b0618bac 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.21.0-0.nightly-arm64-2025-10-19-182251" + "base": "4.21.0-0.nightly-arm64-2025-12-12-014247" }, "images": { - "operator-lifecycle-manager": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:8a7594e9f71021a699d69d3de0af93506ead8c0ed2c5193b65bc20e2c6190ccb", - "operator-registry": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:3ebeebf84baeced6f8c27c87bd6bd3d963a8c5b247e7c69397836f399610d1ed", - "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:aaf25c001f1ca459d0c1d8ae9636bf81b2701be9bca1ef8a863ffff05811cb31" + "operator-lifecycle-manager": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:3c2782471ebec4abc6afd022de2785c3acf79102111a4d5b5fb3e4f700091a4c", + "operator-registry": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:92bcb72a221712e9d063ca5d8ac131b168593436a0f74a74a0a314e7eadcc944", + "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:d4ba33fcc9731eccfbdedcf77a4a53ccff1883d93ce3a3ab6c0014eb26a30e09" } } 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 b3a5f19a93..5ca3aef4b9 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.21.0-0.nightly-2025-10-19-181151" + "base": "4.21.0-0.nightly-2025-12-10-193741" }, "images": { - "operator-lifecycle-manager": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:926010feefc5c7835f6fd4fcb4fdbed75a3284bb4b269c7f671d7fcafa85c3a3", - "operator-registry": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:b52ca59c7d2caac0c58c1bb63b1541cd8bb6f036d0be4224b1c38d4a990d230d", - "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:34eb149d564a29d9376b8176b5e06be7ba12ca80083f9422d337a6225142ccd9" + "operator-lifecycle-manager": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:c4ae8e6acc0e9449ebe3e3592038abc9077bf61bec5774c306ed090eb90e8378", + "operator-registry": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:7bf2e132136e444b3ace65cd83763cd1824e89b37b73c39d4e1b3c62bcd76d4e", + "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:bbeddc00892d4caa3fcfd5926f1ca953594473f892bf65e1e468bd3aecd15b56" } } diff --git a/assets/optional/sriov/crd/sriovnetwork.openshift.io_ovsnetworks.yaml b/assets/optional/sriov/crd/sriovnetwork.openshift.io_ovsnetworks.yaml new file mode 100644 index 0000000000..da03833442 --- /dev/null +++ b/assets/optional/sriov/crd/sriovnetwork.openshift.io_ovsnetworks.yaml @@ -0,0 +1,111 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: ovsnetworks.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: OVSNetwork + listKind: OVSNetworkList + plural: ovsnetworks + singular: ovsnetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: OVSNetwork is the Schema for the ovsnetworks API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: OVSNetworkSpec defines the desired state of OVSNetwork + properties: + bridge: + description: |- + name of the OVS bridge, if not set OVS will automatically select bridge + based on VF PCI address + type: string + capabilities: + description: |- + Capabilities to be configured for this network. + Capabilities supported: (mac|ips), e.g. '{"mac": true}' + type: string + interfaceType: + description: The type of interface on ovs. + type: string + ipam: + description: IPAM configuration to be used for this network. + type: string + metaPlugins: + description: MetaPluginsConfig configuration to be used in order to + chain metaplugins + type: string + mtu: + description: Mtu for the OVS port + type: integer + networkNamespace: + description: Namespace of the NetworkAttachmentDefinition custom resource + type: string + resourceName: + description: OVS Network device plugin endpoint resource name + type: string + trunk: + description: Trunk configuration for the OVS port + items: + description: TrunkConfig contains configuration for bridge trunk + properties: + id: + maximum: 4095 + minimum: 0 + type: integer + maxID: + maximum: 4095 + minimum: 0 + type: integer + minID: + maximum: 4095 + minimum: 0 + type: integer + type: object + type: array + vlan: + description: Vlan to assign for the OVS port + maximum: 4095 + minimum: 0 + type: integer + required: + - resourceName + type: object + status: + description: OVSNetworkStatus defines the observed state of OVSNetwork + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovibnetworks.yaml b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovibnetworks.yaml new file mode 100644 index 0000000000..c8eb80e6b3 --- /dev/null +++ b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovibnetworks.yaml @@ -0,0 +1,84 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: sriovibnetworks.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovIBNetwork + listKind: SriovIBNetworkList + plural: sriovibnetworks + singular: sriovibnetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovIBNetwork is the Schema for the sriovibnetworks API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovIBNetworkSpec defines the desired state of SriovIBNetwork + properties: + capabilities: + description: |- + Capabilities to be configured for this network. + Capabilities supported: (infinibandGUID), e.g. '{"infinibandGUID": true}' + type: string + ipam: + description: IPAM configuration to be used for this network. + type: string + linkState: + description: VF link state (enable|disable|auto) + enum: + - auto + - enable + - disable + type: string + metaPlugins: + description: |- + MetaPluginsConfig configuration to be used in order to chain metaplugins to the sriov interface returned + by the operator. + type: string + networkNamespace: + description: Namespace of the NetworkAttachmentDefinition custom resource + type: string + resourceName: + description: SRIOV Network device plugin endpoint resource name + type: string + required: + - resourceName + type: object + status: + description: SriovIBNetworkStatus defines the observed state of SriovIBNetwork + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml new file mode 100644 index 0000000000..aef366078a --- /dev/null +++ b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml @@ -0,0 +1,219 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: sriovnetworknodepolicies.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetworkNodePolicy + listKind: SriovNetworkNodePolicyList + plural: sriovnetworknodepolicies + singular: sriovnetworknodepolicy + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovNetworkNodePolicy is the Schema for the sriovnetworknodepolicies + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovNetworkNodePolicySpec defines the desired state of SriovNetworkNodePolicy + properties: + bridge: + description: |- + contains bridge configuration for matching PFs, + valid only for eSwitchMode==switchdev + properties: + ovs: + description: contains configuration for the OVS bridge, + properties: + bridge: + description: contains bridge level settings + properties: + datapathType: + description: configure datapath_type field in the Bridge + table in OVSDB + type: string + externalIDs: + additionalProperties: + type: string + description: IDs to inject to external_ids field in the + Bridge table in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: additional options to inject to other_config + field in the bridge table in OVSDB + type: object + type: object + uplink: + description: contains settings for uplink (PF) + properties: + interface: + description: contains settings for PF interface in the + OVS bridge + properties: + externalIDs: + additionalProperties: + type: string + description: external_ids field in the Interface table + in OVSDB + type: object + mtuRequest: + description: mtu_request field in the Interface table + in OVSDB + type: integer + options: + additionalProperties: + type: string + description: options field in the Interface table + in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: other_config field in the Interface table + in OVSDB + type: object + type: + description: type field in the Interface table in + OVSDB + type: string + type: object + type: object + type: object + type: object + deviceType: + default: netdevice + description: The driver type for configured VFs. Allowed value "netdevice", + "vfio-pci". Defaults to netdevice. + enum: + - netdevice + - vfio-pci + type: string + eSwitchMode: + description: NIC Device Mode. Allowed value "legacy","switchdev". + enum: + - legacy + - switchdev + type: string + excludeTopology: + description: Exclude device's NUMA node when advertising this resource + by SRIOV network device plugin. Default to false. + type: boolean + externallyManaged: + description: don't create the virtual function only allocated them + to the device plugin. Defaults to false. + type: boolean + isRdma: + description: RDMA mode. Defaults to false. + type: boolean + linkType: + description: NIC Link Type. Allowed value "eth", "ETH", "ib", and + "IB". + enum: + - eth + - ETH + - ib + - IB + type: string + mtu: + description: MTU of VF + minimum: 1 + type: integer + needVhostNet: + description: mount vhost-net device. Defaults to false. + type: boolean + nicSelector: + description: NicSelector selects the NICs to be configured + properties: + deviceID: + description: The device hex code of SR-IoV device. Allowed value + "0d58", "1572", "158b", "1013", "1015", "1017", "101b". + type: string + netFilter: + description: Infrastructure Networking selection filter. Allowed + value "openstack/NetworkID:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + type: string + pfNames: + description: Name of SR-IoV PF. + items: + type: string + type: array + rootDevices: + description: PCI address of SR-IoV PF. + items: + type: string + type: array + vendor: + description: The vendor hex code of SR-IoV device. Allowed value + "8086", "15b3". + type: string + type: object + nodeSelector: + additionalProperties: + type: string + description: NodeSelector selects the nodes to be configured + type: object + numVfs: + description: Number of VFs for each PF + minimum: 0 + type: integer + priority: + description: Priority of the policy, higher priority policies can + override lower ones. + maximum: 99 + minimum: 0 + type: integer + resourceName: + description: SRIOV Network device plugin endpoint resource name + type: string + vdpaType: + description: VDPA device type. Allowed value "virtio", "vhost" + enum: + - virtio + - vhost + type: string + required: + - nicSelector + - nodeSelector + - numVfs + - resourceName + type: object + status: + description: SriovNetworkNodePolicyStatus defines the observed state of + SriovNetworkNodePolicy + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworknodestates.yaml b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworknodestates.yaml new file mode 100644 index 0000000000..63991800f7 --- /dev/null +++ b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworknodestates.yaml @@ -0,0 +1,375 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: sriovnetworknodestates.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetworkNodeState + listKind: SriovNetworkNodeStateList + plural: sriovnetworknodestates + singular: sriovnetworknodestate + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.syncStatus + name: Sync Status + type: string + - jsonPath: .metadata.annotations.sriovnetwork\.openshift\.io/desired-state + name: Desired Sync State + type: string + - jsonPath: .metadata.annotations.sriovnetwork\.openshift\.io/current-state + name: Current Sync State + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1 + schema: + openAPIV3Schema: + description: SriovNetworkNodeState is the Schema for the sriovnetworknodestates + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovNetworkNodeStateSpec defines the desired state of SriovNetworkNodeState + properties: + bridges: + description: Bridges contains list of bridges + properties: + ovs: + items: + description: OVSConfigExt contains configuration for the concrete + OVS bridge + properties: + bridge: + description: bridge-level configuration for the bridge + properties: + datapathType: + description: configure datapath_type field in the Bridge + table in OVSDB + type: string + externalIDs: + additionalProperties: + type: string + description: IDs to inject to external_ids field in + the Bridge table in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: additional options to inject to other_config + field in the bridge table in OVSDB + type: object + type: object + name: + description: name of the bridge + type: string + uplinks: + description: |- + uplink-level bridge configuration for each uplink(PF). + currently must contain only one element + items: + description: OVSUplinkConfigExt contains configuration + for the concrete OVS uplink(PF) + properties: + interface: + description: configuration from the Interface OVS + table for the PF + properties: + externalIDs: + additionalProperties: + type: string + description: external_ids field in the Interface + table in OVSDB + type: object + mtuRequest: + description: mtu_request field in the Interface + table in OVSDB + type: integer + options: + additionalProperties: + type: string + description: options field in the Interface table + in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: other_config field in the Interface + table in OVSDB + type: object + type: + description: type field in the Interface table + in OVSDB + type: string + type: object + name: + description: name of the PF interface + type: string + pciAddress: + description: pci address of the PF + type: string + required: + - pciAddress + type: object + type: array + required: + - name + type: object + type: array + type: object + interfaces: + items: + properties: + eSwitchMode: + type: string + externallyManaged: + type: boolean + linkType: + type: string + mtu: + type: integer + name: + type: string + numVfs: + type: integer + pciAddress: + type: string + vfGroups: + items: + properties: + deviceType: + type: string + isRdma: + type: boolean + mtu: + type: integer + policyName: + type: string + resourceName: + type: string + vdpaType: + type: string + vfRange: + type: string + type: object + type: array + required: + - pciAddress + type: object + type: array + system: + properties: + rdmaMode: + description: RDMA subsystem. Allowed value "shared", "exclusive". + enum: + - shared + - exclusive + type: string + type: object + type: object + status: + description: SriovNetworkNodeStateStatus defines the observed state of + SriovNetworkNodeState + properties: + bridges: + description: Bridges contains list of bridges + properties: + ovs: + items: + description: OVSConfigExt contains configuration for the concrete + OVS bridge + properties: + bridge: + description: bridge-level configuration for the bridge + properties: + datapathType: + description: configure datapath_type field in the Bridge + table in OVSDB + type: string + externalIDs: + additionalProperties: + type: string + description: IDs to inject to external_ids field in + the Bridge table in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: additional options to inject to other_config + field in the bridge table in OVSDB + type: object + type: object + name: + description: name of the bridge + type: string + uplinks: + description: |- + uplink-level bridge configuration for each uplink(PF). + currently must contain only one element + items: + description: OVSUplinkConfigExt contains configuration + for the concrete OVS uplink(PF) + properties: + interface: + description: configuration from the Interface OVS + table for the PF + properties: + externalIDs: + additionalProperties: + type: string + description: external_ids field in the Interface + table in OVSDB + type: object + mtuRequest: + description: mtu_request field in the Interface + table in OVSDB + type: integer + options: + additionalProperties: + type: string + description: options field in the Interface table + in OVSDB + type: object + otherConfig: + additionalProperties: + type: string + description: other_config field in the Interface + table in OVSDB + type: object + type: + description: type field in the Interface table + in OVSDB + type: string + type: object + name: + description: name of the PF interface + type: string + pciAddress: + description: pci address of the PF + type: string + required: + - pciAddress + type: object + type: array + required: + - name + type: object + type: array + type: object + interfaces: + items: + properties: + Vfs: + items: + properties: + Vlan: + type: integer + assigned: + type: string + deviceID: + type: string + driver: + type: string + guid: + type: string + mac: + type: string + mtu: + type: integer + name: + type: string + pciAddress: + type: string + representorName: + type: string + vdpaType: + type: string + vendor: + type: string + vfID: + type: integer + required: + - pciAddress + - vfID + type: object + type: array + deviceID: + type: string + driver: + type: string + eSwitchMode: + type: string + externallyManaged: + type: boolean + linkAdminState: + type: string + linkSpeed: + type: string + linkType: + type: string + mac: + type: string + mtu: + type: integer + name: + type: string + netFilter: + type: string + numVfs: + type: integer + pciAddress: + type: string + totalvfs: + type: integer + vendor: + type: string + required: + - pciAddress + type: object + type: array + lastSyncError: + type: string + syncStatus: + type: string + system: + properties: + rdmaMode: + description: RDMA subsystem. Allowed value "shared", "exclusive". + enum: + - shared + - exclusive + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml new file mode 100644 index 0000000000..d0a2e31d5d --- /dev/null +++ b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml @@ -0,0 +1,137 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: sriovnetworkpoolconfigs.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetworkPoolConfig + listKind: SriovNetworkPoolConfigList + plural: sriovnetworkpoolconfigs + singular: sriovnetworkpoolconfig + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovNetworkPoolConfig is the Schema for the sriovnetworkpoolconfigs + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovNetworkPoolConfigSpec defines the desired state of SriovNetworkPoolConfig + properties: + maxUnavailable: + anyOf: + - type: integer + - type: string + description: |- + maxUnavailable defines either an integer number or percentage + of nodes in the pool that can go Unavailable during an update. + + + A value larger than 1 will mean multiple nodes going unavailable during + the update, which may affect your workload stress on the remaining nodes. + Drain will respect Pod Disruption Budgets (PDBs) such as etcd quorum guards, + even if maxUnavailable is greater than one. + x-kubernetes-int-or-string: true + nodeSelector: + description: nodeSelector specifies a label selector for Nodes + properties: + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + ovsHardwareOffloadConfig: + description: OvsHardwareOffloadConfig describes the OVS HWOL configuration + for selected Nodes + properties: + name: + description: |- + Name is mandatory and must be unique. + On Kubernetes: + Name is the name of OvsHardwareOffloadConfig + On OpenShift: + Name is the name of MachineConfigPool to be enabled with OVS hardware offload + type: string + type: object + rdmaMode: + description: RDMA subsystem. Allowed value "shared", "exclusive". + enum: + - shared + - exclusive + type: string + type: object + status: + description: SriovNetworkPoolConfigStatus defines the observed state of + SriovNetworkPoolConfig + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworks.yaml b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworks.yaml new file mode 100644 index 0000000000..067e53a7f5 --- /dev/null +++ b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovnetworks.yaml @@ -0,0 +1,142 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: sriovnetworks.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovNetwork + listKind: SriovNetworkList + plural: sriovnetworks + singular: sriovnetwork + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovNetwork is the Schema for the sriovnetworks API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovNetworkSpec defines the desired state of SriovNetwork + properties: + capabilities: + description: |- + Capabilities to be configured for this network. + Capabilities supported: (mac|ips), e.g. '{"mac": true}' + type: string + ipam: + description: IPAM configuration to be used for this network. + type: string + linkState: + description: VF link state (enable|disable|auto) + enum: + - auto + - enable + - disable + type: string + logFile: + description: |- + LogFile sets the log file of the SRIOV CNI plugin logs. If unset (default), this will log to stderr and thus + to multus and container runtime logs. + type: string + logLevel: + default: info + description: |- + LogLevel sets the log level of the SRIOV CNI plugin - either of panic, error, warning, info, debug. Defaults + to info if left blank. + enum: + - panic + - error + - warning + - info + - debug + - "" + type: string + maxTxRate: + description: Maximum tx rate, in Mbps, for the VF. Defaults to 0 (no + rate limiting) + minimum: 0 + type: integer + metaPlugins: + description: |- + MetaPluginsConfig configuration to be used in order to chain metaplugins to the sriov interface returned + by the operator. + type: string + minTxRate: + description: Minimum tx rate, in Mbps, for the VF. Defaults to 0 (no + rate limiting). min_tx_rate should be <= max_tx_rate. + minimum: 0 + type: integer + networkNamespace: + description: Namespace of the NetworkAttachmentDefinition custom resource + type: string + resourceName: + description: SRIOV Network device plugin endpoint resource name + type: string + spoofChk: + description: VF spoof check, (on|off) + enum: + - "on" + - "off" + type: string + trust: + description: VF trust mode (on|off) + enum: + - "on" + - "off" + type: string + vlan: + description: VLAN ID to assign for the VF. Defaults to 0. + maximum: 4096 + minimum: 0 + type: integer + vlanProto: + description: VLAN proto to assign for the VF. Defaults to 802.1q. + enum: + - 802.1q + - 802.1Q + - 802.1ad + - 802.1AD + type: string + vlanQoS: + description: VLAN QoS ID to assign for the VF. Defaults to 0. + maximum: 7 + minimum: 0 + type: integer + required: + - resourceName + type: object + status: + description: SriovNetworkStatus defines the observed state of SriovNetwork + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml new file mode 100644 index 0000000000..a09e2df5c3 --- /dev/null +++ b/assets/optional/sriov/crd/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml @@ -0,0 +1,120 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + creationTimestamp: null + name: sriovoperatorconfigs.sriovnetwork.openshift.io +spec: + group: sriovnetwork.openshift.io + names: + kind: SriovOperatorConfig + listKind: SriovOperatorConfigList + plural: sriovoperatorconfigs + singular: sriovoperatorconfig + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: SriovOperatorConfig is the Schema for the sriovoperatorconfigs + API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: SriovOperatorConfigSpec defines the desired state of SriovOperatorConfig + properties: + configDaemonNodeSelector: + additionalProperties: + type: string + description: NodeSelector selects the nodes to be configured + type: object + configurationMode: + description: |- + Flag to enable the sriov-network-config-daemon to use a systemd service to configure SR-IOV devices on boot + Default mode: daemon + enum: + - daemon + - systemd + type: string + disableDrain: + description: Flag to disable nodes drain during debugging + type: boolean + disablePlugins: + description: DisablePlugins is a list of sriov-network-config-daemon + plugins to disable + items: + description: PluginNameValue defines the plugin name + enum: + - mellanox + type: string + type: array + enableInjector: + description: Flag to control whether the network resource injector + webhook shall be deployed + type: boolean + enableOperatorWebhook: + description: Flag to control whether the operator admission controller + webhook shall be deployed + type: boolean + enableOvsOffload: + description: Flag to enable OVS hardware offload. Set to 'true' to + provision switchdev-configuration.service and enable OpenvSwitch + hw-offload on nodes. + type: boolean + featureGates: + additionalProperties: + type: boolean + description: FeatureGates to enable experimental features + type: object + logLevel: + description: Flag to control the log verbose level of the operator. + Set to '0' to show only the basic logs. And set to '2' to show all + the available logs. + maximum: 2 + minimum: 0 + type: integer + useCDI: + description: Flag to enable Container Device Interface mode for SR-IOV + Network Device Plugin + type: boolean + type: object + status: + description: SriovOperatorConfigStatus defines the observed state of SriovOperatorConfig + properties: + injector: + description: Show the runtime status of the network resource injector + webhook + type: string + operatorWebhook: + description: Show the runtime status of the operator admission controller + webhook + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: null + storedVersions: null diff --git a/assets/optional/sriov/deploy/clusterrole.yaml b/assets/optional/sriov/deploy/clusterrole.yaml new file mode 100644 index 0000000000..fa030fa6ed --- /dev/null +++ b/assets/optional/sriov/deploy/clusterrole.yaml @@ -0,0 +1,122 @@ +rules: + - apiGroups: + - '' + resources: + - nodes + verbs: + - get + - list + - watch + - patch + - update + - apiGroups: + - '' + resources: + - pods + verbs: + - '*' + - apiGroups: + - apps + resources: + - daemonsets + verbs: + - get + - apiGroups: + - machineconfiguration.openshift.io + resources: + - '*' + verbs: + - '*' + - apiGroups: + - config.openshift.io + resources: + - infrastructures + verbs: + - get + - list + - watch +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: sriov-network-config-daemon +--- +rules: + - apiGroups: + - '' + resources: + - nodes + verbs: + - get + - list + - watch + - patch + - update + - apiGroups: + - '' + resources: + - pods + verbs: + - '*' + - apiGroups: + - '' + resources: + - pods/eviction + verbs: + - create + - apiGroups: + - apps + resources: + - daemonsets + verbs: + - get + - apiGroups: + - '' + resources: + - namespaces + - serviceaccounts + verbs: + - '*' + - apiGroups: + - k8s.cni.cncf.io + resources: + - network-attachment-definitions + verbs: + - '*' + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + - clusterrolebindings + verbs: + - '*' + - apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + - validatingwebhookconfigurations + verbs: + - '*' + - apiGroups: + - sriovnetwork.openshift.io + resources: + - '*' + verbs: + - '*' + - apiGroups: + - machineconfiguration.openshift.io + resources: + - '*' + verbs: + - '*' + - apiGroups: + - config.openshift.io + resources: + - infrastructures + verbs: + - get + - list + - watch +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: sriov-network-operator diff --git a/assets/optional/sriov/deploy/clusterrolebinding.yaml b/assets/optional/sriov/deploy/clusterrolebinding.yaml new file mode 100644 index 0000000000..7cabdb8512 --- /dev/null +++ b/assets/optional/sriov/deploy/clusterrolebinding.yaml @@ -0,0 +1,25 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: sriov-network-config-daemon +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: sriov-network-config-daemon +subjects: +- kind: ServiceAccount + name: sriov-network-config-daemon + namespace: sriov-network-operator +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: sriov-network-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: sriov-network-operator +subjects: +- kind: ServiceAccount + name: sriov-network-operator + namespace: sriov-network-operator diff --git a/assets/optional/sriov/deploy/namespace.yaml b/assets/optional/sriov/deploy/namespace.yaml new file mode 100644 index 0000000000..9d5f24da14 --- /dev/null +++ b/assets/optional/sriov/deploy/namespace.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: sriov-network-operator + labels: + name: sriov-network-operator + pod-security.kubernetes.io/enforce: privileged + pod-security.kubernetes.io/audit: privileged + pod-security.kubernetes.io/warn: privileged diff --git a/assets/optional/sriov/deploy/operator.yaml b/assets/optional/sriov/deploy/operator.yaml new file mode 100644 index 0000000000..543d376991 --- /dev/null +++ b/assets/optional/sriov/deploy/operator.yaml @@ -0,0 +1,112 @@ +spec: + replicas: 1 + selector: + matchLabels: + name: sriov-network-operator + strategy: + type: Recreate + template: + metadata: + annotations: + openshift.io/required-scc: restricted-v2 + target.workload.openshift.io/management: '{"effect": "PreferredDuringScheduling"}' + labels: + name: sriov-network-operator + spec: + containers: + - command: + - sriov-network-operator + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.annotations['olm.targetNamespaces'] + - name: SRIOV_CNI_IMAGE + value: registry.redhat.io/openshift4/sriov-cni-rhel9@sha256:76ed6db7ad7d01e1ec70888f3c3ca787bab460ef1139d4930f66e8aab4fe2dd7 + - name: SRIOV_DEVICE_PLUGIN_IMAGE + value: registry.redhat.io/openshift4/ose-sriov-network-device-plugin-rhel9@sha256:ea6942948b23a96054a8c27c4a8b6cffca49b6acc6ca556ce3e0708eb787789d + - name: NETWORK_RESOURCES_INJECTOR_IMAGE + value: registry.redhat.io/openshift4/ose-sriov-dp-admission-controller-rhel9@sha256:f07f432f89667200549eac89c6ef53c734420eb76a29c4008dd85a0a3526ad03 + - name: OPERATOR_NAME + value: sriov-network-operator + - name: SRIOV_NETWORK_CONFIG_DAEMON_IMAGE + value: registry.redhat.io/openshift4/ose-sriov-network-config-daemon-rhel9@sha256:41d6d4232d6ed37f370795908f7ea0b56379ca6538afbb35ef7cfda4f000fafd + - name: SRIOV_NETWORK_WEBHOOK_IMAGE + value: registry.redhat.io/openshift4/ose-sriov-network-webhook-rhel9@sha256:cd12a9afe94fcb823cfff1a274b633c9d687b11537ad37c1752244981e9bda43 + - name: SRIOV_INFINIBAND_CNI_IMAGE + value: registry.redhat.io/openshift4/ose-sriov-infiniband-cni-rhel9@sha256:ad2994a2ef988378926196175d26ffc3bc9ed0be6a8d4d9eb79bae0422641af4 + - name: RDMA_CNI_IMAGE + value: registry.redhat.io/openshift4/ose-sriov-rdma-cni-rhel9@sha256:993925e3e3ca5e3d603ad9b868490e5ede61190ecb20dea873bd597627c65c95 + - name: RESOURCE_PREFIX + value: openshift.io + - name: ADMISSION_CONTROLLERS_ENABLED + value: 'false' + - name: ADMISSION_CONTROLLERS_CERTIFICATES_OPERATOR_SECRET_NAME + value: operator-webhook-service + - name: ADMISSION_CONTROLLERS_CERTIFICATES_INJECTOR_SECRET_NAME + value: network-resources-injector-secret + - name: METRICS_EXPORTER_IMAGE + value: registry.redhat.io/openshift4/ose-sriov-network-metrics-exporter-rhel9@sha256:04358d43922f4d29af64f99baa2a73b0b32cf2895140232b61e538599ec08e46 + - name: METRICS_EXPORTER_KUBE_RBAC_PROXY_IMAGE + value: registry.redhat.io/openshift4/ose-kube-rbac-proxy-rhel9@sha256:5d7478a62742900e39d7b007dde5375cd06c6076ced6dab69d805f5fcce3f342 + - name: METRICS_EXPORTER_SECRET_NAME + value: metrics-exporter-cert + - name: METRICS_EXPORTER_PROMETHEUS_OPERATOR_ENABLED + value: 'false' + - name: METRICS_EXPORTER_PROMETHEUS_DEPLOY_RULES + value: 'true' + - name: METRICS_EXPORTER_PROMETHEUS_OPERATOR_NAMESPACE + value: openshift-monitoring + - name: METRICS_EXPORTER_PROMETHEUS_OPERATOR_SERVICE_ACCOUNT + value: prometheus-k8s + - name: METRICS_EXPORTER_PORT + value: '9110' + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: RELEASE_VERSION + value: 4.20.0 + - name: SRIOV_CNI_BIN_PATH + value: /run/cni/bin + - name: CLUSTER_TYPE + value: kubernetes + image: registry.redhat.io/openshift4/ose-sriov-network-rhel9-operator@sha256:edf864070393e01c4423ead4f86a066cb2e083de870ad84e1367c6c0fee5c84d + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: sriov-network-operator + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: {} + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + nodeSelector: + node-role.kubernetes.io/master: '' + serviceAccountName: sriov-network-operator + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists +apiVersion: apps/v1 +kind: Deployment +metadata: + name: sriov-network-operator + namespace: sriov-network-operator diff --git a/assets/optional/sriov/deploy/role.yaml b/assets/optional/sriov/deploy/role.yaml new file mode 100644 index 0000000000..f83aeffa09 --- /dev/null +++ b/assets/optional/sriov/deploy/role.yaml @@ -0,0 +1,153 @@ +rules: + - apiGroups: + - '' + resources: + - pods + verbs: + - '*' + - apiGroups: + - apps + resources: + - daemonsets + verbs: + - '*' + - apiGroups: + - sriovnetwork.openshift.io + resources: + - '*' + - sriovnetworknodestates + verbs: + - '*' + - apiGroups: + - security.openshift.io + resourceNames: + - privileged + resources: + - securitycontextconstraints + verbs: + - use + - apiGroups: + - '' + resources: + - configmaps + verbs: + - get + - update + - apiGroups: + - '' + resources: + - events + verbs: + - create + - patch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - '*' +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: sriov-network-config-daemon + namespace: sriov-network-operator +--- +rules: + - apiGroups: + - '' + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - '' + resources: + - events + verbs: + - create + - patch + - apiGroups: + - '' + resources: + - pods + - services + - endpoints + - persistentvolumeclaims + - events + - configmaps + - secrets + verbs: + - '*' + - apiGroups: + - apps + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + verbs: + - '*' + - apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - get + - create + - update + - delete + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + - prometheusrules + verbs: + - get + - create + - update + - delete + - apiGroups: + - apps + resourceNames: + - sriov-network-operator + resources: + - deployments/finalizers + verbs: + - update + - apiGroups: + - rbac.authorization.k8s.io + resources: + - serviceaccounts + - roles + - rolebindings + verbs: + - '*' + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - '*' +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: sriov-network-operator + namespace: sriov-network-operator diff --git a/assets/optional/sriov/deploy/rolebinding.yaml b/assets/optional/sriov/deploy/rolebinding.yaml new file mode 100644 index 0000000000..98748390f5 --- /dev/null +++ b/assets/optional/sriov/deploy/rolebinding.yaml @@ -0,0 +1,25 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: sriov-network-config-daemon + namespace: sriov-network-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: sriov-network-config-daemon +subjects: +- kind: ServiceAccount + name: sriov-network-config-daemon +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: sriov-network-operator + namespace: sriov-network-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: sriov-network-operator +subjects: +- kind: ServiceAccount + name: sriov-network-operator diff --git a/assets/optional/sriov/deploy/serviceaccount.yaml b/assets/optional/sriov/deploy/serviceaccount.yaml new file mode 100644 index 0000000000..f787b3adda --- /dev/null +++ b/assets/optional/sriov/deploy/serviceaccount.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + creationTimestamp: null + name: sriov-network-config-daemon + namespace: sriov-network-operator +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + creationTimestamp: null + name: sriov-network-operator + namespace: sriov-network-operator diff --git a/assets/optional/sriov/deploy/sriovoperatorconfig.yaml b/assets/optional/sriov/deploy/sriovoperatorconfig.yaml new file mode 100644 index 0000000000..21c3c994d6 --- /dev/null +++ b/assets/optional/sriov/deploy/sriovoperatorconfig.yaml @@ -0,0 +1,10 @@ +apiVersion: sriovnetwork.openshift.io/v1 +kind: SriovOperatorConfig +metadata: + name: default + namespace: sriov-network-operator +spec: + configDaemonNodeSelector: {} + logLevel: 2 + disableDrain: false + configurationMode: daemon diff --git a/assets/optional/sriov/deploy/supported-nic-ids_v1_configmap.yaml b/assets/optional/sriov/deploy/supported-nic-ids_v1_configmap.yaml new file mode 100644 index 0000000000..5ca40c8ade --- /dev/null +++ b/assets/optional/sriov/deploy/supported-nic-ids_v1_configmap.yaml @@ -0,0 +1,52 @@ +apiVersion: v1 +data: + Broadcom_bnxt_en_BCM57414_NetXtreme-E: 14e4 16d7 16dc + Broadcom_bnxt_en_BCM57508_NetXtreme-E: 14e4 1750 1806 + Broadcom_bnxt_en_BCM57504_NetXtreme-E: 14e4 1751 1806 + Intel_i40e_X710_10G: 8086 1572 154c + Intel_i40e_XL710_40G: 8086 1583 154c + Intel_i40e_XXV710: 8086 158a 154c + Intel_i40e_XXV710_25G: 8086 158b 154c + Intel_i40e_XXV710_N3000: 8086 0d58 154c + Intel_i40e_10G_X710_BACKPLANE: 8086 1581 154c + Intel_i40e_10G_X710_BASE_T: 8086 15ff 154c + Intel_ice_E810: 8086 1591 1889 + Intel_ice_E810-CQDA2_2CQDA2: 8086 1592 1889 + Intel_ice_E810-XXV_BACKPLANE: 8086 1599 1889 + Intel_ice_E810-XXVDA2: 8086 159b 1889 + Intel_ice_E810-XXVDA4: 8086 1593 1889 + Intel_ice_E823L_SFP: 8086 124d 1889 + Intel_ice_E823L_BACKPLANE: 8086 124c 1889 + Intel_ice_Columbiapark_E825C_BACKPLANE: 8086 579c 1889 + Intel_ice_Columbiapark_E825C_QSFP: 8086 579d 1889 + Intel_ice_Columbiapark_E825C_SFP: 8086 579e 1889 + Intel_ice_Connorsville_E830_QSFP: 8086 12d2 1889 + Intel_ice_Connorsville_E830_SFP: 8086 12d3 1889 + Intel_ixgbe_82599ES: 8086 10fb 10ed + Intel_ixgbe_X520: 8086 154d 10ed + Intel_ixgbe_X520-AT2: 8086 1528 1515 + Intel_ixgbe_X550T: 8086 1563 1565 + Marvell_OCTEON_Fusion_CNF105XX: 177d ba00 ba03 + Marvell_OCTEON10_CN10XXX: 177d b900 b903 + Nvidia_mlx4_ConnectX-3_Pro: 15b3 1007 1004 + Nvidia_mlx5_BlueField-2_ConnectX-6_Dx: 15b3 a2d6 101e + Nvidia_mlx5_MT43244_BlueField-3_integrated_ConnectX-7_Dx: 15b3 a2dc 101e + Nvidia_mlx5_ConnectX-4: 15b3 1013 1014 + Nvidia_mlx5_ConnectX-4_Lx: 15b3 1015 1016 + Nvidia_mlx5_ConnectX-5: 15b3 1017 1018 + Nvidia_mlx5_ConnectX-5_Ex: 15b3 1019 101a + Nvidia_mlx5_ConnectX-6: 15b3 101b 101c + Nvidia_mlx5_ConnectX-6_Dx: 15b3 101d 101e + Nvidia_mlx5_ConnectX-6_Lx: 15b3 101f 101e + Nvidia_mlx5_ConnectX-7: 15b3 1021 101e + Pensando_ionic_DSC: 1dd8 1002 1003 + Qlogic_qede_QL41000: 1077 8070 8090 + Qlogic_qede_QL45000_25G: 1077 1656 1664 + Qlogic_qede_QL45000_50G: 1077 1654 1664 + Red_Hat_Virtio_network_device: 1af4 1000 1000 + Red_Hat_Virtio_1_0_network_device: 1af4 1041 1041 + Intel_ixgbe_82576: 8086 10c9 10ca +kind: ConfigMap +metadata: + name: supported-nic-ids + namespace: sriov-network-operator diff --git a/assets/optional/sriov/kustomization.yaml b/assets/optional/sriov/kustomization.yaml new file mode 100644 index 0000000000..efdfe2ca1b --- /dev/null +++ b/assets/optional/sriov/kustomization.yaml @@ -0,0 +1,19 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - crd/sriovnetwork.openshift.io_ovsnetworks.yaml + - crd/sriovnetwork.openshift.io_sriovibnetworks.yaml + - crd/sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml + - crd/sriovnetwork.openshift.io_sriovnetworknodestates.yaml + - crd/sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml + - crd/sriovnetwork.openshift.io_sriovnetworks.yaml + - crd/sriovnetwork.openshift.io_sriovoperatorconfigs.yaml + - deploy/clusterrolebinding.yaml + - deploy/clusterrole.yaml + - deploy/namespace.yaml + - deploy/operator.yaml + - deploy/role.yaml + - deploy/rolebinding.yaml + - deploy/serviceaccount.yaml + - deploy/sriovoperatorconfig.yaml + - deploy/supported-nic-ids_v1_configmap.yaml diff --git a/assets/optional/sriov/release-sriov-aarch64.json b/assets/optional/sriov/release-sriov-aarch64.json new file mode 100644 index 0000000000..2704e63ba9 --- /dev/null +++ b/assets/optional/sriov/release-sriov-aarch64.json @@ -0,0 +1,17 @@ +{ + "release": { + "base": "4.20.0-202511250912" + }, + "images": { + "sriov-cni-image": "registry.redhat.io/openshift4/sriov-cni-rhel9@sha256:76ed6db7ad7d01e1ec70888f3c3ca787bab460ef1139d4930f66e8aab4fe2dd7", + "sriov-device-plugin-image": "registry.redhat.io/openshift4/ose-sriov-network-device-plugin-rhel9@sha256:ea6942948b23a96054a8c27c4a8b6cffca49b6acc6ca556ce3e0708eb787789d", + "network-resources-injector-image": "registry.redhat.io/openshift4/ose-sriov-dp-admission-controller-rhel9@sha256:f07f432f89667200549eac89c6ef53c734420eb76a29c4008dd85a0a3526ad03", + "sriov-network-config-daemon-image": "registry.redhat.io/openshift4/ose-sriov-network-config-daemon-rhel9@sha256:41d6d4232d6ed37f370795908f7ea0b56379ca6538afbb35ef7cfda4f000fafd", + "sriov-network-webhook-image": "registry.redhat.io/openshift4/ose-sriov-network-webhook-rhel9@sha256:cd12a9afe94fcb823cfff1a274b633c9d687b11537ad37c1752244981e9bda43", + "sriov-infiniband-cni-image": "registry.redhat.io/openshift4/ose-sriov-infiniband-cni-rhel9@sha256:ad2994a2ef988378926196175d26ffc3bc9ed0be6a8d4d9eb79bae0422641af4", + "rdma-cni-image": "registry.redhat.io/openshift4/ose-sriov-rdma-cni-rhel9@sha256:993925e3e3ca5e3d603ad9b868490e5ede61190ecb20dea873bd597627c65c95", + "metrics-exporter-image": "registry.redhat.io/openshift4/ose-sriov-network-metrics-exporter-rhel9@sha256:04358d43922f4d29af64f99baa2a73b0b32cf2895140232b61e538599ec08e46", + "metrics-exporter-kube-rbac-proxy-image": "registry.redhat.io/openshift4/ose-kube-rbac-proxy-rhel9@sha256:5d7478a62742900e39d7b007dde5375cd06c6076ced6dab69d805f5fcce3f342", + "sriov-network-operator": "registry.redhat.io/openshift4/ose-sriov-network-rhel9-operator@sha256:edf864070393e01c4423ead4f86a066cb2e083de870ad84e1367c6c0fee5c84d" + } +} diff --git a/assets/optional/sriov/release-sriov-x86_64.json b/assets/optional/sriov/release-sriov-x86_64.json new file mode 100644 index 0000000000..2704e63ba9 --- /dev/null +++ b/assets/optional/sriov/release-sriov-x86_64.json @@ -0,0 +1,17 @@ +{ + "release": { + "base": "4.20.0-202511250912" + }, + "images": { + "sriov-cni-image": "registry.redhat.io/openshift4/sriov-cni-rhel9@sha256:76ed6db7ad7d01e1ec70888f3c3ca787bab460ef1139d4930f66e8aab4fe2dd7", + "sriov-device-plugin-image": "registry.redhat.io/openshift4/ose-sriov-network-device-plugin-rhel9@sha256:ea6942948b23a96054a8c27c4a8b6cffca49b6acc6ca556ce3e0708eb787789d", + "network-resources-injector-image": "registry.redhat.io/openshift4/ose-sriov-dp-admission-controller-rhel9@sha256:f07f432f89667200549eac89c6ef53c734420eb76a29c4008dd85a0a3526ad03", + "sriov-network-config-daemon-image": "registry.redhat.io/openshift4/ose-sriov-network-config-daemon-rhel9@sha256:41d6d4232d6ed37f370795908f7ea0b56379ca6538afbb35ef7cfda4f000fafd", + "sriov-network-webhook-image": "registry.redhat.io/openshift4/ose-sriov-network-webhook-rhel9@sha256:cd12a9afe94fcb823cfff1a274b633c9d687b11537ad37c1752244981e9bda43", + "sriov-infiniband-cni-image": "registry.redhat.io/openshift4/ose-sriov-infiniband-cni-rhel9@sha256:ad2994a2ef988378926196175d26ffc3bc9ed0be6a8d4d9eb79bae0422641af4", + "rdma-cni-image": "registry.redhat.io/openshift4/ose-sriov-rdma-cni-rhel9@sha256:993925e3e3ca5e3d603ad9b868490e5ede61190ecb20dea873bd597627c65c95", + "metrics-exporter-image": "registry.redhat.io/openshift4/ose-sriov-network-metrics-exporter-rhel9@sha256:04358d43922f4d29af64f99baa2a73b0b32cf2895140232b61e538599ec08e46", + "metrics-exporter-kube-rbac-proxy-image": "registry.redhat.io/openshift4/ose-kube-rbac-proxy-rhel9@sha256:5d7478a62742900e39d7b007dde5375cd06c6076ced6dab69d805f5fcce3f342", + "sriov-network-operator": "registry.redhat.io/openshift4/ose-sriov-network-rhel9-operator@sha256:edf864070393e01c4423ead4f86a066cb2e083de870ad84e1367c6c0fee5c84d" + } +} diff --git a/assets/release/release-aarch64.json b/assets/release/release-aarch64.json index b49256029d..8162f8e522 100644 --- a/assets/release/release-aarch64.json +++ b/assets/release/release-aarch64.json @@ -1,16 +1,16 @@ { "release": { - "base": "4.21.0-0.nightly-arm64-2025-10-19-182251" + "base": "4.21.0-0.nightly-arm64-2025-12-12-014247" }, "images": { - "cli": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a841daa016b50a2ff7bd7fe6061ff53af17ebd0c63f8470b7db186d02cda618f", - "coredns": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:50ed89535b2665e1f2ec7801ceadad9eae08f89980bf20c3c878583b746535f5", - "haproxy-router": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:77ea75be344606fc99e8715de496f1cce35c48e10a566cfb94225e777dc6babe", - "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:aaf25c001f1ca459d0c1d8ae9636bf81b2701be9bca1ef8a863ffff05811cb31", - "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:e5944f6a6ded1f90e0da9bdd36dc5f1369dbf32d2e60872c186e21531fd906a6", - "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:39d9a5da43a3dbe850a27fcfb07b0437d1cc0d32f5f0b9eef05a10c48bdd3baa", - "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f8e3ac877e7c1337d528445381d8dcfbe0f92489f199e20d18cb125b9e36d0f8", + "cli": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:f9c8ea4c8325d40eb18af7d7f6afaa9193e267a8e31a353474115659d733daf0", + "coredns": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:65e22e1f8767c0a9b44bdcfac686137832d369e71e28be1e43e72370a5789af9", + "haproxy-router": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:47662a8aede0c313b721e753fb38a3e78ecf0e6d05546799beda7319a2c27287", + "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:d4ba33fcc9731eccfbdedcf77a4a53ccff1883d93ce3a3ab6c0014eb26a30e09", + "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:aa5bc110361122e642c83e0fa15783af05579c50793c8bfe8086f786101cff73", + "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:c3ca03c9bde6e9824886bac4f94d54a402743b0f143d9940f8d5d0db2b7399e1", + "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:8d9c0cc6ae472b095c7ee5ddef96d762fbb91e61cc9cd387184dd6e8729e4b4c", "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:f9452325f357d6cba28bcb9ae8f2a93f97cb2dc9b88b1de10b78d12e9f53b08b" + "csi-snapshot-controller": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:09d865455a5ebe532b787823e3aac953fab40b850fffad25482b2f361c3b3a22" } } diff --git a/assets/release/release-x86_64.json b/assets/release/release-x86_64.json index 3556603c37..18b0191608 100644 --- a/assets/release/release-x86_64.json +++ b/assets/release/release-x86_64.json @@ -1,16 +1,16 @@ { "release": { - "base": "4.21.0-0.nightly-2025-10-19-181151" + "base": "4.21.0-0.nightly-2025-12-10-193741" }, "images": { - "cli": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:32af84cef6897171e63ef8dd894d1be714efe73b8eadca0447b16176bf599735", - "coredns": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:dddbea01a3cca23132bc683779d71b786dd9f660d34dc1a86643faea8f0db143", - "haproxy-router": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:2b0b21eed03676fa52206e0085d6296fb9b3968ea6c7a22716f3318308170830", - "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:34eb149d564a29d9376b8176b5e06be7ba12ca80083f9422d337a6225142ccd9", - "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:5ec21a2b6ef99107080d7b9afb2384f015e5b4d3b71dd92c6ffb6d5cf10e810e", - "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:ae71cf6109569070d74d35dcb8e83d6153e45e1403549acdd8cb827c2fed80e7", - "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:ed7ef97799439f9afc4093c262528ef84b38ea0bf8f33e7d67a70402e182a8dd", + "cli": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:a66878842c091c165a3bdfb5040966417e6274028e736776405417e89b643714", + "coredns": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:18504c088c4b54069cf75c2d7d2dc9dd3d0607c4ac9b6a3f6a302bd80f0890bc", + "haproxy-router": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:8842274553ef52aa327f0c0bc4c8fb8552678d1d0dc0bb545009ecbab5626e29", + "kube-rbac-proxy": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:bbeddc00892d4caa3fcfd5926f1ca953594473f892bf65e1e468bd3aecd15b56", + "ovn-kubernetes-microshift": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:d7389c80c3c112a5ba6db5fc5e815754cdd28a1117632ace2b53ac4bb2c71431", + "pod": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:0622e764c91f3206b12a10df5025a804b032f81a280075f72480d5d4c4eac44d", + "service-ca-operator": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:58ccde0b2b7b8e85dd4703ad2b330481f231ac3954433dba36e29b66a0ae7ea6", "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:df2eff8ddac81d0f9cf1cd2656f9f5b7878756ca15bafc42d7f66aae4fe4c5b9" + "csi-snapshot-controller": "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:274c7411e9a38251cb702041af0dbb09aba7c983f23386bf77090432c6aa6620" } } diff --git a/cmd/generate-config/config/config-openapi-spec.json b/cmd/generate-config/config/config-openapi-spec.json index bb9fc172e4..d615ba026c 100755 --- a/cmd/generate-config/config/config-openapi-spec.json +++ b/cmd/generate-config/config/config-openapi-spec.json @@ -19,6 +19,7 @@ "type": "object", "required": [ "auditLog", + "featureGates", "namedCertificates", "subjectAltNames", "tls" @@ -59,6 +60,39 @@ } } }, + "featureGates": { + "type": "object", + "required": [ + "customNoUpgrade", + "featureSet" + ], + "properties": { + "customNoUpgrade": { + "type": "object", + "required": [ + "disabled", + "enabled" + ], + "properties": { + "disabled": { + "type": "array", + "items": { + "type": "string" + } + }, + "enabled": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "featureSet": { + "type": "string" + } + } + }, "namedCertificates": { "description": "List of custom certificates used to secure requests to specific host names", "type": "array", @@ -144,6 +178,28 @@ "type": "string", "default": "example.com", "example": "microshift.example.com" + }, + "hosts": { + "description": "Hosts contains configuration for the hosts file.", + "type": "object", + "properties": { + "file": { + "description": "File is the path to the hosts file to monitor.\nIf not specified, defaults to \"/etc/hosts\".", + "type": "string", + "default": "/etc/hosts", + "example": "/etc/hosts" + }, + "status": { + "description": "Status controls whether the hosts file is enabled or disabled.\nAllowed values are \"Enabled\" and \"Disabled\".\nIf not specified, defaults to \"Disabled\".", + "type": "string", + "default": "Disabled", + "enum": [ + "Enabled", + "Disabled" + ], + "example": "Enabled" + } + } } } }, diff --git a/dashboards/grafana-dashboard-microshift-telemetry.configmap.yaml b/dashboards/grafana-dashboard-microshift-telemetry.configmap.yaml index c22dadc574..a8be47b6c6 100644 --- a/dashboards/grafana-dashboard-microshift-telemetry.configmap.yaml +++ b/dashboards/grafana-dashboard-microshift-telemetry.configmap.yaml @@ -69,6 +69,614 @@ data: "title": "Production clusters", "type": "row" }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Growth" + }, + "properties": [ + { + "id": "unit", + "value": "percentunit" + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 7 + }, + "id": 49, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^Growth$/", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg_over_time(\n (\n sum(\n max by (_id) (\n max_over_time(cluster:capacity_cpu_cores:sum{label_beta_kubernetes_io_instance_type=\"rhde\"}[$offline_threshold:5m])\n )\n and on(_id)\n (\n max by (_id) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n unless on (_id)\n (\n (\n max by(_id) (max_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n -\n min by(_id) (min_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n ) < $short_lived_threshold\n )\n )\n )\n )\n [14d:2d]\n)", + "legendFormat": "Current", + "range": true, + "refId": "Current" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg_over_time(\n (\n sum(\n max by (_id) (\n max_over_time(cluster:capacity_cpu_cores:sum{label_beta_kubernetes_io_instance_type=\"rhde\"}[$offline_threshold:5m])\n )\n and on(_id)\n (\n max by (_id) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n unless on (_id)\n (\n (\n max by(_id) (max_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n -\n min by(_id) (min_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n ) < $short_lived_threshold\n )\n )\n )\n )\n [14d:2d] offset 30d\n)", + "hide": false, + "instant": false, + "legendFormat": "Past", + "range": true, + "refId": "Past" + } + ], + "title": "Cluster growth over last month", + "transformations": [ + { + "id": "calculateField", + "options": { + "alias": "Difference", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "Current" + } + }, + "operator": "-", + "right": { + "matcher": { + "id": "byName", + "options": "Past" + } + } + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + } + } + }, + { + "id": "calculateField", + "options": { + "alias": "Growth", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "Difference" + } + }, + "operator": "/", + "right": { + "matcher": { + "id": "byName", + "options": "Past" + } + } + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + } + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Growth" + }, + "properties": [ + { + "id": "unit", + "value": "percentunit" + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 7 + }, + "id": 50, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^Growth$/", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg_over_time(\n (\n sum(\n max by (_id) (\n max_over_time(cluster:capacity_cpu_cores:sum{label_beta_kubernetes_io_instance_type=\"rhde\"}[$offline_threshold:5m])\n )\n and on(_id)\n (\n max by (_id) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n unless on (_id)\n (\n (\n max by(_id) (max_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n -\n min by(_id) (min_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n ) < $short_lived_threshold\n )\n )\n )\n )\n [14d:2d]\n)", + "legendFormat": "Current", + "range": true, + "refId": "Current" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg_over_time(\n (\n sum(\n max by (_id) (\n max_over_time(cluster:capacity_cpu_cores:sum{label_beta_kubernetes_io_instance_type=\"rhde\"}[$offline_threshold:5m])\n )\n and on(_id)\n (\n max by (_id) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n unless on (_id)\n (\n (\n max by(_id) (max_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n -\n min by(_id) (min_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n ) < $short_lived_threshold\n )\n )\n )\n )\n [14d:2d] offset 90d\n)", + "hide": false, + "instant": false, + "legendFormat": "Past", + "range": true, + "refId": "Past" + } + ], + "title": "Cluster growth over last 3 months", + "transformations": [ + { + "id": "calculateField", + "options": { + "alias": "Difference", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "Current" + } + }, + "operator": "-", + "right": { + "matcher": { + "id": "byName", + "options": "Past" + } + } + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + } + } + }, + { + "id": "calculateField", + "options": { + "alias": "Growth", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "Difference" + } + }, + "operator": "/", + "right": { + "matcher": { + "id": "byName", + "options": "Past" + } + } + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + } + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Growth" + }, + "properties": [ + { + "id": "unit", + "value": "percentunit" + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 12, + "y": 7 + }, + "id": 45, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^Growth$/", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg_over_time(\n (\n count (\n max by (_id, version) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n and on(_id)\n (\n max by (_id) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n unless on (_id)\n (\n (\n max by(_id) (max_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n -\n min by(_id) (min_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n ) < $short_lived_threshold\n )\n )\n )\n )\n [14d:2d]\n)", + "legendFormat": "Current", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg_over_time(\n (\n count (\n max by (_id, version) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n and on(_id)\n (\n max by (_id) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n unless on (_id)\n (\n (\n max by(_id) (max_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n -\n min by(_id) (min_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n ) < $short_lived_threshold\n )\n )\n )\n )\n [14d:2d] offset 30d\n)", + "hide": false, + "instant": false, + "legendFormat": "Past", + "range": true, + "refId": "B" + } + ], + "title": "CPU growth over last month", + "transformations": [ + { + "id": "calculateField", + "options": { + "alias": "Difference", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "Current" + } + }, + "operator": "-", + "right": { + "matcher": { + "id": "byName", + "options": "Past" + } + } + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + } + } + }, + { + "id": "calculateField", + "options": { + "alias": "Growth", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "Difference" + } + }, + "operator": "/", + "right": { + "matcher": { + "id": "byName", + "options": "Past" + } + } + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + } + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Growth" + }, + "properties": [ + { + "id": "unit", + "value": "percentunit" + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 18, + "y": 7 + }, + "id": 51, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^Growth$/", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg_over_time(\n (\n count (\n max by (_id, version) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n and on(_id)\n (\n max by (_id) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n unless on (_id)\n (\n (\n max by(_id) (max_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n -\n min by(_id) (min_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n ) < $short_lived_threshold\n )\n )\n )\n )\n [14d:2d]\n)", + "legendFormat": "Current", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "avg_over_time(\n (\n count (\n max by (_id, version) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n and on(_id)\n (\n max by (_id) (\n count_over_time(microshift_version[$offline_threshold]) > 0\n )\n unless on (_id)\n (\n (\n max by(_id) (max_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n -\n min by(_id) (min_over_time(timestamp(microshift_version)[$offline_threshold:5m]))\n ) < $short_lived_threshold\n )\n )\n )\n )\n [14d:2d] offset 90d\n)", + "hide": false, + "instant": false, + "legendFormat": "Past", + "range": true, + "refId": "B" + } + ], + "title": "CPU growth over last 3 months", + "transformations": [ + { + "id": "calculateField", + "options": { + "alias": "Difference", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "Current" + } + }, + "operator": "-", + "right": { + "matcher": { + "id": "byName", + "options": "Past" + } + } + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + } + } + }, + { + "id": "calculateField", + "options": { + "alias": "Growth", + "binary": { + "left": { + "matcher": { + "id": "byName", + "options": "Difference" + } + }, + "operator": "/", + "right": { + "matcher": { + "id": "byName", + "options": "Past" + } + } + }, + "mode": "binary", + "reduce": { + "reducer": "sum" + } + } + } + ], + "type": "stat" + }, { "datasource": { "type": "prometheus", @@ -107,7 +715,7 @@ data: "h": 7, "w": 5, "x": 0, - "y": 7 + "y": 12 }, "id": 30, "maxDataPoints": 100, @@ -222,7 +830,7 @@ data: "h": 7, "w": 6, "x": 5, - "y": 7 + "y": 12 }, "id": 31, "options": { @@ -332,7 +940,7 @@ data: "h": 7, "w": 6, "x": 11, - "y": 7 + "y": 12 }, "id": 32, "options": { @@ -501,7 +1109,7 @@ data: "h": 14, "w": 7, "x": 17, - "y": 7 + "y": 12 }, "id": 33, "options": { @@ -633,7 +1241,7 @@ data: "h": 7, "w": 5, "x": 0, - "y": 14 + "y": 19 }, "id": 34, "maxDataPoints": 100, @@ -748,7 +1356,7 @@ data: "h": 7, "w": 6, "x": 5, - "y": 14 + "y": 19 }, "id": 35, "options": { @@ -846,7 +1454,7 @@ data: "h": 7, "w": 6, "x": 11, - "y": 14 + "y": 19 }, "id": 36, "options": { @@ -906,7 +1514,7 @@ data: "h": 7, "w": 5, "x": 0, - "y": 21 + "y": 26 }, "id": 43, "options": { @@ -1010,7 +1618,7 @@ data: "h": 7, "w": 12, "x": 5, - "y": 21 + "y": 26 }, "id": 39, "options": { @@ -1070,7 +1678,7 @@ data: "h": 14, "w": 7, "x": 17, - "y": 21 + "y": 26 }, "id": 37, "options": { @@ -1136,7 +1744,7 @@ data: "h": 7, "w": 5, "x": 0, - "y": 28 + "y": 33 }, "id": 44, "options": { @@ -1242,7 +1850,7 @@ data: "h": 7, "w": 12, "x": 5, - "y": 28 + "y": 33 }, "id": 40, "options": { @@ -1282,7 +1890,7 @@ data: "h": 1, "w": 24, "x": 0, - "y": 35 + "y": 40 }, "id": 24, "panels": [], @@ -1327,7 +1935,7 @@ data: "h": 8, "w": 6, "x": 0, - "y": 36 + "y": 41 }, "id": 38, "maxDataPoints": 100, @@ -1431,7 +2039,7 @@ data: "h": 8, "w": 15, "x": 6, - "y": 36 + "y": 41 }, "id": 42, "options": { @@ -1586,5 +2194,5 @@ data: "timezone": "", "title": "MicroShift Telemetry", "uid": "sK7hN2pXf", - "version": 2 + "version": 3 } diff --git a/deps/github.com/openshift/kubernetes/.go-version b/deps/github.com/openshift/kubernetes/.go-version index 7a429d68a3..eb716f77a7 100644 --- a/deps/github.com/openshift/kubernetes/.go-version +++ b/deps/github.com/openshift/kubernetes/.go-version @@ -1 +1 @@ -1.24.6 +1.24.9 diff --git a/deps/github.com/openshift/kubernetes/CHANGELOG/CHANGELOG-1.34.md b/deps/github.com/openshift/kubernetes/CHANGELOG/CHANGELOG-1.34.md index f731ad90ec..336f60a6e2 100644 --- a/deps/github.com/openshift/kubernetes/CHANGELOG/CHANGELOG-1.34.md +++ b/deps/github.com/openshift/kubernetes/CHANGELOG/CHANGELOG-1.34.md @@ -1,152 +1,256 @@ -- [v1.34.0](#v1340) - - [Downloads for v1.34.0](#downloads-for-v1340) +- [v1.34.1](#v1341) + - [Downloads for v1.34.1](#downloads-for-v1341) - [Source Code](#source-code) - [Client Binaries](#client-binaries) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - [Container Images](#container-images) - - [Changelog since v1.33.0](#changelog-since-v1330) - - [Urgent Upgrade Notes](#urgent-upgrade-notes) - - [(No, really, you MUST read this before you upgrade)](#no-really-you-must-read-this-before-you-upgrade) + - [Changelog since v1.34.0](#changelog-since-v1340) - [Changes by Kind](#changes-by-kind) - - [Deprecation](#deprecation) - - [API Change](#api-change) - - [Feature](#feature) - - [Failing Test](#failing-test) - [Bug or Regression](#bug-or-regression) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake) - [Dependencies](#dependencies) - [Added](#added) - [Changed](#changed) - [Removed](#removed) -- [v1.34.0-rc.2](#v1340-rc2) - - [Downloads for v1.34.0-rc.2](#downloads-for-v1340-rc2) +- [v1.34.0](#v1340) + - [Downloads for v1.34.0](#downloads-for-v1340) - [Source Code](#source-code-1) - [Client Binaries](#client-binaries-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - [Container Images](#container-images-1) - - [Changelog since v1.34.0-rc.1](#changelog-since-v1340-rc1) + - [Changelog since v1.33.0](#changelog-since-v1330) + - [Urgent Upgrade Notes](#urgent-upgrade-notes) + - [(No, really, you MUST read this before you upgrade)](#no-really-you-must-read-this-before-you-upgrade) - [Changes by Kind](#changes-by-kind-1) - - [Feature](#feature-1) - - [Documentation](#documentation) + - [Deprecation](#deprecation) + - [API Change](#api-change) + - [Feature](#feature) + - [Failing Test](#failing-test) - [Bug or Regression](#bug-or-regression-1) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake) - [Dependencies](#dependencies-1) - [Added](#added-1) - [Changed](#changed-1) - [Removed](#removed-1) -- [v1.34.0-rc.1](#v1340-rc1) - - [Downloads for v1.34.0-rc.1](#downloads-for-v1340-rc1) +- [v1.34.0-rc.2](#v1340-rc2) + - [Downloads for v1.34.0-rc.2](#downloads-for-v1340-rc2) - [Source Code](#source-code-2) - [Client Binaries](#client-binaries-2) - [Server Binaries](#server-binaries-2) - [Node Binaries](#node-binaries-2) - [Container Images](#container-images-2) - - [Changelog since v1.34.0-rc.0](#changelog-since-v1340-rc0) + - [Changelog since v1.34.0-rc.1](#changelog-since-v1340-rc1) - [Changes by Kind](#changes-by-kind-2) + - [Feature](#feature-1) + - [Documentation](#documentation) - [Bug or Regression](#bug-or-regression-2) - [Dependencies](#dependencies-2) - [Added](#added-2) - [Changed](#changed-2) - [Removed](#removed-2) -- [v1.34.0-rc.0](#v1340-rc0) - - [Downloads for v1.34.0-rc.0](#downloads-for-v1340-rc0) +- [v1.34.0-rc.1](#v1340-rc1) + - [Downloads for v1.34.0-rc.1](#downloads-for-v1340-rc1) - [Source Code](#source-code-3) - [Client Binaries](#client-binaries-3) - [Server Binaries](#server-binaries-3) - [Node Binaries](#node-binaries-3) - [Container Images](#container-images-3) - - [Changelog since v1.34.0-beta.0](#changelog-since-v1340-beta0) + - [Changelog since v1.34.0-rc.0](#changelog-since-v1340-rc0) - [Changes by Kind](#changes-by-kind-3) - - [Deprecation](#deprecation-1) - - [API Change](#api-change-1) - - [Feature](#feature-2) - - [Failing Test](#failing-test-1) - [Bug or Regression](#bug-or-regression-3) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-1) - [Dependencies](#dependencies-3) - [Added](#added-3) - [Changed](#changed-3) - [Removed](#removed-3) -- [v1.34.0-beta.0](#v1340-beta0) - - [Downloads for v1.34.0-beta.0](#downloads-for-v1340-beta0) +- [v1.34.0-rc.0](#v1340-rc0) + - [Downloads for v1.34.0-rc.0](#downloads-for-v1340-rc0) - [Source Code](#source-code-4) - [Client Binaries](#client-binaries-4) - [Server Binaries](#server-binaries-4) - [Node Binaries](#node-binaries-4) - [Container Images](#container-images-4) - - [Changelog since v1.34.0-alpha.3](#changelog-since-v1340-alpha3) + - [Changelog since v1.34.0-beta.0](#changelog-since-v1340-beta0) - [Changes by Kind](#changes-by-kind-4) - - [API Change](#api-change-2) - - [Feature](#feature-3) + - [Deprecation](#deprecation-1) + - [API Change](#api-change-1) + - [Feature](#feature-2) + - [Failing Test](#failing-test-1) - [Bug or Regression](#bug-or-regression-4) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-2) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-1) - [Dependencies](#dependencies-4) - [Added](#added-4) - [Changed](#changed-4) - [Removed](#removed-4) -- [v1.34.0-alpha.3](#v1340-alpha3) - - [Downloads for v1.34.0-alpha.3](#downloads-for-v1340-alpha3) +- [v1.34.0-beta.0](#v1340-beta0) + - [Downloads for v1.34.0-beta.0](#downloads-for-v1340-beta0) - [Source Code](#source-code-5) - [Client Binaries](#client-binaries-5) - [Server Binaries](#server-binaries-5) - [Node Binaries](#node-binaries-5) - [Container Images](#container-images-5) - - [Changelog since v1.34.0-alpha.2](#changelog-since-v1340-alpha2) + - [Changelog since v1.34.0-alpha.3](#changelog-since-v1340-alpha3) - [Changes by Kind](#changes-by-kind-5) - - [API Change](#api-change-3) - - [Feature](#feature-4) - - [Failing Test](#failing-test-2) + - [API Change](#api-change-2) + - [Feature](#feature-3) - [Bug or Regression](#bug-or-regression-5) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-3) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-2) - [Dependencies](#dependencies-5) - [Added](#added-5) - [Changed](#changed-5) - [Removed](#removed-5) -- [v1.34.0-alpha.2](#v1340-alpha2) - - [Downloads for v1.34.0-alpha.2](#downloads-for-v1340-alpha2) +- [v1.34.0-alpha.3](#v1340-alpha3) + - [Downloads for v1.34.0-alpha.3](#downloads-for-v1340-alpha3) - [Source Code](#source-code-6) - [Client Binaries](#client-binaries-6) - [Server Binaries](#server-binaries-6) - [Node Binaries](#node-binaries-6) - [Container Images](#container-images-6) - - [Changelog since v1.34.0-alpha.1](#changelog-since-v1340-alpha1) + - [Changelog since v1.34.0-alpha.2](#changelog-since-v1340-alpha2) - [Changes by Kind](#changes-by-kind-6) - - [Deprecation](#deprecation-2) - - [API Change](#api-change-4) - - [Feature](#feature-5) + - [API Change](#api-change-3) + - [Feature](#feature-4) + - [Failing Test](#failing-test-2) - [Bug or Regression](#bug-or-regression-6) - - [Other (Cleanup or Flake)](#other-cleanup-or-flake-4) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-3) - [Dependencies](#dependencies-6) - [Added](#added-6) - [Changed](#changed-6) - [Removed](#removed-6) -- [v1.34.0-alpha.1](#v1340-alpha1) - - [Downloads for v1.34.0-alpha.1](#downloads-for-v1340-alpha1) +- [v1.34.0-alpha.2](#v1340-alpha2) + - [Downloads for v1.34.0-alpha.2](#downloads-for-v1340-alpha2) - [Source Code](#source-code-7) - [Client Binaries](#client-binaries-7) - [Server Binaries](#server-binaries-7) - [Node Binaries](#node-binaries-7) - [Container Images](#container-images-7) + - [Changelog since v1.34.0-alpha.1](#changelog-since-v1340-alpha1) + - [Changes by Kind](#changes-by-kind-7) + - [Deprecation](#deprecation-2) + - [API Change](#api-change-4) + - [Feature](#feature-5) + - [Bug or Regression](#bug-or-regression-7) + - [Other (Cleanup or Flake)](#other-cleanup-or-flake-4) + - [Dependencies](#dependencies-7) + - [Added](#added-7) + - [Changed](#changed-7) + - [Removed](#removed-7) +- [v1.34.0-alpha.1](#v1340-alpha1) + - [Downloads for v1.34.0-alpha.1](#downloads-for-v1340-alpha1) + - [Source Code](#source-code-8) + - [Client Binaries](#client-binaries-8) + - [Server Binaries](#server-binaries-8) + - [Node Binaries](#node-binaries-8) + - [Container Images](#container-images-8) - [Changelog since v1.33.0](#changelog-since-v1330-1) - [Urgent Upgrade Notes](#urgent-upgrade-notes-1) - [(No, really, you MUST read this before you upgrade)](#no-really-you-must-read-this-before-you-upgrade-1) - - [Changes by Kind](#changes-by-kind-7) + - [Changes by Kind](#changes-by-kind-8) - [Deprecation](#deprecation-3) - [API Change](#api-change-5) - [Feature](#feature-6) - [Failing Test](#failing-test-3) - - [Bug or Regression](#bug-or-regression-7) + - [Bug or Regression](#bug-or-regression-8) - [Other (Cleanup or Flake)](#other-cleanup-or-flake-5) - - [Dependencies](#dependencies-7) - - [Added](#added-7) - - [Changed](#changed-7) - - [Removed](#removed-7) + - [Dependencies](#dependencies-8) + - [Added](#added-8) + - [Changed](#changed-8) + - [Removed](#removed-8) +# v1.34.1 + + +## Downloads for v1.34.1 + + + +### Source Code + +filename | sha512 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes.tar.gz) | b1262f114376f7bc0532ef688e758657ada0796e958c7b49e1401e8a2789791a7d59e5460c54780131fc8fa7398c6e87a7e59fdc4a84061c15d015c69a07e10d +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-src.tar.gz) | 5109cd698bd249341357f5a0b7ab3cd078a641747ef1a17e168f650c62af854cc46bf3bca884f43ea33d51e81a2be4e31d0d02af639a3f58d79f3f1322b0e238 + +### Client Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-darwin-amd64.tar.gz) | c977b7ede3a07ec721a874ec127a9b2d2e1edce097e33fc5bfe0a7a2ecf61153c4e514787e89003eeb8d463f47ba0c09f3267669769f0cba873c5265674e056d +[kubernetes-client-darwin-arm64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-darwin-arm64.tar.gz) | ae6b112e45e50a9d1ce0738f948f933eed419dde20a70f399cfcf77ebf5179b6af893ae7e1e633f5b99c1f34a499a2238474cc45878afdf250c048ea43c559a2 +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-linux-386.tar.gz) | 3e8aff795fa394343b4d3a943dba25b06b5c122df91fe5893cb354ee605a087f6150cee6225ff60d4b1ed9e0fa02adb9e4ccd8e38cd12337a92cedbdcfaabff2 +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-linux-amd64.tar.gz) | 3abedd362fffd5eb749febdeb59c2edd9902f7f69fb182f879daeb27cc88405983c539513cb74ef9b9587ab3829bde992f22f2067fd181311989345f6e13b867 +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-linux-arm.tar.gz) | 0d28e96ff4bf3f570277f194a975c19e8a1b49e7240908a91278647c44b5f019251dd7774aed5dbbfe7c030ded993701044c90ac97e14de5c51d0e9ae84d2127 +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-linux-arm64.tar.gz) | 279832e1ac95532807aeb68ed951e8099300e3cd4a09f1d829c4b0197e0010d18d1de19e54f73b0ab7f104ee5670ef4897127432fac42867b7a727d75dc8bd48 +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-linux-ppc64le.tar.gz) | 1367d4dfebab6f504612d6aa7e6dd7f6391ec28779c0610ef89c77bb691a5020ff3d863d5414645d62e9dfbf1fe814cf8b3bae3097c210f8e8ad895deb19c291 +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-linux-s390x.tar.gz) | d03ff4bbad2c947a37a6ffc62f3db08cf2cc1d9d702d90b94f80fb9fdcc637c4f96096beb3a466f07ac4ca807d89e81240f15cf7d2ae1c6fbd4a953122728e28 +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-windows-386.tar.gz) | 7929fd442acfa851c1510b52a6c3a11f6d3c2fb318597e68134a1927bac18ab70c6de7d572c0c05ecbc8c5764cf20fc91ab4c1ad604c7cd3707b86c01cb9fd16 +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-windows-amd64.tar.gz) | f73e914d28e0986d4b32bbf0d39c428d3e4d28dac11cf8d2b48eae4f1825511fc8b1b706427a1fe752fc0d280f1b4c539f4261cc31f679f25646ac5234afa7ad +[kubernetes-client-windows-arm64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-client-windows-arm64.tar.gz) | f03de193bc851a1327cbc7338f019cabe7167775ca597c36637b10332b8892a7a4bcc5daa090349f24347f5210fced19c7a15211c69abb94fee87e88c1efaa30 + +### Server Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-server-linux-amd64.tar.gz) | 8fd1e779f4d0188592644e234a6e5b728b9000a2afeb9d8da25131a5a4e54718bb46c4d521c62e26ea971e32745529fbb001c4f011ef2c54091cb5e81b4b90f2 +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-server-linux-arm64.tar.gz) | 77f68803b34f710c9623f388452494075ca9bb38567e7878176ec12a6d2971d2feba381e99462dc8c6e83ff5064dcffcaa7df736b67208880f5e90d71a831c2c +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-server-linux-ppc64le.tar.gz) | 6a5378a02b9b27cce9e0bc26399f8c0a8676372407bb618949fa41caacb4bbfbc7ec5487e00d973fbf409abe848a3aed42b2ead2c78753a1dd7c3251daf61745 +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-server-linux-s390x.tar.gz) | 6b9b4b64907ec817ce93a70faecbfcccf665e6b7681d0c21e26844c9d2645227ee8956c3b6b6a2417725b1e64353d5e1ed7071cf2c8e71ea8551cd47d662c3d8 + +### Node Binaries + +filename | sha512 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-node-linux-amd64.tar.gz) | c9b7d52708c4282757cd7aaa8b059c26f8f427cf8c238dff95cdc85a68d42c28b6e09fbf1aee3fa6f5f377aa395c6b9a73c112c56a6485e22b16a9c8562a8eef +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-node-linux-arm64.tar.gz) | efe54933eb5e7e6b44c76efe0b4cec911340793ef2eafdd595593fb2537e5704429d3a291793cb69ad459fe14058da491a29a12d963ba34ee4c1475cc0799b0f +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-node-linux-ppc64le.tar.gz) | 59a7223e167c890d8cb8544b9692182aaccb3814cb203337ea21a87902e0174d6f0e114d015989c42890d3b73cb73bdf8b1b71ef89fd1b0cf615349d10c23f8f +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-node-linux-s390x.tar.gz) | b648658aaae4812d787b7be04bdfd13dc379316bbcda107eca410ffbdf57713f00bbb68ad4fe9501c3bb26e5d35f589653d4067a5753f681e41f493a28309ea9 +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.34.1/kubernetes-node-windows-amd64.tar.gz) | 4c70f856364a976aa919662f3b3f6f06da3fe7ae156b7bf3fd84de4b5a0b0c70221283220c48c3cc31dddce0f2e0167606126515b1750ca90aaf129f1c9280ce + +### Container Images + +All container images are available as manifest lists and support the described +architectures. It is also possible to pull a specific architecture directly by +adding the "-$ARCH" suffix to the container image name. + +name | architectures +---- | ------------- +[registry.k8s.io/conformance:v1.34.1](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/conformance-s390x) +[registry.k8s.io/kube-apiserver:v1.34.1](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-apiserver-s390x) +[registry.k8s.io/kube-controller-manager:v1.34.1](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-controller-manager-s390x) +[registry.k8s.io/kube-proxy:v1.34.1](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-proxy-s390x) +[registry.k8s.io/kube-scheduler:v1.34.1](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kube-scheduler-s390x) +[registry.k8s.io/kubectl:v1.34.1](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl) | [amd64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl-amd64), [arm64](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl-arm64), [ppc64le](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl-ppc64le), [s390x](https://console.cloud.google.com/artifacts/docker/k8s-artifacts-prod/southamerica-east1/images/kubectl-s390x) + +## Changelog since v1.34.0 + +## Changes by Kind + +### Bug or Regression + +- Fixed SELinux warning controller not emitting events on some SELinux label conflicts. ([#133745](https://github.com/kubernetes/kubernetes/pull/133745), [@jsafrane](https://github.com/jsafrane)) [SIG Apps, Storage and Testing] +- Fixed broken shell completion for api resources. ([#133783](https://github.com/kubernetes/kubernetes/pull/133783), [@vpnachev](https://github.com/vpnachev)) [SIG CLI] +- Kube-apiserver: Fixed a 1.34 regression in CustomResourceDefinition handling that incorrectly warned about unrecognized formats on number and integer properties ([#133901](https://github.com/kubernetes/kubernetes/pull/133901), [@yongruilin](https://github.com/yongruilin)) [SIG API Machinery] +- Kube-apiserver: Fixes a 1.34 regression with spurious "Error getting keys" log messages ([#133866](https://github.com/kubernetes/kubernetes/pull/133866), [@serathius](https://github.com/serathius)) [SIG API Machinery and Etcd] +- Kube-apiserver: Fixes a possible 1.34 performance regression calculating object size statistics for resources not served from the watch cache, typically only Events ([#133879](https://github.com/kubernetes/kubernetes/pull/133879), [@serathius](https://github.com/serathius)) [SIG API Machinery and Etcd] +- Kubeadm: fixed bug where v1beta3's ClusterConfiguration.APIServer.TimeoutForControlPlane is not respected in newer versions of kubeadm where v1beta4 is the default. ([#133753](https://github.com/kubernetes/kubernetes/pull/133753), [@HirazawaUi](https://github.com/HirazawaUi)) [SIG Cluster Lifecycle] + +## Dependencies + +### Added +_Nothing has changed._ + +### Changed +_Nothing has changed._ + +### Removed +_Nothing has changed._ + + + # v1.34.0 [Documentation](https://docs.k8s.io) diff --git a/deps/github.com/openshift/kubernetes/REBASE.openshift.md b/deps/github.com/openshift/kubernetes/REBASE.openshift.md index 68e185b334..1d6d616f8e 100644 --- a/deps/github.com/openshift/kubernetes/REBASE.openshift.md +++ b/deps/github.com/openshift/kubernetes/REBASE.openshift.md @@ -273,19 +273,20 @@ go mod tidy && go mod vendor Alternatively, you can edit `go.mod` file manually with your favourite editor and use search&replace. -## Review test annotation rules +## Review test environmental selection rules -The names of upstream e2e tests are annotated according to the a set of -[declarative rules](openshift-hack/e2e/annotate/rules.go). These annotations -are used to group tests into suites and to skip tests that are known not to be -incompatible with some or all configurations of OpenShift. +Test environmental selection rules are defined in two files: +- [disabled_tests.go](openshift-hack/cmd/k8s-tests-ext/disabled_tests.go) - for completely disabled tests +- [environment_selectors.go](openshift-hack/cmd/k8s-tests-ext/environment_selectors.go) - for conditionally skipped tests + +These rules are used to skip tests that are known to be incompatible with some or all configurations of OpenShift. When performing a rebase, it is important to review the rules to ensure they are still relevant: -- [ ] Ensure that `[Disabled:Alpha]` rules are appropriate for the current kube +- [ ] Ensure that `Alpha` rules in [disabled_tests.go](openshift-hack/cmd/k8s-tests-ext/disabled_tests.go) are appropriate for the current kube level. Alpha features that are not enabled by default should be targeted - by this annotation to ensure that tests of those features are skipped. + by these rules to ensure that tests of those features are skipped. - [ ] Add new skips (along with a bz to track resolution) where e2e tests fail consistently. diff --git a/deps/github.com/openshift/kubernetes/build/build-image/cross/VERSION b/deps/github.com/openshift/kubernetes/build/build-image/cross/VERSION index fc8bcd43d9..14a4b84c20 100644 --- a/deps/github.com/openshift/kubernetes/build/build-image/cross/VERSION +++ b/deps/github.com/openshift/kubernetes/build/build-image/cross/VERSION @@ -1 +1 @@ -v1.34.0-go1.24.6-bullseye.0 +v1.34.0-go1.24.9-bullseye.0 diff --git a/deps/github.com/openshift/kubernetes/build/common.sh b/deps/github.com/openshift/kubernetes/build/common.sh index 38c20f5ffb..2bd3cd0522 100755 --- a/deps/github.com/openshift/kubernetes/build/common.sh +++ b/deps/github.com/openshift/kubernetes/build/common.sh @@ -97,9 +97,9 @@ readonly KUBE_RSYNC_PORT="${KUBE_RSYNC_PORT:-}" readonly KUBE_CONTAINER_RSYNC_PORT=8730 # These are the default versions (image tags) for their respective base images. -readonly __default_distroless_iptables_version=v0.7.8 -readonly __default_go_runner_version=v2.4.0-go1.24.6-bookworm.0 -readonly __default_setcap_version=bookworm-v1.0.4 +readonly __default_distroless_iptables_version=v0.7.11 +readonly __default_go_runner_version=v2.4.0-go1.24.9-bookworm.0 +readonly __default_setcap_version=bookworm-v1.0.6 # These are the base images for the Docker-wrapped binaries. readonly KUBE_GORUNNER_IMAGE="${KUBE_GORUNNER_IMAGE:-$KUBE_BASE_IMAGE_REGISTRY/go-runner:$__default_go_runner_version}" diff --git a/deps/github.com/openshift/kubernetes/build/dependencies.yaml b/deps/github.com/openshift/kubernetes/build/dependencies.yaml index d4c736f25e..3abc723bea 100644 --- a/deps/github.com/openshift/kubernetes/build/dependencies.yaml +++ b/deps/github.com/openshift/kubernetes/build/dependencies.yaml @@ -64,7 +64,7 @@ dependencies: # etcd - name: "etcd" - version: 3.6.4 + version: 3.6.5 refPaths: - path: cluster/gce/manifests/etcd.manifest match: etcd_docker_tag|etcd_version @@ -74,10 +74,6 @@ dependencies: match: DefaultEtcdVersion = - path: hack/lib/etcd.sh match: ETCD_VERSION= - - path: staging/src/k8s.io/sample-apiserver/artifacts/example/deployment.yaml - match: gcr.io/etcd-development/etcd - - path: test/utils/image/manifest.go - match: configs\[Etcd\] = Config{list\.GcEtcdRegistry, "etcd", "\d+\.\d+.\d+(-(alpha|beta|rc).\d+)?(-\d+)?"} - name: "etcd-image" version: 3.6.4 @@ -117,7 +113,7 @@ dependencies: # Golang # TODO: this should really be eliminated and controlled by .go-version - name: "golang: upstream version" - version: 1.24.6 + version: 1.24.9 refPaths: - path: .go-version - path: build/build-image/cross/VERSION @@ -138,13 +134,13 @@ dependencies: match: minimum_go_version=go([0-9]+\.[0-9]+) - name: "registry.k8s.io/kube-cross: dependents" - version: v1.34.0-go1.24.6-bullseye.0 + version: v1.34.0-go1.24.9-bullseye.0 refPaths: - path: build/build-image/cross/VERSION # Base images - name: "registry.k8s.io/debian-base: dependents" - version: bookworm-v1.0.4 + version: bookworm-v1.0.6 refPaths: - path: cluster/images/etcd/Makefile match: BASEIMAGE\?\=registry\.k8s\.io\/build-image\/debian-base:[a-zA-Z]+\-v((([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?) @@ -174,7 +170,7 @@ dependencies: match: registry\.k8s\.io\/build-image\/debian-base:[a-zA-Z]+\-v((([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?)(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?) - name: "registry.k8s.io/distroless-iptables: dependents" - version: v0.7.8 + version: v0.7.11 refPaths: - path: build/common.sh match: __default_distroless_iptables_version= @@ -182,7 +178,7 @@ dependencies: match: configs\[DistrolessIptables\] = Config{list\.BuildImageRegistry, "distroless-iptables", "v([0-9]+)\.([0-9]+)\.([0-9]+)"} - name: "registry.k8s.io/go-runner: dependents" - version: v2.4.0-go1.24.6-bookworm.0 + version: v2.4.0-go1.24.9-bookworm.0 refPaths: - path: build/common.sh match: __default_go_runner_version= @@ -240,7 +236,7 @@ dependencies: match: configs\[Pause\] = Config{list\.GcRegistry, "pause", "\d+\.\d+(.\d+)?"} - name: "registry.k8s.io/build-image/setcap: dependents" - version: bookworm-v1.0.4 + version: bookworm-v1.0.6 refPaths: - path: build/common.sh match: __default_setcap_version= diff --git a/deps/github.com/openshift/kubernetes/cluster/addons/addon-manager/Makefile b/deps/github.com/openshift/kubernetes/cluster/addons/addon-manager/Makefile index 239fdaec6d..8727a80417 100644 --- a/deps/github.com/openshift/kubernetes/cluster/addons/addon-manager/Makefile +++ b/deps/github.com/openshift/kubernetes/cluster/addons/addon-manager/Makefile @@ -18,7 +18,7 @@ TEMP_DIR:=$(shell mktemp -d) VERSION=v9.1.8 KUBECTL_VERSION?=v1.32.2 -BASEIMAGE=registry.k8s.io/build-image/debian-base-$(ARCH):bookworm-v1.0.4 +BASEIMAGE=registry.k8s.io/build-image/debian-base-$(ARCH):bookworm-v1.0.6 SUDO=$(if $(filter 0,$(shell id -u)),,sudo) diff --git a/deps/github.com/openshift/kubernetes/cluster/common.sh b/deps/github.com/openshift/kubernetes/cluster/common.sh index 448b3fe121..1111f5ef41 100755 --- a/deps/github.com/openshift/kubernetes/cluster/common.sh +++ b/deps/github.com/openshift/kubernetes/cluster/common.sh @@ -481,13 +481,13 @@ EOF ;; server) echo "Generate server certificates..." - echo '{"CN":"'"${member_ip}"'","hosts":[""],"key":{"algo":"ecdsa","size":256}}' \ + echo '{"CN":"'"${member_ip}"'","hosts":[],"key":{"algo":"ecdsa","size":256}}' \ | ${CFSSL_BIN} gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server -hostname="${member_ip},127.0.0.1" - \ | ${CFSSLJSON_BIN} -bare "${prefix}" ;; peer) echo "Generate peer certificates..." - echo '{"CN":"'"${member_ip}"'","hosts":[""],"key":{"algo":"ecdsa","size":256}}' \ + echo '{"CN":"'"${member_ip}"'","hosts":[],"key":{"algo":"ecdsa","size":256}}' \ | ${CFSSL_BIN} gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer -hostname="${member_ip},127.0.0.1" - \ | ${CFSSLJSON_BIN} -bare "${prefix}" ;; diff --git a/deps/github.com/openshift/kubernetes/cluster/gce/config-default.sh b/deps/github.com/openshift/kubernetes/cluster/gce/config-default.sh index ab7804bcfa..2e26d07786 100755 --- a/deps/github.com/openshift/kubernetes/cluster/gce/config-default.sh +++ b/deps/github.com/openshift/kubernetes/cluster/gce/config-default.sh @@ -88,7 +88,7 @@ fi # By default, the latest image from the image family will be used unless an # explicit image will be set. GCI_VERSION=${KUBE_GCI_VERSION:-} -IMAGE_FAMILY=${KUBE_IMAGE_FAMILY:-cos-109-lts} +IMAGE_FAMILY=${KUBE_IMAGE_FAMILY:-cos-121-lts} export MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-} export MASTER_IMAGE_FAMILY=${KUBE_GCE_MASTER_IMAGE_FAMILY:-${IMAGE_FAMILY}} export MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-cos-cloud} diff --git a/deps/github.com/openshift/kubernetes/cluster/gce/config-test.sh b/deps/github.com/openshift/kubernetes/cluster/gce/config-test.sh index d950f67bdd..9838984584 100755 --- a/deps/github.com/openshift/kubernetes/cluster/gce/config-test.sh +++ b/deps/github.com/openshift/kubernetes/cluster/gce/config-test.sh @@ -101,7 +101,7 @@ ALLOWED_NOTREADY_NODES=${ALLOWED_NOTREADY_NODES:-$(($(get-num-nodes) / 100))} # By default, the latest image from the image family will be used unless an # explicit image will be set. GCI_VERSION=${KUBE_GCI_VERSION:-} -IMAGE_FAMILY=${KUBE_IMAGE_FAMILY:-cos-109-lts} +IMAGE_FAMILY=${KUBE_IMAGE_FAMILY:-cos-121-lts} export MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-} export MASTER_IMAGE_FAMILY=${KUBE_GCE_MASTER_IMAGE_FAMILY:-${IMAGE_FAMILY}} export MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-cos-cloud} diff --git a/deps/github.com/openshift/kubernetes/cluster/gce/gci/configure-helper.sh b/deps/github.com/openshift/kubernetes/cluster/gce/gci/configure-helper.sh index c21361817f..c57e8d253b 100755 --- a/deps/github.com/openshift/kubernetes/cluster/gce/gci/configure-helper.sh +++ b/deps/github.com/openshift/kubernetes/cluster/gce/gci/configure-helper.sh @@ -1963,10 +1963,14 @@ def resolve(host): fi sed -i -e "s@{{ *etcd_protocol *}}@$etcd_protocol@g" "${temp_file}" sed -i -e "s@{{ *etcd_apiserver_protocol *}}@$etcd_apiserver_protocol@g" "${temp_file}" - sed -i -e "s@{{ *etcd_creds *}}@$etcd_creds@g" "${temp_file}" + + etcd_creds_and_extra_args="${etcd_creds} ${etcd_apiserver_creds} ${etcd_extra_args}" + etcd_creds_and_extra_args=$(echo "$etcd_creds_and_extra_args" | awk '{for (i=1;i<=NF;i++) printf "\"%s\"%s", $i, (i>/var/log/etcd{{ suffix }}.log 2>&1; fi; exec /usr/local/bin/etcd --name etcd-{{ hostname }} --listen-peer-urls {{ etcd_protocol }}://{{ host_ip }}:{{ server_port }} --initial-advertise-peer-urls {{ etcd_protocol }}://{{ hostname }}:{{ server_port }} --advertise-client-urls {{ etcd_apiserver_protocol }}://127.0.0.1:{{ port }} --listen-client-urls {{ etcd_apiserver_protocol }}://{{ listen_client_ip }}:{{ port }} {{ quota_bytes }} --data-dir /var/etcd/data{{ suffix }} --initial-cluster-state {{ cluster_state }} --initial-cluster {{ etcd_cluster }} {{ etcd_creds }} {{ etcd_apiserver_creds }} {{ etcd_extra_args }} 1>>/var/log/etcd{{ suffix }}.log 2>&1" - ], + "/usr/local/bin/etcd", + "--name=etcd-{{ hostname }}", + "--listen-peer-urls={{ etcd_protocol }}://{{ host_ip }}:{{ server_port }}", + "--initial-advertise-peer-urls={{ etcd_protocol }}://{{ hostname }}:{{ server_port }}", + "--advertise-client-urls={{ etcd_apiserver_protocol }}://127.0.0.1:{{ port }}", + "--listen-client-urls={{ etcd_apiserver_protocol }}://{{ listen_client_ip }}:{{ port }}", + "{{ quota_bytes }}", + "--data-dir=/var/etcd/data{{ suffix }}", + "--initial-cluster-state={{ cluster_state }}", + "--initial-cluster={{ etcd_cluster }}", + "--log-outputs=/var/log/etcd{{ suffix }}.log", + {{ etcd_creds_and_extra_args }} + ], "env": [ { "name": "TARGET_STORAGE", "value": "{{ pillar.get('storage_backend', 'etcd3') }}" }, { "name": "TARGET_VERSION", - "value": "{{ pillar.get('etcd_version', '3.6.4') }}" + "value": "{{ pillar.get('etcd_version', '3.6.5') }}" }, { "name": "DO_NOT_MOVE_BINARIES", @@ -52,12 +61,6 @@ { "name": "INITIAL_ADVERTISE_PEER_URLS", "value": "{{ etcd_protocol }}://{{ hostname }}:{{ server_port }}" }, - { "name": "ETCD_CREDS", - "value": "{{ etcd_creds }}" - }, - { "name": "ETCD_APISERVER_CREDS", - "value": "{{ etcd_apiserver_creds }}" - }, { "name": "ETCD_SNAPSHOT_COUNT", "value": "10000" }, @@ -72,9 +75,12 @@ "livenessProbe": { "exec": { "command": [ - "/bin/sh", - "-c", - "set -x; exec /usr/local/bin/etcdctl --endpoints=127.0.0.1:{{ port }} {{ etcdctl_certs }} --command-timeout=15s endpoint health" + "/usr/local/bin/etcdctl", + "--endpoints=127.0.0.1:{{ port }}", + "--command-timeout=15s", + {{ etcdctl_certs }} + "endpoint", + "health" ] }, "initialDelaySeconds": {{ liveness_probe_initial_delay }}, diff --git a/deps/github.com/openshift/kubernetes/cluster/gce/upgrade-aliases.sh b/deps/github.com/openshift/kubernetes/cluster/gce/upgrade-aliases.sh index 417f8a509f..fb88cd80cf 100755 --- a/deps/github.com/openshift/kubernetes/cluster/gce/upgrade-aliases.sh +++ b/deps/github.com/openshift/kubernetes/cluster/gce/upgrade-aliases.sh @@ -170,8 +170,8 @@ export KUBE_GCE_ENABLE_IP_ALIASES=true export SECONDARY_RANGE_NAME="pods-default" export STORAGE_BACKEND="etcd3" export STORAGE_MEDIA_TYPE="application/vnd.kubernetes.protobuf" -export ETCD_IMAGE=3.6.4-0 -export ETCD_VERSION=3.6.4 +export ETCD_IMAGE=3.6.5-0 +export ETCD_VERSION=3.6.5 # Upgrade master with updated kube envs "${KUBE_ROOT}/cluster/gce/upgrade.sh" -M -l diff --git a/deps/github.com/openshift/kubernetes/cluster/gce/util.sh b/deps/github.com/openshift/kubernetes/cluster/gce/util.sh index 72ad580306..98f2002aac 100755 --- a/deps/github.com/openshift/kubernetes/cluster/gce/util.sh +++ b/deps/github.com/openshift/kubernetes/cluster/gce/util.sh @@ -1835,7 +1835,7 @@ function generate-certs { # make the config for the signer echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","client auth"]}}}' > "ca-config.json" # create the kubelet client cert with the correct groups - echo '{"CN":"kubelet","names":[{"O":"system:nodes"}],"hosts":[""],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare kubelet + echo '{"CN":"kubelet","names":[{"O":"system:nodes"}],"hosts":[],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare kubelet mv "kubelet-key.pem" "pki/private/kubelet.key" mv "kubelet.pem" "pki/issued/kubelet.crt" rm -f "kubelet.csr" @@ -1900,7 +1900,7 @@ function generate-aggregator-certs { # make the config for the signer echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","client auth"]}}}' > "ca-config.json" # create the aggregator client cert with the correct groups - echo '{"CN":"aggregator","hosts":[""],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare proxy-client + echo '{"CN":"aggregator","hosts":[],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare proxy-client mv "proxy-client-key.pem" "pki/private/proxy-client.key" mv "proxy-client.pem" "pki/issued/proxy-client.crt" rm -f "proxy-client.csr" @@ -1961,7 +1961,7 @@ function generate-konnectivity-server-certs { # make the config for the signer echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","client auth"]}}}' > "ca-config.json" # create the konnectivity server cert with the correct groups - echo '{"CN":"konnectivity-server","hosts":[""],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare konnectivity-server + echo '{"CN":"konnectivity-server","hosts":[],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare konnectivity-server rm -f "konnectivity-server.csr" # Make the agent <-> konnectivity server side certificates. @@ -1977,7 +1977,7 @@ function generate-konnectivity-server-certs { # make the config for the signer echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","agent auth"]}}}' > "ca-config.json" # create the konnectivity server cert with the correct groups - echo '{"CN":"koonectivity-server","hosts":[""],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare konnectivity-agent + echo '{"CN":"koonectivity-server","hosts":[],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare konnectivity-agent rm -f "konnectivity-agent.csr" echo "completed main certificate section") &>"${cert_create_debug_output}" || true @@ -2039,7 +2039,7 @@ function generate-cloud-pvl-admission-certs { # make the config for the signer echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","client auth"]}}}' > "ca-config.json" # create the cloud-pvl-admission cert with the correct groups - echo '{"CN":"cloud-pvl-admission","hosts":[""],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare cloud-pvl-admission + echo '{"CN":"cloud-pvl-admission","hosts":[],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare cloud-pvl-admission rm -f "cloud-pvl-admission.csr" # Make the cloud-pvl-admission server side certificates. @@ -2055,7 +2055,7 @@ function generate-cloud-pvl-admission-certs { # make the config for the signer echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","agent auth"]}}}' > "ca-config.json" # create the cloud-pvl-admission server cert with the correct groups - echo '{"CN":"cloud-pvl-admission","hosts":[""],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare konnectivity-agent + echo '{"CN":"cloud-pvl-admission","hosts":[],"key":{"algo":"rsa","size":2048}}' | "${CFSSL_BIN}" gencert -ca=pki/ca.crt -ca-key=pki/private/ca.key -config=ca-config.json - | "${CFSSLJSON_BIN}" -bare konnectivity-agent rm -f "konnectivity-agent.csr" echo "completed main certificate section") &>"${cert_create_debug_output}" || true diff --git a/deps/github.com/openshift/kubernetes/cluster/images/etcd/Makefile b/deps/github.com/openshift/kubernetes/cluster/images/etcd/Makefile index 650b4c13dc..7178ef7333 100644 --- a/deps/github.com/openshift/kubernetes/cluster/images/etcd/Makefile +++ b/deps/github.com/openshift/kubernetes/cluster/images/etcd/Makefile @@ -92,19 +92,19 @@ DOCKERFILE.windows = Dockerfile.windows DOCKERFILE := ${DOCKERFILE.${OS}} ifeq ($(ARCH),amd64) - BASEIMAGE?=registry.k8s.io/build-image/debian-base:bookworm-v1.0.4 + BASEIMAGE?=registry.k8s.io/build-image/debian-base:bookworm-v1.0.6 endif ifeq ($(ARCH),arm) - BASEIMAGE?=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.4 + BASEIMAGE?=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.6 endif ifeq ($(ARCH),arm64) - BASEIMAGE?=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.4 + BASEIMAGE?=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.6 endif ifeq ($(ARCH),ppc64le) - BASEIMAGE?=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.4 + BASEIMAGE?=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.6 endif ifeq ($(ARCH),s390x) - BASEIMAGE?=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.4 + BASEIMAGE?=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.6 endif BASE.windows = mcr.microsoft.com/windows/nanoserver diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/certs.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/certs.go index f4e7d92454..1e5115a558 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/certs.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/certs.go @@ -49,6 +49,7 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/util/errors" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" "k8s.io/kubernetes/cmd/kubeadm/app/util/output" + staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod" ) var ( @@ -346,7 +347,10 @@ func getInternalCfg(cfgPath string, client kubernetes.Interface, cfg kubeadmapiv // In case the user is not providing a custom config, try to get current config from the cluster. // NB. this operation should not block, because we want to allow certificate renewal also in case of not-working clusters if cfgPath == "" && client != nil { - internalcfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, logPrefix, false, false) + getNodeRegistration := true + getAPIEndpoint := staticpodutil.IsControlPlaneNode() + getComponentConfigs := true + internalcfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, logPrefix, getNodeRegistration, getAPIEndpoint, getComponentConfigs) if err == nil { printer.Println() // add empty line to separate the FetchInitConfigurationFromCluster output from the command output // certificate renewal or expiration checking doesn't depend on a running cluster, which means the CertificatesDir diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/init.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/init.go index ba21ebf35e..e25b9dea49 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/init.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/init.go @@ -19,9 +19,11 @@ package cmd import ( "fmt" "io" + "net" "os" "path/filepath" "slices" + "strconv" "github.com/spf13/cobra" flag "github.com/spf13/pflag" @@ -569,24 +571,26 @@ func (d *initData) Client() (clientset.Interface, error) { return d.client, nil } -// ClientWithoutBootstrap returns a dry-run client or a regular client from admin.conf. -// Unlike Client(), it does not call EnsureAdminClusterRoleBinding() or sets d.client. -// This means the client only has anonymous permissions and does not persist in initData. -func (d *initData) ClientWithoutBootstrap() (clientset.Interface, error) { - var ( - client clientset.Interface - err error - ) - if d.dryRun { - client, err = getDryRunClient(d) - if err != nil { - return nil, err - } - } else { // Use a real client - client, err = kubeconfigutil.ClientSetFromFile(d.KubeConfigPath()) - if err != nil { - return nil, err - } +// WaitControlPlaneClient returns a basic client used for the purpose of waiting +// for control plane components to report 'ok' on their respective health check endpoints. +// It uses the admin.conf as the base, but modifies it to point at the local API server instead +// of the control plane endpoint. +func (d *initData) WaitControlPlaneClient() (clientset.Interface, error) { + config, err := clientcmd.LoadFromFile(d.KubeConfigPath()) + if err != nil { + return nil, err + } + for _, v := range config.Clusters { + v.Server = fmt.Sprintf("https://%s", + net.JoinHostPort( + d.Cfg().LocalAPIEndpoint.AdvertiseAddress, + strconv.Itoa(int(d.Cfg().LocalAPIEndpoint.BindPort)), + ), + ) + } + client, err := kubeconfigutil.ToClientSet(config) + if err != nil { + return nil, err } return client, nil } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/join.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/join.go index 8916bc7091..12fce4a1cc 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/join.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/join.go @@ -19,8 +19,10 @@ package cmd import ( "fmt" "io" + "net" "os" "path/filepath" + "strconv" "strings" "text/template" @@ -625,6 +627,31 @@ func (j *joinData) Client() (clientset.Interface, error) { return client, nil } +// WaitControlPlaneClient returns a basic client used for the purpose of waiting +// for control plane components to report 'ok' on their respective health check endpoints. +// It uses the admin.conf as the base, but modifies it to point at the local API server instead +// of the control plane endpoint. +func (j *joinData) WaitControlPlaneClient() (clientset.Interface, error) { + pathAdmin := filepath.Join(j.KubeConfigDir(), kubeadmconstants.AdminKubeConfigFileName) + config, err := clientcmd.LoadFromFile(pathAdmin) + if err != nil { + return nil, err + } + for _, v := range config.Clusters { + v.Server = fmt.Sprintf("https://%s", + net.JoinHostPort( + j.Cfg().ControlPlane.LocalAPIEndpoint.AdvertiseAddress, + strconv.Itoa(int(j.Cfg().ControlPlane.LocalAPIEndpoint.BindPort)), + ), + ) + } + client, err := kubeconfigutil.ToClientSet(config) + if err != nil { + return nil, err + } + return client, nil +} + // IgnorePreflightErrors returns the list of preflight errors to ignore. func (j *joinData) IgnorePreflightErrors() sets.Set[string] { return j.ignorePreflightErrors @@ -665,7 +692,10 @@ func fetchInitConfigurationFromJoinConfiguration(cfg *kubeadmapi.JoinConfigurati } // Create the final KubeConfig file with the cluster name discovered after fetching the cluster configuration - _, clusterinfo := kubeconfigutil.GetClusterFromKubeConfig(tlsBootstrapCfg) + _, clusterinfo, err := kubeconfigutil.GetClusterFromKubeConfig(tlsBootstrapCfg) + if err != nil { + return nil, errors.Wrap(err, "the TLS bootstrap kubeconfig is malformed") + } tlsBootstrapCfg.Clusters = map[string]*clientcmdapi.Cluster{ initConfiguration.ClusterName: clusterinfo, } @@ -682,7 +712,10 @@ func fetchInitConfigurationFromJoinConfiguration(cfg *kubeadmapi.JoinConfigurati // fetchInitConfiguration reads the cluster configuration from the kubeadm-admin configMap func fetchInitConfiguration(client clientset.Interface) (*kubeadmapi.InitConfiguration, error) { - initConfiguration, err := configutil.FetchInitConfigurationFromCluster(client, nil, "preflight", true, false) + getNodeRegistration := false + getAPIEndpoint := false + getComponentConfigs := true + initConfiguration, err := configutil.FetchInitConfigurationFromCluster(client, nil, "preflight", getNodeRegistration, getAPIEndpoint, getComponentConfigs) if err != nil { return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap") } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/data.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/data.go index 21bf077803..6e7b8ba3a6 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/data.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/data.go @@ -47,7 +47,7 @@ type InitData interface { ExternalCA() bool OutputWriter() io.Writer Client() (clientset.Interface, error) - ClientWithoutBootstrap() (clientset.Interface, error) + WaitControlPlaneClient() (clientset.Interface, error) Tokens() []string PatchesDir() string } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/data_test.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/data_test.go index 8229cfc76c..8465021446 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/data_test.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/data_test.go @@ -50,6 +50,6 @@ func (t *testInitData) KubeletDir() string { r func (t *testInitData) ExternalCA() bool { return false } func (t *testInitData) OutputWriter() io.Writer { return nil } func (t *testInitData) Client() (clientset.Interface, error) { return nil, nil } -func (t *testInitData) ClientWithoutBootstrap() (clientset.Interface, error) { return nil, nil } +func (t *testInitData) WaitControlPlaneClient() (clientset.Interface, error) { return nil, nil } func (t *testInitData) Tokens() []string { return nil } func (t *testInitData) PatchesDir() string { return "" } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go index 51308db289..c93d02aef1 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/init/waitcontrolplane.go @@ -58,8 +58,7 @@ func runWaitControlPlanePhase(c workflow.RunData) error { } } - // Both Wait* calls below use a /healthz endpoint, thus a client without permissions works fine - client, err := data.ClientWithoutBootstrap() + client, err := data.WaitControlPlaneClient() if err != nil { return errors.Wrap(err, "cannot obtain client without bootstrap") } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/data.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/data.go index 8005a6b07f..f6b3e769b2 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/data.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/data.go @@ -38,6 +38,7 @@ type JoinData interface { TLSBootstrapCfg() (*clientcmdapi.Config, error) InitCfg() (*kubeadmapi.InitConfiguration, error) Client() (clientset.Interface, error) + WaitControlPlaneClient() (clientset.Interface, error) IgnorePreflightErrors() sets.Set[string] OutputWriter() io.Writer PatchesDir() string diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/data_test.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/data_test.go index c03e06bea1..5995acf7d7 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/data_test.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/data_test.go @@ -32,16 +32,17 @@ type testJoinData struct{} // testJoinData must satisfy JoinData. var _ JoinData = &testJoinData{} -func (j *testJoinData) CertificateKey() string { return "" } -func (j *testJoinData) Cfg() *kubeadmapi.JoinConfiguration { return nil } -func (j *testJoinData) TLSBootstrapCfg() (*clientcmdapi.Config, error) { return nil, nil } -func (j *testJoinData) InitCfg() (*kubeadmapi.InitConfiguration, error) { return nil, nil } -func (j *testJoinData) Client() (clientset.Interface, error) { return nil, nil } -func (j *testJoinData) IgnorePreflightErrors() sets.Set[string] { return nil } -func (j *testJoinData) OutputWriter() io.Writer { return nil } -func (j *testJoinData) PatchesDir() string { return "" } -func (j *testJoinData) DryRun() bool { return false } -func (j *testJoinData) KubeConfigDir() string { return "" } -func (j *testJoinData) KubeletDir() string { return "" } -func (j *testJoinData) ManifestDir() string { return "" } -func (j *testJoinData) CertificateWriteDir() string { return "" } +func (j *testJoinData) CertificateKey() string { return "" } +func (j *testJoinData) Cfg() *kubeadmapi.JoinConfiguration { return nil } +func (j *testJoinData) TLSBootstrapCfg() (*clientcmdapi.Config, error) { return nil, nil } +func (j *testJoinData) InitCfg() (*kubeadmapi.InitConfiguration, error) { return nil, nil } +func (j *testJoinData) Client() (clientset.Interface, error) { return nil, nil } +func (j *testJoinData) WaitControlPlaneClient() (clientset.Interface, error) { return nil, nil } +func (j *testJoinData) IgnorePreflightErrors() sets.Set[string] { return nil } +func (j *testJoinData) OutputWriter() io.Writer { return nil } +func (j *testJoinData) PatchesDir() string { return "" } +func (j *testJoinData) DryRun() bool { return false } +func (j *testJoinData) KubeConfigDir() string { return "" } +func (j *testJoinData) KubeletDir() string { return "" } +func (j *testJoinData) ManifestDir() string { return "" } +func (j *testJoinData) CertificateWriteDir() string { return "" } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/waitcontrolplane.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/waitcontrolplane.go index ba4bb82b34..bd29eabbf6 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/waitcontrolplane.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/phases/join/waitcontrolplane.go @@ -50,7 +50,7 @@ func runWaitControlPlanePhase(c workflow.RunData) error { return nil } - client, err := data.Client() + client, err := data.WaitControlPlaneClient() if err != nil { return err } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/reset.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/reset.go index 818b6eb276..23f2bf62a1 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/reset.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/reset.go @@ -44,6 +44,7 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/util/errors" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" utilruntime "k8s.io/kubernetes/cmd/kubeadm/app/util/runtime" + staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod" ) var ( @@ -132,7 +133,10 @@ func newResetData(cmd *cobra.Command, opts *resetOptions, in io.Reader, out io.W if err == nil { klog.V(1).Infof("[reset] Loaded client set from kubeconfig file: %s", opts.kubeconfigPath) - initCfg, err = configutil.FetchInitConfigurationFromCluster(client, nil, "reset", false, false) + getNodeRegistration := true + getAPIEndpoint := staticpodutil.IsControlPlaneNode() + getComponentConfigs := true + initCfg, err = configutil.FetchInitConfigurationFromCluster(client, nil, "reset", getNodeRegistration, getAPIEndpoint, getComponentConfigs) if err != nil { klog.Warningf("[reset] Unable to fetch the kubeadm-config ConfigMap from cluster: %v", err) } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go index a7bae51dd0..c6c61ed3ac 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/apply.go @@ -229,7 +229,10 @@ func newApplyData(cmd *cobra.Command, args []string, applyFlags *applyFlags) (*a // Fetches the cluster configuration. klog.V(1).Infoln("[upgrade] retrieving configuration from cluster") - initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", false, false) + getNodeRegistration := true + isControlPlaneNode := true + getComponentConfigs := true + initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", getNodeRegistration, isControlPlaneNode, getComponentConfigs) if err != nil { if apierrors.IsNotFound(err) { _, _ = printer.Printf("[upgrade] In order to upgrade, a ConfigMap called %q in the %q namespace must exist.\n", constants.KubeadmConfigConfigMap, metav1.NamespaceSystem) diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go index a3579e5325..0fee21e2ec 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/common.go @@ -45,6 +45,7 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/util/errors" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" "k8s.io/kubernetes/cmd/kubeadm/app/util/output" + staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod" ) // enforceRequirements verifies that it's okay to upgrade and then returns the variables needed for the rest of the procedure @@ -92,7 +93,10 @@ func enforceRequirements(flagSet *pflag.FlagSet, flags *applyPlanFlags, args []s return nil, nil, nil, nil, err } - initCfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, "upgrade/config", false, false) + getNodeRegistration := true + getAPIEndpoint := staticpodutil.IsControlPlaneNode() + getComponentConfigs := true + initCfg, err := configutil.FetchInitConfigurationFromCluster(client, printer, "upgrade/config", getNodeRegistration, getAPIEndpoint, getComponentConfigs) if err != nil { return nil, nil, nil, nil, errors.Wrap(err, "[upgrade/init config] FATAL") } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff.go index 947d763a57..3d5bf468e9 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff.go @@ -41,6 +41,7 @@ import ( "k8s.io/kubernetes/cmd/kubeadm/app/util/errors" kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig" "k8s.io/kubernetes/cmd/kubeadm/app/util/output" + staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod" ) type diffFlags struct { @@ -106,7 +107,7 @@ func validateManifestsPath(manifests ...string) (err error) { } // FetchInitConfigurationFunc defines the signature of the function which will fetch InitConfiguration from cluster. -type FetchInitConfigurationFunc func(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) +type FetchInitConfigurationFunc func(client clientset.Interface, printer output.Printer, logPrefix string, getNodeRegistration, getAPIEndpoint, getComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) func runDiff(fs *pflag.FlagSet, flags *diffFlags, args []string, fetchInitConfigurationFromCluster FetchInitConfigurationFunc) error { externalCfg := &v1beta4.UpgradeConfiguration{} @@ -119,7 +120,10 @@ func runDiff(fs *pflag.FlagSet, flags *diffFlags, args []string, fetchInitConfig if err != nil { return errors.Wrapf(err, "couldn't create a Kubernetes client from file %q", flags.kubeConfigPath) } - initCfg, err := fetchInitConfigurationFromCluster(client, &output.TextPrinter{}, "upgrade/diff", false, true) + getNodeRegistration := true + getAPIEndpoint := staticpodutil.IsControlPlaneNode() + getComponentConfigs := false + initCfg, err := fetchInitConfigurationFromCluster(client, &output.TextPrinter{}, "upgrade/diff", getNodeRegistration, getAPIEndpoint, getComponentConfigs) if err != nil { return err } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff_test.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff_test.go index f230412859..7e65ee1a18 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff_test.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/diff_test.go @@ -44,7 +44,7 @@ func createTestRunDiffFile(contents []byte) (string, error) { return file.Name(), nil } -func fakeFetchInitConfig(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) { +func fakeFetchInitConfig(client clientset.Interface, printer output.Printer, logPrefix string, getNodeRegistration, getAPIEndpoint, getComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) { return &kubeadmapi.InitConfiguration{ ClusterConfiguration: kubeadmapi.ClusterConfiguration{ KubernetesVersion: "v1.0.1", diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/node.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/node.go index b0f57d0b1e..1e3cd71041 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/node.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/upgrade/node.go @@ -19,14 +19,12 @@ package upgrade import ( "fmt" "io" - "os" "github.com/spf13/cobra" flag "github.com/spf13/pflag" "k8s.io/apimachinery/pkg/util/sets" clientset "k8s.io/client-go/kubernetes" - "k8s.io/klog/v2" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta4" @@ -40,6 +38,7 @@ import ( configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config" "k8s.io/kubernetes/cmd/kubeadm/app/util/errors" "k8s.io/kubernetes/cmd/kubeadm/app/util/output" + staticpodutil "k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod" ) // nodeOptions defines all the options exposed via flags by kubeadm upgrade node. @@ -164,13 +163,8 @@ func addUpgradeNodeFlags(flagSet *flag.FlagSet, nodeOptions *nodeOptions) { // This func takes care of validating nodeOptions passed to the command, and then it converts // options into the internal InitConfiguration type that is used as input all the phases in the kubeadm upgrade node workflow func newNodeData(cmd *cobra.Command, nodeOptions *nodeOptions, out io.Writer) (*nodeData, error) { - // Checks if a node is a control-plane node by looking up the kube-apiserver manifest file - isControlPlaneNode := true - filepath := constants.GetStaticPodFilepath(constants.KubeAPIServer, constants.GetStaticPodDirectory()) - if _, err := os.Stat(filepath); os.IsNotExist(err) { - klog.V(1).Infof("assuming this is not a control plane node because %q is missing", filepath) - isControlPlaneNode = false - } + isControlPlaneNode := staticpodutil.IsControlPlaneNode() + if len(nodeOptions.kubeConfigPath) == 0 { // Update the kubeconfig path depending on whether this is a control plane node or not. nodeOptions.kubeConfigPath = constants.GetKubeletKubeConfigPath() @@ -198,9 +192,10 @@ func newNodeData(cmd *cobra.Command, nodeOptions *nodeOptions, out io.Writer) (* } // Fetches the cluster configuration - // NB in case of control-plane node, we are reading all the info for the node; in case of NOT control-plane node - // (worker node), we are not reading local API address and the CRI socket from the node object - initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", !isControlPlaneNode, false) + getNodeRegistration := true + getAPIEndpoint := isControlPlaneNode + getComponentConfigs := true + initCfg, err := configutil.FetchInitConfigurationFromCluster(client, nil, "upgrade", getNodeRegistration, getAPIEndpoint, getComponentConfigs) if err != nil { return nil, errors.Wrap(err, "unable to fetch the kubeadm-config ConfigMap") } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/util/join.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/util/join.go index feded1d06d..aad2e4dff0 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/util/join.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/util/join.go @@ -56,9 +56,9 @@ func getJoinCommand(kubeConfigFile, token, key string, controlPlane, skipTokenPr } // load the default cluster config - _, clusterConfig := kubeconfigutil.GetClusterFromKubeConfig(config) - if clusterConfig == nil { - return "", errors.New("failed to get default cluster config") + _, clusterConfig, err := kubeconfigutil.GetClusterFromKubeConfig(config) + if err != nil { + return "", errors.Wrapf(err, "malformed kubeconfig file: %s", kubeConfigFile) } // load CA certificates from the kubeconfig (either from PEM data or by file path) diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/util/join_test.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/util/join_test.go index c9d08f3b17..d883ac0479 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/util/join_test.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/cmd/util/join_test.go @@ -133,7 +133,7 @@ func TestGetJoinCommand(t *testing.T) { kubeConfig: &clientcmdapi.Config{}, token: "test-token", expectError: true, - errorMessage: "failed to get default cluster config", + errorMessage: "the current context is invalid", }, { name: "Error when CA certificate is invalid", diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/constants/constants.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/constants/constants.go index 21e49e24e6..4935f0530b 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/constants/constants.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/constants/constants.go @@ -323,10 +323,10 @@ const ( KubeletHealthzPort = 10248 // MinExternalEtcdVersion indicates minimum external etcd version which kubeadm supports - MinExternalEtcdVersion = "3.5.21-0" + MinExternalEtcdVersion = "3.5.24-0" // DefaultEtcdVersion indicates the default etcd version that kubeadm uses - DefaultEtcdVersion = "3.6.4-0" + DefaultEtcdVersion = "3.6.5-0" // Etcd defines variable used internally when referring to etcd component Etcd = "etcd" @@ -498,10 +498,10 @@ var ( // SupportedEtcdVersion lists officially supported etcd versions with corresponding Kubernetes releases SupportedEtcdVersion = map[uint8]string{ - 31: "3.5.21-0", - 32: "3.5.21-0", - 33: "3.5.21-0", - 34: "3.6.4-0", + 31: "3.5.24-0", + 32: "3.5.24-0", + 33: "3.5.24-0", + 34: "3.6.5-0", } // KubeadmCertsClusterRoleName sets the name for the ClusterRole that allows diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/discovery.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/discovery.go index dbb45a5389..ae51a902dc 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/discovery.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/discovery.go @@ -21,6 +21,7 @@ import ( clientset "k8s.io/client-go/kubernetes" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + bootstrapapi "k8s.io/cluster-bootstrap/token/api" "k8s.io/klog/v2" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" @@ -51,7 +52,10 @@ func For(client clientset.Interface, cfg *kubeadmapi.JoinConfiguration) (*client if len(cfg.Discovery.TLSBootstrapToken) != 0 { klog.V(1).Info("[discovery] Using provided TLSBootstrapToken as authentication credentials for the join process") - _, clusterinfo := kubeconfigutil.GetClusterFromKubeConfig(config) + _, clusterinfo, err := kubeconfigutil.GetClusterFromKubeConfig(config) + if err != nil { + return nil, errors.Wrapf(err, "malformed kubeconfig in the %s ConfigMap", bootstrapapi.ConfigMapClusterInfo) + } return kubeconfigutil.CreateWithToken( clusterinfo.Server, kubeadmapiv1.DefaultClusterName, diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/file/file.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/file/file.go index 4a5cf3801c..2cc7caeb26 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/file/file.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/file/file.go @@ -52,9 +52,9 @@ func ValidateConfigInfo(config *clientcmdapi.Config, discoveryTimeout time.Durat if len(config.Clusters) < 1 { return nil, errors.New("the provided kubeconfig file must have at least one Cluster defined") } - currentClusterName, currentCluster := kubeconfigutil.GetClusterFromKubeConfig(config) - if currentCluster == nil { - return nil, errors.New("the provided kubeconfig file must have a unnamed Cluster or a CurrentContext that specifies a non-nil Cluster") + currentClusterName, currentCluster, err := kubeconfigutil.GetClusterFromKubeConfig(config) + if err != nil { + return nil, errors.Wrap(err, "the provided kubeconfig file is malformed") } if err := clientcmd.Validate(*config); err != nil { return nil, err @@ -124,7 +124,10 @@ func ValidateConfigInfo(config *clientcmdapi.Config, discoveryTimeout time.Durat return config, nil } - _, refreshedCluster := kubeconfigutil.GetClusterFromKubeConfig(refreshedBaseKubeConfig) + _, refreshedCluster, err := kubeconfigutil.GetClusterFromKubeConfig(refreshedBaseKubeConfig) + if err != nil { + return nil, errors.Wrapf(err, "malformed kubeconfig in the %s ConfigMap", bootstrapapi.ConfigMapClusterInfo) + } if currentCluster.Server != refreshedCluster.Server { klog.Warningf("[discovery] the API Server endpoint %q in use is different from the endpoint %q which defined in the %s ConfigMap", currentCluster.Server, refreshedCluster.Server, bootstrapapi.ConfigMapClusterInfo) } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/token/token.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/token/token.go index c05be64889..195678b143 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/token/token.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/token/token.go @@ -103,9 +103,9 @@ func retrieveValidatedConfigInfo(client clientset.Interface, cfg *kubeadmapi.Dis return nil, errors.Wrapf(err, "couldn't parse the kubeconfig file in the %s ConfigMap", bootstrapapi.ConfigMapClusterInfo) } - // The ConfigMap should contain a single cluster - if len(insecureConfig.Clusters) != 1 { - return nil, errors.Errorf("expected the kubeconfig file in the %s ConfigMap to have a single cluster, but it had %d", bootstrapapi.ConfigMapClusterInfo, len(insecureConfig.Clusters)) + _, _, err = kubeconfigutil.GetClusterFromKubeConfig(insecureConfig) + if err != nil { + return nil, errors.Wrapf(err, "malformed kubeconfig in the %s ConfigMap", bootstrapapi.ConfigMapClusterInfo) } // If no TLS root CA pinning was specified, we're done diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go index a823af66cc..2614662dce 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/discovery/token/token_test.go @@ -77,10 +77,12 @@ users: null name string tokenID string tokenSecret string + currentContextCluster string cfg *kubeadmapi.Discovery configMap *fakeConfigMap delayedJWSSignaturePatch bool expectedError bool + expectedErrorString string }{ { // This is the default behavior. The JWS signature is patched after the cluster-info ConfigMap is created @@ -130,6 +132,24 @@ users: null data: nil, }, }, + { + name: "invalid: the kubeconfig in the configmap has the wrong current context", + tokenID: "123456", + tokenSecret: "abcdef1234567890", + cfg: &kubeadmapi.Discovery{ + BootstrapToken: &kubeadmapi.BootstrapTokenDiscovery{ + Token: "123456.abcdef1234567890", + CACertHashes: []string{caCertHash}, + }, + }, + configMap: &fakeConfigMap{ + name: bootstrapapi.ConfigMapClusterInfo, + data: nil, + }, + currentContextCluster: "foo", + expectedError: true, + expectedErrorString: `malformed kubeconfig in the cluster-info ConfigMap: no matching cluster for the current context: token-bootstrap-client@somecluster`, + }, { name: "invalid: token format is invalid", tokenID: "foo", @@ -216,6 +236,13 @@ users: null for _, test := range tests { t.Run(test.name, func(t *testing.T) { kubeconfig := buildSecureBootstrapKubeConfig("127.0.0.1", []byte(caCert), "somecluster") + if len(test.currentContextCluster) > 0 { + currentContext := kubeconfig.Contexts[kubeconfig.CurrentContext] + if currentContext == nil { + t.Fatal("unexpected nil current context") + } + currentContext.Cluster = test.currentContextCluster + } kubeconfigBytes, err := clientcmd.Write(*kubeconfig) if err != nil { t.Fatalf("cannot marshal kubeconfig %v", err) @@ -267,8 +294,13 @@ users: null t.Errorf("expected error %v, got %v, error: %v", test.expectedError, err != nil, err) } - // Return if an error is expected if err != nil { + if len(test.expectedErrorString) > 0 && test.expectedErrorString != err.Error() { + t.Fatalf("expected error string: %s, got: %s", + test.expectedErrorString, err.Error()) + } + + // Return if an error is expected return } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/preflight/checks.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/preflight/checks.go index 36978405d1..bc99a641bb 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/preflight/checks.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/preflight/checks.go @@ -463,11 +463,8 @@ func (subnet HTTPProxyCIDRCheck) Check() (warnings, errorList []error) { return nil, []error{errors.Wrapf(err, "unable to get first IP address from the given CIDR (%s)", cidr.String())} } - testIPstring := testIP.String() - if len(testIP) == net.IPv6len { - testIPstring = fmt.Sprintf("[%s]:1234", testIP) - } - url := fmt.Sprintf("%s://%s/", subnet.Proto, testIPstring) + testHostString := net.JoinHostPort(testIP.String(), "1234") + url := fmt.Sprintf("%s://%s/", subnet.Proto, testHostString) req, err := http.NewRequest("GET", url, nil) if err != nil { diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/apiclient/wait.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/apiclient/wait.go index af8fa7e9f4..3938f35ec3 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/apiclient/wait.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/apiclient/wait.go @@ -23,6 +23,7 @@ import ( "io" "net" "net/http" + "strconv" "strings" "text/template" "time" @@ -357,7 +358,8 @@ func (w *KubeWaiter) WaitForKubelet(healthzAddress string, healthzPort int32) er var ( lastError error start = time.Now() - healthzEndpoint = fmt.Sprintf("http://%s:%d/healthz", healthzAddress, healthzPort) + addrPort = net.JoinHostPort(healthzAddress, strconv.Itoa(int(healthzPort))) + healthzEndpoint = fmt.Sprintf("http://%s/healthz", addrPort) ) if healthzPort == 0 { diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/config/cluster.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/config/cluster.go index 724530f692..40ba9b2dbd 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/config/cluster.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/config/cluster.go @@ -52,7 +52,7 @@ import ( ) // FetchInitConfigurationFromCluster fetches configuration from a ConfigMap in the cluster -func FetchInitConfigurationFromCluster(client clientset.Interface, printer output.Printer, logPrefix string, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) { +func FetchInitConfigurationFromCluster(client clientset.Interface, printer output.Printer, logPrefix string, getNodeRegistration, getAPIEndpoint, getComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) { if printer == nil { printer = &output.TextPrinter{} } @@ -61,7 +61,7 @@ func FetchInitConfigurationFromCluster(client clientset.Interface, printer outpu _, _ = printer.Printf("[%s] Use 'kubeadm init phase upload-config kubeadm --config your-config-file' to re-upload it.\n", logPrefix) // Fetch the actual config from cluster - cfg, err := getInitConfigurationFromCluster(constants.KubernetesDir, client, newControlPlane, skipComponentConfigs) + cfg, err := getInitConfigurationFromCluster(constants.KubernetesDir, client, getNodeRegistration, getAPIEndpoint, getComponentConfigs) if err != nil { return nil, err } @@ -76,7 +76,7 @@ func FetchInitConfigurationFromCluster(client clientset.Interface, printer outpu } // getInitConfigurationFromCluster is separate only for testing purposes, don't call it directly, use FetchInitConfigurationFromCluster instead -func getInitConfigurationFromCluster(kubeconfigDir string, client clientset.Interface, newControlPlane, skipComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) { +func getInitConfigurationFromCluster(kubeconfigDir string, client clientset.Interface, getNodeRegistration, getAPIEndpoint, getComponentConfigs bool) (*kubeadmapi.InitConfiguration, error) { // Also, the config map really should be KubeadmConfigConfigMap... configMap, err := apiclient.GetConfigMapWithShortRetry(client, metav1.NamespaceSystem, constants.KubeadmConfigConfigMap) if err != nil { @@ -106,26 +106,28 @@ func getInitConfigurationFromCluster(kubeconfigDir string, client clientset.Inte return nil, errors.Wrap(err, "failed to decode cluster configuration data") } - if !skipComponentConfigs { + if getComponentConfigs { // get the component configs from the corresponding config maps if err := componentconfigs.FetchFromCluster(&initcfg.ClusterConfiguration, client); err != nil { return nil, errors.Wrap(err, "failed to get component configs") } } - // if this isn't a new controlplane instance (e.g. in case of kubeadm upgrades) - // get nodes specific information as well - if !newControlPlane { + if getNodeRegistration { // gets the nodeRegistration for the current from the node object kubeconfigFile := filepath.Join(kubeconfigDir, constants.KubeletKubeConfigFileName) if err := GetNodeRegistration(kubeconfigFile, client, &initcfg.NodeRegistration, &initcfg.ClusterConfiguration); err != nil { return nil, errors.Wrap(err, "failed to get node registration") } - // gets the APIEndpoint for the current node - if err := getAPIEndpoint(client, initcfg.NodeRegistration.Name, &initcfg.LocalAPIEndpoint); err != nil { + } + + if getAPIEndpoint { + // gets the APIEndpoint for the current control plane node + if err := GetAPIEndpoint(client, initcfg.NodeRegistration.Name, &initcfg.LocalAPIEndpoint); err != nil { return nil, errors.Wrap(err, "failed to getAPIEndpoint") } } + return initcfg, nil } @@ -258,7 +260,8 @@ func getNodeNameFromSSR(client clientset.Interface) (string, error) { return strings.TrimPrefix(user, constants.NodesUserPrefix), nil } -func getAPIEndpoint(client clientset.Interface, nodeName string, apiEndpoint *kubeadmapi.APIEndpoint) error { +// GetAPIEndpoint gets the API endpoint for a given node. +func GetAPIEndpoint(client clientset.Interface, nodeName string, apiEndpoint *kubeadmapi.APIEndpoint) error { return getAPIEndpointWithRetry(client, nodeName, apiEndpoint, constants.KubernetesAPICallRetryInterval, kubeadmapi.GetActiveTimeouts().KubernetesAPICall.Duration) } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/config/cluster_test.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/config/cluster_test.go index 94aa9917c9..41329eee45 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/config/cluster_test.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/config/cluster_test.go @@ -491,13 +491,14 @@ func TestGetInitConfigurationFromCluster(t *testing.T) { defer os.RemoveAll(tmpdir) var tests = []struct { - name string - fileContents []byte - node *v1.Node - staticPods []testresources.FakeStaticPod - configMaps []testresources.FakeConfigMap - newControlPlane bool - expectedError bool + name string + fileContents []byte + node *v1.Node + staticPods []testresources.FakeStaticPod + configMaps []testresources.FakeConfigMap + getNodeRegistration bool + getAPIEndpoint bool + expectedError bool }{ { name: "invalid - No kubeadm-config ConfigMap", @@ -556,6 +557,8 @@ func TestGetInitConfigurationFromCluster(t *testing.T) { Taints: []v1.Taint{kubeadmconstants.ControlPlaneTaint}, }, }, + getNodeRegistration: true, + getAPIEndpoint: true, }, { name: "valid v1beta3 - new control plane == true", // InitConfiguration composed with data from different places, without node specific information @@ -588,7 +591,8 @@ func TestGetInitConfigurationFromCluster(t *testing.T) { }, }, }, - newControlPlane: true, + getNodeRegistration: false, + getAPIEndpoint: false, }, } @@ -629,7 +633,8 @@ func TestGetInitConfigurationFromCluster(t *testing.T) { } } - cfg, err := getInitConfigurationFromCluster(tmpdir, client, rt.newControlPlane, false) + getComponentConfigs := true + cfg, err := getInitConfigurationFromCluster(tmpdir, client, rt.getNodeRegistration, rt.getAPIEndpoint, getComponentConfigs) if rt.expectedError != (err != nil) { t.Errorf("unexpected return err from getInitConfigurationFromCluster: %v", err) return @@ -649,13 +654,13 @@ func TestGetInitConfigurationFromCluster(t *testing.T) { if cfg.NodeRegistration.ImagePullPolicy != kubeadmapiv1.DefaultImagePullPolicy { t.Errorf("invalid cfg.NodeRegistration.ImagePullPolicy %v", cfg.NodeRegistration.ImagePullPolicy) } - if !rt.newControlPlane && (cfg.LocalAPIEndpoint.AdvertiseAddress != "1.2.3.4" || cfg.LocalAPIEndpoint.BindPort != 1234) { + if rt.getNodeRegistration && rt.getAPIEndpoint && (cfg.LocalAPIEndpoint.AdvertiseAddress != "1.2.3.4" || cfg.LocalAPIEndpoint.BindPort != 1234) { t.Errorf("invalid cfg.LocalAPIEndpoint: %v", cfg.LocalAPIEndpoint) } - if !rt.newControlPlane && (cfg.NodeRegistration.Name != nodeName || cfg.NodeRegistration.CRISocket != "myCRIsocket" || len(cfg.NodeRegistration.Taints) != 1) { + if rt.getNodeRegistration && (cfg.NodeRegistration.Name != nodeName || cfg.NodeRegistration.CRISocket != "myCRIsocket" || len(cfg.NodeRegistration.Taints) != 1) { t.Errorf("invalid cfg.NodeRegistration: %v", cfg.NodeRegistration) } - if rt.newControlPlane && len(cfg.NodeRegistration.CRISocket) > 0 { + if !rt.getNodeRegistration && len(cfg.NodeRegistration.CRISocket) > 0 { t.Errorf("invalid cfg.NodeRegistration.CRISocket: expected empty CRISocket, but got %v", cfg.NodeRegistration.CRISocket) } if _, ok := cfg.ComponentConfigs[componentconfigs.KubeletGroup]; !ok { diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/dryrun/dryrun.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/dryrun/dryrun.go index 2d1adff724..a8ea57be90 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/dryrun/dryrun.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/dryrun/dryrun.go @@ -19,8 +19,10 @@ package dryrun import ( "fmt" "io" + "net" "os" "path/filepath" + "strconv" "time" v1 "k8s.io/api/core/v1" @@ -103,7 +105,11 @@ func (w *Waiter) WaitForPodsWithLabel(kvLabel string) error { // WaitForKubelet blocks until the kubelet /healthz endpoint returns 'ok' func (w *Waiter) WaitForKubelet(healthzAddress string, healthzPort int32) error { - fmt.Printf("[dryrun] Would make sure the kubelet returns 'ok' at http://%s:%d/healthz\n", healthzAddress, healthzPort) + var ( + addrPort = net.JoinHostPort(healthzAddress, strconv.Itoa(int(healthzPort))) + healthzEndpoint = fmt.Sprintf("http://%s/healthz", addrPort) + ) + fmt.Printf("[dryrun] Would make sure the kubelet returns 'ok' at %s\n", healthzEndpoint) return nil } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/kubeconfig/kubeconfig.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/kubeconfig/kubeconfig.go index 58bb616f50..1b94364572 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/kubeconfig/kubeconfig.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/kubeconfig/kubeconfig.go @@ -104,17 +104,21 @@ func WriteToDisk(filename string, kubeconfig *clientcmdapi.Config) error { } // GetClusterFromKubeConfig returns the default Cluster of the specified KubeConfig -func GetClusterFromKubeConfig(config *clientcmdapi.Config) (string, *clientcmdapi.Cluster) { +func GetClusterFromKubeConfig(config *clientcmdapi.Config) (string, *clientcmdapi.Cluster, error) { // If there is an unnamed cluster object, use it if config.Clusters[""] != nil { - return "", config.Clusters[""] + return "", config.Clusters[""], nil } currentContext := config.Contexts[config.CurrentContext] if currentContext != nil { - return currentContext.Cluster, config.Clusters[currentContext.Cluster] + if config.Clusters[currentContext.Cluster] != nil { + return currentContext.Cluster, config.Clusters[currentContext.Cluster], nil + } + return "", nil, errors.Errorf("no matching cluster for the current context: %s", config.CurrentContext) } - return "", nil + + return "", nil, errors.Errorf("the current context is invalid: %s", config.CurrentContext) } // HasAuthenticationCredentials returns true if the current user has valid authentication credentials for diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/kubeconfig/kubeconfig_test.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/kubeconfig/kubeconfig_test.go index 45934874b8..d108d1acc2 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/kubeconfig/kubeconfig_test.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/kubeconfig/kubeconfig_test.go @@ -351,38 +351,53 @@ func TestGetClusterFromKubeConfig(t *testing.T) { config *clientcmdapi.Config expectedClusterName string expectedCluster *clientcmdapi.Cluster + expectedError bool }{ { - name: "cluster is empty", + name: "an existing cluster with an empty name is returned directly", config: &clientcmdapi.Config{ - CurrentContext: "kubernetes", + Clusters: map[string]*clientcmdapi.Cluster{ + "": {Server: "http://foo:8080"}, + }, }, expectedClusterName: "", - expectedCluster: nil, + expectedCluster: &clientcmdapi.Cluster{ + Server: "http://foo:8080", + }, }, { - name: "cluster and currentContext are not empty", + name: "the current context is invalid", config: &clientcmdapi.Config{ CurrentContext: "foo", Contexts: map[string]*clientcmdapi.Context{ - "foo": {AuthInfo: "foo", Cluster: "foo"}, "bar": {AuthInfo: "bar", Cluster: "bar"}, }, + }, + expectedClusterName: "", + expectedCluster: nil, + expectedError: true, + }, + { + name: "no matching cluster for the current context", + config: &clientcmdapi.Config{ + CurrentContext: "foo", + Contexts: map[string]*clientcmdapi.Context{ + "foo": {AuthInfo: "bar", Cluster: "bar"}, + }, Clusters: map[string]*clientcmdapi.Cluster{ - "foo": {Server: "http://foo:8080"}, - "bar": {Server: "https://bar:16443"}, + "baz": {Server: "https://bar:16443"}, }, }, - expectedClusterName: "foo", - expectedCluster: &clientcmdapi.Cluster{ - Server: "http://foo:8080", - }, + expectedClusterName: "", + expectedCluster: nil, + expectedError: true, }, { - name: "cluster is not empty and currentContext is not in contexts", + name: "valid current context and cluster", config: &clientcmdapi.Config{ CurrentContext: "foo", Contexts: map[string]*clientcmdapi.Context{ + "foo": {AuthInfo: "foo", Cluster: "foo"}, "bar": {AuthInfo: "bar", Cluster: "bar"}, }, Clusters: map[string]*clientcmdapi.Cluster{ @@ -390,19 +405,25 @@ func TestGetClusterFromKubeConfig(t *testing.T) { "bar": {Server: "https://bar:16443"}, }, }, - expectedClusterName: "", - expectedCluster: nil, + expectedClusterName: "foo", + expectedCluster: &clientcmdapi.Cluster{ + Server: "http://foo:8080", + }, }, } for _, rt := range tests { t.Run(rt.name, func(t *testing.T) { - clusterName, cluster := GetClusterFromKubeConfig(rt.config) + clusterName, cluster, err := GetClusterFromKubeConfig(rt.config) if clusterName != rt.expectedClusterName { t.Errorf("got cluster name = %s, expected %s", clusterName, rt.expectedClusterName) } if !reflect.DeepEqual(cluster, rt.expectedCluster) { t.Errorf("got cluster = %+v, expected %+v", cluster, rt.expectedCluster) } + if (err != nil) != rt.expectedError { + t.Errorf("expected error: %v, got: %v, error: %v", + rt.expectedError, err != nil, err) + } }) } } diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/pkiutil/pki_helpers.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/pkiutil/pki_helpers.go index 9fdde7be3c..d733a6c6bc 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/pkiutil/pki_helpers.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/pkiutil/pki_helpers.go @@ -385,15 +385,18 @@ func GetAPIServerAltNames(cfg *kubeadmapi.InitConfiguration) (*certutil.AltNames return nil, errors.Wrapf(err, "unable to get first IP address from the given CIDR: %v", cfg.Networking.ServiceSubnet) } + var dnsNames []string + if len(cfg.NodeRegistration.Name) > 0 { + dnsNames = append(dnsNames, cfg.NodeRegistration.Name) + } + dnsNames = append(dnsNames, "kubernetes", "kubernetes.default", "kubernetes.default.svc") + if len(cfg.Networking.DNSDomain) > 0 { + dnsNames = append(dnsNames, fmt.Sprintf("kubernetes.default.svc.%s", cfg.Networking.DNSDomain)) + } + // create AltNames with defaults DNSNames/IPs altNames := &certutil.AltNames{ - DNSNames: []string{ - cfg.NodeRegistration.Name, - "kubernetes", - "kubernetes.default", - "kubernetes.default.svc", - fmt.Sprintf("kubernetes.default.svc.%s", cfg.Networking.DNSDomain), - }, + DNSNames: dnsNames, IPs: []net.IP{ internalAPIServerVirtualIP, advertiseAddress, @@ -441,9 +444,16 @@ func getAltNames(cfg *kubeadmapi.InitConfiguration, certName string) (*certutil. cfg.LocalAPIEndpoint.AdvertiseAddress) } + var dnsNames []string + if len(cfg.NodeRegistration.Name) > 0 { + dnsNames = []string{cfg.NodeRegistration.Name, "localhost"} + } else { + dnsNames = []string{"localhost"} + } + // create AltNames with defaults DNSNames/IPs altNames := &certutil.AltNames{ - DNSNames: []string{cfg.NodeRegistration.Name, "localhost"}, + DNSNames: dnsNames, IPs: []net.IP{advertiseAddress, net.IPv4(127, 0, 0, 1), net.IPv6loopback}, } @@ -665,13 +675,15 @@ func NewSelfSignedCACert(cfg *CertConfig, key crypto.Signer) (*x509.Certificate, CommonName: cfg.CommonName, Organization: cfg.Organization, }, - DNSNames: []string{cfg.CommonName}, NotBefore: notBefore, NotAfter: notAfter, KeyUsage: keyUsage, BasicConstraintsValid: true, IsCA: true, } + if len(cfg.CommonName) > 0 { + tmpl.DNSNames = []string{cfg.CommonName} + } certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &tmpl, &tmpl, key.Public(), key) if err != nil { diff --git a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/staticpod/utils.go b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/staticpod/utils.go index 5b70cb89c3..b49940d6c9 100644 --- a/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/staticpod/utils.go +++ b/deps/github.com/openshift/kubernetes/cmd/kubeadm/app/util/staticpod/utils.go @@ -436,3 +436,18 @@ func DeepHashObject(hasher hash.Hash, objectToWrite interface{}) { hasher.Reset() fmt.Fprintf(hasher, "%v", dump.ForHash(objectToWrite)) } + +// IsControlPlaneNode returns true if the kube-apiserver static pod manifest is present +// on the host. +func IsControlPlaneNode() bool { + isControlPlaneNode := true + + filepath := kubeadmconstants.GetStaticPodFilepath(kubeadmconstants.KubeAPIServer, + kubeadmconstants.GetStaticPodDirectory()) + + if _, err := os.Stat(filepath); os.IsNotExist(err) { + isControlPlaneNode = false + } + + return isControlPlaneNode +} diff --git a/deps/github.com/openshift/kubernetes/go.mod b/deps/github.com/openshift/kubernetes/go.mod index b0f2492440..4cee5adbda 100644 --- a/deps/github.com/openshift/kubernetes/go.mod +++ b/deps/github.com/openshift/kubernetes/go.mod @@ -124,8 +124,9 @@ require ( k8s.io/mount-utils v0.0.0 k8s.io/pod-security-admission v0.0.0 k8s.io/sample-apiserver v0.0.0 - k8s.io/system-validators v1.10.1 + k8s.io/system-validators v1.10.2 k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 sigs.k8s.io/knftables v0.0.17 sigs.k8s.io/randfill v1.0.0 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 @@ -228,13 +229,13 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // 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/kustomize/api v0.20.1 // indirect sigs.k8s.io/kustomize/kustomize/v5 v5.7.1 // indirect sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect ) replace ( + github.com/google/cadvisor => github.com/openshift/google-cadvisor v0.52.1-openshift-4.21-1 github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 k8s.io/api => ./staging/src/k8s.io/api k8s.io/apiextensions-apiserver => ./staging/src/k8s.io/apiextensions-apiserver diff --git a/deps/github.com/openshift/kubernetes/go.sum b/deps/github.com/openshift/kubernetes/go.sum index c462285756..29c578035a 100644 --- a/deps/github.com/openshift/kubernetes/go.sum +++ b/deps/github.com/openshift/kubernetes/go.sum @@ -175,8 +175,6 @@ github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2 github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/cadvisor v0.52.1 h1:sC8SZ6jio9ds+P2dk51bgbeYeufxo55n0X3tmrpA9as= -github.com/google/cadvisor v0.52.1/go.mod h1:OAhPcx1nOm5YwMh/JhpUOMKyv1YKLRtS9KgzWPndHmA= github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI= github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= @@ -315,6 +313,8 @@ github.com/openshift/apiserver-library-go v0.0.0-20251015164739-79d04067059d/go. github.com/openshift/build-machinery-go v0.0.0-20250530140348-dc5b2804eeee/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235 h1:9JBeIXmnHlpXTQPi7LPmu1jdxznBhAE7bb1K+3D8gxY= github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235/go.mod h1:L49W6pfrZkfOE5iC1PqEkuLkXG4W0BX4w8b+L2Bv7fM= +github.com/openshift/google-cadvisor v0.52.1-openshift-4.21-1 h1:GNwO7gdyk6kAbFwIRo0T8NOTgxKYA2J6tSAtVMYavY0= +github.com/openshift/google-cadvisor v0.52.1-openshift-4.21-1/go.mod h1:OAhPcx1nOm5YwMh/JhpUOMKyv1YKLRtS9KgzWPndHmA= github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 h1:bANtDc8SgetSK4nQehf59x3+H9FqVJCprgjs49/OTg0= github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5/go.mod h1:OlFFws1AO51uzfc48MsStGE4SFMWlMZD0+f5a/zCtKI= github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 h1:PMTgifBcBRLJJiM+LgSzPDTk9/Rx4qS09OUrfpY6GBQ= @@ -548,8 +548,8 @@ 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/system-validators v1.10.1 h1:bIO3YRgxJkh/W3ghcd5ViXNPGmjwQKlHk/ySPdw6K00= -k8s.io/system-validators v1.10.1/go.mod h1:awfSS706v9R12VC7u7K89FKfqVy44G+E0L1A0FX9Wmw= +k8s.io/system-validators v1.10.2 h1:7rC7VdrQCaM55E08Pw3I1v1Op9ObLxdKAu5Ff5hIPwY= +k8s.io/system-validators v1.10.2/go.mod h1:awfSS706v9R12VC7u7K89FKfqVy44G+E0L1A0FX9Wmw= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM= diff --git a/deps/github.com/openshift/kubernetes/hack/lib/etcd.sh b/deps/github.com/openshift/kubernetes/hack/lib/etcd.sh index c6fc45a5fa..6e99d244c8 100755 --- a/deps/github.com/openshift/kubernetes/hack/lib/etcd.sh +++ b/deps/github.com/openshift/kubernetes/hack/lib/etcd.sh @@ -16,7 +16,7 @@ # A set of helpers for starting/running etcd for tests -ETCD_VERSION=${ETCD_VERSION:-3.6.4} +ETCD_VERSION=${ETCD_VERSION:-3.6.5} ETCD_HOST=${ETCD_HOST:-127.0.0.1} ETCD_PORT=${ETCD_PORT:-2379} # This is intentionally not called ETCD_LOG_LEVEL: diff --git a/deps/github.com/openshift/kubernetes/hack/lib/util.sh b/deps/github.com/openshift/kubernetes/hack/lib/util.sh index 6000505318..cae8a49920 100755 --- a/deps/github.com/openshift/kubernetes/hack/lib/util.sh +++ b/deps/github.com/openshift/kubernetes/hack/lib/util.sh @@ -478,7 +478,7 @@ function kube::util::create_client_certkey { done ${sudo} /usr/bin/env bash -e < 0 { filter += " && " } - filter += fmt.Sprintf("!name.contains('%s')", s) + filter += fmt.Sprintf("!name.contains('%s') && !labels.exists(l, l == '%s')", s, s) } if baseExpr != "" { diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/cmd/k8s-tests-ext/labels.go b/deps/github.com/openshift/kubernetes/openshift-hack/cmd/k8s-tests-ext/labels.go index 747f2db5f3..1195b4e80b 100644 --- a/deps/github.com/openshift/kubernetes/openshift-hack/cmd/k8s-tests-ext/labels.go +++ b/deps/github.com/openshift/kubernetes/openshift-hack/cmd/k8s-tests-ext/labels.go @@ -17,8 +17,6 @@ func addLabelsToSpecs(specs et.ExtensionTestSpecs) { "Should be able to support the 1.7 Sample API Server using the current Aggregator", // down apiservices break other clients today https://bugzilla.redhat.com/show_bug.cgi?id=1623195 - "[Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) [sig-autoscaling] ReplicationController light Should scale from 1 pod to 2 pods", - "should prevent Ingress creation if more than 1 IngressClass marked as default", // https://bugzilla.redhat.com/show_bug.cgi?id=1822286 "[sig-network] IngressClass [Feature:Ingress] should set default value on new IngressClass", //https://bugzilla.redhat.com/show_bug.cgi?id=1833583 @@ -46,6 +44,10 @@ func addLabelsToSpecs(specs et.ExtensionTestSpecs) { "[Feature:GKELocalSSD]", "[Feature:GKENodePool]", }, + // tests that will be configured to run manually through their own dedicated prow jobs + "[DedicatedJob]": { + "[Feature:HPA]", + }, } for label, names := range namesByLabel { diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/annotate.go b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/annotate.go deleted file mode 100644 index 096ae2a00a..0000000000 --- a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/annotate.go +++ /dev/null @@ -1,290 +0,0 @@ -package annotate - -import ( - "fmt" - "io/ioutil" - "os" - "os/exec" - "regexp" - "sort" - "strings" - - "github.com/onsi/ginkgo/v2" - "github.com/onsi/ginkgo/v2/types" -) - -var reHasSig = regexp.MustCompile(`\[sig-[\w-]+\]`) - -// Run generates tests annotations for the targeted package. -// It accepts testMaps which defines labeling rules and filter -// function to remove elements based on test name and their labels. -func Run(testMaps map[string][]string, filter func(name string) bool) { - var errors []string - - if len(os.Args) != 2 && len(os.Args) != 3 { - fmt.Fprintf(os.Stderr, "error: requires exactly one argument\n") - os.Exit(1) - } - filename := os.Args[len(os.Args)-1] - - generator := newGenerator(testMaps) - ginkgo.GetSuite().BuildTree() - ginkgo.GetSuite().WalkTests(generator.generateRename) - if len(generator.errors) > 0 { - errors = append(errors, generator.errors...) - } - - renamer := newRenamerFromGenerated(generator.output) - // generated file has a map[string]string in the following format: - // original k8s name: k8s name with our labels at the end - ginkgo.GetSuite().WalkTests(renamer.updateNodeText) - if len(renamer.missing) > 0 { - var names []string - for name := range renamer.missing { - names = append(names, name) - } - sort.Strings(names) - fmt.Fprintf(os.Stderr, "failed:\n%s\n", strings.Join(names, "\n")) - os.Exit(1) - } - - // All tests must be associated with a sig (either upstream), or downstream - // If you get this error, you should add the [sig-X] tag to your test (if its - // in origin) or if it is upstream add a new rule to rules.go that assigns - // the test in question to the right sig. - // - // Upstream sigs map to teams (if you have representation on that sig, you - // own those tests in origin) - // Downstream sigs: sig-imageregistry, sig-builds, sig-devex - for from, to := range generator.output { - if !reHasSig.MatchString(from) && !reHasSig.MatchString(to) { - errors = append(errors, fmt.Sprintf("all tests must define a [sig-XXXX] tag or have a rule %q", from)) - } - } - if len(errors) > 0 { - sort.Strings(errors) - for _, s := range errors { - fmt.Fprintf(os.Stderr, "failed: %s\n", s) - } - os.Exit(1) - } - - var pairs []string - for testName, labels := range generator.output { - if filter(fmt.Sprintf("%s%s", testName, labels)) { - continue - } - pairs = append(pairs, fmt.Sprintf("%q:\n%q,", testName, labels)) - } - sort.Strings(pairs) - contents := fmt.Sprintf(` -package generated - -import ( - "fmt" - "github.com/onsi/ginkgo/v2" - "github.com/onsi/ginkgo/v2/types" -) - -var Annotations = map[string]string{ -%s -} - -func init() { - ginkgo.GetSuite().SetAnnotateFn(func(name string, node types.TestSpec) { - if newLabels, ok := Annotations[name]; ok { - node.AppendText(newLabels) - } else { - panic(fmt.Sprintf("unable to find test %%s", name)) - } - }) -} -`, strings.Join(pairs, "\n\n")) - if err := ioutil.WriteFile(filename, []byte(contents), 0644); err != nil { - fmt.Fprintf(os.Stderr, "error: %v", err) - os.Exit(1) - } - if _, err := exec.Command("gofmt", "-s", "-w", filename).Output(); err != nil { - fmt.Fprintf(os.Stderr, "error: %v", err) - os.Exit(1) - } -} - -func newGenerator(testMaps map[string][]string) *ginkgoTestRenamer { - var allLabels []string - matches := make(map[string]*regexp.Regexp) - stringMatches := make(map[string][]string) - - for label, items := range testMaps { - sort.Strings(items) - allLabels = append(allLabels, label) - var remain []string - for _, item := range items { - re := regexp.MustCompile(item) - if p, ok := re.LiteralPrefix(); ok { - stringMatches[label] = append(stringMatches[label], p) - } else { - remain = append(remain, item) - } - } - if len(remain) > 0 { - matches[label] = regexp.MustCompile(strings.Join(remain, `|`)) - } - } - sort.Strings(allLabels) - - excludedTestsFilter := regexp.MustCompile(strings.Join(ExcludedTests, `|`)) - - return &ginkgoTestRenamer{ - allLabels: allLabels, - stringMatches: stringMatches, - matches: matches, - excludedTestsFilter: excludedTestsFilter, - output: make(map[string]string), - } -} - -func newRenamerFromGenerated(names map[string]string) *ginkgoTestRenamer { - return &ginkgoTestRenamer{ - output: names, - missing: make(map[string]struct{}), - } -} - -type ginkgoTestRenamer struct { - // keys defined in TestMaps in openshift-hack/e2e/annotate/rules.go - allLabels []string - // exact substrings to match to apply a particular label - stringMatches map[string][]string - // regular expressions to match to apply a particular label - matches map[string]*regexp.Regexp - // regular expression excluding permanently a set of tests - // see ExcludedTests in openshift-hack/e2e/annotate/rules.go - excludedTestsFilter *regexp.Regexp - - // output from the generateRename and also input for updateNodeText - output map[string]string - // map of unmatched test names - missing map[string]struct{} - // a list of errors to display - errors []string -} - -func (r *ginkgoTestRenamer) updateNodeText(name string, node types.TestSpec) { - if newLables, ok := r.output[name]; ok { - node.AppendText(newLables) - } else { - r.missing[name] = struct{}{} - } -} - -func (r *ginkgoTestRenamer) generateRename(name string, node types.TestSpec) { - newLabels := "" - newName := name - for { - count := 0 - for _, label := range r.allLabels { - // never apply a sig label twice - if strings.HasPrefix(label, "[sig-") && strings.Contains(newName, "[sig-") { - continue - } - if strings.Contains(newName, label) { - continue - } - - var hasLabel bool - for _, segment := range r.stringMatches[label] { - hasLabel = strings.Contains(newName, segment) - if hasLabel { - break - } - } - if !hasLabel { - if re := r.matches[label]; re != nil { - hasLabel = r.matches[label].MatchString(newName) - } - } - - if hasLabel { - count++ - newLabels += " " + label - newName += " " + label - } - } - if count == 0 { - break - } - } - - // Append suite name to test, if it doesn't already have one - if !r.excludedTestsFilter.MatchString(newName) && !strings.Contains(newName, "[Suite:") { - isSerial := strings.Contains(newName, "[Serial]") - isConformance := strings.Contains(newName, "[Conformance]") - switch { - case isSerial && isConformance: - newLabels += " [Suite:openshift/conformance/serial/minimal]" - case isSerial: - newLabels += " [Suite:openshift/conformance/serial]" - case isConformance: - newLabels += " [Suite:openshift/conformance/parallel/minimal]" - default: - newLabels += " [Suite:openshift/conformance/parallel]" - } - } - codeLocations := node.CodeLocations() - if isGoModulePath(codeLocations[len(codeLocations)-1].FileName, "k8s.io/kubernetes", "test/e2e") { - newLabels += " [Suite:k8s]" - } - - if err := checkBalancedBrackets(newName); err != nil { - r.errors = append(r.errors, err.Error()) - } - r.output[name] = newLabels -} - -// isGoModulePath returns true if the packagePath reported by reflection is within a -// module and given module path. When go mod is in use, module and modulePath are not -// contiguous as they were in older golang versions with vendoring, so naive contains -// tests fail. -// -// historically: ".../vendor/k8s.io/kubernetes/test/e2e" -// go.mod: "k8s.io/kubernetes@0.18.4/test/e2e" -func isGoModulePath(packagePath, module, modulePath string) bool { - return regexp.MustCompile(fmt.Sprintf(`\b%s(@[^/]*|)/%s\b`, regexp.QuoteMeta(module), regexp.QuoteMeta(modulePath))).MatchString(packagePath) -} - -// checkBalancedBrackets ensures that square brackets are balanced in generated test -// names. If they are not, it returns an error with the name of the test and a guess -// where the unmatched bracket(s) are. -func checkBalancedBrackets(testName string) error { - stack := make([]int, 0, len(testName)) - for idx, c := range testName { - if c == '[' { - stack = append(stack, idx) - } else if c == ']' { - // case when we start off with a ] - if len(stack) == 0 { - stack = append(stack, idx) - } else { - stack = stack[:len(stack)-1] - } - } - } - - if len(stack) > 0 { - msg := testName + "\n" - outerLoop: - for i := 0; i < len(testName); i++ { - for _, loc := range stack { - if i == loc { - msg += "^" - continue outerLoop - } - } - msg += " " - } - return fmt.Errorf("unbalanced brackets in test name:\n%s\n", msg) - } - - return nil -} diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/annotate_test.go b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/annotate_test.go deleted file mode 100644 index 614c902e29..0000000000 --- a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/annotate_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package annotate - -import ( - "fmt" - "os" - "testing" -) - -func Test_checkBalancedBrackets(t *testing.T) { - tests := []struct { - testCase string - testName string - wantErr bool - }{ - { - testCase: "balanced brackets succeeds", - testName: "[sig-storage] Test that storage [apigroup:storage.openshift.io] actually works [Driver:azure][Serial][Late]", - wantErr: false, - }, - { - testCase: "unbalanced brackets errors", - testName: "[sig-storage] Test that storage [apigroup:storage.openshift.io actually works [Driver:azure][Serial][Late]", - wantErr: true, - }, - { - testCase: "start with close bracket errors", - testName: "[sig-storage] test with a random bracket ]", - wantErr: true, - }, - { - testCase: "multiple unbalanced brackets errors", - testName: "[sig-storage Test that storage [apigroup:storage.openshift.io actually works [Driver:azure]", - wantErr: true, - }, - { - testCase: "balanced deeply nested brackets succeeds", - testName: "[[[[[[some weird test with deeply nested brackets]]]]]]", - wantErr: false, - }, - { - testCase: "unbalanced deeply nested brackets errors", - testName: "[[[[[[some weird test with deeply nested brackets]]]]]", - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.testCase, func(t *testing.T) { - if err := checkBalancedBrackets(tt.testName); (err != nil) != tt.wantErr { - t.Errorf("checkBalancedBrackets() error = %v, wantErr %v", err, tt.wantErr) - } else if err != nil { - fmt.Fprintf(os.Stderr, "checkBalancedBrackets() success, found expected err = \n%s\n", err.Error()) - } - }) - } -} diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/cmd/main.go b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/cmd/main.go deleted file mode 100644 index c1666ce9e0..0000000000 --- a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/cmd/main.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -import ( - "k8s.io/kubernetes/openshift-hack/e2e/annotate" -) - -func main() { - annotate.Run(annotate.TestMaps, func(name string) bool { return false }) -} diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/generated/zz_generated.annotations.go b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/generated/zz_generated.annotations.go deleted file mode 100644 index 90d2925af0..0000000000 --- a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/generated/zz_generated.annotations.go +++ /dev/null @@ -1,14905 +0,0 @@ -package generated - -import ( - "fmt" - "github.com/onsi/ginkgo/v2" - "github.com/onsi/ginkgo/v2/types" -) - -var Annotations = map[string]string{ - "[sig-api-machinery] API Streaming (aka. WatchList) [FeatureGate:WatchList] [Beta] [Serial] reflector doesn't support receiving resources as Tables": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] API Streaming (aka. WatchList) [FeatureGate:WatchList] [Beta] [Serial] server supports sending resources in Table format": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] API Streaming (aka. WatchList) [FeatureGate:WatchList] [Beta] [Serial] should NOT be requested by client-go's List method when WatchListClient is enabled": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] API Streaming (aka. WatchList) [FeatureGate:WatchList] [Beta] [Serial] should NOT be requested by dynamic client's List method when WatchListClient is enabled": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] API Streaming (aka. WatchList) [FeatureGate:WatchList] [Beta] [Serial] should NOT be requested by metadata client's List method when WatchListClient is enabled": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] API Streaming (aka. WatchList) [FeatureGate:WatchList] [Beta] [Serial] should be requested by informers when WatchListClient is enabled": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] API Streaming (aka. WatchList) [FeatureGate:WatchList] [Beta] [Serial] should be requested by metadatainformer when WatchListClient is enabled": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] API priority and fairness should ensure that requests can be classified by adding FlowSchema and PriorityLevelConfiguration": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] API priority and fairness should ensure that requests can't be drowned out (fairness)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] API priority and fairness should ensure that requests can't be drowned out (priority)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] API priority and fairness should support FlowSchema API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] API priority and fairness should support PriorityLevelConfiguration API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] listing mutating webhooks should work [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] listing validating webhooks should work [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] patching/updating a mutating webhook should work [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] patching/updating a validating webhook should work [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should be able to create and update mutating webhook configurations with match conditions [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should be able to create and update validating webhook configurations with match conditions [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should be able to deny attaching pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should be able to deny custom resource creation, update and deletion [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should be able to deny pod and configmap creation [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should deny crd creation [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should honor timeout [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should include webhook resources in discovery documents [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should mutate configmap [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should mutate custom resource [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should mutate custom resource with different stored version [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should mutate custom resource with pruning [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should mutate everything except 'skip-me' configmaps [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should mutate pod and apply defaults after mutation [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should not be able to mutate or prevent deletion of webhook configuration objects [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should reject mutating webhook configurations with invalid match conditions [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should reject validating webhook configurations with invalid match conditions [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AdmissionWebhook [Privileged:ClusterAdmin] should unconditionally reject operations on fail closed webhook [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AggregatedDiscovery should support aggregated discovery interface [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AggregatedDiscovery should support aggregated discovery interface for CRDs [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AggregatedDiscovery should support raw aggregated discovery endpoint Accept headers [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] AggregatedDiscovery should support raw aggregated discovery request for CRDs [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Aggregator Should be able to support the 1.17 Sample API Server using the current Aggregator [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CBOR [Feature:CBOR] clients remain compatible with the 1.17 sample-apiserver [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] CRDValidationRatcheting [Privileged:ClusterAdmin] [FeatureGate:CRDValidationRatcheting] MUST NOT fail to update a resource due to CRD Validation Rule errors on unchanged correlatable fields": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CRDValidationRatcheting [Privileged:ClusterAdmin] [FeatureGate:CRDValidationRatcheting] MUST NOT fail to update a resource due to JSONSchema errors on unchanged correlatable fields": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CRDValidationRatcheting [Privileged:ClusterAdmin] [FeatureGate:CRDValidationRatcheting] MUST NOT ratchet errors raised by transition rules": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CRDValidationRatcheting [Privileged:ClusterAdmin] [FeatureGate:CRDValidationRatcheting] MUST evaluate a CRD Validation Rule with oldSelf = nil for new values when optionalOldSelf is true": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CRDValidationRatcheting [Privileged:ClusterAdmin] [FeatureGate:CRDValidationRatcheting] MUST fail to update a resource due to CRD Validation Rule errors on changed fields": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CRDValidationRatcheting [Privileged:ClusterAdmin] [FeatureGate:CRDValidationRatcheting] MUST fail to update a resource due to CRD Validation Rule errors on unchanged uncorrelatable fields": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CRDValidationRatcheting [Privileged:ClusterAdmin] [FeatureGate:CRDValidationRatcheting] MUST fail to update a resource due to JSONSchema errors on changed fields": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CRDValidationRatcheting [Privileged:ClusterAdmin] [FeatureGate:CRDValidationRatcheting] MUST fail to update a resource due to JSONSchema errors on unchanged uncorrelatable fields": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CoordinatedLeaderElection [Feature:CoordinatedLeaderElection] [FeatureGate:CoordinatedLeaderElection] [Beta] [Feature:OffByDefault] CLE Preemption": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CoordinatedLeaderElection [Feature:CoordinatedLeaderElection] [FeatureGate:CoordinatedLeaderElection] [Beta] [Feature:OffByDefault] CLE downgrade to disabled": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CoordinatedLeaderElection [Feature:CoordinatedLeaderElection] [FeatureGate:CoordinatedLeaderElection] [Beta] [Feature:OffByDefault] CLE upgrade to enabled": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CoordinatedLeaderElection [Feature:CoordinatedLeaderElection] [FeatureGate:CoordinatedLeaderElection] [Beta] [Feature:OffByDefault] multiple LeaseCandidate": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CoordinatedLeaderElection [Feature:CoordinatedLeaderElection] [FeatureGate:CoordinatedLeaderElection] [Beta] [Feature:OffByDefault] multiple LeaseCandidates third party strategy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CoordinatedLeaderElection [Feature:CoordinatedLeaderElection] [FeatureGate:CoordinatedLeaderElection] [Beta] [Feature:OffByDefault] single LeaseCandidate": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceConversionWebhook [Privileged:ClusterAdmin] should be able to convert a non homogeneous list of CRs [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceConversionWebhook [Privileged:ClusterAdmin] should be able to convert from CR v1 to CR v2 [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceDefinition Watch [Privileged:ClusterAdmin] CustomResourceDefinition Watch watch on custom resource definition objects [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceDefinition resources [Privileged:ClusterAdmin] Simple CustomResourceDefinition creating/deleting custom resource definition objects works [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceDefinition resources [Privileged:ClusterAdmin] Simple CustomResourceDefinition getting/updating/patching custom resource definition status sub-resource works [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceDefinition resources [Privileged:ClusterAdmin] Simple CustomResourceDefinition listing custom resource definition objects works [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceDefinition resources [Privileged:ClusterAdmin] custom resource defaulting for requests and from storage works [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceDefinition resources [Privileged:ClusterAdmin] should include custom resource definition resources in discovery documents [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceFieldSelectors [Privileged:ClusterAdmin] CustomResourceFieldSelectors MUST list and watch custom resources matching the field selector [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] [Flaky] kubectl explain works for CR with the same resource name as built-in object.": " [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] removes definition from spec when one version gets changed to not be served [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] updates the published spec when one version gets renamed [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] works for CRD preserving unknown fields at the schema root [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] works for CRD preserving unknown fields in an embedded object [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] works for CRD with validation schema [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] works for CRD without validation schema [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] works for multiple CRDs of different groups [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] works for multiple CRDs of same group and version but different kinds [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourcePublishOpenAPI [Privileged:ClusterAdmin] works for multiple CRDs of same group but different versions [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceValidationRules [Privileged:ClusterAdmin] MUST NOT fail validation for create of a custom resource that satisfies the x-kubernetes-validations rules": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceValidationRules [Privileged:ClusterAdmin] MUST fail create of a custom resource definition that contains a x-kubernetes-validations rule that refers to a property that do not exist": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceValidationRules [Privileged:ClusterAdmin] MUST fail create of a custom resource definition that contains an x-kubernetes-validations rule that contains a syntax error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceValidationRules [Privileged:ClusterAdmin] MUST fail create of a custom resource definition that contains an x-kubernetes-validations rule that exceeds the estimated cost limit": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceValidationRules [Privileged:ClusterAdmin] MUST fail create of a custom resource that exceeds the runtime cost limit for x-kubernetes-validations rule execution": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceValidationRules [Privileged:ClusterAdmin] MUST fail update of a custom resource that does not satisfy a x-kubernetes-validations transition rule": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] CustomResourceValidationRules [Privileged:ClusterAdmin] MUST fail validation for create of a custom resource that does not satisfy the x-kubernetes-validations rules": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Discovery Custom resource should have storage version hash": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Discovery should accurately determine present and missing resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Discovery should locate the groupVersion and a resource within each APIGroup [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Discovery should validate PreferredVersion for each APIGroup [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Etcd failure [Disruptive] should recover from SIGKILL": " [Serial] [Suite:k8s]", - - "[sig-api-machinery] Etcd failure [Disruptive] should recover from network partition with master": " [Serial] [Suite:k8s]", - - "[sig-api-machinery] FieldValidation should create/apply a CR with unknown fields for CRD with no validation schema [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] FieldValidation should create/apply a valid CR for CRD with validation schema [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] FieldValidation should create/apply an invalid CR with extra properties for CRD with validation schema [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] FieldValidation should detect duplicates in a CR when preserving unknown fields [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] FieldValidation should detect unknown and duplicate fields of a typed object [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] FieldValidation should detect unknown metadata fields in both the root and embedded object of a CR [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] FieldValidation should detect unknown metadata fields of a typed object [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should delete RS created by deployment when not orphaning [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should delete jobs and pods created by cronjob": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should delete pods created by rc when not orphaning [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should keep the rc around until all its pods are deleted if the deleteOptions says so [Serial] [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should not be blocked by dependency circle [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should not delete dependents that have both valid owner and owner that's waiting for dependents to be deleted [Serial] [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should orphan RS created by deployment when deleteOptions.PropagationPolicy is Orphan [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should orphan pods created by rc if delete options say so [Serial] [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should orphan pods created by rc if deleteOptions.OrphanDependents is nil": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should support cascading deletion of custom resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Garbage collector should support orphan deletion of custom resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Generated clientset should create pods, set the deletionTimestamp and deletionGracePeriodSeconds of the pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Generated clientset should create v1 cronJobs, delete cronJobs, watch cronJobs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] MutatingAdmissionPolicy [Privileged:ClusterAdmin] [Feature:MutatingAdmissionPolicy] [FeatureGate:MutatingAdmissionPolicy] [Beta] [Feature:OffByDefault] should mutate a Deployment": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] MutatingAdmissionPolicy [Privileged:ClusterAdmin] [Feature:MutatingAdmissionPolicy] [FeatureGate:MutatingAdmissionPolicy] [Beta] [Feature:OffByDefault] should support MutatingAdmissionPolicy API operations": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] MutatingAdmissionPolicy [Privileged:ClusterAdmin] [Feature:MutatingAdmissionPolicy] [FeatureGate:MutatingAdmissionPolicy] [Beta] [Feature:OffByDefault] should support MutatingAdmissionPolicyBinding API operations": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Namespaces [Serial] should always delete fast (ALL of 100 namespaces in 150 seconds) [Feature:ComprehensiveNamespaceDraining]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] Namespaces [Serial] should apply a finalizer to a Namespace [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-api-machinery] Namespaces [Serial] should apply an update to a Namespace [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-api-machinery] Namespaces [Serial] should apply changes to a namespace status [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-api-machinery] Namespaces [Serial] should delete fast enough (90 percent of 100 namespaces in 150 seconds)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] Namespaces [Serial] should ensure that all pods are removed when a namespace is deleted [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-api-machinery] Namespaces [Serial] should ensure that all services are removed when a namespace is deleted [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-api-machinery] Namespaces [Serial] should patch a Namespace [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-api-machinery] OpenAPIV3 should contain OpenAPI V3 for Aggregated APIServer [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-api-machinery] OpenAPIV3 should publish OpenAPI V3 for CustomResourceDefinition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] OpenAPIV3 should round trip OpenAPI V3 for all built-in group versions": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] OrderedNamespaceDeletion namespace deletion should delete pod first [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota [Feature:PodPriority] should verify ResourceQuota's multiple priority class scope (quota set to pod count: 2) against 2 pods with same priority classes.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota [Feature:PodPriority] should verify ResourceQuota's priority class scope (cpu, memory quota set) against a pod with same priority class.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota [Feature:PodPriority] should verify ResourceQuota's priority class scope (quota set to pod count: 1) against 2 pods with different priority class.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota [Feature:PodPriority] should verify ResourceQuota's priority class scope (quota set to pod count: 1) against 2 pods with same priority class.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota [Feature:PodPriority] should verify ResourceQuota's priority class scope (quota set to pod count: 1) against a pod with different priority class (ScopeSelectorOpExists).": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota [Feature:PodPriority] should verify ResourceQuota's priority class scope (quota set to pod count: 1) against a pod with different priority class (ScopeSelectorOpNotIn).": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota [Feature:PodPriority] should verify ResourceQuota's priority class scope (quota set to pod count: 1) against a pod with same priority class.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota [FeatureGate:VolumeAttributesClass] should verify ResourceQuota's volume attributes class scope (quota set to pvc count: 1) against 2 pvcs with same volume attributes class.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota [FeatureGate:VolumeAttributesClass] should verify ResourceQuota's volume attributes class scope (quota set to pvc count: 1) against a pvc with different volume attributes class.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should apply changes to a resourcequota status [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should be able to update and delete ResourceQuota. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a ResourceClaim [FeatureGate:DynamicResourceAllocation] [DRA]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a configMap. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a custom resource.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a persistent volume claim with a storage class": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a persistent volume claim": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a pod. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a replica set. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a replication controller. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a secret. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and capture the life of a service. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should create a ResourceQuota and ensure its status is promptly calculated. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should manage the lifecycle of a ResourceQuota [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should verify ResourceQuota with best effort scope using scope-selectors.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should verify ResourceQuota with best effort scope. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should verify ResourceQuota with cross namespace pod affinity scope using scope-selectors.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should verify ResourceQuota with terminating scopes through scope selectors.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ResourceQuota should verify ResourceQuota with terminating scopes. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Server request timeout default timeout should be used if the specified timeout in the request URL is 0s": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Server request timeout should return HTTP status code 400 if the user specifies an invalid timeout in the request URL": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Server request timeout the request should be served with a default timeout if the specified timeout in the request URL exceeds maximum allowed": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ServerSideApply should create an applied object if it does not already exist": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ServerSideApply should give up ownership of a field if forced applied by a controller": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ServerSideApply should ignore conflict errors if force apply is used": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ServerSideApply should not remove a field if an owner unsets the field but other managers still have ownership of the field": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ServerSideApply should remove a field if it is owned but removed in the apply request": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ServerSideApply should work for CRDs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ServerSideApply should work for subresources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Servers with support for API chunking should return chunks of results for list calls [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Servers with support for API chunking should support continue listing from the last key if the original version has been compacted away, though the list is inconsistent [Slow] [Conformance]": " [Suite:k8s]", - - "[sig-api-machinery] Servers with support for Table transformation should return a 406 for a backend which does not implement metadata [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Servers with support for Table transformation should return chunks of table results for list calls": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Servers with support for Table transformation should return generic metadata details across all namespaces for nodes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] Servers with support for Table transformation should return pod details": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] StorageVersion resources [Feature:StorageVersionAPI] storage version with non-existing id should be GC'ed": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ValidatingAdmissionPolicy [Privileged:ClusterAdmin] should allow expressions to refer variables. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ValidatingAdmissionPolicy [Privileged:ClusterAdmin] should support ValidatingAdmissionPolicy API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ValidatingAdmissionPolicy [Privileged:ClusterAdmin] should support ValidatingAdmissionPolicyBinding API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] ValidatingAdmissionPolicy [Privileged:ClusterAdmin] should type check a CRD": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ValidatingAdmissionPolicy [Privileged:ClusterAdmin] should type check validation expressions": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] ValidatingAdmissionPolicy [Privileged:ClusterAdmin] should validate against a Deployment [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Watchers should be able to restart watching from the last resource version observed by the previous watch [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Watchers should be able to start watching from a specific resource version [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Watchers should observe add, update, and delete watch notifications on configmaps [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Watchers should observe an object deletion if it stops meeting the requirements of the selector [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] Watchers should receive events on concurrent watches in same order [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-api-machinery] client-go should negotiate watch and report errors with accept \"application/json,application/vnd.kubernetes.protobuf\"": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] client-go should negotiate watch and report errors with accept \"application/json\"": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] client-go should negotiate watch and report errors with accept \"application/vnd.kubernetes.protobuf,application/json\"": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] client-go should negotiate watch and report errors with accept \"application/vnd.kubernetes.protobuf\"": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] health handlers should contain necessary checks": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-api-machinery] kube-apiserver identity [Feature:APIServerIdentity] kube-apiserver identity should persist after restart [Disruptive]": " [Serial] [Suite:k8s]", - - "[sig-api-machinery] server version should find the server version [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ControllerRevision [Serial] should manage the lifecycle of a ControllerRevision [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-apps] CronJob should be able to schedule after more than 100 missed schedule": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] CronJob should delete failed finished jobs with limit of one job": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] CronJob should delete successful finished jobs with limit of one successful job": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] CronJob should not emit unexpected warnings": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] CronJob should not schedule jobs when suspended [Slow] [Conformance]": " [Suite:k8s]", - - "[sig-apps] CronJob should not schedule new jobs when ForbidConcurrent [Slow] [Conformance]": " [Suite:k8s]", - - "[sig-apps] CronJob should remove from active list jobs that have been deleted": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] CronJob should replace jobs when ReplaceConcurrent [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] CronJob should schedule multiple jobs concurrently [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] CronJob should set the cronjob-scheduled-timestamp annotation on a job": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] CronJob should support CronJob API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] CronJob should support timezone": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should list and delete a collection of DaemonSets [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should not update pod when spec was updated and update strategy is OnDelete": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should retry creating failed daemon pods [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should rollback without unnecessary restarts [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should run and stop complex daemon [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should run and stop complex daemon with node affinity": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should run and stop simple daemon [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should surge pods onto nodes when spec was updated and update strategy is RollingUpdate": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should update pod when spec was updated and update strategy is RollingUpdate [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-apps] Daemon set [Serial] should verify changes to a daemon set status [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-apps] DaemonRestart [Disruptive] Controller Manager should not create/delete replicas across restart": " [Serial] [Suite:k8s]", - - "[sig-apps] DaemonRestart [Disruptive] Kube-proxy should recover after being killed accidentally": " [Serial] [Suite:k8s]", - - "[sig-apps] DaemonRestart [Disruptive] Kubelet should not restart containers across restart": " [Serial] [Suite:k8s]", - - "[sig-apps] DaemonRestart [Disruptive] Scheduler should continue assigning pods to nodes across restart": " [Serial] [Suite:k8s]", - - "[sig-apps] Deployment Deployment should have a working scale subresource [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Deployment RecreateDeployment should delete old pods and create new ones [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Deployment RollingUpdateDeployment should delete old pods and create new ones [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Deployment deployment reaping should cascade to its replica sets and pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Deployment deployment should delete old replica sets [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Deployment deployment should support proportional scaling [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Deployment deployment should support rollover [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Deployment iterative rollouts should eventually progress": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Deployment should not disrupt a cloud load-balancer's connectivity during rollout": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Deployment should run the lifecycle of a Deployment [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Deployment should validate Deployment Status endpoints [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Deployment test Deployment ReplicaSet orphaning and adoption regarding controllerRef": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController Listing PodDisruptionBudgets for all namespaces should list and delete a collection of PodDisruptionBudgets [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] DisruptionController evictions: enough pods, absolute => should allow an eviction": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController evictions: enough pods, replicaSet, percentage => should allow an eviction": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController evictions: maxUnavailable allow single eviction, percentage => should allow an eviction": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController evictions: maxUnavailable deny evictions, integer => should not allow an eviction [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-apps] DisruptionController evictions: no PDB => should allow an eviction": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController evictions: too few pods, absolute => should not allow an eviction": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController evictions: too few pods, replicaSet, percentage => should not allow an eviction [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-apps] DisruptionController should block an eviction until the PDB is updated to allow it [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] DisruptionController should create a PodDisruptionBudget [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] DisruptionController should evict ready pods with AlwaysAllow UnhealthyPodEvictionPolicy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController should evict ready pods with Default UnhealthyPodEvictionPolicy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController should evict ready pods with IfHealthyBudget UnhealthyPodEvictionPolicy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController should evict unready pods with AlwaysAllow UnhealthyPodEvictionPolicy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController should not evict unready pods with Default UnhealthyPodEvictionPolicy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController should not evict unready pods with IfHealthyBudget UnhealthyPodEvictionPolicy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController should observe PodDisruptionBudget status updated [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] DisruptionController should observe that the PodDisruptionBudget status is not updated for unmanaged pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] DisruptionController should update/patch PodDisruptionBudget status [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job containers restarted by container restart policy should not trigger PodFailurePolicy [Feature:ContainerRestartRules] [FeatureGate:ContainerRestartRules] [Alpha] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should adopt matching orphans and release non-matching pods [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should allow to delegate reconciliation to external controller": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should allow to use a pod failure policy to ignore failure matching on DisruptionTarget condition [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should allow to use a pod failure policy to ignore failure matching on exit code": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should allow to use the pod failure policy on exit code to fail the job early [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should apply changes to a job status [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should create pods for an Indexed job with completion indexes and specified hostname [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should create pods with completion indexes for an Indexed Job": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should delete a job [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should delete pods when suspended": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should execute all indexes despite some failing when using backoffLimitPerIndex [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should fail to exceed backoffLimit": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should fail when exceeds active deadline": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should manage the lifecycle of a job [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should mark indexes as failed when the FailIndex action is matched in podFailurePolicy [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should not create pods when created in suspend state": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should record the failure-count in the Pod annotation when using backoffLimitPerIndex": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should recreate pods only after they have failed if pod replacement policy is set to Failed": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should remove pods when job is deleted": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should run a job to completion when tasks sometimes fail and are locally restarted [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should run a job to completion when tasks sometimes fail and are not locally restarted": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should run a job to completion when tasks succeed": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job should run a job to completion with CPU requests [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-apps] Job should terminate job execution when the number of failed indexes exceeds maxFailedIndexes [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job should update the status ready field": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] Job with successPolicy should succeeded when all indexes succeeded [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job with successPolicy succeededCount rule should succeeded even when some indexes remain pending [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] Job with successPolicy succeededIndexes rule should succeeded even when some indexes remain pending [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicaSet Replace and Patch tests [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicaSet Replicaset should have a working scale subresource [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicaSet should adopt matching pods on creation and release no longer matching pods [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicaSet should list and delete a collection of ReplicaSets [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicaSet should serve a basic image on each replica with a private image": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] ReplicaSet should serve a basic image on each replica with a public image [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicaSet should surface a failure condition on a common issue like exceeded quota": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] ReplicaSet should validate Replicaset Status endpoints [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicationController should adopt matching pods on creation [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicationController should get and update a ReplicationController scale [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicationController should release no longer matching pods [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicationController should serve a basic image on each replica with a private image": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] ReplicationController should serve a basic image on each replica with a public image [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicationController should surface a failure condition on a common issue like exceeded quota [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] ReplicationController should test the lifecycle of a ReplicationController [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] StatefulSet Automatically recreate PVC for pending pod when PVC is missing PVC should be recreated when pod is pending due to missing PVC [Disruptive] [Serial]": " [Suite:k8s]", - - "[sig-apps] StatefulSet AvailableReplicas should get updated accordingly when MinReadySeconds is enabled": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] Burst scaling should run to completion even with unhealthy pods [Slow] [Conformance]": " [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] Scaling should happen in predictable order and halt if any stateful pod is unhealthy [Slow] [Conformance]": " [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] Should recreate evicted statefulset [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should adopt matching orphans and release non-matching pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should have a working scale subresource [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should implement legacy replacement when the update strategy is OnDelete": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should list, patch and delete a collection of StatefulSets [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should not deadlock when a pod's predecessor fails": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should perform canary updates and phased rolling updates of template modifications [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should perform canary updates and phased rolling updates of template modifications for partiton1 and delete pod-0 with failing container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should perform canary updates and phased rolling updates of template modifications for partiton1 and delete pod-0 without failing container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should perform rolling updates and roll backs of template modifications [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should perform rolling updates and roll backs of template modifications with PVCs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should provide basic identity": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Basic StatefulSet functionality [StatefulSetBasic] should validate Statefulset Status endpoints [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-apps] StatefulSet Deploy clustered applications [Feature:StatefulSet] [Slow] should creating a working CockroachDB cluster": " [Suite:k8s]", - - "[sig-apps] StatefulSet Deploy clustered applications [Feature:StatefulSet] [Slow] should creating a working mysql cluster": " [Suite:k8s]", - - "[sig-apps] StatefulSet Deploy clustered applications [Feature:StatefulSet] [Slow] should creating a working zookeeper cluster": " [Suite:k8s]", - - "[sig-apps] StatefulSet MinReadySeconds should be honored when enabled": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Non-retain StatefulSetPersistentVolumeClaimPolicy should delete PVCs after adopting pod (WhenDeleted)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Non-retain StatefulSetPersistentVolumeClaimPolicy should delete PVCs after adopting pod (WhenScaled)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Non-retain StatefulSetPersistentVolumeClaimPolicy should delete PVCs with a OnScaledown policy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Non-retain StatefulSetPersistentVolumeClaimPolicy should delete PVCs with a WhenDeleted policy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Non-retain StatefulSetPersistentVolumeClaimPolicy should not delete PVC with OnScaledown policy if another controller owns the PVC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Non-retain StatefulSetPersistentVolumeClaimPolicy should not delete PVCs when there is another controller": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Scaling StatefulSetStartOrdinal Decreasing .start.ordinal": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Scaling StatefulSetStartOrdinal Increasing .start.ordinal": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Scaling StatefulSetStartOrdinal Removing .start.ordinal": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] StatefulSet Scaling StatefulSetStartOrdinal Setting .start.ordinal": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] TTLAfterFinished job should be deleted once it finishes after TTL seconds": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-apps] stateful Upgrade [Feature:StatefulUpgrade] stateful upgrade should maintain a functioning cluster": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-architecture] Conformance Tests should have at least two untainted nodes [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] Certificates API [Privileged:ClusterAdmin] should support CSR API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] Certificates API [Privileged:ClusterAdmin] should support building a client with a CSR": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] NodeAuthenticator The kubelet can delegate ServiceAccount tokens to the API server": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] NodeAuthenticator The kubelet's main port 10250 should reject requests with no credentials": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] SelfSubjectReview should support SelfSubjectReview API operations": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] SelfSubjectReview testing SSR in different API groups authentication/v1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] SelfSubjectReview testing SSR in different API groups authentication/v1beta1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] ServiceAccount admission controller migration [Feature:BoundServiceAccountTokenVolume] master upgrade should maintain a functioning cluster": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] ServiceAccounts ServiceAccountIssuerDiscovery should support OIDC discovery of service account issuer [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] ServiceAccounts no secret-based service account token should be auto-generated": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] ServiceAccounts should allow opting out of API token automount [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] ServiceAccounts should create a serviceAccountToken and ensure a successful TokenReview [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] ServiceAccounts should guarantee kube-root-ca.crt exist in any namespace [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] ServiceAccounts should mount an API token into pods [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] ServiceAccounts should mount projected service account token [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] ServiceAccounts should run through the lifecycle of a ServiceAccount [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] ServiceAccounts should set ownership and permission when RunAsUser or FsGroup is present [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] ServiceAccounts should support InClusterConfig with token rotation [Slow]": " [Suite:k8s]", - - "[sig-auth] ServiceAccounts should update a ServiceAccount [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] SubjectReview should support SubjectReview API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-auth] ValidatingAdmissionPolicy can restrict access by-node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [Feature:NodeAuthorizer] A node shouldn't be able to create another node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [Feature:NodeAuthorizer] A node shouldn't be able to delete another node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [Feature:NodeAuthorizer] Getting a non-existent configmap should exit with the Forbidden error, not a NotFound error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [Feature:NodeAuthorizer] Getting a non-existent secret should exit with the Forbidden error, not a NotFound error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [Feature:NodeAuthorizer] Getting a secret for a workload the node has access to should succeed": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [Feature:NodeAuthorizer] Getting an existing configmap should exit with the Forbidden error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [Feature:NodeAuthorizer] Getting an existing secret should exit with the Forbidden error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [FeatureGate:ClusterTrustBundle] [Beta] [Feature:OffByDefault] [FeatureGate:ClusterTrustBundleProjection] [Beta] [Feature:OffByDefault] should be able to mount a big number (>100) of CTBs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [FeatureGate:ClusterTrustBundle] [Beta] [Feature:OffByDefault] [FeatureGate:ClusterTrustBundleProjection] [Beta] [Feature:OffByDefault] should be able to mount a single ClusterTrustBundle by name": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [FeatureGate:ClusterTrustBundle] [Beta] [Feature:OffByDefault] [FeatureGate:ClusterTrustBundleProjection] [Beta] [Feature:OffByDefault] should be able to specify multiple CTB volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [FeatureGate:ClusterTrustBundle] [Beta] [Feature:OffByDefault] [FeatureGate:ClusterTrustBundleProjection] [Beta] [Feature:OffByDefault] should be capable to mount multiple trust bundles by signer+labels can combine all signer CTBs with an empty label selector": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [FeatureGate:ClusterTrustBundle] [Beta] [Feature:OffByDefault] [FeatureGate:ClusterTrustBundleProjection] [Beta] [Feature:OffByDefault] should be capable to mount multiple trust bundles by signer+labels can combine multiple CTBs with signer name and label selector": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [FeatureGate:ClusterTrustBundle] [Beta] [Feature:OffByDefault] [FeatureGate:ClusterTrustBundleProjection] [Beta] [Feature:OffByDefault] should be capable to mount multiple trust bundles by signer+labels should start if only signer name and explicit label selector matches nothing + optional=true": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [FeatureGate:ClusterTrustBundle] [Beta] [Feature:OffByDefault] [FeatureGate:ClusterTrustBundleProjection] [Beta] [Feature:OffByDefault] should be capable to mount multiple trust bundles by signer+labels should start if only signer name and nil label selector + optional=true": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [FeatureGate:ClusterTrustBundle] [Beta] [Feature:OffByDefault] [FeatureGate:ClusterTrustBundleProjection] [Beta] [Feature:OffByDefault] should prevent a pod from starting if: sets optional=false and no trust bundle matches query": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-auth] [FeatureGate:ClusterTrustBundle] [Beta] [Feature:OffByDefault] [FeatureGate:ClusterTrustBundleProjection] [Beta] [Feature:OffByDefault] should prevent a pod from starting if: sets optional=false and the configured CTB does not exist": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should be able to scale down by draining multiple pods one by one as dictated by pdb [Feature:ClusterSizeAutoscalingScaleDown]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should be able to scale down by draining system pods with pdb [Feature:ClusterSizeAutoscalingScaleDown]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should be able to scale down when rescheduling a pod is required and pdb allows for it [Feature:ClusterSizeAutoscalingScaleDown]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should correctly scale down after a node is not needed [Feature:ClusterSizeAutoscalingScaleDown]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should increase cluster size if pending pods are small [Feature:ClusterSizeAutoscalingScaleUp]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should increase cluster size if pod requesting EmptyDir volume is pending [Feature:ClusterSizeAutoscalingScaleUp]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should increase cluster size if pods are pending due to host port conflict [Feature:ClusterSizeAutoscalingScaleUp]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should increase cluster size if pods are pending due to pod anti-affinity [Feature:ClusterSizeAutoscalingScaleUp]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should scale down when expendable pod is running [Feature:ClusterSizeAutoscalingScaleDown]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should scale up when non expendable pod is created [Feature:ClusterSizeAutoscalingScaleUp]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] should scale up when unprocessed pod is created and is going to be unschedulable [Feature:ClusterScaleUpBypassScheduler]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] shouldn't be able to scale down when rescheduling a pod is required, but pdb doesn't allow drain [Feature:ClusterSizeAutoscalingScaleDown]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] shouldn't increase cluster size if pending pod is too large [Feature:ClusterSizeAutoscalingScaleUp]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] shouldn't scale down when non expendable pod is running [Feature:ClusterSizeAutoscalingScaleDown]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] shouldn't scale up when expendable pod is created [Feature:ClusterSizeAutoscalingScaleUp]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] shouldn't scale up when expendable pod is preempted [Feature:ClusterSizeAutoscalingScaleUp]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] shouldn't scale up when unprocessed pod is created and is going to be schedulable [Feature:ClusterScaleUpBypassScheduler]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] shouldn't scale up when unprocessed pod is created and scheduler is not specified to be bypassed [Feature:ClusterScaleUpBypassScheduler]": " [Suite:k8s]", - - "[sig-autoscaling] Cluster size autoscaling [Slow] shouldn't trigger additional scale-ups during processing scale-up [Feature:ClusterSizeAutoscalingScaleUp]": " [Suite:k8s]", - - "[sig-autoscaling] [Feature:ClusterSizeAutoscalingScaleUp] [Slow] Autoscaling Autoscaling a service from 1 pod and 3 nodes to 8 pods and >=4 nodes takes less than 15 minutes": " [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPAConfigurableTolerance] [FeatureGate:HPAConfigurableTolerance] [Alpha] [Feature:OffByDefault] Horizontal pod autoscaling (configurable tolerance) with large configurable tolerance should not scale": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with autoscaling disabled shouldn't scale down": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with autoscaling disabled shouldn't scale up": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with both scale up and down controls configured should keep recommendation within the range over two stabilization windows": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with both scale up and down controls configured should keep recommendation within the range with stabilization window and pod limit rate": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with long upscale stabilization window should scale up only after the stabilization period": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with scale limited by number of Pods rate should scale down no more than given number of Pods per minute": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with scale limited by number of Pods rate should scale up no more than given number of Pods per minute": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with scale limited by percentage should scale down no more than given percentage of current Pods per minute": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with scale limited by percentage should scale up no more than given percentage of current Pods per minute": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (non-default behavior) with short downscale stabilization window should scale down soon after the stabilization period": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) CustomResourceDefinition Should scale with a CRD targetRef": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) Deployment (Container Resource) Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Utilization for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) Deployment (Container Resource) Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Value for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) Deployment (Pod Resource) Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Utilization for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) Deployment (Pod Resource) Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Value for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) Deployment (Pod Resource) Should scale from 5 pods to 3 pods and then from 3 pods to 1 pod using Average Utilization for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) Deployment (Pod-level Resources ContainerResource Metric) [FeatureGate:PodLevelResources] [Beta] Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Utilization for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) Deployment (Pod-level Resources Resource Metric) [FeatureGate:PodLevelResources] [Beta] Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Utilization for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicaSet Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicaSet Should scale from 5 pods to 3 pods and then from 3 pods to 1 pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicaSet with idle sidecar (ContainerResource use case) Should not scale up on a busy sidecar with an idle application": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicaSet with idle sidecar (ContainerResource use case) Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods on a busy application with an idle sidecar container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicationController Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods and verify decision stability": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicationController Should scale from 5 pods to 3 pods and then from 3 pods to 1 pod and verify decision stability": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicationController light Should scale from 1 pod to 2 pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicationController light Should scale from 2 pods to 1 pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: Memory) Deployment (Container Resource) Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Utilization for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: Memory) Deployment (Container Resource) Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Value for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: Memory) Deployment (Pod Resource) Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Utilization for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: Memory) Deployment (Pod Resource) Should scale from 1 pod to 3 pods and then from 3 pods to 5 pods using Average Value for aggregation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-autoscaling] [Feature:KubeDNSAutoscaler] DNS horizontal autoscaling [Serial] [Slow] kube-dns-autoscaler should scale kube-dns pods when cluster size changed": " [Suite:k8s]", - - "[sig-autoscaling] [Feature:KubeDNSAutoscaler] DNS horizontal autoscaling kube-dns-autoscaler should scale kube-dns pods in both nonfaulty and faulty scenarios": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding Shutdown client connection while the remote stream is writing data to the port-forward connection port-forward should keep working after detect broken connection": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding With a server listening on 0.0.0.0 should support forwarding over websockets": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding With a server listening on 0.0.0.0 that expects NO client request should support a client that connects, sends DATA, and disconnects": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding With a server listening on 0.0.0.0 that expects a client request should support a client that connects, sends DATA, and disconnects": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding With a server listening on 0.0.0.0 that expects a client request should support a client that connects, sends NO DATA, and disconnects": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding With a server listening on localhost should support forwarding over websockets": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding With a server listening on localhost that expects NO client request should support a client that connects, sends DATA, and disconnects": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding With a server listening on localhost that expects a client request should support a client that connects, sends DATA, and disconnects": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding With a server listening on localhost that expects a client request should support a client that connects, sends NO DATA, and disconnects": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl Port forwarding with a pod being removed should stop port-forwarding": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Guestbook application should create and stop a working application [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl api-versions should check if v1 is in available api versions [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl apply apply set/view last-applied": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl apply should apply a new configuration to an existing RC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl apply should reuse port when apply to an existing SVC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl cluster-info dump should check if cluster-info dump succeeds": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl cluster-info should check if Kubernetes control plane services is included in cluster-info [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl copy should copy a file from a running Pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl create quota should create a quota with scopes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl create quota should create a quota without scopes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl create quota should reject quota with invalid scopes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl describe should check if kubectl describe prints relevant information for cronjob": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl describe should check if kubectl describe prints relevant information for rc and pods [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl diff should check if kubectl diff finds a difference for Deployments [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl events should show event when pod is created": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl expose should create services for rc [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl get componentstatuses should get componentstatuses": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl label should update the label on a resource [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl patch should add annotations for pods in rc [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl prune with applyset should apply and prune objects": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl replace should update a single-container pod's image [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl run pod should create a pod from an image when restart is Never [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl server-side dry-run should check if kubectl can dry-run update Pods [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl taint [Serial] should remove all the taints with the same key off a node": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl taint [Serial] should update the taint on a node": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl validation should create/apply a CR with unknown fields for CRD with no validation schema": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl validation should create/apply a valid CR for CRD with validation schema": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl validation should create/apply an invalid/valid CR with arbitrary-extra properties for CRD with partially-specified validation schema": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl validation should detect unknown metadata fields in both the root and embedded object of a CR": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl validation should detect unknown metadata fields of a typed object": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Kubectl version should check is all data is printed [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Proxy server should support --unix-socket=/path [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Proxy server should support proxy with --port 0 [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod Kubectl run [Slow] running a failing command with --leave-stdin-open": " [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod Kubectl run [Slow] running a failing command without --restart=Never": " [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod Kubectl run [Slow] running a failing command without --restart=Never, but with --rm": " [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod Kubectl run running a failing command": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod Kubectl run running a successful command": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod [Slow] should support exec idle connections": " [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should contain last line of the log": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should return command exit codes execing into a container with a failing command": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should return command exit codes execing into a container with a successful command": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should return command exit codes should handle in-cluster config": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should return command exit codes should support port-forward": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should support exec through an HTTP proxy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should support exec through kubectl proxy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should support exec using resource/name": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should support exec": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should support inline execution and attach with websockets or fallback to spdy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Simple pod should support inline execution and attach": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client Update Demo should create and stop a replication controller [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client Update Demo should scale a replication controller [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl client kubectl subresource flag GET on status subresource of built-in type (node) returns identical info as GET on the built-in type": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client kubectl subresource flag should not be used in a bulk GET": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl client kubectl wait should ignore not found error with --for=delete": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl delete interactive based on user confirmation input": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl exec should be able to execute 1000 times in a container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl logs all pod logs the Deployment has 2 replicas and each pod has 2 containers should get logs from all pods based on default container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl logs all pod logs the Deployment has 2 replicas and each pod has 2 containers should get logs from each pod and each container in Deployment": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl logs default container logs the second container is the default-container by annotation should log default container if not specified": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] Kubectl logs logs should be able to retrieve and filter logs [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-cli] Kubectl rollout undo undo should rollback and update deployment env": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] kubectl debug custom profile should be applied on static profiles on ephemeral container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] kubectl debug custom profile should be applied on static profiles while copying from pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] kubectl kuberc given preferences should be applied": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cli] kubectl kuberc given preferences should be ignored when flags are explicitly passed": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Downgrade [Feature:Downgrade] cluster downgrade should maintain a functioning cluster [Feature:ClusterDowngrade]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cloud-provider-gcp] GKE node pools [Feature:GKENodePool] should create a cluster with multiple node pools [Feature:GKENodePool]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cloud-provider-gcp] HA-master [Feature:HAMaster] survive addition/removal replicas different zones [Serial] [Disruptive]": " [Suite:k8s]", - - "[sig-cloud-provider-gcp] HA-master [Feature:HAMaster] survive addition/removal replicas multizone workers [Serial] [Disruptive]": " [Suite:k8s]", - - "[sig-cloud-provider-gcp] HA-master [Feature:HAMaster] survive addition/removal replicas same zone [Serial] [Disruptive]": " [Suite:k8s]", - - "[sig-cloud-provider-gcp] Nodes [Disruptive] Resize [Slow] should be able to add nodes": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Nodes [Disruptive] Resize [Slow] should be able to delete nodes": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Ports Security Check [Feature:KubeletSecurity] should not be able to proxy to cadvisor port 4194 using proxy subresource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Ports Security Check [Feature:KubeletSecurity] should not be able to proxy to the readonly kubelet port 10255 using proxy subresource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Ports Security Check [Feature:KubeletSecurity] should not have port 10255 open on its all public IP addresses": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Ports Security Check [Feature:KubeletSecurity] should not have port 4194 open on its all public IP addresses": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Reboot [Disruptive] [Feature:Reboot] each node by dropping all inbound packets for a while and ensure they function afterwards": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Reboot [Disruptive] [Feature:Reboot] each node by dropping all outbound packets for a while and ensure they function afterwards": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Reboot [Disruptive] [Feature:Reboot] each node by ordering clean reboot and ensure they function upon restart": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Reboot [Disruptive] [Feature:Reboot] each node by ordering unclean reboot and ensure they function upon restart": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Reboot [Disruptive] [Feature:Reboot] each node by switching off the network interface and ensure they function upon switch on": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Reboot [Disruptive] [Feature:Reboot] each node by triggering kernel panic and ensure they function upon restart": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Restart [Disruptive] [KubeUp] should restart all nodes and ensure all nodes and pods recover": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Upgrade [Feature:Upgrade] cluster upgrade should maintain a functioning cluster [Feature:ClusterUpgrade]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cloud-provider-gcp] Upgrade [Feature:Upgrade] master upgrade should maintain a functioning cluster [Feature:MasterUpgrade]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cloud-provider-gcp] [Disruptive] NodeLease NodeLease deletion node lease should be deleted when corresponding node is deleted": " [Serial] [Suite:k8s]", - - "[sig-cloud-provider] [Feature:CloudProvider] [Disruptive] Nodes should be deleted on API server if it doesn't exist in the cloud provider": " [Serial] [Suite:k8s]", - - "[sig-cluster-lifecycle] [Feature:BootstrapTokens] should delete the signed bootstrap tokens from clusterInfo ConfigMap when bootstrap token is deleted": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cluster-lifecycle] [Feature:BootstrapTokens] should delete the token secret when the secret expired": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cluster-lifecycle] [Feature:BootstrapTokens] should not delete the token secret when the secret is not expired": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-cluster-lifecycle] [Feature:BootstrapTokens] should resign the bootstrap tokens when the clusterInfo ConfigMap updated [Serial] [Disruptive]": " [Suite:k8s]", - - "[sig-cluster-lifecycle] [Feature:BootstrapTokens] should sign the new added bootstrap tokens": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-instrumentation] Events API should delete a collection of events [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-instrumentation] Events API should ensure that an event can be fetched, patched, deleted, and listed [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-instrumentation] Events should delete a collection of events [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-instrumentation] Events should manage the lifecycle of an event [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-instrumentation] Logging soak [Performance] [Slow] [Disruptive] should survive logging 1KB every 1s seconds, for a duration of 2m0s": " [Serial] [Suite:k8s]", - - "[sig-instrumentation] Metrics should grab all metrics from kubelet /metrics/resource endpoint": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-instrumentation] MetricsGrabber should grab all metrics from API server.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-instrumentation] MetricsGrabber should grab all metrics from a ControllerManager.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-instrumentation] MetricsGrabber should grab all metrics from a Kubelet.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-instrumentation] MetricsGrabber should grab all metrics from a Scheduler.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-instrumentation] MetricsGrabber should grab all metrics slis from API server.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Connectivity Pod Lifecycle should be able to connect from a Pod to a terminating Pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Connectivity Pod Lifecycle should be able to connect to other Pod from a terminating Pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Connectivity Pod Lifecycle should be able to have zero downtime on a Blue Green deployment using Services and Readiness Gates": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Conntrack proxy implementation should not be vulnerable to the invalid conntrack state bug [Privileged]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Conntrack should be able to cleanup conntrack entries when UDP service target port changes for a NodePort service": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Conntrack should be able to preserve UDP traffic when initial unready endpoints get ready": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Conntrack should be able to preserve UDP traffic when server pod cycles for a ClusterIP service and client is hostNetwork": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Conntrack should be able to preserve UDP traffic when server pod cycles for a ClusterIP service with InternalTrafficPolicy set to Local": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Conntrack should be able to preserve UDP traffic when server pod cycles for a ClusterIP service": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Conntrack should be able to preserve UDP traffic when server pod cycles for a NodePort service": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] DNS HostNetwork should resolve DNS of partial qualified names for services on hostNetwork pods with dnsPolicy: ClusterFirstWithHostNet [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] DNS HostNetwork spec.Hostname field is not silently ignored and is used for hostname for a Pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] DNS HostNetwork spec.Hostname field is silently ignored and the node hostname is used when hostNetwork is set to true for a Pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] DNS configMap nameserver Change stubDomain should be able to change stubDomain configuration [Slow] [Serial]": " [Suite:k8s]", - - "[sig-network] DNS configMap nameserver Forward PTR lookup should forward PTR records lookup to upstream nameserver [Slow] [Serial]": " [Suite:k8s]", - - "[sig-network] DNS configMap nameserver Forward external name lookup should forward externalname lookup to upstream nameserver [Slow] [Serial]": " [Suite:k8s]", - - "[sig-network] DNS should provide /etc/hosts entries for the cluster [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] DNS should provide DNS for ExternalName services [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] DNS should provide DNS for pods for Hostname [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] DNS should provide DNS for pods for Subdomain [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] DNS should provide DNS for services [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] DNS should provide DNS for the cluster [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] DNS should provide DNS for the cluster [Provider:GCE]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] DNS should resolve DNS of partial qualified names for services [LinuxOnly] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] DNS should resolve DNS of partial qualified names for the cluster [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] DNS should support configurable pod DNS nameservers [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] DNS should support configurable pod resolv.conf": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] DNS should work with a search path containing an underscore and a search path with a single dot": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] DNS should work with a service name that starts with a digit [FeatureGate:RelaxedServiceNameValidation] [Alpha] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] DNS should work with the pod containing more than 6 DNS search paths and longer than 256 search list characters": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] EndpointSlice should create Endpoints and EndpointSlices for Pods matching a Service [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] EndpointSlice should create and delete Endpoints and EndpointSlices for a Service with a selector specified [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] EndpointSlice should have Endpoints and EndpointSlices pointing to API Server [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] EndpointSlice should support a Service with multiple endpoint IPs specified in multiple EndpointSlices [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] EndpointSlice should support a Service with multiple ports specified in multiple EndpointSlices [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] EndpointSlice should support creating EndpointSlice API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] EndpointSliceMirroring should mirror a custom Endpoint with multiple subsets and same IP address": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] EndpointSliceMirroring should mirror a custom Endpoints resource through create update and delete [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] HostPort validates that there is no conflict between pods with same hostPort but different hostIP and protocol [LinuxOnly] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Ingress API should support creating Ingress API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] IngressClass API should support creating IngressClass API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] IngressClass [Feature:Ingress] should allow IngressClass to have Namespace-scoped parameters [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-network] IngressClass [Feature:Ingress] should choose the one with the later CreationTimestamp, if equal the one with the lower name when two ingressClasses are marked as default [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-network] IngressClass [Feature:Ingress] should not set default value if no default IngressClass [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-network] IngressClass [Feature:Ingress] should set default value on new IngressClass [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-network] KubeProxy should set TCP CLOSE_WAIT timeout [Privileged]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] KubeProxyNFAcct [Feature:KubeProxyNFAcct] should update metric for tracking accepted packets destined for localhost nodeports": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] LoadBalancers ExternalTrafficPolicy: Local [Feature:LoadBalancer] [Slow] should only target nodes with endpoints": " [Suite:k8s]", - - "[sig-network] LoadBalancers ExternalTrafficPolicy: Local [Feature:LoadBalancer] [Slow] should target all nodes with endpoints": " [Suite:k8s]", - - "[sig-network] LoadBalancers ExternalTrafficPolicy: Local [Feature:LoadBalancer] [Slow] should work for type=LoadBalancer": " [Suite:k8s]", - - "[sig-network] LoadBalancers ExternalTrafficPolicy: Local [Feature:LoadBalancer] [Slow] should work from pods": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to change the type and ports of a TCP service [Slow]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to change the type and ports of a UDP service [Slow]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to create LoadBalancer Service without NodePort and change it [Slow]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to preserve UDP traffic when server pod cycles for a LoadBalancer service on different nodes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to preserve UDP traffic when server pod cycles for a LoadBalancer service on the same nodes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to switch session affinity for LoadBalancer service with Cluster traffic policy [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to switch session affinity for LoadBalancer service with Local traffic policy [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should handle load balancer cleanup finalizer for service [Slow]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should have session affinity work for LoadBalancer service with Cluster traffic policy [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should have session affinity work for LoadBalancer service with Local traffic policy [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should not have connectivity disruption during rolling update with externalTrafficPolicy=Cluster [Slow]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should not have connectivity disruption during rolling update with externalTrafficPolicy=Local [Slow]": " [Suite:k8s]", - - "[sig-network] LoadBalancers [Feature:LoadBalancer] should only allow access from service loadbalancer source ranges [Slow]": " [Suite:k8s]", - - "[sig-network] Netpol API should support creating NetworkPolicy API operations": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol API should support creating NetworkPolicy API with endport field": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should allow egress access on one named port [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should allow egress access to server in CIDR block [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should allow ingress access from namespace on one named port [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should allow ingress access from updated namespace [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should allow ingress access from updated pod [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should allow ingress access on one named port [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should deny egress from all pods in a namespace [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should deny egress from pods based on PodSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should deny ingress access to updated pod [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should deny ingress from pods on other namespaces [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce egress policy allowing traffic to a server in a different namespace based on PodSelector and NamespaceSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce except clause while egress access to server in CIDR block [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce ingress policy allowing any port traffic to a server on a specific protocol [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce multiple egress policies with egress allow-all policy taking precedence [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce multiple ingress policies with ingress allow-all policy taking precedence [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce multiple, stacked policies with overlapping podSelectors [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policies to check ingress and egress policies can be controlled independently based on PodSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy based on Multiple PodSelectors and NamespaceSelectors [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy based on NamespaceSelector with MatchExpressions [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy based on NamespaceSelector with MatchExpressions using default ns label [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy based on PodSelector and NamespaceSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy based on PodSelector or NamespaceSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy based on PodSelector with MatchExpressions [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy based on Ports [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy based on any PodSelectors [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy to allow ingress traffic for a target [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy to allow ingress traffic from pods in all namespaces [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy to allow traffic based on NamespaceSelector with MatchLabels using default ns label [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy to allow traffic from pods within server namespace based on PodSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy to allow traffic only from a different namespace, based on NamespaceSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce policy to allow traffic only from a pod in a different namespace based on PodSelector and NamespaceSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should enforce updated policy [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should ensure an IP overlapping both IPBlock.CIDR and IPBlock.Except is allowed [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should not allow access by TCP when a policy specifies only UDP [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should not mistakenly treat 'protocol: SCTP' as 'protocol: TCP', even if the plugin doesn't support SCTP [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should properly isolate pods that are selected by a policy allowing SCTP, even if the plugin doesn't support SCTP [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should stop enforcing policies after they are deleted [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should support a 'default-deny-all' policy [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should support a 'default-deny-ingress' policy [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should support allow-all policy [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should support denying of egress traffic on the client side (even if the server explicitly allows this traffic) [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol NetworkPolicy between server and client should work with Ingress, Egress specified together [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol [Feature:SCTPConnectivity] [LinuxOnly] NetworkPolicy between server and client using SCTP should enforce policy based on Ports [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol [Feature:SCTPConnectivity] [LinuxOnly] NetworkPolicy between server and client using SCTP should enforce policy to allow traffic only from a pod in a different namespace based on PodSelector and NamespaceSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol [Feature:SCTPConnectivity] [LinuxOnly] NetworkPolicy between server and client using SCTP should support a 'default-deny-ingress' policy [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol [LinuxOnly] NetworkPolicy between server and client using UDP should enforce policy based on Ports [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol [LinuxOnly] NetworkPolicy between server and client using UDP should enforce policy to allow traffic only from a pod in a different namespace based on PodSelector and NamespaceSelector [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Netpol [LinuxOnly] NetworkPolicy between server and client using UDP should support a 'default-deny-ingress' policy [Feature:NetworkPolicy]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Pods should function for intra-pod communication: http [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Pods should function for intra-pod communication: sctp [LinuxOnly] [Feature:SCTPConnectivity]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Pods should function for intra-pod communication: udp [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Pods should function for node-pod communication: http [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Pods should function for node-pod communication: sctp [LinuxOnly] [Feature:SCTPConnectivity]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Pods should function for node-pod communication: udp [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should be able to handle large requests: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should be able to handle large requests: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for client IP based session affinity: http [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for client IP based session affinity: udp [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for endpoint-Service: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for endpoint-Service: sctp [Feature:SCTPConnectivity]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for endpoint-Service: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for multiple endpoint-Services with same selector": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for node-Service: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for node-Service: sctp [Feature:SCTPConnectivity]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for node-Service: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for pod-Service: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for pod-Service: sctp [Feature:SCTPConnectivity]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for pod-Service: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should function for service endpoints using hostNetwork": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should support basic nodePort: udp functionality": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should update endpoints: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should update endpoints: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should update nodePort: http [Slow]": " [Suite:k8s]", - - "[sig-network] Networking Granular Checks: Services should update nodePort: udp [Slow]": " [Suite:k8s]", - - "[sig-network] Networking IPerf2 [Feature:Networking-Performance] should run iperf2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking should allow creating a Pod with an SCTP HostPort [LinuxOnly] [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-network] Networking should check kube-proxy urls": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking should provide Internet connection for containers [Feature:Networking-IPv4]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking should provide Internet connection for containers [Feature:Networking-IPv6] [Experimental][LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking should provide unchanging, static URL paths for kubernetes api services": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking should provider Internet connection for containers using DNS [Feature:Networking-DNS]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Networking should recreate its iptables rules if they are deleted [Disruptive]": " [Serial] [Suite:k8s]", - - "[sig-network] NoSNAT Should be able to send traffic between Pods without SNAT": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Proxy version v1 A set of valid responses are returned for both pod and service Proxy [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Proxy version v1 A set of valid responses are returned for both pod and service ProxyWithPath [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Proxy version v1 should proxy logs on node using proxy subresource ": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Proxy version v1 should proxy logs on node with explicit kubelet port using proxy subresource ": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Proxy version v1 should proxy through a service and a pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Service CIDRs should create Services and serve on different Service CIDRs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Service endpoints latency should not be very high [Conformance]": " [Serial] [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-network] ServiceCIDR and IPAddress API should support IPAddress API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] ServiceCIDR and IPAddress API should support ServiceCIDR API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should allow creating a basic SCTP service with pod and endpoints [LinuxOnly] [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-network] Services should allow pods to hairpin back to themselves through services": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should be able to change the type from ClusterIP to ExternalName [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should be able to change the type from ExternalName to ClusterIP [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should be able to change the type from ExternalName to NodePort [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should be able to change the type from NodePort to ExternalName [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should be able to connect to terminating and unready endpoints if PublishNotReadyAddresses is true": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should be able to create a functioning NodePort service [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should be able to switch session affinity for NodePort service [LinuxOnly] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should be able to switch session affinity for service with type clusterIP [LinuxOnly] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should be able to up and down services": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should be able to update service type to NodePort listening on same port number but different protocols": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should be possible to connect to a service via ExternalIP when the external IP is not assigned to a node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should be rejected for evicted pods (no endpoints exist)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should be rejected when no endpoints exist": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should be updated after adding or deleting ports ": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should check NodePort out-of-range": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should complete a service status lifecycle [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should connect to the named ports exposed by restartable init containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should connect to the ports exposed by restartable init containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should create endpoints for unready pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should delete a collection of services [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should fail health check node port if there are only terminating endpoints": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should fallback to local terminating endpoints when there are no ready endpoints with externalTrafficPolicy=Local": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should fallback to local terminating endpoints when there are no ready endpoints with internalTrafficPolicy=Local": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should fallback to terminating endpoints when there are no ready endpoints with externallTrafficPolicy=Cluster": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should fallback to terminating endpoints when there are no ready endpoints with internalTrafficPolicy=Cluster": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should find a service from listing all namespaces [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should have session affinity timeout work for NodePort service [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should have session affinity timeout work for service with type clusterIP [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should have session affinity work for NodePort service [LinuxOnly] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should have session affinity work for service with type clusterIP [LinuxOnly] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should implement NodePort and HealthCheckNodePort correctly when ExternalTrafficPolicy changes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should implement service.kubernetes.io/headless": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should implement service.kubernetes.io/service-proxy-name": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should not be able to connect to terminating and unready endpoints if PublishNotReadyAddresses is false": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should preserve source pod IP for traffic thru service cluster IP [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should prevent NodePort collisions": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should provide secure master service [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should release NodePorts on delete": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should respect internalTrafficPolicy=Local Pod (hostNetwork: true) to Pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should respect internalTrafficPolicy=Local Pod and Node, to Pod (hostNetwork: true)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should respect internalTrafficPolicy=Local Pod to Pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should serve a basic endpoint from pods [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should serve endpoints on same port and different protocol for internal traffic on Type LoadBalancer ": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should serve endpoints on same port and different protocols [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should serve multiport endpoints from pods [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should support externalTrafficPolicy=Local for type=NodePort": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should support named targetPorts that resolve to different ports on different endpoints": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Services should test the lifecycle of an Endpoint [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-network] Services should work after restarting apiserver [Disruptive]": " [Serial] [Suite:k8s]", - - "[sig-network] Services should work after restarting kube-proxy [Disruptive]": " [Serial] [Suite:k8s]", - - "[sig-network] Services should work after the service has been recreated": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Topology Hints should distribute endpoints evenly": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Traffic Distribution should route traffic correctly between pods on multiple nodes when using PreferClose": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Traffic Distribution should route traffic correctly between pods on multiple nodes when using PreferSameZone [FeatureGate:PreferSameTrafficDistribution] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Traffic Distribution should route traffic to an endpoint in the same zone when using PreferClose": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Traffic Distribution should route traffic to an endpoint in the same zone when using PreferSameZone [FeatureGate:PreferSameTrafficDistribution] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Traffic Distribution should route traffic to an endpoint on the same node or fall back to same zone when using PreferSameNode [FeatureGate:PreferSameTrafficDistribution] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] Traffic Distribution should route traffic to an endpoint on the same node when using PreferSameNode and fall back when the endpoint becomes unavailable [FeatureGate:PreferSameTrafficDistribution] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should be able to handle large requests: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should be able to handle large requests: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for client IP based session affinity: http [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for client IP based session affinity: udp [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for endpoint-Service: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for endpoint-Service: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for node-Service: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for node-Service: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for pod-Service: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for pod-Service: sctp [Feature:SCTPConnectivity]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for pod-Service: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should function for service endpoints using hostNetwork": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should update endpoints: http": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] Granular Checks: Services Secondary IP Family [LinuxOnly] should update endpoints: udp": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] should be able to reach pod on ipv4 and ipv6 ip": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] should create a single stack service with cluster ip from primary service range": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] should create pod, add ipv6 and ipv4 ip to host ips": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] should create pod, add ipv6 and ipv4 ip to pod ips": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] should create service with ipv4 cluster ip": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] should create service with ipv4,v6 cluster ip": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] should create service with ipv6 cluster ip": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] should create service with ipv6,v4 cluster ip": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:IPv6DualStack] should have ipv4 and ipv6 internal node ip": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-network] [Feature:PerformanceDNS] [Serial] Should answer DNS query for maximum number of services per cluster": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-network] kube-proxy migration [Serial] [Disruptive] [Feature:KubeProxyDaemonSetMigration] Downgrade kube-proxy from a DaemonSet to static pods should maintain a functioning cluster [Feature:KubeProxyDaemonSetDowngrade]": " [Suite:k8s]", - - "[sig-network] kube-proxy migration [Serial] [Disruptive] [Feature:KubeProxyDaemonSetMigration] Upgrade kube-proxy from static pods to a DaemonSet should maintain a functioning cluster [Feature:KubeProxyDaemonSetUpgrade]": " [Suite:k8s]", - - "[sig-node] AppArmor load AppArmor profiles can disable an AppArmor profile, using unconfined": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] AppArmor load AppArmor profiles should enforce an AppArmor profile specified in annotations": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] AppArmor load AppArmor profiles should enforce an AppArmor profile specified on the container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] AppArmor load AppArmor profiles should enforce an AppArmor profile specified on the pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] ConfigMap should be consumable as environment variable names with various prefixes [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] ConfigMap should be consumable via environment variable [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] ConfigMap should be consumable via the environment [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] ConfigMap should fail to create ConfigMap with empty key [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] ConfigMap should run through a ConfigMap lifecycle [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] ConfigMap should update ConfigMap successfully": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Container Lifecycle Hook when create a pod with lifecycle hook should execute poststart exec hook properly [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Container Lifecycle Hook when create a pod with lifecycle hook should execute poststart http hook properly [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Container Lifecycle Hook when create a pod with lifecycle hook should execute poststart https hook properly [MinimumKubeletVersion:1.23] [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Container Lifecycle Hook when create a pod with lifecycle hook should execute prestop exec hook properly [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Container Lifecycle Hook when create a pod with lifecycle hook should execute prestop http hook properly [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Container Lifecycle Hook when create a pod with lifecycle hook should execute prestop https hook properly [MinimumKubeletVersion:1.23] [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test on terminated container should report termination message as empty when pod succeeds and TerminationMessagePolicy FallbackToLogsOnError is set [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test on terminated container should report termination message from file when pod succeeds and TerminationMessagePolicy FallbackToLogsOnError is set [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test on terminated container should report termination message from log output if TerminationMessagePolicy FallbackToLogsOnError is set [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test on terminated container should report termination message if TerminationMessagePath is set [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test on terminated container should report termination message if TerminationMessagePath is set as non-root user and at a non-default path [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test when running a container with a new image should be able to pull from private registry with secret [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test when running a container with a new image should be able to pull image [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test when running a container with a new image should not be able to pull from private registry without secret [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test when running a container with a new image should not be able to pull image from invalid registry [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Container Runtime blackbox test when starting a container that exits should run with the expected status [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Containers should be able to override the image's default arguments (container cmd) [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Containers should be able to override the image's default command (container entrypoint) [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Containers should be able to override the image's default command and arguments [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Containers should use the image defaults if command and args are blank [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Downward API [Feature:PodLevelResources] [FeatureGate:PodLevelResources] [Beta] Downward API tests for pod level resources should provide default limits.cpu/memory from pod level resources or node allocatable": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Downward API [Feature:PodLevelResources] [FeatureGate:PodLevelResources] [Beta] Downward API tests for pod level resources should provide default limits.cpu/memory from pod level resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Downward API [Serial] [Disruptive] [Feature:DownwardAPIHugePages] Downward API tests for hugepages should provide container's limits.hugepages- and requests.hugepages- as env vars": " [Suite:k8s]", - - "[sig-node] Downward API [Serial] [Disruptive] [Feature:DownwardAPIHugePages] Downward API tests for hugepages should provide default limits.hugepages- from node allocatable": " [Suite:k8s]", - - "[sig-node] Downward API should provide container's limits.cpu/memory and requests.cpu/memory as env vars [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Downward API should provide default limits.cpu/memory from node allocatable [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Downward API should provide host IP and pod IP as an env var if pod uses host network [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Downward API should provide host IP as an env var [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Downward API should provide hostIPs as an env var [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Downward API should provide pod UID as env vars [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Downward API should provide pod name, namespace and IP address as env vars [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Ephemeral Containers [NodeConformance] should update the ephemeral containers in an existing pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Ephemeral Containers [NodeConformance] will start an ephemeral container in an existing pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Events should be sent by kubelets and the scheduler about pods scheduling and running ": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should allow ephemeralContainer to consume fileKeyRef": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should allow initContainer to consume fileKeyRef": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should be consumable by multiple containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should be consumable in postStart lifecycle hooks": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should be consumable in preStop lifecycle hooks": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should be consumable via FileKeyRef": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should fail when file or key does not exist": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should fail when initContainer consumes fileKeyRef from non-emptyDir volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should fail when volume is not emptyDir": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should fail when volumeName does not exist": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should handle optional keys": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] FileKeyRef [FeatureGate:EnvFiles] [Alpha] [Feature:OffByDefault] should handle optional missing file or key": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] ImageCredentialProvider [Feature:KubeletCredentialProviders] should be able to create pod with image credentials fetched from external credential provider ": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] InitContainer [NodeConformance] should invoke init containers on a RestartAlways pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] InitContainer [NodeConformance] should invoke init containers on a RestartNever pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] InitContainer [NodeConformance] should not start app containers and fail the pod if init containers fail on a RestartNever pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] InitContainer [NodeConformance] should not start app containers if init containers fail on a RestartAlways pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Kubelet [Serial] [Slow] experimental resource usage tracking [Feature:ExperimentalResourceUsageTracking] resource tracking for 100 pods per node": " [Suite:k8s]", - - "[sig-node] Kubelet [Serial] [Slow] regular resource usage tracking [Feature:RegularResourceUsageTracking] resource tracking for 0 pods per node": " [Suite:k8s]", - - "[sig-node] Kubelet [Serial] [Slow] regular resource usage tracking [Feature:RegularResourceUsageTracking] resource tracking for 100 pods per node": " [Suite:k8s]", - - "[sig-node] Kubelet when scheduling a busybox command in a pod should print the output to logs [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Kubelet when scheduling a busybox command that always fails in a pod should be possible to delete [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Kubelet when scheduling a busybox command that always fails in a pod should have an terminated reason [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Kubelet when scheduling a read only busybox container should not write to root filesystem [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Kubelet when scheduling an agnhost Pod with hostAliases should write entries to /etc/hosts [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Kubelet with pods in a privileged namespace when scheduling an agnhost Pod with hostAliases and hostNetwork should write entries to /etc/hosts when hostNetwork is enabled [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] KubeletManagedEtcHosts should test kubelet managed /etc/hosts file [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Lease lease API should be available [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Lifecycle Sleep Hook when create a pod with lifecycle hook using sleep action ignore terminated container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Lifecycle Sleep Hook when create a pod with lifecycle hook using sleep action reduce GracePeriodSeconds during runtime": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Lifecycle Sleep Hook when create a pod with lifecycle hook using sleep action valid prestop hook using sleep action": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Lifecycle sleep action zero value when create a pod with lifecycle hook using sleep action with a duration of zero seconds prestop hook using sleep action with zero duration": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Mount propagation should propagate mounts within defined scopes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] NoExecuteTaintManager Multiple Pods [Serial] evicts pods with minTolerationSeconds [Disruptive] [Conformance]": " [Suite:k8s]", - - "[sig-node] NoExecuteTaintManager Multiple Pods [Serial] only evicts pods without tolerations from tainted nodes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] NoExecuteTaintManager Single Pod [Serial] doesn't evict pod with tolerations from tainted nodes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] NoExecuteTaintManager Single Pod [Serial] eventually evict pod with finite tolerations from tainted nodes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] NoExecuteTaintManager Single Pod [Serial] evicts pods from tainted nodes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] NoExecuteTaintManager Single Pod [Serial] pods evicted from tainted nodes have pod disruption condition": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] NoExecuteTaintManager Single Pod [Serial] removing taint cancels eviction [Disruptive] [Conformance]": " [Suite:k8s]", - - "[sig-node] Node Lifecycle should run through the lifecycle of a node [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] NodeLease NodeLease should have OwnerReferences set": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] NodeLease NodeLease the kubelet should create and update a lease in the kube-node-lease namespace": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] NodeLease NodeLease the kubelet should report node status infrequently": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] NodeProblemDetector [Feature:NodeProblemDetector] should run without error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Override hostname of Pod [FeatureGate:HostnameOverride] [Alpha] [Feature:OffByDefault] a pod has hostnameOverride field with value that is a valid DNS subdomain.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Override hostname of Pod [FeatureGate:HostnameOverride] [Alpha] [Feature:OffByDefault] a pod with hostNetwork and hostnameOverride fields will fail to be created": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Override hostname of Pod [FeatureGate:HostnameOverride] [Alpha] [Feature:OffByDefault] a pod with hostname and hostnameOverride fields will have hostnameOverride as hostname": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Override hostname of Pod [FeatureGate:HostnameOverride] [Alpha] [Feature:OffByDefault] a pod with non-RFC1123 subdomain string for hostnameOverride field will fail to be created": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Override hostname of Pod [FeatureGate:HostnameOverride] [Alpha] [Feature:OffByDefault] a pod with only hostnameOverride field will have hostnameOverride as hostname": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Override hostname of Pod [FeatureGate:HostnameOverride] [Alpha] [Feature:OffByDefault] a pod with setHostnameAsFQDN and hostnameOverride fields will fail to be created": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Override hostname of Pod [FeatureGate:HostnameOverride] [Alpha] [Feature:OffByDefault] a pod with subdomain and hostnameOverride fields will have hostnameOverride as hostname": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod Extended (container restart policy) [FeatureGate:ContainerRestartRules] [Alpha] [Feature:OffByDefault] Container Restart Rules should not restart container on rule mismatch, container restart policy Never": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod Extended (container restart policy) [FeatureGate:ContainerRestartRules] [Alpha] [Feature:OffByDefault] Container Restart Rules should restart container on container-level restart policy Always": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod Extended (container restart policy) [FeatureGate:ContainerRestartRules] [Alpha] [Feature:OffByDefault] Container Restart Rules should restart container on container-level restart policy Never": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod Extended (container restart policy) [FeatureGate:ContainerRestartRules] [Alpha] [Feature:OffByDefault] Container Restart Rules should restart container on pod-level restart policy Always when no container-level restart policy": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod Extended (container restart policy) [FeatureGate:ContainerRestartRules] [Alpha] [Feature:OffByDefault] Container Restart Rules should restart container on rule match": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] BestEffort QoS pod - empty resize": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] BestEffort pod - try requesting memory, expect error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod with memory requests + limits - decrease memory limit": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, mixed containers - add limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, mixed containers - add requests": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, mixed containers - scale up cpu and memory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container - decrease CPU (NotRequired) & memory (RestartContainer)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container - decrease memory request (RestartContainer memory resize policy)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container - increase memory request (NoRestart memory resize policy)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with CPU requests + limits, cpu requests - remove memory requests": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - decrease CPU limits only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - decrease CPU requests and increase CPU limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - decrease CPU requests and increase memory limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - decrease CPU requests and limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - decrease CPU requests only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - decrease memory requests and increase CPU limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - decrease memory requests and increase memory limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - decrease memory requests only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - increase CPU limits only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - increase CPU requests and decrease CPU limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - increase CPU requests and limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - increase CPU requests only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - increase memory limits only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - increase memory requests and decrease CPU limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - increase memory requests and limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - increase memory requests only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - remove CPU limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests + limits - remove memory limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests - decrease memory request": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu & memory requests - increase cpu request": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with cpu requests and limits - resize with equivalents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container with memory requests + limits, cpu requests - remove CPU requests": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container, one restartable init container - decrease init container CPU only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container, one restartable init container - decrease init container memory requests only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container, one restartable init container - increase init container CPU & memory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container, one restartable init container - increase init container CPU only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, one container, one restartable init container - increase init container memory only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, three containers - decrease c1 resources, increase c2 resources, no change for c3 (net increase for pod)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, three containers - increase c1 resources, no change for c2, decrease c3 resources (no net change for pod)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, three containers - no change for c1, increase c2 resources, decrease c3 (net decrease for pod)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Burstable QoS pod, two containers with cpu & memory requests + limits - reorder containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Guaranteed QoS pod, one container - decrease CPU only": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Guaranteed QoS pod, one container - increase CPU & memory with an extended resource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Guaranteed QoS pod, one container - increase CPU & memory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Guaranteed QoS pod, one container - increase CPU (NotRequired) & memory (RestartContainer)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Guaranteed QoS pod, one container, one restartable init container - decrease init container CPU": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Guaranteed QoS pod, one restartable init container - decrease CPU & increase memory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Guaranteed QoS pod, one restartable init container - increase CPU & memory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] Guaranteed QoS pod, three containers (c1, c2, c3) - increase: CPU (c1,c3), memory (c2, c3) ; decrease: CPU (c2)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] decrease memory limit below usage": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] pod-resize-limit-ranger-test": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod InPlace Resize Container [FeatureGate:InPlacePodVerticalScaling] [Beta] pod-resize-resource-quota-test": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pod Level Resources [Serial] [Feature:PodLevelResources] [FeatureGate:PodLevelResources] [Beta] Burstable QoS pod with container resources": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] Pod Level Resources [Serial] [Feature:PodLevelResources] [FeatureGate:PodLevelResources] [Beta] Burstable QoS pod, 1 container with resources": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] Pod Level Resources [Serial] [Feature:PodLevelResources] [FeatureGate:PodLevelResources] [Beta] Burstable QoS pod, no container resources": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] Pod Level Resources [Serial] [Feature:PodLevelResources] [FeatureGate:PodLevelResources] [Beta] Guaranteed QoS pod with container resources": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] Pod Level Resources [Serial] [Feature:PodLevelResources] [FeatureGate:PodLevelResources] [Beta] Guaranteed QoS pod, 1 container with resources": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] Pod Level Resources [Serial] [Feature:PodLevelResources] [FeatureGate:PodLevelResources] [Beta] Guaranteed QoS pod, no container resources": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] Pod garbage collector [Feature:PodGarbageCollector] [Slow] should handle the creation of 1000 pods": " [Suite:k8s]", - - "[sig-node] PodOSRejection [NodeConformance] Kubelet [LinuxOnly] should reject pod when the node OS doesn't match pod's OS": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] PodRejectionStatus Kubelet should reject pod when the node didn't have enough resource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] PodTemplates should delete a collection of pod templates [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] PodTemplates should replace a pod template [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] PodTemplates should run the lifecycle of PodTemplates [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods Extended (pod generation) [Feature:PodObservedGenerationTracking] [FeatureGate:PodObservedGenerationTracking] [Beta] Pod Generation custom-set generation on new pods and graceful delete": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended (pod generation) [Feature:PodObservedGenerationTracking] [FeatureGate:PodObservedGenerationTracking] [Beta] Pod Generation issue 500 podspec updates and verify generation and observedGeneration eventually converge": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended (pod generation) [Feature:PodObservedGenerationTracking] [FeatureGate:PodObservedGenerationTracking] [Beta] Pod Generation pod generation should start at 1 and increment per update": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended (pod generation) [Feature:PodObservedGenerationTracking] [FeatureGate:PodObservedGenerationTracking] [Beta] Pod Generation pod observedGeneration field set in pod conditions": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended (pod generation) [Feature:PodObservedGenerationTracking] [FeatureGate:PodObservedGenerationTracking] [Beta] Pod Generation pod rejected by kubelet should have updated generation and observedGeneration": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended Delete Grace Period should be submitted and removed": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended Pod Container Status should never report container start when an init container fails": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended Pod Container Status should never report success for a pending container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended Pod Container lifecycle evicted pods should be terminal": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended Pod Container lifecycle should not create extra sandbox if all containers are done": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended Pod TerminationGracePeriodSeconds is negative pod with negative grace period": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods Extended Pods Set QOS Class should be set on Pods with matching resource requests and limits for memory and cpu [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should allow activeDeadlineSeconds to be updated [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should be submitted and removed [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should be updated [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should cap back-off at MaxContainerBackOff [Slow] [NodeConformance]": " [Suite:k8s]", - - "[sig-node] Pods should contain environment variables for services [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should delete a collection of pods [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should get a host IP [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should have their auto-restart back-off timer reset on image update [Slow] [NodeConformance]": " [Suite:k8s]", - - "[sig-node] Pods should patch a pod status [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should run through the lifecycle of Pods and PodStatus [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should support pod readiness gates [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Pods should support remote command execution over websockets [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Pods should support retrieving logs from the container over websockets [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] PreStop graceful pod terminated should wait until preStop hook completes the process": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] PreStop should call prestop when killing a pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] PrivilegedPod [NodeConformance] should enable privileged commands [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should *not* be restarted by liveness probe because startup probe delays it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should *not* be restarted with a /healthz http liveness probe [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Probing container should *not* be restarted with a GRPC liveness probe [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Probing container should *not* be restarted with a exec \"cat /tmp/health\" liveness probe [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Probing container should *not* be restarted with a non-local redirect http liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should *not* be restarted with a tcp:8080 liveness probe [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Probing container should be ready immediately after startupProbe succeeds": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should be restarted by liveness probe after startup probe enables it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should be restarted startup probe fails": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should be restarted with a /healthz http liveness probe [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Probing container should be restarted with a GRPC liveness probe [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Probing container should be restarted with a exec \"cat /tmp/health\" liveness probe [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Probing container should be restarted with a failing exec liveness probe that took longer than the timeout": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should be restarted with a local redirect http liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should be restarted with an exec liveness probe with timeout [MinimumKubeletVersion:1.20] [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should have monotonically increasing restart count [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Probing container should mark readiness on pods to false and disable liveness probes while pod is in progress of terminating": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should mark readiness on pods to false while pod is in progress of terminating when a pod has a readiness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should not be ready with an exec readiness probe timeout [MinimumKubeletVersion:1.20] [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should override timeoutGracePeriodSeconds when LivenessProbe field is set [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container should override timeoutGracePeriodSeconds when StartupProbe field is set [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Probing container with readiness probe should not be ready before initial delay and never restart [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Probing container with readiness probe that fails should never be ready and never restart [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] RuntimeClass should reject a Pod requesting a RuntimeClass with an unconfigured handler [Feature:RuntimeHandler]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] RuntimeClass should reject a Pod requesting a RuntimeClass with conflicting node selector": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] RuntimeClass should reject a Pod requesting a deleted RuntimeClass [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] RuntimeClass should reject a Pod requesting a non-existent RuntimeClass [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] RuntimeClass should run a Pod requesting a RuntimeClass with a configured handler [Feature:RuntimeHandler]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] RuntimeClass should run a Pod requesting a RuntimeClass with scheduling with taints [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] RuntimeClass should run a Pod requesting a RuntimeClass with scheduling without taints ": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] RuntimeClass should schedule a Pod requesting a RuntimeClass and initialize its Overhead [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] RuntimeClass should schedule a Pod requesting a RuntimeClass without PodOverhead [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] RuntimeClass should support RuntimeClasses API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] SSH should SSH to all nodes and run commands": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Secrets should be consumable as environment variable names variable names with various prefixes [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Secrets should be consumable from pods in env vars [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Secrets should be consumable via the environment [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Secrets should fail to create secret due to empty secret key [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Secrets should patch a secret [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Security Context SupplementalGroupsPolicy [LinuxOnly] [Feature:SupplementalGroupsPolicy] [FeatureGate:SupplementalGroupsPolicy] [Beta] when SupplementalGroupsPolicy nil in SecurityContext when if the container's primary UID belongs to some groups in the image when scheduled node does not support SupplementalGroupsPolicy it should add SupplementalGroups to them [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context SupplementalGroupsPolicy [LinuxOnly] [Feature:SupplementalGroupsPolicy] [FeatureGate:SupplementalGroupsPolicy] [Beta] when SupplementalGroupsPolicy nil in SecurityContext when if the container's primary UID belongs to some groups in the image when scheduled node supports SupplementalGroupsPolicy it should add SupplementalGroups to them [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context SupplementalGroupsPolicy [LinuxOnly] [Feature:SupplementalGroupsPolicy] [FeatureGate:SupplementalGroupsPolicy] [Beta] when SupplementalGroupsPolicy was set to Merge in PodSpec when the container's primary UID belongs to some groups in the image when scheduled node does not support SupplementalGroupsPolicy it should add SupplementalGroups to them [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context SupplementalGroupsPolicy [LinuxOnly] [Feature:SupplementalGroupsPolicy] [FeatureGate:SupplementalGroupsPolicy] [Beta] when SupplementalGroupsPolicy was set to Merge in PodSpec when the container's primary UID belongs to some groups in the image when scheduled node supports SupplementalGroupsPolicy it should add SupplementalGroups to them [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context SupplementalGroupsPolicy [LinuxOnly] [Feature:SupplementalGroupsPolicy] [FeatureGate:SupplementalGroupsPolicy] [Beta] when SupplementalGroupsPolicy was set to Strict in PodSpec when the container's primary UID belongs to some groups in the image when scheduled node does not support SupplementalGroupsPolicy it should reject the pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context SupplementalGroupsPolicy [LinuxOnly] [Feature:SupplementalGroupsPolicy] [FeatureGate:SupplementalGroupsPolicy] [Beta] when SupplementalGroupsPolicy was set to Strict in PodSpec when the container's primary UID belongs to some groups in the image when scheduled node supports SupplementalGroupsPolicy it should NOT add SupplementalGroups to them [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a container with runAsNonRoot should not run with an explicit root user ID [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a container with runAsNonRoot should not run without a specified user ID": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a container with runAsNonRoot should run with an explicit non-root user ID [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a container with runAsNonRoot should run with an image specified user ID": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a container with runAsUser should run the container with uid 0 [LinuxOnly] [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a container with runAsUser should run the container with uid 65534 [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with HostUsers metrics should report count of started and failed user namespaced pods [LinuxOnly] [Feature:UserNamespacesSupport] [FeatureGate:UserNamespacesSupport] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with HostUsers must create the user namespace if set to false [LinuxOnly] [Feature:UserNamespacesSupport] [FeatureGate:UserNamespacesSupport] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with HostUsers must create the user namespace in the configured hostUID/hostGID range [LinuxOnly] [Feature:UserNamespacesSupport] [FeatureGate:UserNamespacesSupport] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with HostUsers must not create the user namespace if set to true [LinuxOnly] [Feature:UserNamespacesSupport] [FeatureGate:UserNamespacesSupport] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with HostUsers should mount all volumes with proper permissions with hostUsers=false [LinuxOnly] [Feature:UserNamespacesSupport] [FeatureGate:UserNamespacesSupport] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with HostUsers should set FSGroup to user inside the container with hostUsers=false [LinuxOnly] [Feature:UserNamespacesSupport] [FeatureGate:UserNamespacesSupport] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with privileged should run the container as privileged when true [LinuxOnly] [Feature:HostAccess]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with privileged should run the container as unprivileged when false [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with readOnlyRootFilesystem should run the container with readonly rootfs when readOnlyRootFilesystem=true [LinuxOnly] [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context When creating a pod with readOnlyRootFilesystem should run the container with writable rootfs when readOnlyRootFilesystem=false [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Security Context should support container.SecurityContext.RunAsUser And container.SecurityContext.RunAsGroup [LinuxOnly] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Security Context should support container.SecurityContext.RunAsUser [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context should support pod.Spec.SecurityContext.RunAsUser And pod.Spec.SecurityContext.RunAsGroup [LinuxOnly] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Security Context should support pod.Spec.SecurityContext.RunAsUser [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context should support pod.Spec.SecurityContext.SupplementalGroups [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context should support seccomp default which is unconfined [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context should support seccomp runtime/default [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context should support seccomp unconfined on the container [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context should support seccomp unconfined on the pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context should support volume SELinux relabeling [Flaky] [LinuxOnly]": " [Suite:k8s]", - - "[sig-node] Security Context should support volume SELinux relabeling when using hostIPC [Flaky] [LinuxOnly]": " [Suite:k8s]", - - "[sig-node] Security Context should support volume SELinux relabeling when using hostPID [Flaky] [LinuxOnly]": " [Suite:k8s]", - - "[sig-node] Security Context when creating containers with AllowPrivilegeEscalation should allow privilege escalation when not explicitly set and uid != 0 [LinuxOnly] [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context when creating containers with AllowPrivilegeEscalation should allow privilege escalation when true [LinuxOnly] [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Security Context when creating containers with AllowPrivilegeEscalation should not allow privilege escalation when false [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Security Context when if the container's primary UID belongs to some groups in the image [LinuxOnly] should add pod.Spec.SecurityContext.SupplementalGroups to them [LinuxOnly] in resultant supplementary groups for the container processes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Sysctls [LinuxOnly] [NodeConformance] should not launch unsafe, but not explicitly enabled sysctls on the node [MinimumKubeletVersion:1.21]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Sysctls [LinuxOnly] [NodeConformance] should reject invalid sysctls [MinimumKubeletVersion:1.21] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Sysctls [LinuxOnly] [NodeConformance] should support sysctls [MinimumKubeletVersion:1.21] [Environment:NotInUserNS] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Sysctls [LinuxOnly] [NodeConformance] should support sysctls with slashes as separator [MinimumKubeletVersion:1.23] [Environment:NotInUserNS]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] User Namespaces for Pod Security Standards [LinuxOnly] with UserNamespacesSupport and UserNamespacesPodSecurityStandards enabled should allow pod [Feature:UserNamespacesPodSecurityStandards] [FeatureGate:UserNamespacesSupport] [Beta] [FeatureGate:UserNamespacesPodSecurityStandards] [Alpha] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Variable Expansion allow almost all printable ASCII characters as environment variable names": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] Variable Expansion should allow composing env vars into new env vars [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Variable Expansion should allow substituting values in a container's args [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Variable Expansion should allow substituting values in a container's command [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Variable Expansion should allow substituting values in a volume subpath [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Variable Expansion should fail substituting values in a volume subpath with absolute path [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Variable Expansion should fail substituting values in a volume subpath with backticks [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Variable Expansion should succeed in writing subpaths in container [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-node] Variable Expansion should verify that a failing subpath expansion can be modified during the lifecycle of a container [Slow] [Conformance]": " [Suite:k8s]", - - "[sig-node] [DRA] ResourceSlice Controller creates slices [ConformanceCandidate]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] [FeatureGate:DRAExtendedResource] [Alpha] [Feature:OffByDefault] must run a pod with extended resource with one container one resource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] [FeatureGate:DRAExtendedResource] [Alpha] [Feature:OffByDefault] must run a pod with extended resource with one container three resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] [FeatureGate:DRAExtendedResource] [Alpha] [Feature:OffByDefault] must run a pod with extended resource with three containers multiple resources each": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] [FeatureGate:DRAExtendedResource] [Alpha] [Feature:OffByDefault] must run a pod with extended resource with three containers one resource each": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] [FeatureGate:DRAExtendedResource] [Alpha] [Feature:OffByDefault] must run pods with extended resource on dra nodes and device plugin nodes [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] must deallocate after use": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] retries pod scheduling after creating device class": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] retries pod scheduling after updating device class": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] runs a pod without a generated resource claim": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] supports claim and class parameters": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] supports external claim referenced by multiple containers of multiple pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] supports external claim referenced by multiple pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] supports init containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] supports inline claim referenced by multiple containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] supports reusing resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] supports sharing a claim concurrently": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] supports simple pod referencing external resource claim": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] supports simple pod referencing inline resource claim": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] with different ResourceSlices keeps pod pending because of CEL runtime errors": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane [ConformanceCandidate] with node-local resources uses all resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane must apply per-node permission checks [ConformanceCandidate]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane must be possible for the driver to update the ResourceClaim.Status.Devices once allocated [FeatureGate:DRAResourceClaimDeviceStatus] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane supports count/resourceclaims.resource.k8s.io ResourceQuota [ConformanceCandidate]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane truncates the name of a generated resource claim [ConformanceCandidate]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] control plane validate ResourceClaimTemplate and ResourceClaim for admin access [FeatureGate:DRAAdminAccess] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] DaemonSet with admin access [FeatureGate:DRAAdminAccess] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRAConsumableCapacity] [Alpha] [Feature:OffByDefault] must allow multiple allocations and consume capacity [KubeletMinVersion:1.34]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRADeviceTaints] [Alpha] [Feature:OffByDefault] DeviceTaint keeps pod pending": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRADeviceTaints] [Alpha] [Feature:OffByDefault] DeviceTaintRule evicts pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRADeviceTaints] [Alpha] [Feature:OffByDefault] DeviceToleration enables pod scheduling": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRAPartitionableDevices] [Alpha] [Feature:OffByDefault] must consume and free up counters": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRAPrioritizedList] [Beta] chooses the correct subrequest subject to constraints": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRAPrioritizedList] [Beta] filters config correctly for multiple devices": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRAPrioritizedList] [Beta] selects the first subrequest that can be satisfied": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] [FeatureGate:DRAPrioritizedList] [Beta] uses the config for the selected subrequest": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] blocks new pod after force-delete [KubeletMinVersion:1.34]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] deletes generated claims when pod is done": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] does not delete generated claims when pod is restarting": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] failed update [KubeletMinVersion:1.33]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] must call NodePrepareResources even if not used by any container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] must manage ResourceSlices": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] must map configs and devices to the right containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] must not run a pod if a claim is not ready": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] must retry NodePrepareResources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] must unprepare resources for force-deleted pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on multiple nodes with different ResourceSlices keeps pod pending because of CEL runtime errors": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on multiple nodes with node-local resources uses all resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node must deallocate after use": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node retries pod scheduling after creating device class": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node retries pod scheduling after updating device class": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node runs a pod without a generated resource claim": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports claim and class parameters": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports extended resources together with ResourceClaim [Serial] [Flaky]": " [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports external claim referenced by multiple containers of multiple pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports external claim referenced by multiple pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports init containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports inline claim referenced by multiple containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports reusing resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports sharing a claim concurrently": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports simple pod referencing external resource claim": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] on single node supports simple pod referencing inline resource claim": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] registers plugin": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] removes reservation from claim when pod is done": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] rolling update [KubeletMinVersion:1.33]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] runs pod after driver starts": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] sequential update with pods replacing each other [KubeletMinVersion:1.33] [Slow]": " [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] supports init containers with external claims": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] with multiple drivers using drapbv1beta1 and drapbv1 work": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] with multiple drivers using only drapbv1 [KubeletMinVersion:1.34] work": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] with multiple drivers using only drapbv1beta1 work": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] with v1beta1 API supports requests with alternatives [FeatureGate:DRAPrioritizedList] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] with v1beta1 API supports simple ResourceClaim": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] with v1beta2 API supports requests with alternatives [FeatureGate:DRAPrioritizedList] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [DRA] kubelet [Feature:DynamicResourceAllocation] with v1beta2 API supports simple ResourceClaim": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:ContainerStopSignals] [FeatureGate:ContainerStopSignals] [Alpha] [Feature:OffByDefault] when create a pod with a StopSignal lifecycle StopSignal defined with pod.OS": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:Example] Downward API should create a pod that prints his name and namespace": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:Example] Liveness liveness pods should be automatically restarted": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:Example] Secret should create a pod that reads a secret": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:GPUDevicePlugin] [Serial] Sanity test using nvidia-smi should run nvidia-smi and cuda-demo-suite": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] [Feature:GPUDevicePlugin] [Serial] Test using a Job should run gpu based jobs": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] [Feature:GPUDevicePlugin] [Serial] Test using a Pod should run gpu based matrix multiplication": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should *not* be restarted by liveness probe because startup probe delays it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should *not* be restarted with a /healthz http liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should *not* be restarted with a GRPC liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should *not* be restarted with a exec \"cat /tmp/health\" liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should *not* be restarted with a non-local redirect http liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should *not* be restarted with a tcp:8080 liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should be ready immediately after startupProbe succeeds": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should be restarted by liveness probe after startup probe enables it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should be restarted startup probe fails": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should be restarted with a /healthz http liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should be restarted with a GRPC liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should be restarted with a exec \"cat /tmp/health\" liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should be restarted with a failing exec liveness probe that took longer than the timeout": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should be restarted with a local redirect http liveness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should be restarted with an exec liveness probe with timeout [MinimumKubeletVersion:1.20]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should have monotonically increasing restart count": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should mark readiness on pods to false and disable liveness probes while pod is in progress of terminating": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should mark readiness on pods to false while pod is in progress of terminating when a pod has a readiness probe": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should not be ready with an exec readiness probe timeout [MinimumKubeletVersion:1.20]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should override timeoutGracePeriodSeconds when LivenessProbe field is set": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container should override timeoutGracePeriodSeconds when StartupProbe field is set": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container with readiness probe should not be ready before initial delay and never restart": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Probing restartable init container with readiness probe that fails should never be ready and never restart": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Restartable Init Container Lifecycle Hook when create a pod with lifecycle hook should execute poststart exec hook properly": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Restartable Init Container Lifecycle Hook when create a pod with lifecycle hook should execute poststart http hook properly": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Restartable Init Container Lifecycle Hook when create a pod with lifecycle hook should execute poststart https hook properly [MinimumKubeletVersion:1.23]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Restartable Init Container Lifecycle Hook when create a pod with lifecycle hook should execute prestop exec hook properly": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Restartable Init Container Lifecycle Hook when create a pod with lifecycle hook should execute prestop http hook properly": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Feature:SidecarContainers] [FeatureGate:SidecarContainers] Restartable Init Container Lifecycle Hook when create a pod with lifecycle hook should execute prestop https hook properly [MinimumKubeletVersion:1.23]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [FeatureGate:KubeletFineGrainedAuthz] [Beta] when calling kubelet API check /healthz enpoint is accessible via nodes/healthz RBAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [FeatureGate:KubeletFineGrainedAuthz] [Beta] when calling kubelet API check /healthz enpoint is accessible via nodes/proxy RBAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [FeatureGate:KubeletFineGrainedAuthz] [Beta] when calling kubelet API check /healthz enpoint is not accessible via nodes/configz RBAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] [Serial] Pod InPlace Resize Container (deferred-resizes) [FeatureGate:InPlacePodVerticalScaling] [Beta] pod-resize-retry-deferred-test-1": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] [Serial] Pod InPlace Resize Container (deferred-resizes) [FeatureGate:InPlacePodVerticalScaling] [Beta] pod-resize-retry-deferred-test-2": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] [Serial] Pod InPlace Resize Container (deferred-resizes) [FeatureGate:InPlacePodVerticalScaling] [Beta] pod-resize-retry-deferred-test-3": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] [Serial] Pod InPlace Resize Container (scheduler-focused) [FeatureGate:InPlacePodVerticalScaling] [Beta] pod-resize-scheduler-tests": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] crictl should be able to run crictl on the node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] kubelet Clean up pods on node kubelet should be able to delete 10 pods per node in 1m0s.": " [Serial] [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-node] kubelet host cleanup with volume mounts [HostCleanup] [Flaky] Host cleanup after disrupting NFS volume [NFS] after stopping the nfs-server and deleting the (active) client pod, the NFS mount and the pod's UID directory should be removed.": " [Suite:k8s]", - - "[sig-node] kubelet host cleanup with volume mounts [HostCleanup] [Flaky] Host cleanup after disrupting NFS volume [NFS] after stopping the nfs-server and deleting the (sleeping) client pod, the NFS mount and the pod's UID directory should be removed.": " [Suite:k8s]", - - "[sig-node] kubelet kubectl get --raw \"/api/v1/nodes//proxy/logs/?query=/ [Feature:NodeLogQuery] should return the Microsoft-Windows-Security-SPP logs with the pattern Health": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] kubelet kubectl get --raw \"/api/v1/nodes//proxy/logs/?query=/ [Feature:NodeLogQuery] should return the Microsoft-Windows-Security-SPP logs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] kubelet kubectl get --raw \"/api/v1/nodes//proxy/logs/?query=/ [Feature:NodeLogQuery] should return the error with an empty --query option": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] kubelet kubectl get --raw \"/api/v1/nodes//proxy/logs/?query=/ [Feature:NodeLogQuery] should return the kubelet logs ": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] kubelet kubectl get --raw \"/api/v1/nodes//proxy/logs/?query=/ [Feature:NodeLogQuery] should return the kubelet logs for the current boot with the pattern container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] kubelet kubectl get --raw \"/api/v1/nodes//proxy/logs/?query=/ [Feature:NodeLogQuery] should return the kubelet logs for the current boot": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] kubelet kubectl get --raw \"/api/v1/nodes//proxy/logs/?query=/ [Feature:NodeLogQuery] should return the kubelet logs since the current date and time": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] kubelet kubectl get --raw \"/api/v1/nodes//proxy/logs/?query=/ [Feature:NodeLogQuery] should return the last three lines of the Microsoft-Windows-Security-SPP logs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] kubelet kubectl get --raw \"/api/v1/nodes//proxy/logs/?query=/ [Feature:NodeLogQuery] should return the last three lines of the kubelet logs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-node] specific log stream [Feature:PodLogsQuerySplitStreams] [FeatureGate:PodLogsQuerySplitStreams] [Alpha] [Feature:OffByDefault] kubectl get --raw /api/v1/namespaces/default/pods//log?stream": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-scheduling] LimitRange should create a LimitRange with defaults and ensure pod has those defaults applied. [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-scheduling] LimitRange should list, patch and delete a LimitRange by collection [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-scheduling] Multi-AZ Clusters should spread the pods of a replication controller across zones [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] Multi-AZ Clusters should spread the pods of a service across zones [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] PodTopologySpread Filtering validates 4 pods with MaxSkew=1 are evenly distributed into 2 nodes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates Pods with non-empty schedulingGates are blocked on scheduling": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates local ephemeral storage resource limits of pods that are allowed to run": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates pod overhead is considered along with resource limits of pods that are allowed to run verify pod overhead is accounted for": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates resource limits of pods that are allowed to run [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates that NodeAffinity is respected if not matching": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates that NodeSelector is respected if matching [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates that NodeSelector is respected if not matching [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates that required NodeAffinity setting is respected if matching": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates that taints-tolerations is respected if matching": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates that taints-tolerations is respected if not matching": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates that there exists conflict between pods with same hostPort and protocol but one using 0.0.0.0 hostIP [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] validates that there is no conflict between pods with same hostPort but different hostIP and protocol": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPredicates [Serial] when PVC has node-affinity to non-existent/illegal nodes, the pod should be scheduled normally if suitable nodes exist": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPreemption [Serial] PodTopologySpread Preemption validates proper pods are preempted": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPreemption [Serial] PreemptionExecutionPath runs ReplicaSets to verify preemption running path [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-scheduling] SchedulerPreemption [Serial] PriorityClass endpoints verify PriorityClass endpoints can be operated with different HTTP methods [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-scheduling] SchedulerPreemption [Serial] validates basic preemption works [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-scheduling] SchedulerPreemption [Serial] validates lower priority pod preemption by critical pod [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-scheduling] SchedulerPreemption [Serial] validates pod disruption condition is added to the preempted pod [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-scheduling] SchedulerPreemption [Serial] validates various priority Pods preempt expectedly with the async preemption [Feature:SchedulerAsyncPreemption] [FeatureGate:SchedulerAsyncPreemption] [Beta]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPriorities [Serial] Pod should be preferably scheduled to nodes pod can tolerate": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPriorities [Serial] Pod should be scheduled to node that don't match the PodAntiAffinity terms": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-scheduling] SchedulerPriorities [Serial] PodTopologySpread Scoring validates pod should be preferably scheduled to node which makes the matching pods more evenly distributed": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock Node Volume Health [FeatureGate:CSIVolumeHealth] [Alpha] [Feature:OffByDefault] CSI Mock Node Volume Health [Slow] return normal volume stats with abnormal volume condition": " [Suite:k8s]", - - "[sig-storage] CSI Mock Node Volume Health [FeatureGate:CSIVolumeHealth] [Alpha] [Feature:OffByDefault] CSI Mock Node Volume Health [Slow] return normal volume stats without volume condition": " [Suite:k8s]", - - "[sig-storage] CSI Mock Node Volume Health [FeatureGate:CSIVolumeHealth] [Alpha] [Feature:OffByDefault] CSI Mock Node Volume Health [Slow] return normal volume stats": " [Suite:k8s]", - - "[sig-storage] CSI Mock fsgroup as mount option Delegate FSGroup to CSI driver [LinuxOnly] should not pass FSGroup to CSI driver if it is set in pod and driver supports VOLUME_MOUNT_GROUP": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock fsgroup as mount option Delegate FSGroup to CSI driver [LinuxOnly] should pass FSGroup to CSI driver if it is set in pod and driver supports VOLUME_MOUNT_GROUP": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy changes using mock driver should honor pv reclaim policy after it is changed from deleted to retain": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy changes using mock driver should honor pv reclaim policy after it is changed from retain to deleted": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy using mock driver Dynamic provisioning should honor pv delete reclaim policy when deleting pv then pvc": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy using mock driver Dynamic provisioning should honor pv delete reclaim policy when deleting pvc": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy using mock driver Dynamic provisioning should honor pv retain reclaim policy when deleting pv then pvc": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy using mock driver Dynamic provisioning should honor pv retain reclaim policy when deleting pvc then pv": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy using mock driver Static provisioning should honor pv delete reclaim policy when deleting pv then pvc": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy using mock driver Static provisioning should honor pv delete reclaim policy when deleting pvc": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy using mock driver Static provisioning should honor pv retain reclaim policy when deleting pv then pvc": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock honor pv reclaim policy CSI honor pv reclaim policy using mock driver Static provisioning should honor pv retain reclaim policy when deleting pvc then pv": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should add SELinux mount option to existing mount options [FeatureGate:SELinuxMountReadWriteOncePod] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should not pass SELinux mount option for CSI driver that does not support SELinux mount [FeatureGate:SELinuxMountReadWriteOncePod] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should not pass SELinux mount option for Pod without SELinux context [FeatureGate:SELinuxMountReadWriteOncePod] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should not pass SELinux mount option for RWO volume with SELinuxMount disabled [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [Feature:SELinuxMountReadWriteOncePodOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should not pass SELinux mount option for RWO volume with SELinuxMount disabled and Recursive policy [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should not pass SELinux mount option for RWO volume with only SELinuxChangePolicy enabled [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [Feature:SELinuxMountReadWriteOncePodOnly] [FeatureGate:SELinuxChangePolicy] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should not unstage RWO volume when starting a second pod with the same SELinux context [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should not unstage RWOP volume when starting a second pod with the same SELinux context [FeatureGate:SELinuxMountReadWriteOncePod] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should pass SELinux mount option for RWO volume with SELinuxMount enabled and MountOption policy [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should pass SELinux mount option for RWO volume with SELinuxMount enabled and nil policy [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should pass SELinux mount option for RWOP volume and Pod with SELinux context set [FeatureGate:SELinuxMountReadWriteOncePod] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should unstage RWO volume when starting a second pod with different SELinux context [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should unstage RWO volume when starting a second pod with different policy (MountOption -> Recursive) [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should unstage RWO volume when starting a second pod with different policy (Recursive -> MountOption) [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount SELinuxMount [LinuxOnly] [Feature:SELinux] should unstage RWOP volume when starting a second pod with different SELinux context [FeatureGate:SELinuxMountReadWriteOncePod] [Beta]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is bumped on a privileged and unprivileged Pod with given SELinux with MountOption policy [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is bumped on an unprivileged and privileged Pod with given SELinux with MountOption policy [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is bumped on two Pods with MountOption policy and a different context on RWOP volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is bumped on two Pods with a different context on RWO volume and SELinuxMount enabled [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is bumped on two Pods with a different context on RWOP volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMountReadWriteOncePod] [Beta]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is bumped on two Pods with a different context on RWX volume and SELinuxMount enabled [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is bumped on two Pods with a different policy on RWO volume and SELinuxMount enabled (Recursive + MountOption) [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is bumped on two Pods with a different policy on RWO volume and SELinuxMount enabled (Recursive + nil) [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is bumped on two Pods with a different policy on RWO volume and SELinuxMount enabled (nil + Recursive) [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is not bumped on a privileged and unprivileged Pod with given SELinux context and recursive policy [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is not bumped on two Pods with Recursive policy and a different context on RWX volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is not bumped on two Pods with the same context on RWO volume and SELinuxMount enabled [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is not bumped on two Pods with the same policy RWX volume (MountOption + MountOption) [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is not bumped on two Pods with the same policy RWX volume (nil + MountOption) [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is not bumped on two privileged Pods with mount policy RWO volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] error is not bumped on two privileged Pods with recursive policy RWO volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxMount] [Beta] [Feature:OffByDefault]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] warning is bumped on two Pods with a different context on RWO volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [Feature:SELinuxMountReadWriteOncePodOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] warning is bumped on two Pods with different policies on RWO volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [Feature:SELinuxMountReadWriteOncePodOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] warning is not bumped on two Pods with Recursive policy and a different context on RWO volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [Feature:SELinuxMountReadWriteOncePodOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock selinux on mount metrics and SELinuxWarningController SELinuxMount metrics [LinuxOnly] [Feature:SELinux] [Serial] warning is not bumped on two Pods with the same context on RWO volume [FeatureGate:SELinuxMountReadWriteOncePod] [Beta] [FeatureGate:SELinuxChangePolicy] [Beta] [Feature:SELinuxMountReadWriteOncePodOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Mock volume attach CSI CSIDriver deployment after pod creation using non-attachable mock driver should bringup pod after deploying CSIDriver attach=false [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume attach CSI attach test using mock driver should not require VolumeAttach for drivers without attachment": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume attach CSI attach test using mock driver should preserve attachment policy when no CSIDriver present": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume attach CSI attach test using mock driver should require VolumeAttach for drivers with attachment": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume attach CSI attach test using mock driver should require VolumeAttach for ephemermal volume and drivers with attachment": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion CSI Volume expansion should expand volume by restarting pod if attach=off, nodeExpansion=on": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion CSI Volume expansion should expand volume by restarting pod if attach=on, nodeExpansion=on": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion CSI Volume expansion should expand volume without restarting pod if nodeExpansion=off": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion CSI Volume expansion should not expand volume if resizingOnDriver=off, resizingOnSC=on": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion CSI Volume expansion should not have staging_path missing in node expand volume pod if attach=on, nodeExpansion=on": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion CSI online volume expansion should expand volume without restarting pod if attach=off, nodeExpansion=on": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion CSI online volume expansion should expand volume without restarting pod if attach=on, nodeExpansion=on": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion CSI online volume expansion with secret should expand volume without restarting pod if attach=on, nodeExpansion=on, csiNodeExpandSecret=on": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion Expansion with recovery recovery should be possible for node-only expanded volumes with final error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion Expansion with recovery recovery should be possible for node-only expanded volumes with infeasible error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion Expansion with recovery recovery should not be possible in partially expanded volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion Expansion with recovery should allow recovery if controller expansion fails with final error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion Expansion with recovery should allow recovery if controller expansion fails with infeasible error": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume expansion Expansion with recovery should record target size in allocated resources": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume fsgroup policies CSI FSGroupPolicy Update [LinuxOnly] should not update fsGroup if update from File to None": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume fsgroup policies CSI FSGroupPolicy Update [LinuxOnly] should not update fsGroup if update from detault to None": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume fsgroup policies CSI FSGroupPolicy Update [LinuxOnly] should update fsGroup if update from File to default": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume fsgroup policies CSI FSGroupPolicy Update [LinuxOnly] should update fsGroup if update from None to File": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume fsgroup policies CSI FSGroupPolicy Update [LinuxOnly] should update fsGroup if update from None to default": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume fsgroup policies CSI FSGroupPolicy Update [LinuxOnly] should update fsGroup if update from detault to File": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume fsgroup policies CSI FSGroupPolicy [LinuxOnly] should modify fsGroup if fsGroupPolicy=File": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume fsgroup policies CSI FSGroupPolicy [LinuxOnly] should modify fsGroup if fsGroupPolicy=default": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume fsgroup policies CSI FSGroupPolicy [LinuxOnly] should not modify fsGroup if fsGroupPolicy=None": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume limit CSI volume limit information using mock driver should report attach limit for generic ephemeral volume when persistent volume is attached [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume limit CSI volume limit information using mock driver should report attach limit for persistent volume when generic ephemeral volume is attached [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume limit CSI volume limit information using mock driver should report attach limit when limit is bigger than 0 [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume node stage CSI NodeStage error cases [Slow] should call NodeUnstage after NodeStage ephemeral error": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume node stage CSI NodeStage error cases [Slow] should call NodeUnstage after NodeStage success": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume node stage CSI NodeStage error cases [Slow] should not call NodeUnstage after NodeStage final error": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume node stage CSI NodeStage error cases [Slow] should retry NodeStage after NodeStage ephemeral error": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume node stage CSI NodeStage error cases [Slow] should retry NodeStage after NodeStage final error": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume node stage CSI NodeUnstage error cases [Slow] should call NodeStage after NodeUnstage success": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume node stage CSI NodeUnstage error cases [Slow] two pods: should call NodeStage after previous NodeUnstage final error": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume node stage CSI NodeUnstage error cases [Slow] two pods: should call NodeStage after previous NodeUnstage transient error": " [Suite:k8s]", - - "[sig-storage] CSI Mock volume service account token CSIServiceAccountToken token should be plumbed down when csiServiceAccountTokenEnabled=true": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume service account token CSIServiceAccountToken token should not be plumbed down when CSIDriver is not deployed": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume service account token CSIServiceAccountToken token should not be plumbed down when csiServiceAccountTokenEnabled=false": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume snapshot CSI Snapshot Controller metrics [Feature:VolumeSnapshotDataSource] snapshot controller should emit dynamic CreateSnapshot, CreateSnapshotAndReady, and DeleteSnapshot metrics": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume snapshot CSI Snapshot Controller metrics [Feature:VolumeSnapshotDataSource] snapshot controller should emit pre-provisioned CreateSnapshot, CreateSnapshotAndReady, and DeleteSnapshot metrics": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume snapshot CSI Volume Snapshots [Feature:VolumeSnapshotDataSource] volumesnapshotcontent and pvc in Bound state with deletion timestamp set should not get deleted while snapshot finalizer exists": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume snapshot CSI Volume Snapshots secrets [Feature:VolumeSnapshotDataSource] volume snapshot create/delete with secrets": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume storage capacity CSIStorageCapacity CSIStorageCapacity disabled": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume storage capacity CSIStorageCapacity CSIStorageCapacity unused": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume storage capacity CSIStorageCapacity CSIStorageCapacity used, have capacity": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume storage capacity CSIStorageCapacity CSIStorageCapacity used, insufficient capacity": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume storage capacity CSIStorageCapacity CSIStorageCapacity used, no capacity": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume storage capacity storage capacity exhausted, immediate binding": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume storage capacity storage capacity exhausted, late binding, no topology": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume storage capacity storage capacity exhausted, late binding, with topology": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock volume storage capacity storage capacity unlimited": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock when kubelet restart [Serial] [Disruptive] should not umount volume when the pvc is terminating but still used by a running pod": " [Suite:k8s]", - - "[sig-storage] CSI Mock workload info CSI PodInfoOnMount Update should be passed when update from false to true": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock workload info CSI PodInfoOnMount Update should not be passed when update from true to false": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock workload info CSI workload information using mock driver contain ephemeral=true when using inline volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock workload info CSI workload information using mock driver should be passed when podInfoOnMount=true": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock workload info CSI workload information using mock driver should not be passed when CSIDriver does not exist": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Mock workload info CSI workload information using mock driver should not be passed when podInfoOnMount=false": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] pvc-deletion-performance should delete volumes at scale within performance constraints [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should be protected by vac-protection finalizer": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should create a volume with VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume that already has a VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume with no VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should recover from invalid target VAC by updating PVC to new valid VAC [Flaky]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should modify volumes with a different volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should provision volumes with volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] read-write-once-pod [MinimumKubeletVersion:1.27] should block a second pod from using an in-use ReadWriteOncePod volume on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] read-write-once-pod [MinimumKubeletVersion:1.27] should preempt lower priority pods using ReadWriteOncePod volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should be protected by vac-protection finalizer": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should create a volume with VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume that already has a VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume with no VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should recover from invalid target VAC by updating PVC to new valid VAC [Flaky]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should modify volumes with a different volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should provision volumes with volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] volume-lifecycle-performance should provision volumes at scale within performance constraints [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should be protected by vac-protection finalizer": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should create a volume with VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume that already has a VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume with no VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should recover from invalid target VAC by updating PVC to new valid VAC [Flaky]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should modify volumes with a different volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should provision volumes with volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic Snapshot (delete policy)] snapshottable-stress [Feature:VolumeSnapshotDataSource] should support snapshotting of many volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Dynamic Snapshot (retain policy)] snapshottable-stress [Feature:VolumeSnapshotDataSource] should support snapshotting of many volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Ephemeral Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Ephemeral Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Ephemeral Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Ephemeral Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: csi-hostpath] [Testpattern: Pre-provisioned Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] pvc-deletion-performance should delete volumes at scale within performance constraints [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should be protected by vac-protection finalizer": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should create a volume with VAC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume that already has a VAC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume with no VAC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should recover from invalid target VAC by updating PVC to new valid VAC [Flaky]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should modify volumes with a different volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should provision volumes with volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] read-write-once-pod [MinimumKubeletVersion:1.27] should block a second pod from using an in-use ReadWriteOncePod volume on the same node": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] read-write-once-pod [MinimumKubeletVersion:1.27] should preempt lower priority pods using ReadWriteOncePod volumes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should be protected by vac-protection finalizer": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should create a volume with VAC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume that already has a VAC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume with no VAC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should recover from invalid target VAC by updating PVC to new valid VAC [Flaky]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should modify volumes with a different volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should provision volumes with volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] volume-lifecycle-performance should provision volumes at scale within performance constraints [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should be protected by vac-protection finalizer": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should create a volume with VAC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume that already has a VAC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume with no VAC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should recover from invalid target VAC by updating PVC to new valid VAC [Flaky]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should modify volumes with a different volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should provision volumes with volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic Snapshot (delete policy)] snapshottable-stress [Feature:VolumeSnapshotDataSource] should support snapshotting of many volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Dynamic Snapshot (retain policy)] snapshottable-stress [Feature:VolumeSnapshotDataSource] should support snapshotting of many volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Ephemeral Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Ephemeral Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Ephemeral Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Ephemeral Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSI Volumes [Driver: pd.csi.storage.gke.io] [Serial] [Testpattern: Pre-provisioned Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] CSIInlineVolumes should run through the lifecycle of a CSIDriver [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] CSIInlineVolumes should support CSIVolumeSource in Pod API [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] CSINodes CSI Conformance should run through the lifecycle of a csinode [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] CSIStorageCapacity should support CSIStorageCapacities API operations [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap Should fail non-optional pod creation due to configMap object does not exist [Slow]": " [Suite:k8s]", - - "[sig-storage] ConfigMap Should fail non-optional pod creation due to the key in the configMap object does not exist [Slow]": " [Suite:k8s]", - - "[sig-storage] ConfigMap binary data should be reflected in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap optional updates should be reflected in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable from pods in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable from pods in volume as non-root [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable from pods in volume as non-root with FSGroup [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable from pods in volume as non-root with defaultMode and fsGroup set [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable from pods in volume with defaultMode set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable from pods in volume with mappings [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable from pods in volume with mappings and Item mode set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable from pods in volume with mappings as non-root [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable from pods in volume with mappings as non-root with FSGroup [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] ConfigMap should be consumable in multiple volumes in the same pod [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap should be immutable if `immutable` field is set [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] ConfigMap updates should be reflected in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API [Serial] [Disruptive] [Feature:EphemeralStorage] Downward API tests for local ephemeral storage should provide container's limits.ephemeral-storage and requests.ephemeral-storage as env vars": " [Suite:k8s]", - - "[sig-storage] Downward API [Serial] [Disruptive] [Feature:EphemeralStorage] Downward API tests for local ephemeral storage should provide default limits.ephemeral-storage from node allocatable": " [Suite:k8s]", - - "[sig-storage] Downward API volume should provide container's cpu limit [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should provide container's cpu request [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should provide container's memory limit [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should provide container's memory request [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should provide node allocatable (cpu) as default cpu limit if the limit is not set [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should provide node allocatable (memory) as default memory limit if the limit is not set [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should provide podname as non-root with fsgroup [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Downward API volume should provide podname as non-root with fsgroup and defaultMode [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Downward API volume should provide podname only [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should set DefaultMode on files [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should set mode on item file [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should update annotations on modification [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Downward API volume should update labels on modification [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Dynamic Provisioning DynamicProvisioner Default should be disabled by changing the default annotation [Serial] [Disruptive]": " [Suite:k8s]", - - "[sig-storage] Dynamic Provisioning DynamicProvisioner Default should be disabled by removing the default annotation [Serial] [Disruptive]": " [Suite:k8s]", - - "[sig-storage] Dynamic Provisioning DynamicProvisioner Default should create and delete default persistent volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] Dynamic Provisioning DynamicProvisioner External should let an external dynamic provisioner create and delete persistent volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] Dynamic Provisioning DynamicProvisioner [Slow] [Feature:StorageProvider] should provision storage with different parameters": " [Suite:k8s]", - - "[sig-storage] Dynamic Provisioning Invalid AWS KMS key should report an error and create no PV": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes pod should support memory backed volumes of specified size": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes pod should support shared volumes between containers [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (non-root,0644,default) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (non-root,0644,tmpfs) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (non-root,0666,default) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (non-root,0666,tmpfs) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (non-root,0777,default) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (non-root,0777,tmpfs) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (root,0644,default) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (root,0644,tmpfs) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (root,0666,default) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (root,0666,tmpfs) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (root,0777,default) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes should support (root,0777,tmpfs) [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes volume on default medium should have the correct mode [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes volume on tmpfs should have the correct mode [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes when FSGroup is specified [LinuxOnly] files with FSGroup ownership should support (root,0644,tmpfs)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes when FSGroup is specified [LinuxOnly] new files should be created with FSGroup ownership when container is non-root": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes when FSGroup is specified [LinuxOnly] new files should be created with FSGroup ownership when container is root": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes when FSGroup is specified [LinuxOnly] nonexistent volume subPath should have the correct mode and owner using FSGroup": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes when FSGroup is specified [LinuxOnly] volume on default medium should have the correct mode using FSGroup": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] EmptyDir volumes when FSGroup is specified [LinuxOnly] volume on tmpfs should have the correct mode using FSGroup": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] EmptyDir wrapper volumes should not cause race condition when used for configmaps [Serial] [Conformance]": " [Suite:openshift/conformance/serial/minimal] [Suite:k8s]", - - "[sig-storage] EmptyDir wrapper volumes should not cause race condition when used for git_repo [FeatureGate:GitRepoVolumeDriver] [Deprecated] [Feature:OffByDefault] [Serial] [Slow]": " [Suite:k8s]", - - "[sig-storage] EmptyDir wrapper volumes should not conflict [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Ephemeralstorage When pod refers to non-existent ephemeral storage should allow deletion of pod with invalid volume : configmap": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Ephemeralstorage When pod refers to non-existent ephemeral storage should allow deletion of pod with invalid volume : projected": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Ephemeralstorage When pod refers to non-existent ephemeral storage should allow deletion of pod with invalid volume : secret": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Flexvolumes should be mountable when attachable [Feature:Flexvolumes]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Flexvolumes should be mountable when non-attachable": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] GenericPersistentVolume [Disruptive] When kubelet restarts Should test that a file written to the mount before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] GenericPersistentVolume [Disruptive] When kubelet restarts Should test that a volume mounted to a pod that is deleted while the kubelet is down unmounts when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] GenericPersistentVolume [Disruptive] When kubelet restarts Should test that a volume mounted to a pod that is force deleted while the kubelet is down unmounts when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] HostPath should give a volume the correct mode [LinuxOnly] [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] HostPath should support r/w [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] HostPath should support subPath [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] HostPathType Block Device [Slow] Should be able to mount block device 'ablkdev' successfully when HostPathType is HostPathBlockDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Block Device [Slow] Should be able to mount block device 'ablkdev' successfully when HostPathType is HostPathUnset": " [Suite:k8s]", - - "[sig-storage] HostPathType Block Device [Slow] Should fail on mounting block device 'ablkdev' when HostPathType is HostPathCharDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Block Device [Slow] Should fail on mounting block device 'ablkdev' when HostPathType is HostPathDirectory": " [Suite:k8s]", - - "[sig-storage] HostPathType Block Device [Slow] Should fail on mounting block device 'ablkdev' when HostPathType is HostPathFile": " [Suite:k8s]", - - "[sig-storage] HostPathType Block Device [Slow] Should fail on mounting block device 'ablkdev' when HostPathType is HostPathSocket": " [Suite:k8s]", - - "[sig-storage] HostPathType Block Device [Slow] Should fail on mounting non-existent block device 'does-not-exist-blk-dev' when HostPathType is HostPathBlockDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Character Device [Slow] Should be able to mount character device 'achardev' successfully when HostPathType is HostPathCharDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Character Device [Slow] Should be able to mount character device 'achardev' successfully when HostPathType is HostPathUnset": " [Suite:k8s]", - - "[sig-storage] HostPathType Character Device [Slow] Should fail on mounting character device 'achardev' when HostPathType is HostPathBlockDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Character Device [Slow] Should fail on mounting character device 'achardev' when HostPathType is HostPathDirectory": " [Suite:k8s]", - - "[sig-storage] HostPathType Character Device [Slow] Should fail on mounting character device 'achardev' when HostPathType is HostPathFile": " [Suite:k8s]", - - "[sig-storage] HostPathType Character Device [Slow] Should fail on mounting character device 'achardev' when HostPathType is HostPathSocket": " [Suite:k8s]", - - "[sig-storage] HostPathType Character Device [Slow] Should fail on mounting non-existent character device 'does-not-exist-char-dev' when HostPathType is HostPathCharDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Directory [Slow] Should be able to mount directory 'adir' successfully when HostPathType is HostPathDirectory": " [Suite:k8s]", - - "[sig-storage] HostPathType Directory [Slow] Should be able to mount directory 'adir' successfully when HostPathType is HostPathUnset": " [Suite:k8s]", - - "[sig-storage] HostPathType Directory [Slow] Should fail on mounting directory 'adir' when HostPathType is HostPathBlockDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Directory [Slow] Should fail on mounting directory 'adir' when HostPathType is HostPathCharDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Directory [Slow] Should fail on mounting directory 'adir' when HostPathType is HostPathFile": " [Suite:k8s]", - - "[sig-storage] HostPathType Directory [Slow] Should fail on mounting directory 'adir' when HostPathType is HostPathSocket": " [Suite:k8s]", - - "[sig-storage] HostPathType Directory [Slow] Should fail on mounting non-existent directory 'does-not-exist-dir' when HostPathType is HostPathDirectory": " [Suite:k8s]", - - "[sig-storage] HostPathType File [Slow] Should be able to mount file 'afile' successfully when HostPathType is HostPathFile": " [Suite:k8s]", - - "[sig-storage] HostPathType File [Slow] Should be able to mount file 'afile' successfully when HostPathType is HostPathUnset": " [Suite:k8s]", - - "[sig-storage] HostPathType File [Slow] Should fail on mounting file 'afile' when HostPathType is HostPathBlockDev": " [Suite:k8s]", - - "[sig-storage] HostPathType File [Slow] Should fail on mounting file 'afile' when HostPathType is HostPathCharDev": " [Suite:k8s]", - - "[sig-storage] HostPathType File [Slow] Should fail on mounting file 'afile' when HostPathType is HostPathDirectory": " [Suite:k8s]", - - "[sig-storage] HostPathType File [Slow] Should fail on mounting file 'afile' when HostPathType is HostPathSocket": " [Suite:k8s]", - - "[sig-storage] HostPathType File [Slow] Should fail on mounting non-existent file 'does-not-exist-file' when HostPathType is HostPathFile": " [Suite:k8s]", - - "[sig-storage] HostPathType Socket [Slow] Should be able to mount socket 'asocket' successfully when HostPathType is HostPathSocket": " [Suite:k8s]", - - "[sig-storage] HostPathType Socket [Slow] Should be able to mount socket 'asocket' successfully when HostPathType is HostPathUnset": " [Suite:k8s]", - - "[sig-storage] HostPathType Socket [Slow] Should fail on mounting non-existent socket 'does-not-exist-socket' when HostPathType is HostPathSocket": " [Suite:k8s]", - - "[sig-storage] HostPathType Socket [Slow] Should fail on mounting socket 'asocket' when HostPathType is HostPathBlockDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Socket [Slow] Should fail on mounting socket 'asocket' when HostPathType is HostPathCharDev": " [Suite:k8s]", - - "[sig-storage] HostPathType Socket [Slow] Should fail on mounting socket 'asocket' when HostPathType is HostPathDirectory": " [Suite:k8s]", - - "[sig-storage] HostPathType Socket [Slow] Should fail on mounting socket 'asocket' when HostPathType is HostPathFile": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-disk] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: azure-file] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: cinder] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: emptydir] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPathSymlink] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: hostPath] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: iscsi] [Feature:Volumes] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: block] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: blockfs] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-bindmounted] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link-bindmounted] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir-link] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: dir] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: local] [LocalVolumeType: tmpfs] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail in binding dynamic provisioned PV to PVC [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to create pod by failing to mount volume [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] In-tree Volumes [Driver: vsphere] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] MutableCSINodeAllocatableCount [FeatureGate:MutableCSINodeAllocatableCount] [Beta] [Feature:OffByDefault] Attach Limit Exceeded should transition pod to failed state when attachment limit exceeded": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] MutableCSINodeAllocatableCount [FeatureGate:MutableCSINodeAllocatableCount] [Beta] [Feature:OffByDefault] Dynamic Allocatable Count should observe dynamic changes in CSINode allocatable count": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] NFSPersistentVolumes [Disruptive] when kubelet restarts Should test that a file written to the mount before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] NFSPersistentVolumes [Disruptive] when kubelet restarts Should test that a volume mounted to a pod that is deleted while the kubelet is down unmounts when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] NFSPersistentVolumes [Disruptive] when kubelet restarts Should test that a volume mounted to a pod that is force deleted while the kubelet is down unmounts when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: (delete policy)] volumegroupsnapshottable [Feature:volumegroupsnapshot] VolumeGroupSnapshottable should create snapshots for multiple volumes in a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: CSI Ephemeral-volume (default fs)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] pvc-deletion-performance should delete volumes at scale within performance constraints [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should be protected by vac-protection finalizer": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should create a volume with VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume that already has a VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume with no VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should recover from invalid target VAC by updating PVC to new valid VAC [Flaky]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should modify volumes with a different volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should provision volumes with volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)(allowExpansion)] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] capacity provides storage capacity information": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (Always)[LinuxOnly], rwop pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, new pod fsgroup applied to volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with different fsgroup applied to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] fsgroupchangepolicy (OnRootMismatch)[LinuxOnly], pod created with an initial fsgroup, volume contents ownership changed via chgrp in first pod, new pod with same fsgroup skips ownership changes to the volume contents": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] read-write-once-pod [MinimumKubeletVersion:1.27] should block a second pod from using an in-use ReadWriteOncePod volume on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] read-write-once-pod [MinimumKubeletVersion:1.27] should preempt lower priority pods using ReadWriteOncePod volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should be protected by vac-protection finalizer": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should create a volume with VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume that already has a VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume with no VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should recover from invalid target VAC by updating PVC to new valid VAC [Flaky]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should modify volumes with a different volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should provision volumes with volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volume-stress multiple pods should access different volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (delayed binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (delayed binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] volume-lifecycle-performance should provision volumes at scale within performance constraints [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (immediate binding)] topology should fail to schedule a pod which has topologies that conflict with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (immediate binding)] topology should provision a volume and schedule a pod with AllowedTopologies": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand Verify if offline PVC expansion works": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited and the pod is re-created on the same node after controller resize is finished": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)(allowExpansion)] [Feature:Windows] volume-expand should resize volume when PVC is edited while pod is using it": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should mount multiple PV pointing to the same storage on the same node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision correct filesystem size when restoring snapshot to larger size pvc [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with any volume data source [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with mount options": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source (ROX mode)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source in parallel [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with pvc data source": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source (ROX mode) [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] provisioning should provision storage with snapshot data source [Feature:VolumeSnapshotDataSource]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-expand should not allow expansion of pvcs without AllowVolumeExpansion property": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should be protected by vac-protection finalizer": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should create a volume with VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume that already has a VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should modify volume with no VAC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] should recover from invalid target VAC by updating PVC to new valid VAC [Flaky]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should modify volumes with a different volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volume-modify-stress [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass] multiple pods should provision volumes with volumeAttributesClass [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic Snapshot (delete policy)] snapshottable-stress [Feature:VolumeSnapshotDataSource] should support snapshotting of many volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Dynamic Snapshot (retain policy)] snapshottable-stress [Feature:VolumeSnapshotDataSource] should support snapshotting of many volumes repeatedly [Slow] [Serial]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Ephemeral Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Ephemeral Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Ephemeral Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Ephemeral Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (block volmode) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support expansion of pvcs created for ephemeral pvcs": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should support volume limits [Serial]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Generic Ephemeral-volume (default fs)] volumeLimits should verify that all csinodes have volume limits": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Inline-volume (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down cleans up when the kubelet returns.": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (block volmode)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if non-existent subpath is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath directory is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath file is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should fail if subpath with backstepping is outside the volume [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support creating multiple subpath from same volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing directory": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support existing single file [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support file as subpath [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support non-existent path": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly directory specified in the volumeMount": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using directory as subpath [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should support restarting containers using file as subpath [Slow] [LinuxOnly]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is force deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should unmount if pod is gracefully deleted while kubelet is down [Disruptive] [Slow] [LinuxOnly]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] subPath should verify container cannot write to subpath readonly volumes [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] volumeIO should write files of various sizes, verify size, validate content [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (ext3)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (ext3)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (ext4)] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (ext4)] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv used in a pod that is force deleted while the kubelet is down is usable by a new pod with a different SELinux context when kubelet returns [Feature:SELinux]": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] disruptive [Disruptive] [LinuxOnly] Should test that pv written before kubelet restart is readable after restart.": " [Serial] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with different volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should access to two volumes with the same volume mode and retain data across pod recreation on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single read-only volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on different node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the single volume from pods on the same node": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and its clone from pods on the same node [LinuxOnly] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] multiVolume [Slow] should concurrently access the volume and restored snapshot from pods on the same node [LinuxOnly] [Feature:VolumeSnapshotDataSource] [Feature:VolumeSourceXFS]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should fail to use a volume in a pod with mismatched mode [Slow]": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (filesystem volmode)] volumeMode should not mount / map unused volumes in a pod [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should allow exec of files on the volume": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (ntfs)] [Feature:Windows] volumes should store data": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should allow exec of files on the volume": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned PV (xfs)] [Slow] volumes should store data": " [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned Snapshot (delete policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works after modifying source data, check deletion (persistent)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] OCP CSI Volumes [Driver: csi-hostpath-groupsnapshot] [OCPFeatureGate:VolumeGroupSnapshot] [Testpattern: Pre-provisioned Snapshot (retain policy)] snapshottable [Feature:VolumeSnapshotDataSource] volume snapshot controller should check snapshot fields, check restore correctly works, check deletion (ephemeral)": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PV Protection Verify \"immediate\" deletion of a PV that is not bound to a PVC": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PV Protection Verify that PV bound to a PVC is not removed immediately": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PVC Protection Verify \"immediate\" deletion of a PVC that is not in active use by a pod": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PVC Protection Verify that PVC in active use by a pod is not removed immediately": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PVC Protection Verify that scheduling of a pod that uses PVC that is being deleted fails and the pod becomes Unschedulable": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes CSI Conformance should apply changes to a pv/pvc status [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] PersistentVolumes CSI Conformance should run through the lifecycle of a PV and a PVC [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] PersistentVolumes Default StorageClass [LinuxOnly] pods that use multiple volumes should be reschedulable [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS when invoking the Recycle reclaim policy should test that a PV becomes Available and is clean after the PVC is deleted.": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV and a pre-bound PVC: test phase transition timestamp is set": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV and a pre-bound PVC: test phase transition timestamp multiple updates": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV and a pre-bound PVC: test write access": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV: test phase transition timestamp is set and phase is Available": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PVC and a pre-bound PV: test write access": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PVC and non-pre-bound PV: test write access": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs should create a non-pre-bound PV and PVC: test write access ": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with multiple PVs and PVCs all in same ns should create 2 PVs and 4 PVCs: test write access": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with multiple PVs and PVCs all in same ns should create 3 PVs and 3 PVCs: test write access": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes NFS with multiple PVs and PVCs all in same ns should create 4 PVs and 2 PVCs: test write access [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-expansion loopback local block volume should support online expansion on node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local Local volume that cannot be mounted [Slow] should fail due to non-existent path": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local Local volume that cannot be mounted [Slow] should fail due to wrong node": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local Pod with node different from PV's NodeAffinity should fail scheduling due to different NodeAffinity": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local Pod with node different from PV's NodeAffinity should fail scheduling due to different NodeSelector": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local StatefulSet with pod affinity [Slow] should use volumes on one node when pod has affinity": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local StatefulSet with pod affinity [Slow] should use volumes on one node when pod management is parallel and pod has affinity": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local StatefulSet with pod affinity [Slow] should use volumes spread across nodes when pod has anti-affinity": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local StatefulSet with pod affinity [Slow] should use volumes spread across nodes when pod management is parallel and pod has anti-affinity": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local Stress with local volumes [Serial] should be able to process many pods and reuse local volumes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: block] One pod requesting one prebound PVC should be able to mount volume and read from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: block] One pod requesting one prebound PVC should be able to mount volume and write from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: block] Set fsGroup for local volume should set different fsGroup for second pod if first pod is deleted [Flaky]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: block] Set fsGroup for local volume should set fsGroup for one pod [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: block] Set fsGroup for local volume should set same fsGroup for two pods simultaneously [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: block] Two pods mounting a local volume at the same time should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: block] Two pods mounting a local volume one after the other should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithformat] One pod requesting one prebound PVC should be able to mount volume and read from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithformat] One pod requesting one prebound PVC should be able to mount volume and write from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithformat] Set fsGroup for local volume should set different fsGroup for second pod if first pod is deleted [Flaky]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithformat] Set fsGroup for local volume should set fsGroup for one pod [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithformat] Set fsGroup for local volume should set same fsGroup for two pods simultaneously [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithformat] Two pods mounting a local volume at the same time should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithformat] Two pods mounting a local volume one after the other should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithoutformat] One pod requesting one prebound PVC should be able to mount volume and read from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithoutformat] One pod requesting one prebound PVC should be able to mount volume and write from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithoutformat] Set fsGroup for local volume should set different fsGroup for second pod if first pod is deleted [Flaky]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithoutformat] Set fsGroup for local volume should set fsGroup for one pod [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithoutformat] Set fsGroup for local volume should set same fsGroup for two pods simultaneously [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithoutformat] Two pods mounting a local volume at the same time should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: blockfswithoutformat] Two pods mounting a local volume one after the other should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-bindmounted] One pod requesting one prebound PVC should be able to mount volume and read from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-bindmounted] One pod requesting one prebound PVC should be able to mount volume and write from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-bindmounted] Set fsGroup for local volume should set different fsGroup for second pod if first pod is deleted [Flaky]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-bindmounted] Set fsGroup for local volume should set fsGroup for one pod [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-bindmounted] Set fsGroup for local volume should set same fsGroup for two pods simultaneously [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-bindmounted] Two pods mounting a local volume at the same time should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-bindmounted] Two pods mounting a local volume one after the other should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link-bindmounted] One pod requesting one prebound PVC should be able to mount volume and read from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link-bindmounted] One pod requesting one prebound PVC should be able to mount volume and write from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link-bindmounted] Set fsGroup for local volume should set different fsGroup for second pod if first pod is deleted [Flaky]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link-bindmounted] Set fsGroup for local volume should set fsGroup for one pod [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link-bindmounted] Set fsGroup for local volume should set same fsGroup for two pods simultaneously [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link-bindmounted] Two pods mounting a local volume at the same time should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link-bindmounted] Two pods mounting a local volume one after the other should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link] One pod requesting one prebound PVC should be able to mount volume and read from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link] One pod requesting one prebound PVC should be able to mount volume and write from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link] Set fsGroup for local volume should set different fsGroup for second pod if first pod is deleted [Flaky]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link] Set fsGroup for local volume should set fsGroup for one pod [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link] Set fsGroup for local volume should set same fsGroup for two pods simultaneously [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link] Two pods mounting a local volume at the same time should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir-link] Two pods mounting a local volume one after the other should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir] One pod requesting one prebound PVC should be able to mount volume and read from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir] One pod requesting one prebound PVC should be able to mount volume and write from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir] Set fsGroup for local volume should set different fsGroup for second pod if first pod is deleted [Flaky]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir] Set fsGroup for local volume should set fsGroup for one pod [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir] Set fsGroup for local volume should set same fsGroup for two pods simultaneously [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir] Two pods mounting a local volume at the same time should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: dir] Two pods mounting a local volume one after the other should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: gce-localssd-scsi-fs] [Serial] One pod requesting one prebound PVC should be able to mount volume and read from pod1": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: gce-localssd-scsi-fs] [Serial] One pod requesting one prebound PVC should be able to mount volume and write from pod1": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: gce-localssd-scsi-fs] [Serial] Set fsGroup for local volume should set different fsGroup for second pod if first pod is deleted [Flaky]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: gce-localssd-scsi-fs] [Serial] Set fsGroup for local volume should set fsGroup for one pod [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: gce-localssd-scsi-fs] [Serial] Set fsGroup for local volume should set same fsGroup for two pods simultaneously [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: gce-localssd-scsi-fs] [Serial] Two pods mounting a local volume at the same time should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: gce-localssd-scsi-fs] [Serial] Two pods mounting a local volume one after the other should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: tmpfs] One pod requesting one prebound PVC should be able to mount volume and read from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: tmpfs] One pod requesting one prebound PVC should be able to mount volume and write from pod1": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: tmpfs] Set fsGroup for local volume should set different fsGroup for second pod if first pod is deleted [Flaky]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: tmpfs] Set fsGroup for local volume should set fsGroup for one pod [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: tmpfs] Set fsGroup for local volume should set same fsGroup for two pods simultaneously [Slow]": " [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: tmpfs] Two pods mounting a local volume at the same time should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] PersistentVolumes-local [Volume type: tmpfs] Two pods mounting a local volume one after the other should be able to write from pod1 and read from pod2": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Projected combined should project all components that make up the projection API [Projection] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected configMap Should fail non-optional pod creation due to configMap object does not exist [Slow]": " [Suite:k8s]", - - "[sig-storage] Projected configMap Should fail non-optional pod creation due to the key in the configMap object does not exist [Slow]": " [Suite:k8s]", - - "[sig-storage] Projected configMap optional updates should be reflected in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable from pods in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable from pods in volume as non-root [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable from pods in volume as non-root with FSGroup [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable from pods in volume as non-root with defaultMode and fsGroup set [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable from pods in volume with defaultMode set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable from pods in volume with mappings [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable from pods in volume with mappings and Item mode set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable from pods in volume with mappings as non-root [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable from pods in volume with mappings as non-root with FSGroup [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Projected configMap should be consumable in multiple volumes in the same pod [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected configMap updates should be reflected in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should provide container's cpu limit [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should provide container's cpu request [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should provide container's memory limit [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should provide container's memory request [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should provide node allocatable (cpu) as default cpu limit if the limit is not set [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should provide node allocatable (memory) as default memory limit if the limit is not set [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should provide podname as non-root with fsgroup [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should provide podname as non-root with fsgroup and defaultMode [LinuxOnly]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should provide podname only [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should set DefaultMode on files [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should set mode on item file [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should update annotations on modification [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected downwardAPI should update labels on modification [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected secret Should fail non-optional pod creation due to secret object does not exist [Slow]": " [Suite:k8s]", - - "[sig-storage] Projected secret Should fail non-optional pod creation due to the key in the secret object does not exist [Slow]": " [Suite:k8s]", - - "[sig-storage] Projected secret optional updates should be reflected in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected secret should be able to mount in a volume regardless of a different secret existing with same name in different namespace [NodeConformance]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] Projected secret should be consumable from pods in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected secret should be consumable from pods in volume as non-root with defaultMode and fsGroup set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected secret should be consumable from pods in volume with defaultMode set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected secret should be consumable from pods in volume with mappings [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected secret should be consumable from pods in volume with mappings and Item Mode set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Projected secret should be consumable in multiple volumes in a pod [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Retroactive StorageClass Assignment should assign default StorageClass to PVCs retroactively [Disruptive] [Serial]": " [Suite:k8s]", - - "[sig-storage] Secrets Should fail non-optional pod creation due to secret object does not exist [Slow]": " [Suite:k8s]", - - "[sig-storage] Secrets Should fail non-optional pod creation due to the key in the secret object does not exist [Slow]": " [Suite:k8s]", - - "[sig-storage] Secrets optional updates should be reflected in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Secrets should be able to mount in a volume regardless of a different secret existing with same name in different namespace [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Secrets should be consumable from pods in volume [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Secrets should be consumable from pods in volume as non-root with defaultMode and fsGroup set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Secrets should be consumable from pods in volume with defaultMode set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Secrets should be consumable from pods in volume with mappings [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Secrets should be consumable from pods in volume with mappings and Item Mode set [LinuxOnly] [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Secrets should be consumable in multiple volumes in a pod [NodeConformance] [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Secrets should be immutable if `immutable` field is set [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] StaticPods [Feature:Kind] should run after kubelet stopped with CSI volume mounted [Disruptive] [Serial]": " [Suite:k8s]", - - "[sig-storage] StorageClasses CSI Conformance should run through the lifecycle of a StorageClass [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Subpath Atomic writer volumes should support subpaths with configmap pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Subpath Atomic writer volumes should support subpaths with configmap pod with mountPath of existing file [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Subpath Atomic writer volumes should support subpaths with downward pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Subpath Atomic writer volumes should support subpaths with projected pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Subpath Atomic writer volumes should support subpaths with secret pod [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] Subpath Container restart should verify that container can restart successfully after configmaps modified": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] VolumeAttachment Conformance should apply changes to a volumeattachment status [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] VolumeAttachment Conformance should run through the lifecycle of a VolumeAttachment [Conformance]": " [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]", - - "[sig-storage] VolumeAttributesClass [FeatureGate:VolumeAttributesClass] should run through the lifecycle of a VolumeAttributesClass": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-storage] [Disruptive] [LinuxOnly] NonGracefulNodeShutdown [NonGracefulNodeShutdown] pod that uses a persistent volume via gce pd driver should get immediately rescheduled to a different node after non graceful node shutdown ": " [Serial] [Suite:k8s]", - - "[sig-storage] [Feature:Flexvolumes] Detaching volumes should not work when mount is in progress [Slow]": " [Suite:k8s]", - - "[sig-storage] [Feature:Flexvolumes] Mounted flexvolume expand [Slow] Should verify mounted flex volumes can be resized": " [Suite:k8s]", - - "[sig-storage] [Feature:Flexvolumes] Mounted flexvolume volume expand [Slow] should be resizable when mounted": " [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics Ephemeral should create metrics for total number of volumes in A/D Controller": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics Ephemeral should create metrics for total time taken in volume operations in P/V Controller": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics Ephemeral should create prometheus metrics for volume provisioning and attach/detach": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics Ephemeral should create prometheus metrics for volume provisioning errors [Slow]": " [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics Ephemeral should create volume metrics in Volume Manager": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics Ephemeral should create volume metrics with the correct BlockMode PVC ref": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics Ephemeral should create volume metrics with the correct FilesystemMode PVC ref": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVC should create metrics for total number of volumes in A/D Controller": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVC should create metrics for total time taken in volume operations in P/V Controller": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVC should create prometheus metrics for volume provisioning and attach/detach": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVC should create prometheus metrics for volume provisioning errors [Slow]": " [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVC should create volume metrics in Volume Manager": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVC should create volume metrics with the correct BlockMode PVC ref": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVC should create volume metrics with the correct FilesystemMode PVC ref": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVController should create bound pv/pvc count metrics for pvc controller after creating both pv and pvc": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVController should create bound pv/pvc count metrics for pvc controller with volume attributes class dimension after creating both pv and pvc [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVController should create none metrics for pvc controller before creating any PV or PVC": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVController should create total pv count metrics for with plugin and volume mode labels after creating pv": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVController should create unbound pv count metrics for pvc controller after creating pv only": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVController should create unbound pvc count metrics for pvc controller after creating pvc only": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-storage] [Serial] Volume metrics PVController should create unbound pvc count metrics for pvc controller with volume attributes class dimension after creating pvc only [FeatureGate:VolumeAttributesClass] [Feature:VolumeAttributesClass]": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-windows] Hybrid cluster network for all supported CNIs should have stable networking for Linux and Windows pods": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] Hybrid cluster network for all supported CNIs should provide Internet connection and DNS for Windows containers [Feature:Networking-IPv4] [Feature:Networking-DNS]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] Hybrid cluster network for all supported CNIs should provide Internet connection for Linux containers [Feature:Networking-IPv4]": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] Services should be able to create a functioning NodePort service for Windows": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:GPUDevicePlugin] Device Plugin should be able to create a functioning device plugin for Windows": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:WindowsHostProcessContainers] [MinimumKubeletVersion:1.22] HostProcess containers container command path validation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:WindowsHostProcessContainers] [MinimumKubeletVersion:1.22] HostProcess containers container stats validation": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:WindowsHostProcessContainers] [MinimumKubeletVersion:1.22] HostProcess containers metrics should report count of started and failed to start HostProcess containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:WindowsHostProcessContainers] [MinimumKubeletVersion:1.22] HostProcess containers should run as a process on the host/node": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:WindowsHostProcessContainers] [MinimumKubeletVersion:1.22] HostProcess containers should run as localgroup accounts": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:WindowsHostProcessContainers] [MinimumKubeletVersion:1.22] HostProcess containers should support init containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:WindowsHostProcessContainers] [MinimumKubeletVersion:1.22] HostProcess containers should support querying api-server using in-cluster config": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:WindowsHostProcessContainers] [MinimumKubeletVersion:1.22] HostProcess containers should support various volume mount types": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:WindowsHyperVContainers] HyperV containers should start a hyperv isolated container": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Cpu Resources [Serial] Container limits should not be exceeded after waiting 2 minutes": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] DNS should support configurable pod DNS servers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Density [Serial] [Slow] create a batch of pods latency/resource should be within limit when create 10 pods with 0s interval": " [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Eviction [Serial] [Slow] [Disruptive] should evict a pod when a node experiences memory pressure": " [Suite:k8s]", - - "[sig-windows] [Feature:Windows] GMSA Full [Serial] [Slow] GMSA support can read and write file to remote SMB folder": " [Suite:k8s]", - - "[sig-windows] [Feature:Windows] GMSA Full [Serial] [Slow] GMSA support works end to end": " [Suite:k8s]", - - "[sig-windows] [Feature:Windows] GMSA Kubelet [Slow] kubelet GMSA support when creating a pod with correct GMSA credential specs passes the credential specs down to the Pod's containers": " [Suite:k8s]", - - "[sig-windows] [Feature:Windows] GracefulNodeShutdown [Serial] [Disruptive] [Slow] should be able to gracefully shutdown pods with various grace periods": " [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Kubelet-Stats Kubelet stats collection for Windows nodes when running 3 pods should return within 10 seconds": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Kubelet-Stats Kubelet stats collection for Windows nodes when windows is booted should return bootid within 10 seconds": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Kubelet-Stats [Serial] Kubelet stats collection for Windows nodes when running 10 pods should return within 10 seconds": " [Suite:openshift/conformance/serial] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Memory Limits [Serial] [Slow] Allocatable node memory should be equal to a calculated allocatable memory value": " [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Memory Limits [Serial] [Slow] attempt to deploy past allocatable memory limits should fail deployments of pods once there isn't enough memory": " [Suite:k8s]", - - "[sig-windows] [Feature:Windows] SecurityContext should be able create pods and run containers with a given username": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] SecurityContext should be able to create pod and run containers": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] SecurityContext should ignore Linux Specific SecurityContext if set": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] SecurityContext should not be able to create pods with containers running as CONTAINERADMINISTRATOR when runAsNonRoot is true": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] SecurityContext should not be able to create pods with containers running as ContainerAdministrator when runAsNonRoot is true": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] SecurityContext should not be able to create pods with unknown usernames at Container level": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] SecurityContext should not be able to create pods with unknown usernames at Pod level": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] SecurityContext should override SecurityContext username if set": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Windows volume mounts check volume mount permissions container should have readOnly permissions on emptyDir": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] Windows volume mounts check volume mount permissions container should have readOnly permissions on hostMapPath": " [Suite:openshift/conformance/parallel] [Suite:k8s]", - - "[sig-windows] [Feature:Windows] [Excluded:WindowsDocker] [MinimumKubeletVersion:1.22] RebootHost containers [Serial] [Disruptive] [Slow] should run as a reboot process on the host/node": " [Suite:k8s]", -} - -func init() { - ginkgo.GetSuite().SetAnnotateFn(func(name string, node types.TestSpec) { - if newLabels, ok := Annotations[name]; ok { - node.AppendText(newLabels) - } else { - panic(fmt.Sprintf("unable to find test %s", name)) - } - }) -} diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/rules.go b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/rules.go deleted file mode 100644 index 9ece42f8d3..0000000000 --- a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/rules.go +++ /dev/null @@ -1,37 +0,0 @@ -package annotate - -import ( - // ensure all the ginkgo tests are loaded - _ "k8s.io/kubernetes/openshift-hack/e2e" -) - -var ( - TestMaps = map[string][]string{ - // tests that must be run without competition - "[Serial]": { - `\[Disruptive\]`, - `\[Feature:Performance\]`, // requires isolation - - `Service endpoints latency`, // requires low latency - `Clean up pods on node`, // schedules up to max pods per node - `DynamicProvisioner should test that deleting a claim before the volume is provisioned deletes the volume`, // test is very disruptive to other tests - - `Should be able to support the 1\.7 Sample API Server using the current Aggregator`, // down apiservices break other clients today https://bugzilla.redhat.com/show_bug.cgi?id=1623195 - - `\[Feature:HPA\] Horizontal pod autoscaling \(scale resource: CPU\) \[sig-autoscaling\] ReplicationController light Should scale from 1 pod to 2 pods`, - - `should prevent Ingress creation if more than 1 IngressClass marked as default`, // https://bugzilla.redhat.com/show_bug.cgi?id=1822286 - - `\[sig-network\] IngressClass \[Feature:Ingress\] should set default value on new IngressClass`, //https://bugzilla.redhat.com/show_bug.cgi?id=1833583 - }, - } - - ExcludedTests = []string{ - `\[Disabled:`, - `\[Disruptive\]`, - `\[Skipped\]`, - `\[Slow\]`, - `\[Flaky\]`, - `\[Local\]`, - } -) diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/rules_test.go b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/rules_test.go deleted file mode 100644 index 6a413a2ef9..0000000000 --- a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/annotate/rules_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package annotate - -import ( - "testing" - - "github.com/onsi/ginkgo/v2/types" -) - -type testNode struct { - text string -} - -func (n *testNode) CodeLocations() []types.CodeLocation { - return []types.CodeLocation{{FileName: "k8s.io/kubernetes"}} -} - -func (n *testNode) Text() string { - return n.text -} - -func (n *testNode) AppendText(text string) { - n.text += text -} - -func (n *testNode) Labels() []string { - return nil -} - -func TestStockRules(t *testing.T) { - tests := []struct { - name string - - testName string - - expectedLabel string - expectedText string - }{ - { - name: "simple serial match", - testName: "[Serial] test", - expectedLabel: " [Suite:openshift/conformance/serial]", - expectedText: "[Serial] test [Suite:openshift/conformance/serial]", - }, - { - name: "don't tag skipped", - testName: `[Serial] example test [Skipped:gce]`, - expectedLabel: ` [Suite:openshift/conformance/serial]`, - expectedText: `[Serial] example test [Skipped:gce] [Suite:openshift/conformance/serial]`, // notice that this isn't categorized into any of our buckets - }, - { - name: "not skipped", - testName: `[sig-network] Networking Granular Checks: Pods should function for intra-pod communication: http [LinuxOnly] [NodeConformance] [Conformance]`, - expectedLabel: ` [Suite:openshift/conformance/parallel/minimal]`, - expectedText: `[sig-network] Networking Granular Checks: Pods should function for intra-pod communication: http [LinuxOnly] [NodeConformance] [Conformance] [Suite:openshift/conformance/parallel/minimal]`, - }, - { - name: "should skip localssd on gce", - testName: `[sig-storage] In-tree Volumes [Driver: local][LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted`, - expectedLabel: ` [Skipped:gce] [Suite:openshift/conformance/serial]`, - expectedText: `[sig-storage] In-tree Volumes [Driver: local][LocalVolumeType: gce-localssd-scsi-fs] [Serial] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [Skipped:gce] [Suite:openshift/conformance/serial]`, // notice that this isn't categorized into any of our buckets - }, - { - name: "should skip NetworkPolicy tests on multitenant", - testName: `should do something with NetworkPolicy`, - expectedLabel: ` [Suite:openshift/conformance/parallel]`, - expectedText: `should do something with NetworkPolicy [Suite:openshift/conformance/parallel]`, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - testRenamer := newGenerator(TestMaps) - testNode := &testNode{ - text: test.testName, - } - - testRenamer.generateRename(test.testName, testNode) - changed := testRenamer.output[test.testName] - - if e, a := test.expectedLabel, changed; e != a { - t.Error(a) - } - testRenamer = newRenamerFromGenerated(map[string]string{test.testName: test.expectedLabel}) - testRenamer.updateNodeText(test.testName, testNode) - - if e, a := test.expectedText, testNode.Text(); e != a { - t.Logf(e) - t.Error(a) - } - }) - } -} diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/include.go b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/include.go index e0b481a17f..465631dc9d 100644 --- a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/include.go +++ b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/include.go @@ -5,7 +5,6 @@ package e2e // k8s.io/kubernetes/test/e2e/e2e_test.go. It is intended to affect: // // - what is included in the k8s-e2e.test binary built from this package -// - the annotations generated by the annotate package import ( // define and freeze constants diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/kube_e2e_test.go b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/kube_e2e_test.go index de60ab2e27..afa37b052f 100644 --- a/deps/github.com/openshift/kubernetes/openshift-hack/e2e/kube_e2e_test.go +++ b/deps/github.com/openshift/kubernetes/openshift-hack/e2e/kube_e2e_test.go @@ -1,7 +1,5 @@ package e2e -//go:generate go run -mod vendor ./annotate/cmd -- ./annotate/generated/zz_generated.annotations.go - // This file duplicates most of test/e2e/e2e_test.go but limits the included // tests (via include.go) to tests that are relevant to openshift. @@ -112,9 +110,6 @@ func TestE2E(t *testing.T) { // In order to properly skip tests, we must add the labels that the OTE external binary supplies to the test name // This will then be used by Ginkgo to skip specific tests oteCmd := exec.Command("k8s-tests-ext", "list", "tests") - // We can't have OTE also add annotations to the spec names to map to labels, or they won't match the actual spec names - //TODO(sgoeddel): once annotation logic is removed, this can be as well - oteCmd.Env = append(oteCmd.Env, "OMIT_ANNOTATIONS=true") oteCmd.Stderr = os.Stderr output, err := oteCmd.Output() if err != nil { @@ -140,7 +135,7 @@ func TestE2E(t *testing.T) { } } else { // If the name isn't found in the mapping, it is because the test has been disabled via OTE - node.AppendText(" [Disabled:missing]") + node.AppendText(" [Disabled:removed]") } if strings.Contains(name, "Kubectl client Kubectl prune with applyset should apply and prune objects") { fmt.Printf("Trying to annotate %q\n", name) diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/images/hyperkube/Dockerfile.rhel b/deps/github.com/openshift/kubernetes/openshift-hack/images/hyperkube/Dockerfile.rhel index 45bdab6369..00c494e974 100644 --- a/deps/github.com/openshift/kubernetes/openshift-hack/images/hyperkube/Dockerfile.rhel +++ b/deps/github.com/openshift/kubernetes/openshift-hack/images/hyperkube/Dockerfile.rhel @@ -14,4 +14,4 @@ COPY --from=builder /tmp/build/* /usr/bin/ LABEL io.k8s.display-name="OpenShift Kubernetes Server Commands" \ io.k8s.description="OpenShift is a platform for developing, building, and deploying containerized applications." \ io.openshift.tags="openshift,hyperkube" \ - io.openshift.build.versions="kubernetes=1.34.1" \ No newline at end of file + io.openshift.build.versions="kubernetes=1.34.2" \ No newline at end of file diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/test-kubernetes-e2e.sh b/deps/github.com/openshift/kubernetes/openshift-hack/test-kubernetes-e2e.sh index 5157557d9d..c7a07270c6 100755 --- a/deps/github.com/openshift/kubernetes/openshift-hack/test-kubernetes-e2e.sh +++ b/deps/github.com/openshift/kubernetes/openshift-hack/test-kubernetes-e2e.sh @@ -29,7 +29,7 @@ NETWORK_SKIPS="\[Skipped:Network/OVNKubernetes\]|\[Feature:Networking-IPv6\]|\[F # Support serial and parallel test suites TEST_SUITE="${TEST_SUITE:-parallel}" -COMMON_SKIPS="\[Slow\]|\[Disruptive\]|\[Flaky\]|\[Disabled:.+\]|\[Skipped:${PLATFORM}\]|${NETWORK_SKIPS}" +COMMON_SKIPS="\[Slow\]|\[Disruptive\]|\[Flaky\]|\[Disabled:.+\]|\[Skipped:${PLATFORM}\]|\[DedicatedJob\]|${NETWORK_SKIPS}" # Skip tests for features that require a TechPreview cluster. TODO: Remove when the feature is enabled by default. COMMON_SKIPS="\[OCPFeatureGate:VolumeGroupSnapshot\]|\[Feature:OffByDefault\]|\[DRA\]|${COMMON_SKIPS}" diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/update-test-annotations.sh b/deps/github.com/openshift/kubernetes/openshift-hack/update-test-annotations.sh deleted file mode 100755 index 82aa9b36bb..0000000000 --- a/deps/github.com/openshift/kubernetes/openshift-hack/update-test-annotations.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. -source "${KUBE_ROOT}/hack/lib/init.sh" - -kube::golang::setup_env - -# Update e2e test annotations that indicate openshift compatibility -go generate -mod vendor ./openshift-hack/e2e diff --git a/deps/github.com/openshift/kubernetes/openshift-hack/verify-test-annotations.sh b/deps/github.com/openshift/kubernetes/openshift-hack/verify-test-annotations.sh deleted file mode 100755 index 1b04bb0d60..0000000000 --- a/deps/github.com/openshift/kubernetes/openshift-hack/verify-test-annotations.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o nounset -set -o pipefail - -KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. -source "${KUBE_ROOT}/hack/lib/init.sh" - -# Make sure that all packages that define k8s tests are properly imported -EXCLUDE_PACKAGES="\ -k8s.io/kubernetes/test/e2e/framework,\ -k8s.io/kubernetes/test/e2e/framework/debug/init,\ -k8s.io/kubernetes/test/e2e/framework/metrics/init,\ -k8s.io/kubernetes/test/e2e/framework/node/init,\ -k8s.io/kubernetes/test/e2e/framework/testfiles,\ -k8s.io/kubernetes/test/e2e/storage/external,\ -k8s.io/kubernetes/test/e2e/testing-manifests,\ -k8s.io/kubernetes/test/e2e/windows" - -GO111MODULE=on go run ./openshift-hack/cmd/go-imports-diff \ - -exclude "$EXCLUDE_PACKAGES" \ - test/e2e/e2e_test.go \ - openshift-hack/e2e/include.go - -# Verify e2e test annotations that indicate openshift compatibility -"${KUBE_ROOT}"/hack/update-test-annotations.sh -git diff --quiet "${KUBE_ROOT}/openshift-hack/e2e/annotate/generated/" diff --git a/deps/github.com/openshift/kubernetes/pkg/api/service/warnings.go b/deps/github.com/openshift/kubernetes/pkg/api/service/warnings.go index 41e69704bc..92fef3afa9 100644 --- a/deps/github.com/openshift/kubernetes/pkg/api/service/warnings.go +++ b/deps/github.com/openshift/kubernetes/pkg/api/service/warnings.go @@ -48,7 +48,7 @@ func GetWarningsForService(service, oldService *api.Service) []string { if len(service.Spec.ExternalIPs) > 0 { warnings = append(warnings, "spec.externalIPs is ignored for headless services") } - if service.Spec.SessionAffinity != "" { + if service.Spec.SessionAffinity != api.ServiceAffinityNone { warnings = append(warnings, "spec.SessionAffinity is ignored for headless services") } } diff --git a/deps/github.com/openshift/kubernetes/pkg/api/service/warnings_test.go b/deps/github.com/openshift/kubernetes/pkg/api/service/warnings_test.go index 763d16f101..dcf2a2ade1 100644 --- a/deps/github.com/openshift/kubernetes/pkg/api/service/warnings_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/api/service/warnings_test.go @@ -62,6 +62,7 @@ func TestGetWarningsForService(t *testing.T) { s.Spec.Type = api.ServiceTypeClusterIP s.Spec.ClusterIP = api.ClusterIPNone s.Spec.LoadBalancerIP = "1.2.3.4" + s.Spec.SessionAffinity = api.ServiceAffinityNone // default value }, numWarnings: 1, }, { @@ -70,10 +71,11 @@ func TestGetWarningsForService(t *testing.T) { s.Spec.Type = api.ServiceTypeClusterIP s.Spec.ClusterIP = api.ClusterIPNone s.Spec.ExternalIPs = []string{"1.2.3.4"} + s.Spec.SessionAffinity = api.ServiceAffinityNone // default value }, numWarnings: 1, }, { - name: "SessionAffinity set when headless service", + name: "SessionAffinity Client IP set when headless service", tweakSvc: func(s *api.Service) { s.Spec.Type = api.ServiceTypeClusterIP s.Spec.ClusterIP = api.ClusterIPNone @@ -81,16 +83,25 @@ func TestGetWarningsForService(t *testing.T) { }, numWarnings: 1, }, { - name: "ExternalIPs, LoadBalancerIP and SessionAffinity set when headless service", + name: "SessionAffinity None set when headless service", tweakSvc: func(s *api.Service) { s.Spec.Type = api.ServiceTypeClusterIP s.Spec.ClusterIP = api.ClusterIPNone - s.Spec.ExternalIPs = []string{"1.2.3.4"} - s.Spec.LoadBalancerIP = "1.2.3.4" - s.Spec.SessionAffinity = api.ServiceAffinityClientIP + s.Spec.SessionAffinity = api.ServiceAffinityNone }, - numWarnings: 3, - }} + numWarnings: 0, + }, + { + name: "ExternalIPs, LoadBalancerIP and SessionAffinity set when headless service", + tweakSvc: func(s *api.Service) { + s.Spec.Type = api.ServiceTypeClusterIP + s.Spec.ClusterIP = api.ClusterIPNone + s.Spec.ExternalIPs = []string{"1.2.3.4"} + s.Spec.LoadBalancerIP = "1.2.3.4" + s.Spec.SessionAffinity = api.ServiceAffinityClientIP + }, + numWarnings: 3, + }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { diff --git a/deps/github.com/openshift/kubernetes/pkg/apis/batch/validation/validation.go b/deps/github.com/openshift/kubernetes/pkg/apis/batch/validation/validation.go index 5203c837ec..17ffbbe4b4 100644 --- a/deps/github.com/openshift/kubernetes/pkg/apis/batch/validation/validation.go +++ b/deps/github.com/openshift/kubernetes/pkg/apis/batch/validation/validation.go @@ -913,6 +913,15 @@ func IsConditionTrue(list []batch.JobCondition, cType batch.JobConditionType) bo return false } +func IsConditionFalse(list []batch.JobCondition, cType batch.JobConditionType) bool { + for _, c := range list { + if c.Type == cType && c.Status == api.ConditionFalse { + return true + } + } + return false +} + func validateFailedIndexesNotOverlapCompleted(completedIndexesStr string, failedIndexesStr string, completions int32) error { if len(completedIndexesStr) == 0 || len(failedIndexesStr) == 0 { return nil diff --git a/deps/github.com/openshift/kubernetes/pkg/apis/certificates/v1beta1/defaults_test.go b/deps/github.com/openshift/kubernetes/pkg/apis/certificates/v1beta1/defaults_test.go index fcfeef26ed..b2bf13f6fd 100644 --- a/deps/github.com/openshift/kubernetes/pkg/apis/certificates/v1beta1/defaults_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/apis/certificates/v1beta1/defaults_test.go @@ -86,7 +86,7 @@ func TestIsKubeletServingCSR(t *testing.T) { exp: false, }, "does not default to kubelet-serving if it specifies an emailAddress SAN": { - req: newCSR(kubeletServerPEMOptions, pemOptions{emailAddresses: []string{"something"}}), + req: newCSR(kubeletServerPEMOptions, pemOptions{emailAddresses: []string{"something@example.com"}}), usages: kubeletServerUsages, exp: false, }, @@ -131,7 +131,7 @@ func TestIsKubeletClientCSR(t *testing.T) { exp: false, }, "does not default to kube-apiserver-client-kubelet if an emailAddress is set": { - req: newCSR(kubeletClientPEMOptions, pemOptions{emailAddresses: []string{"something"}}), + req: newCSR(kubeletClientPEMOptions, pemOptions{emailAddresses: []string{"something@example.com"}}), usages: kubeletClientUsages, exp: false, }, @@ -326,7 +326,7 @@ func TestSetDefaults_CertificateSigningRequestSpec_KubeletServing(t *testing.T) }, "does not default to kubelet-serving if it specifies an emailAddress SAN": { csr: capi.CertificateSigningRequestSpec{ - Request: csrWithOpts(kubeletServerPEMOptions, pemOptions{emailAddresses: []string{"something"}}), + Request: csrWithOpts(kubeletServerPEMOptions, pemOptions{emailAddresses: []string{"something@example.com"}}), Usages: kubeletServerUsages, Username: kubeletServerPEMOptions.cn, }, diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/controller_utils.go b/deps/github.com/openshift/kubernetes/pkg/controller/controller_utils.go index c847ad4f22..c6c3b31f0d 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/controller_utils.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/controller_utils.go @@ -89,12 +89,9 @@ const ( // PodNodeNameKeyIndex is the name of the index used by PodInformer to index pods by their node name. PodNodeNameKeyIndex = "spec.nodeName" - // OrphanPodIndexKey is used to index all Orphan pods to this key - OrphanPodIndexKey = "_ORPHAN_POD" - - // podControllerUIDIndex is the name for the Pod store's index function, - // which is to index by pods's controllerUID. - PodControllerUIDIndex = "podControllerUID" + // PodControllerIndex is the name for the Pod store's index function, + // which indexes by the key returned from PodControllerIndexKey. + PodControllerIndex = "podController" ) var UpdateTaintBackoff = wait.Backoff{ @@ -1139,43 +1136,59 @@ func AddPodNodeNameIndexer(podInformer cache.SharedIndexInformer) error { }) } -// OrphanPodIndexKeyForNamespace returns the orphan pod index key for a specific namespace. -func OrphanPodIndexKeyForNamespace(namespace string) string { - return OrphanPodIndexKey + "/" + namespace +// PodControllerIndexKey returns the index key to locate pods with the specified controller ownerReference. +// If ownerReference is nil, the returned key locates pods in the namespace without a controller ownerReference. +func PodControllerIndexKey(namespace string, ownerReference *metav1.OwnerReference) string { + if ownerReference == nil { + return namespace + } + return namespace + "/" + ownerReference.Kind + "/" + ownerReference.Name + "/" + string(ownerReference.UID) } -// AddPodControllerUIDIndexer adds an indexer for Pod's controllerRef.UID to the given PodInformer. +// AddPodControllerIndexer adds an indexer for Pod's controllerRef.UID to the given PodInformer. // This indexer is used to efficiently look up pods by their ControllerRef.UID -func AddPodControllerUIDIndexer(podInformer cache.SharedIndexInformer) error { - if _, exists := podInformer.GetIndexer().GetIndexers()[PodControllerUIDIndex]; exists { +func AddPodControllerIndexer(podInformer cache.SharedIndexInformer) error { + if _, exists := podInformer.GetIndexer().GetIndexers()[PodControllerIndex]; exists { // indexer already exists, do nothing return nil } return podInformer.AddIndexers(cache.Indexers{ - PodControllerUIDIndex: func(obj interface{}) ([]string, error) { + PodControllerIndex: func(obj interface{}) ([]string, error) { pod, ok := obj.(*v1.Pod) if !ok { return nil, nil } - // Get the ControllerRef of the Pod to check if it's managed by a controller - if ref := metav1.GetControllerOf(pod); ref != nil { - return []string{string(ref.UID)}, nil - } - // If the Pod has no controller (i.e., it's orphaned), index it with the OrphanPodIndexKeyForNamespace - // This helps identify orphan pods for reconciliation and adoption by controllers - return []string{OrphanPodIndexKeyForNamespace(pod.Namespace)}, nil + // Get the ControllerRef of the Pod to check if it's managed by a controller. + // Index with a non-nil controller (indicating an owned pod) or a nil controller (indicating an orphan pod). + return []string{PodControllerIndexKey(pod.Namespace, metav1.GetControllerOf(pod))}, nil }, }) } // FilterPodsByOwner gets the Pods managed by an owner or orphan Pods in the owner's namespace -func FilterPodsByOwner(podIndexer cache.Indexer, owner *metav1.ObjectMeta) ([]*v1.Pod, error) { +func FilterPodsByOwner(podIndexer cache.Indexer, owner *metav1.ObjectMeta, ownerKind string, includeOrphanedPods bool) ([]*v1.Pod, error) { result := []*v1.Pod{} - // Iterate over two keys: - // - the UID of the owner, which identifies Pods that are controlled by the owner - // - the OrphanPodIndexKey, which identifies orphaned Pods in the owner's namespace and might be adopted by the owner later - for _, key := range []string{string(owner.UID), OrphanPodIndexKeyForNamespace(owner.Namespace)} { - pods, err := podIndexer.ByIndex(PodControllerUIDIndex, key) + + if len(owner.Namespace) == 0 { + return nil, fmt.Errorf("no owner namespace provided") + } + if len(owner.Name) == 0 { + return nil, fmt.Errorf("no owner name provided") + } + if len(owner.UID) == 0 { + return nil, fmt.Errorf("no owner uid provided") + } + if len(ownerKind) == 0 { + return nil, fmt.Errorf("no owner kind provided") + } + // Always include the owner key, which identifies Pods that are controlled by the owner + keys := []string{PodControllerIndexKey(owner.Namespace, &metav1.OwnerReference{Name: owner.Name, Kind: ownerKind, UID: owner.UID})} + if includeOrphanedPods { + // Optionally include the unowned key, which identifies orphaned Pods in the owner's namespace and might be adopted by the owner later + keys = append(keys, PodControllerIndexKey(owner.Namespace, nil)) + } + for _, key := range keys { + pods, err := podIndexer.ByIndex(PodControllerIndex, key) if err != nil { return nil, err } diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/controller_utils_test.go b/deps/github.com/openshift/kubernetes/pkg/controller/controller_utils_test.go index 819d44be1e..20fb805641 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/controller_utils_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/controller_utils_test.go @@ -1612,27 +1612,37 @@ func TestFilterPodsByOwner(t *testing.T) { return pod } + ownerKind := "OwnerKind" + ownerName := "ownerName" cases := map[string]struct { owner *metav1.ObjectMeta + ownedOnly bool allPods []*v1.Pod wantPodsKeys sets.Set[string] }{ "multiple Pods, some are owned by the owner": { owner: &metav1.ObjectMeta{ Namespace: "ns1", + Name: ownerName, UID: "abc", }, allPods: []*v1.Pod{ newPod("a", "ns1", &metav1.OwnerReference{ UID: "abc", + Kind: ownerKind, + Name: ownerName, Controller: ptr.To(true), }), newPod("b", "ns1", &metav1.OwnerReference{ UID: "def", + Kind: ownerKind, + Name: ownerName, Controller: ptr.To(true), }), newPod("c", "ns1", &metav1.OwnerReference{ UID: "abc", + Kind: ownerKind, + Name: ownerName, Controller: ptr.To(true), }), }, @@ -1641,6 +1651,8 @@ func TestFilterPodsByOwner(t *testing.T) { "orphan Pods in multiple namespaces": { owner: &metav1.ObjectMeta{ Namespace: "ns1", + Name: ownerName, + UID: "abc", }, allPods: []*v1.Pod{ newPod("a", "ns1", nil), @@ -1651,6 +1663,7 @@ func TestFilterPodsByOwner(t *testing.T) { "owned Pods and orphan Pods in the owner's namespace": { owner: &metav1.ObjectMeta{ Namespace: "ns1", + Name: ownerName, UID: "abc", }, allPods: []*v1.Pod{ @@ -1658,11 +1671,62 @@ func TestFilterPodsByOwner(t *testing.T) { newPod("b", "ns2", nil), newPod("c", "ns1", &metav1.OwnerReference{ UID: "abc", + Kind: ownerKind, + Name: ownerName, Controller: ptr.To(true), }), }, wantPodsKeys: sets.New("ns1/a", "ns1/c"), }, + "exclude orphan pods, pods in mismatched ns,uid,kind,name,controller": { + owner: &metav1.ObjectMeta{ + Namespace: "ns1", + Name: ownerName, + UID: "abc", + }, + allPods: []*v1.Pod{ + newPod("a", "ns1", nil), + newPod("other-ns-orphan", "ns2", nil), + newPod("other-ns-owned", "ns2", &metav1.OwnerReference{ + UID: "abc", + Kind: ownerKind, + Name: ownerName, + Controller: ptr.To(true), + }), + newPod("c", "ns1", &metav1.OwnerReference{ + UID: "abc", + Kind: ownerKind, + Name: ownerName, + Controller: ptr.To(true), + }), + newPod("other-uid", "ns1", &metav1.OwnerReference{ + UID: "other-uid", + Kind: ownerKind, + Name: ownerName, + Controller: ptr.To(true), + }), + newPod("other-kind", "ns1", &metav1.OwnerReference{ + UID: "abc", + Kind: "OtherKind", + Name: ownerName, + Controller: ptr.To(true), + }), + newPod("other-name", "ns1", &metav1.OwnerReference{ + UID: "abc", + Kind: ownerKind, + Name: "otherName", + Controller: ptr.To(true), + }), + newPod("non-controller", "ns1", &metav1.OwnerReference{ + UID: "abc", + Kind: ownerKind, + Name: ownerName, + Controller: ptr.To(false), + }), + }, + ownedOnly: true, + wantPodsKeys: sets.New("ns1/c"), + }, } for name, tc := range cases { t.Run(name, func(t *testing.T) { @@ -1670,7 +1734,7 @@ func TestFilterPodsByOwner(t *testing.T) { sharedInformers := informers.NewSharedInformerFactory(fakeClient, 0) podInformer := sharedInformers.Core().V1().Pods() - err := AddPodControllerUIDIndexer(podInformer.Informer()) + err := AddPodControllerIndexer(podInformer.Informer()) if err != nil { t.Fatalf("failed to register indexer: %v", err) } @@ -1680,7 +1744,10 @@ func TestFilterPodsByOwner(t *testing.T) { t.Fatalf("failed adding Pod to indexer: %v", err) } } - gotPods, _ := FilterPodsByOwner(podIndexer, tc.owner) + gotPods, err := FilterPodsByOwner(podIndexer, tc.owner, ownerKind, !tc.ownedOnly) + if err != nil { + t.Fatal(err) + } gotPodKeys := sets.New[string]() for _, pod := range gotPods { gotPodKeys.Insert(pod.Namespace + "/" + pod.Name) diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/daemon/daemon_controller.go b/deps/github.com/openshift/kubernetes/pkg/controller/daemon/daemon_controller.go index 4965cb75c8..0ab4290ae5 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/daemon/daemon_controller.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/daemon/daemon_controller.go @@ -223,7 +223,7 @@ func NewDaemonSetsController( dsc.podLister = podInformer.Lister() dsc.podStoreSynced = podInformer.Informer().HasSynced controller.AddPodNodeNameIndexer(podInformer.Informer()) - controller.AddPodControllerUIDIndexer(podInformer.Informer()) + controller.AddPodControllerIndexer(podInformer.Informer()) dsc.podIndexer = podInformer.Informer().GetIndexer() nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -710,7 +710,7 @@ func (dsc *DaemonSetsController) getDaemonPods(ctx context.Context, ds *apps.Dae return nil, err } // List all pods indexed to DS UID and Orphan pods - pods, err := controller.FilterPodsByOwner(dsc.podIndexer, &ds.ObjectMeta) + pods, err := controller.FilterPodsByOwner(dsc.podIndexer, &ds.ObjectMeta, "DaemonSet", true) if err != nil { return nil, err } diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/history/controller_history.go b/deps/github.com/openshift/kubernetes/pkg/controller/history/controller_history.go index 19ae0999af..9f4f82223a 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/history/controller_history.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/history/controller_history.go @@ -111,27 +111,9 @@ func SortControllerRevisions(revisions []*apps.ControllerRevision) { // EqualRevision returns true if lhs and rhs are either both nil, or both point to non-nil ControllerRevisions that // contain semantically equivalent data. Otherwise this method returns false. func EqualRevision(lhs *apps.ControllerRevision, rhs *apps.ControllerRevision) bool { - var lhsHash, rhsHash *uint32 if lhs == nil || rhs == nil { return lhs == rhs } - if hs, found := lhs.Labels[ControllerRevisionHashLabel]; found { - hash, err := strconv.ParseInt(hs, 10, 32) - if err == nil { - lhsHash = new(uint32) - *lhsHash = uint32(hash) - } - } - if hs, found := rhs.Labels[ControllerRevisionHashLabel]; found { - hash, err := strconv.ParseInt(hs, 10, 32) - if err == nil { - rhsHash = new(uint32) - *rhsHash = uint32(hash) - } - } - if lhsHash != nil && rhsHash != nil && *lhsHash != *rhsHash { - return false - } return bytes.Equal(lhs.Data.Raw, rhs.Data.Raw) && apiequality.Semantic.DeepEqual(lhs.Data.Object, rhs.Data.Object) } diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/job/job_controller.go b/deps/github.com/openshift/kubernetes/pkg/controller/job/job_controller.go index 6a74ee0bd5..4de4bdc302 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/job/job_controller.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/job/job_controller.go @@ -226,7 +226,7 @@ func newControllerWithClock(ctx context.Context, podInformer coreinformers.PodIn jm.podStore = podInformer.Lister() jm.podStoreSynced = podInformer.Informer().HasSynced - err := controller.AddPodControllerUIDIndexer(podInformer.Informer()) + err := controller.AddPodControllerIndexer(podInformer.Informer()) if err != nil { return nil, fmt.Errorf("adding Pod controller UID indexer: %w", err) } @@ -769,7 +769,7 @@ func (jm *Controller) getPodsForJob(ctx context.Context, j *batch.Job) ([]*v1.Po } // list all pods managed by this Job using the pod indexer - pods, err := controller.FilterPodsByOwner(jm.podIndexer, &j.ObjectMeta) + pods, err := controller.FilterPodsByOwner(jm.podIndexer, &j.ObjectMeta, "Job", true) if err != nil { return nil, err } diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/job/job_controller_test.go b/deps/github.com/openshift/kubernetes/pkg/controller/job/job_controller_test.go index 891feef67a..b2970f9414 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/job/job_controller_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/job/job_controller_test.go @@ -28,6 +28,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + batch "k8s.io/api/batch/v1" v1 "k8s.io/api/core/v1" apiequality "k8s.io/apimachinery/pkg/api/equality" @@ -2949,6 +2950,7 @@ func TestSyncJobWhenManagedBy(t *testing.T) { TypeMeta: metav1.TypeMeta{Kind: "Job"}, ObjectMeta: metav1.ObjectMeta{ Name: "foobar", + UID: "foobaruid", Namespace: metav1.NamespaceDefault, }, Spec: batch.JobSpec{ diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/replicaset/replica_set.go b/deps/github.com/openshift/kubernetes/pkg/controller/replicaset/replica_set.go index 8934bd4605..204f4c46a6 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/replicaset/replica_set.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/replicaset/replica_set.go @@ -220,7 +220,7 @@ func NewBaseController(logger klog.Logger, rsInformer appsinformers.ReplicaSetIn }) rsc.podLister = podInformer.Lister() rsc.podListerSynced = podInformer.Informer().HasSynced - controller.AddPodControllerUIDIndexer(podInformer.Informer()) //nolint:errcheck + controller.AddPodControllerIndexer(podInformer.Informer()) //nolint:errcheck rsc.podIndexer = podInformer.Informer().GetIndexer() rsc.syncHandler = rsc.syncReplicaSet @@ -728,7 +728,7 @@ func (rsc *ReplicaSetController) syncReplicaSet(ctx context.Context, key string) } // List all pods indexed to RS UID and Orphan pods - allRSPods, err := controller.FilterPodsByOwner(rsc.podIndexer, &rs.ObjectMeta) + allRSPods, err := controller.FilterPodsByOwner(rsc.podIndexer, &rs.ObjectMeta, rsc.Kind, true) if err != nil { return err } diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set.go b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set.go index 36e49ca084..007766df25 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set.go @@ -131,7 +131,7 @@ func NewStatefulSetController( }) ssc.podLister = podInformer.Lister() ssc.podListerSynced = podInformer.Informer().HasSynced - controller.AddPodControllerUIDIndexer(podInformer.Informer()) + controller.AddPodControllerIndexer(podInformer.Informer()) ssc.podIndexer = podInformer.Informer().GetIndexer() setInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ @@ -312,7 +312,7 @@ func (ssc *StatefulSetController) deletePod(logger klog.Logger, obj interface{}) // NOTE: Returned Pods are pointers to objects from the cache. // If you need to modify one, you need to copy it first. func (ssc *StatefulSetController) getPodsForStatefulSet(ctx context.Context, set *apps.StatefulSet, selector labels.Selector) ([]*v1.Pod, error) { - podsForSts, err := controller.FilterPodsByOwner(ssc.podIndexer, &set.ObjectMeta) + podsForSts, err := controller.FilterPodsByOwner(ssc.podIndexer, &set.ObjectMeta, "StatefulSet", true) if err != nil { return nil, err } diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_compatibility_test.go b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_compatibility_test.go new file mode 100644 index 0000000000..ce3d3dcb1b --- /dev/null +++ b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_compatibility_test.go @@ -0,0 +1,149 @@ +/* +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 statefulset + +import ( + "os" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "sigs.k8s.io/json" + + appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/fake" + "k8s.io/kubernetes/pkg/api/legacyscheme" +) + +func TestStatefulSetCompatibility(t *testing.T) { + set133 := &appsv1.StatefulSet{} + set134 := &appsv1.StatefulSet{} + rev133 := &appsv1.ControllerRevision{} + rev134 := &appsv1.ControllerRevision{} + load(t, "compatibility_set_1.33.0.json", set133) + load(t, "compatibility_set_1.34.0.json", set134) + load(t, "compatibility_revision_1.33.0.json", rev133) + load(t, "compatibility_revision_1.34.0.json", rev134) + + testcases := []struct { + name string + set *appsv1.StatefulSet + revisions []*appsv1.ControllerRevision + }{ + { + name: "1.33 set, 1.33 rev", + set: set133.DeepCopy(), + revisions: []*appsv1.ControllerRevision{rev133.DeepCopy()}, + }, + { + name: "1.34 set, 1.34 rev", + set: set134.DeepCopy(), + revisions: []*appsv1.ControllerRevision{rev134.DeepCopy()}, + }, + { + name: "1.34 set, 1.33+1.34 rev", + set: set134.DeepCopy(), + revisions: []*appsv1.ControllerRevision{rev133.DeepCopy(), rev134.DeepCopy()}, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + latestRev := tc.revisions[len(tc.revisions)-1] + client := fake.NewClientset(tc.set) + _, _, ssc := setupController(client) + currentRev, updateRev, _, err := ssc.(*defaultStatefulSetControl).getStatefulSetRevisions(tc.set, tc.revisions) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(currentRev, latestRev) { + t.Fatalf("expected no change from latestRev, got %s", cmp.Diff(latestRev, currentRev)) + } + if !reflect.DeepEqual(updateRev, latestRev) { + t.Fatalf("expected no change from latestRev, got %s", cmp.Diff(latestRev, updateRev)) + } + }) + } +} + +func BenchmarkStatefulSetCompatibility(b *testing.B) { + set133 := &appsv1.StatefulSet{} + set134 := &appsv1.StatefulSet{} + rev133 := &appsv1.ControllerRevision{} + rev134 := &appsv1.ControllerRevision{} + load(b, "compatibility_set_1.33.0.json", set133) + load(b, "compatibility_set_1.34.0.json", set134) + load(b, "compatibility_revision_1.33.0.json", rev133) + load(b, "compatibility_revision_1.34.0.json", rev134) + + testcases := []struct { + name string + set *appsv1.StatefulSet + revisions []*appsv1.ControllerRevision + }{ + { + name: "1.33 set, 1.33 rev", + set: set133.DeepCopy(), + revisions: []*appsv1.ControllerRevision{rev133.DeepCopy()}, + }, + { + name: "1.34 set, 1.34 rev", + set: set134.DeepCopy(), + revisions: []*appsv1.ControllerRevision{rev134.DeepCopy()}, + }, + { + name: "1.34 set, 1.33+1.34 rev", + set: set134.DeepCopy(), + revisions: []*appsv1.ControllerRevision{rev133.DeepCopy(), rev134.DeepCopy()}, + }, + } + + for _, tc := range testcases { + b.Run(tc.name, func(b *testing.B) { + latestRev := tc.revisions[len(tc.revisions)-1] + client := fake.NewClientset(tc.set) + _, _, ssc := setupController(client) + for i := 0; i < b.N; i++ { + currentRev, updateRev, _, err := ssc.(*defaultStatefulSetControl).getStatefulSetRevisions(tc.set, tc.revisions) + if err != nil { + b.Fatal(err) + } + if !reflect.DeepEqual(currentRev, latestRev) { + b.Fatalf("expected no change from latestRev, got %s", cmp.Diff(latestRev, currentRev)) + } + if !reflect.DeepEqual(updateRev, latestRev) { + b.Fatalf("expected no change from latestRev, got %s", cmp.Diff(latestRev, updateRev)) + } + } + }) + } +} + +func load(t testing.TB, filename string, object runtime.Object) { + data, err := os.ReadFile("testdata/" + filename) + if err != nil { + t.Fatal(err) + } + if strictErrs, err := json.UnmarshalStrict(data, object); err != nil { + t.Fatal(err) + } else if len(strictErrs) > 0 { + t.Fatal(strictErrs) + } + // apply defaulting just as if it was read from etcd + legacyscheme.Scheme.Default(object) +} diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_control.go b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_control.go index 7d4f4990ba..78dd40081e 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_control.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_control.go @@ -21,13 +21,17 @@ import ( "sort" "sync" + "k8s.io/klog/v2" + "k8s.io/utils/lru" + apps "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/klog/v2" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/controller/history" "k8s.io/kubernetes/pkg/features" ) @@ -61,13 +65,15 @@ func NewDefaultStatefulSetControl( podControl *StatefulPodControl, statusUpdater StatefulSetStatusUpdaterInterface, controllerHistory history.Interface) StatefulSetControlInterface { - return &defaultStatefulSetControl{podControl, statusUpdater, controllerHistory} + return &defaultStatefulSetControl{podControl, statusUpdater, controllerHistory, lru.New(maxRevisionEqualityCacheEntries)} } type defaultStatefulSetControl struct { podControl *StatefulPodControl statusUpdater StatefulSetStatusUpdaterInterface controllerHistory history.Interface + + revisionEqualityCache *lru.Cache } // UpdateStatefulSet executes the core logic loop for a stateful set, applying the predictable and @@ -207,6 +213,49 @@ func (ssc *defaultStatefulSetControl) truncateHistory( return nil } +// maxRevisionEqualityCacheEntries is the size of the memory cache for equal set/controllerrevisions. +// Allowing up to 10,000 entries takes ~1MB. Each entry consumes up to ~111 bytes: +// - 40 bytes for the cache key (revisionEqualityKey{}) +// - 16 for the cache value (interface{} --> struct{}{}) +// - 36 bytes for the setUID string +// - 19 bytes for the revisionResourceVersion string +const maxRevisionEqualityCacheEntries = 10_000 + +// revisionEqualityKey is the cache key for remembering a particular revision RV +// is equal to the revision that results from a particular set UID at a particular set generation. +type revisionEqualityKey struct { + setUID types.UID + setGeneration int64 + revisionResourceVersion string +} + +// setMatchesLatestExistingRevision returns true if the set/proposedRevision already matches what would be produced from restoring latestExistingRevision. +func setMatchesLatestExistingRevision(set *apps.StatefulSet, proposedRevision *apps.ControllerRevision, latestExistingRevision *apps.ControllerRevision, memory *lru.Cache) bool { + if !utilfeature.DefaultFeatureGate.Enabled(features.StatefulSetSemanticRevisionComparison) { + return false + } + equalityCacheKey := revisionEqualityKey{setUID: set.UID, setGeneration: set.Generation, revisionResourceVersion: latestExistingRevision.ResourceVersion} + if _, ok := memory.Get(equalityCacheKey); ok { + return true + } + // see if reverting to the latest existing revision would produce the same thing as proposedRevision + latestSet, err := ApplyRevision(set, latestExistingRevision) + if err != nil { + return false + } + legacyscheme.Scheme.Default(latestSet) + reconstructedLatestRevision, err := newRevision(latestSet, -1, nil) + if err != nil { + return false + } + // if they match, cache this combination of set(uid,generation)+revision(resourceVersion) to minimize expensive comparisons in steady state + if history.EqualRevision(proposedRevision, reconstructedLatestRevision) { + memory.Add(equalityCacheKey, struct{}{}) + return true + } + return false +} + // getStatefulSetRevisions returns the current and update ControllerRevisions for set. It also // returns a collision count that records the number of name collisions set saw when creating // new ControllerRevisions. This count is incremented on every name collision and is used in @@ -250,6 +299,9 @@ func (ssc *defaultStatefulSetControl) getStatefulSetRevisions( if err != nil { return nil, nil, collisionCount, err } + } else if revisionCount > 0 && setMatchesLatestExistingRevision(set, updateRevision, revisions[revisionCount-1], ssc.revisionEqualityCache) { + // the update revision has not changed + updateRevision = revisions[revisionCount-1] } else { //if there is no equivalent revision we create a new one updateRevision, err = ssc.controllerHistory.CreateControllerRevision(set, updateRevision, &collisionCount) diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_control_test.go b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_control_test.go index 897ec9c297..a1c6356f52 100644 --- a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_control_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/stateful_set_control_test.go @@ -31,6 +31,7 @@ import ( "testing" "time" + "k8s.io/utils/lru" "k8s.io/utils/ptr" apps "k8s.io/api/apps/v1" @@ -883,7 +884,7 @@ func TestStatefulSetControl_getSetRevisions(t *testing.T) { informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc()) spc := NewStatefulPodControlFromManager(newFakeObjectManager(informerFactory), &noopRecorder{}) ssu := newFakeStatefulSetStatusUpdater(informerFactory.Apps().V1().StatefulSets()) - ssc := defaultStatefulSetControl{spc, ssu, history.NewFakeHistory(informerFactory.Apps().V1().ControllerRevisions())} + ssc := defaultStatefulSetControl{spc, ssu, history.NewFakeHistory(informerFactory.Apps().V1().ControllerRevisions()), lru.New(maxRevisionEqualityCacheEntries)} stop := make(chan struct{}) defer close(stop) diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_revision_1.33.0.json b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_revision_1.33.0.json new file mode 100644 index 0000000000..0b874adf4c --- /dev/null +++ b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_revision_1.33.0.json @@ -0,0 +1,25 @@ +{ + "apiVersion":"apps/v1", + "kind":"ControllerRevision", + "metadata":{ + "creationTimestamp":"2025-10-31T18:19:02Z", + "labels":{ + "app":"foo", + "controller.kubernetes.io/hash":"c77f6d978" + }, + "name":"test-c77f6d978", + "namespace":"default", + "ownerReferences":[{ + "apiVersion":"apps/v1", + "blockOwnerDeletion":true, + "controller":true, + "kind":"StatefulSet", + "name":"test", + "uid":"ec335e25-1045-4216-8634-50cfbe05f3d6" + }], + "resourceVersion":"2209", + "uid":"af6e1945-ed14-4d1a-b420-813aa683a0fd" + }, + "data":{"spec":{"template":{"$patch":"replace","metadata":{"annotations":{"test":"value"},"creationTimestamp":null,"labels":{"app":"foo"}},"spec":{"containers":[{"image":"test","imagePullPolicy":"Always","name":"test","resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}}}, + "revision":1 +} diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_revision_1.34.0.json b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_revision_1.34.0.json new file mode 100644 index 0000000000..085eea4da0 --- /dev/null +++ b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_revision_1.34.0.json @@ -0,0 +1,25 @@ +{ + "apiVersion":"apps/v1", + "kind":"ControllerRevision", + "metadata":{ + "creationTimestamp":"2025-11-03T19:46:23Z", + "labels":{ + "app":"foo", + "controller.kubernetes.io/hash":"776999688b" + }, + "name":"test-776999688b", + "namespace":"default", + "ownerReferences":[{ + "apiVersion":"apps/v1", + "blockOwnerDeletion":true, + "controller":true, + "kind":"StatefulSet", + "name":"test", + "uid":"ec335e25-1045-4216-8634-50cfbe05f3d6" + }], + "resourceVersion":"16318", + "uid":"47df387b-5f17-40b6-9964-4c43cf6ad5d1" + }, + "data":{"spec":{"template":{"$patch":"replace","metadata":{"annotations":{"test":"value"},"labels":{"app":"foo"}},"spec":{"containers":[{"image":"test","imagePullPolicy":"Always","name":"test","resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File"}],"dnsPolicy":"ClusterFirst","restartPolicy":"Always","schedulerName":"default-scheduler","securityContext":{},"terminationGracePeriodSeconds":30}}}}, + "revision":2 +} diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_set_1.33.0.json b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_set_1.33.0.json new file mode 100644 index 0000000000..e263ffad12 --- /dev/null +++ b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_set_1.33.0.json @@ -0,0 +1,104 @@ +{ + "apiVersion": "apps/v1", + "kind": "StatefulSet", + "metadata": { + "creationTimestamp": "2025-10-31T18:19:02Z", + "generation": 1, + "labels": { + "sslabel": "value" + }, + "name": "test", + "namespace": "default", + "resourceVersion": "2219", + "uid": "ec335e25-1045-4216-8634-50cfbe05f3d6" + }, + "spec": { + "persistentVolumeClaimRetentionPolicy": { + "whenDeleted": "Retain", + "whenScaled": "Retain" + }, + "podManagementPolicy": "OrderedReady", + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "foo" + } + }, + "serviceName": "", + "template": { + "metadata": { + "annotations": { + "test": "value" + }, + "creationTimestamp": null, + "labels": { + "app": "foo" + } + }, + "spec": { + "containers": [ + { + "image": "test", + "imagePullPolicy": "Always", + "name": "test", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + }, + "updateStrategy": { + "rollingUpdate": { + "partition": 0 + }, + "type": "RollingUpdate" + }, + "volumeClaimTemplates": [ + { + "apiVersion": "v1", + "kind": "PersistentVolumeClaim", + "metadata": { + "annotations": { + "key": "value" + }, + "creationTimestamp": null, + "labels": { + "key": "value" + }, + "name": "test" + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "1Gi" + } + }, + "volumeMode": "Filesystem" + }, + "status": { + "phase": "Pending" + } + } + ] + }, + "status": { + "availableReplicas": 1, + "collisionCount": 0, + "currentReplicas": 1, + "currentRevision": "test-c77f6d978", + "observedGeneration": 1, + "replicas": 1, + "updateRevision": "test-c77f6d978", + "updatedReplicas": 1 + } +} \ No newline at end of file diff --git a/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_set_1.34.0.json b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_set_1.34.0.json new file mode 100644 index 0000000000..45a3fc56ec --- /dev/null +++ b/deps/github.com/openshift/kubernetes/pkg/controller/statefulset/testdata/compatibility_set_1.34.0.json @@ -0,0 +1,102 @@ +{ + "apiVersion": "apps/v1", + "kind": "StatefulSet", + "metadata": { + "creationTimestamp": "2025-10-31T18:19:02Z", + "generation": 1, + "labels": { + "sslabel": "value" + }, + "name": "test", + "namespace": "default", + "resourceVersion": "16319", + "uid": "ec335e25-1045-4216-8634-50cfbe05f3d6" + }, + "spec": { + "persistentVolumeClaimRetentionPolicy": { + "whenDeleted": "Retain", + "whenScaled": "Retain" + }, + "podManagementPolicy": "OrderedReady", + "replicas": 1, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "app": "foo" + } + }, + "serviceName": "", + "template": { + "metadata": { + "annotations": { + "test": "value" + }, + "labels": { + "app": "foo" + } + }, + "spec": { + "containers": [ + { + "image": "test", + "imagePullPolicy": "Always", + "name": "test", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File" + } + ], + "dnsPolicy": "ClusterFirst", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "terminationGracePeriodSeconds": 30 + } + }, + "updateStrategy": { + "rollingUpdate": { + "partition": 0 + }, + "type": "RollingUpdate" + }, + "volumeClaimTemplates": [ + { + "apiVersion": "v1", + "kind": "PersistentVolumeClaim", + "metadata": { + "annotations": { + "key": "value" + }, + "labels": { + "key": "value" + }, + "name": "test" + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "1Gi" + } + }, + "volumeMode": "Filesystem" + }, + "status": { + "phase": "Pending" + } + } + ] + }, + "status": { + "availableReplicas": 1, + "collisionCount": 0, + "currentReplicas": 1, + "currentRevision": "test-776999688b", + "observedGeneration": 1, + "replicas": 1, + "updateRevision": "test-776999688b", + "updatedReplicas": 1 + } +} \ No newline at end of file diff --git a/deps/github.com/openshift/kubernetes/pkg/features/kube_features.go b/deps/github.com/openshift/kubernetes/pkg/features/kube_features.go index a3b55db585..5b7794431e 100644 --- a/deps/github.com/openshift/kubernetes/pkg/features/kube_features.go +++ b/deps/github.com/openshift/kubernetes/pkg/features/kube_features.go @@ -941,6 +941,12 @@ const ( // Enables policies controlling deletion of PVCs created by a StatefulSet. StatefulSetAutoDeletePVC featuregate.Feature = "StatefulSetAutoDeletePVC" + // owner: @liggitt + // + // Mitigates spurious statefulset rollouts due to controller revision comparison mismatches + // which are not semantically significant (e.g. serialization differences or missing defaulted fields). + StatefulSetSemanticRevisionComparison = "StatefulSetSemanticRevisionComparison" + // owner: @cupnes // kep: https://kep.k8s.io/4049 // @@ -1679,7 +1685,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate }, SchedulerAsyncAPICalls: { - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.Beta}, + {Version: version.MustParse("1.34"), Default: false, PreRelease: featuregate.Beta}, }, SchedulerAsyncPreemption: { @@ -1755,6 +1761,12 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.32, remove in 1.35 }, + StatefulSetSemanticRevisionComparison: { + // This is a mitigation for a 1.34 regression due to serialization differences that cannot be feature-gated, + // so this mitigation should not auto-disable even if emulating versions prior to 1.34 with --emulation-version. + {Version: version.MustParse("1.0"), Default: true, PreRelease: featuregate.Beta}, + }, + StorageCapacityScoring: { {Version: version.MustParse("1.33"), Default: false, PreRelease: featuregate.Alpha}, }, diff --git a/deps/github.com/openshift/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_manager.go b/deps/github.com/openshift/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_manager.go index 2b76d3bd34..5305546ccf 100644 --- a/deps/github.com/openshift/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_manager.go +++ b/deps/github.com/openshift/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_manager.go @@ -62,6 +62,9 @@ type DRAPluginManager struct { wipingDelay time.Duration streamHandler StreamHandler + // withIdleTimeout is only for unit testing, ignore if <= 0. + withIdleTimeout time.Duration + wg sync.WaitGroup mutex sync.RWMutex @@ -115,7 +118,13 @@ func (m *monitoredPlugin) HandleConn(_ context.Context, stats grpcstats.ConnStat case *grpcstats.ConnEnd: // We have to ask for a reconnect, otherwise gRPC wouldn't try and // thus we wouldn't be notified about a restart of the plugin. - m.conn.Connect() + // + // This must be done in a goroutine because gRPC deadlocks + // when called directly from inside HandleConn when a connection + // goes idle (and only then). It looks like cc.idlenessMgr.ExitIdleMode + // in Connect tries to lock a mutex that is already locked by + // the caller of HandleConn. + go m.conn.Connect() default: return } @@ -361,12 +370,15 @@ func (pm *DRAPluginManager) add(driverName string, endpoint string, chosenServic // The gRPC connection gets created once. gRPC then connects to the gRPC server on demand. target := "unix:" + endpoint logger.V(4).Info("Creating new gRPC connection", "target", target) - conn, err := grpc.NewClient( - target, + options := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithChainUnaryInterceptor(newMetricsInterceptor(driverName)), grpc.WithStatsHandler(mp), - ) + } + if pm.withIdleTimeout > 0 { + options = append(options, grpc.WithIdleTimeout(pm.withIdleTimeout)) + } + conn, err := grpc.NewClient(target, options...) if err != nil { return fmt.Errorf("create gRPC connection to DRA driver %s plugin at endpoint %s: %w", driverName, endpoint, err) } diff --git a/deps/github.com/openshift/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_test.go b/deps/github.com/openshift/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_test.go index b3af8c75b3..c8eb975b9b 100644 --- a/deps/github.com/openshift/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_test.go @@ -185,6 +185,44 @@ func TestGRPCConnIsReused(t *testing.T) { require.Equal(t, 2, reusedConns[conn], "expected counter to be 2 but got %d", reusedConns[conn]) } +func TestGRPCConnUsableAfterIdle(t *testing.T) { + tCtx := ktesting.Init(t) + service := drapbv1.DRAPluginService + addr := path.Join(t.TempDir(), "dra.sock") + teardown, err := setupFakeGRPCServer(service, addr) + require.NoError(t, err) + defer teardown() + + driverName := "dummy-driver" + + // ensure the plugin we are using is registered + draPlugins := NewDRAPluginManager(tCtx, nil, nil, &mockStreamHandler{}, 0) + draPlugins.withIdleTimeout = 5 * time.Second + tCtx.ExpectNoError(draPlugins.add(driverName, addr, service, defaultClientCallTimeout), "add plugin") + plugin, err := draPlugins.GetPlugin(driverName) + tCtx.ExpectNoError(err, "get plugin") + + // The connection doesn't really become idle because HandleConn + // kicks it back to ready by calling Connect. Just sleep long + // enough here, the code should be reached... + tCtx.Log("Waiting for idle timeout...") + time.Sleep(2 * draPlugins.withIdleTimeout) + + req := &drapbv1.NodePrepareResourcesRequest{ + Claims: []*drapbv1.Claim{ + { + Namespace: "dummy-namespace", + UID: "dummy-uid", + Name: "dummy-claim", + }, + }, + } + + callCtx := ktesting.WithTimeout(tCtx, 10*time.Second, "call timed out") + _, err = plugin.NodePrepareResources(callCtx, req) + tCtx.ExpectNoError(err, "NodePrepareResources") +} + func TestGetDRAPlugin(t *testing.T) { for _, test := range []struct { description string diff --git a/deps/github.com/openshift/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go b/deps/github.com/openshift/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go index a1d9453f89..c837212d98 100644 --- a/deps/github.com/openshift/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/deps/github.com/openshift/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -56,6 +56,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/events" + "k8s.io/kubernetes/pkg/kubelet/managed" proberesults "k8s.io/kubernetes/pkg/kubelet/prober/results" "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" @@ -625,6 +626,8 @@ func (m *kubeGenericRuntimeManager) getPodContainerStatuses(ctx context.Context, return nil, nil, err } + isManagedPod := managed.IsManagedPodFromRuntimeService(ctx, m.runtimeService, activePodSandboxID) + statuses := []*kubecontainer.Status{} activeContainerStatuses := []*kubecontainer.Status{} // TODO: optimization: set maximum number of containers per container name to examine. @@ -647,6 +650,9 @@ func (m *kubeGenericRuntimeManager) getPodContainerStatuses(ctx context.Context, return nil, nil, remote.ErrContainerStatusNil } cStatus := m.convertToKubeContainerStatus(ctx, status) + if isManagedPod && cStatus.Resources != nil { // Clear CPU resources for managed pods (workload-pinned) + cStatus.Resources.CPURequest, cStatus.Resources.CPULimit = nil, nil + } statuses = append(statuses, cStatus) if c.PodSandboxId == activePodSandboxID { activeContainerStatuses = append(activeContainerStatuses, cStatus) diff --git a/deps/github.com/openshift/kubernetes/pkg/kubelet/managed/managed.go b/deps/github.com/openshift/kubernetes/pkg/kubelet/managed/managed.go index d9266e440f..bd78adeee1 100644 --- a/deps/github.com/openshift/kubernetes/pkg/kubelet/managed/managed.go +++ b/deps/github.com/openshift/kubernetes/pkg/kubelet/managed/managed.go @@ -17,6 +17,7 @@ limitations under the License. package managed import ( + "context" "encoding/json" "fmt" "os" @@ -24,6 +25,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" ) var ( @@ -88,6 +90,40 @@ func IsPodManaged(pod *v1.Pod) (bool, string, string) { return false, "", "" } +// podSandboxStatusGetter is an interface for getting pod sandbox status +type podSandboxStatusGetter interface { + PodSandboxStatus(ctx context.Context, podSandboxID string, verbose bool) (*runtimeapi.PodSandboxStatusResponse, error) +} + +// IsPodSandboxManagedPod checks if a pod sandbox belongs to a managed pod +// by looking for workload pinning annotations. +func IsPodSandboxManagedPod(sandboxAnnotations map[string]string) bool { + if sandboxAnnotations == nil { + return false + } + for annotation := range sandboxAnnotations { + if strings.HasPrefix(annotation, WorkloadsAnnotationPrefix) { + return true + } + } + return false +} + +// IsManagedPodFromRuntimeService checks if a pod is managed by fetching the pod sandbox +// status and checking for workload pinning annotations. +func IsManagedPodFromRuntimeService(ctx context.Context, runtimeService podSandboxStatusGetter, podSandboxID string) bool { + if podSandboxID == "" { + return false + } + + sandboxResp, err := runtimeService.PodSandboxStatus(ctx, podSandboxID, false) + if err != nil || sandboxResp == nil || sandboxResp.GetStatus() == nil { + return false + } + + return IsPodSandboxManagedPod(sandboxResp.GetStatus().Annotations) +} + // ModifyStaticPodForPinnedManagement will modify a pod for pod management func ModifyStaticPodForPinnedManagement(pod *v1.Pod) (*v1.Pod, string, error) { pod = pod.DeepCopy() diff --git a/deps/github.com/openshift/kubernetes/pkg/kubelet/managed/managed_test.go b/deps/github.com/openshift/kubernetes/pkg/kubelet/managed/managed_test.go index 3a2f2b3a18..f4417370f9 100644 --- a/deps/github.com/openshift/kubernetes/pkg/kubelet/managed/managed_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/kubelet/managed/managed_test.go @@ -1,12 +1,14 @@ package managed import ( + "context" "fmt" "testing" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" ) func TestModifyStaticPodForPinnedManagementErrorStates(t *testing.T) { @@ -1007,3 +1009,173 @@ func createPod(annotations map[string]string, initContainer, container *v1.Conta return pod } + +func TestIsPodSandboxManagedPod(t *testing.T) { + testCases := []struct { + name string + annotations map[string]string + expected bool + }{ + { + name: "nil annotations", + annotations: nil, + expected: false, + }, + { + name: "empty annotations", + annotations: map[string]string{}, + expected: false, + }, + { + name: "regular pod annotations without workload annotations", + annotations: map[string]string{ + "some.annotation": "value", + "another.annotation": "value2", + "io.kubernetes.pod.id": "12345", + }, + expected: false, + }, + { + name: "managed pod with workload management annotation", + annotations: map[string]string{ + "some.annotation": "value", + WorkloadsAnnotationPrefix + "management": `{"effect": "PreferredDuringScheduling"}`, + }, + expected: true, + }, + { + name: "managed pod with workload throttle annotation", + annotations: map[string]string{ + WorkloadsAnnotationPrefix + "throttle": `{"effect": "PreferredDuringScheduling"}`, + }, + expected: true, + }, + { + name: "pod with annotation similar to workload prefix but not matching", + annotations: map[string]string{ + "target.workload.openshift.io": "value", // missing trailing slash + "some.other.annotation": "value2", + }, + expected: false, + }, + { + name: "managed pod with multiple annotations", + annotations: map[string]string{ + "io.kubernetes.pod.name": "test-pod", + "io.kubernetes.pod.namespace": "default", + WorkloadsAnnotationPrefix + "management": `{"effect": "PreferredDuringScheduling"}`, + "custom.annotation": "custom-value", + }, + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + result := IsPodSandboxManagedPod(tc.annotations) + if result != tc.expected { + t.Errorf("IsPodSandboxManagedPod() = %v, expected %v for annotations: %v", + result, tc.expected, tc.annotations) + } + }) + } +} + +// mockRuntimeService is a simple mock for testing +type mockRuntimeService struct { + sandboxStatus *runtimeapi.PodSandboxStatusResponse + err error +} + +func (m *mockRuntimeService) PodSandboxStatus(ctx context.Context, podSandboxID string, verbose bool) (*runtimeapi.PodSandboxStatusResponse, error) { + return m.sandboxStatus, m.err +} + +func TestIsManagedPodFromRuntimeService(t *testing.T) { + ctx := context.Background() + + testCases := []struct { + name string + podSandboxID string + sandboxStatus *runtimeapi.PodSandboxStatusResponse + err error + expected bool + }{ + { + name: "empty sandbox ID", + podSandboxID: "", + expected: false, + }, + { + name: "runtime service returns error", + podSandboxID: "sandbox123", + err: fmt.Errorf("runtime error"), + expected: false, + }, + { + name: "nil sandbox response", + podSandboxID: "sandbox123", + sandboxStatus: nil, + expected: false, + }, + { + name: "nil status in response", + podSandboxID: "sandbox123", + sandboxStatus: &runtimeapi.PodSandboxStatusResponse{ + Status: nil, + }, + expected: false, + }, + { + name: "regular pod without workload annotations", + podSandboxID: "sandbox123", + sandboxStatus: &runtimeapi.PodSandboxStatusResponse{ + Status: &runtimeapi.PodSandboxStatus{ + Annotations: map[string]string{ + "some.annotation": "value", + }, + }, + }, + expected: false, + }, + { + name: "managed pod with workload annotations", + podSandboxID: "sandbox123", + sandboxStatus: &runtimeapi.PodSandboxStatusResponse{ + Status: &runtimeapi.PodSandboxStatus{ + Annotations: map[string]string{ + "some.annotation": "value", + WorkloadsAnnotationPrefix + "management": `{"effect": "PreferredDuringScheduling"}`, + }, + }, + }, + expected: true, + }, + { + name: "managed pod with empty annotations but has workload prefix", + podSandboxID: "sandbox123", + sandboxStatus: &runtimeapi.PodSandboxStatusResponse{ + Status: &runtimeapi.PodSandboxStatus{ + Annotations: map[string]string{ + WorkloadsAnnotationPrefix + "throttle": "", + }, + }, + }, + expected: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + mockService := &mockRuntimeService{ + sandboxStatus: tc.sandboxStatus, + err: tc.err, + } + + result := IsManagedPodFromRuntimeService(ctx, mockService, tc.podSandboxID) + if result != tc.expected { + t.Errorf("IsManagedPodFromRuntimeService() = %v, expected %v", result, tc.expected) + } + }) + } +} diff --git a/deps/github.com/openshift/kubernetes/pkg/kubelet/prober/worker.go b/deps/github.com/openshift/kubernetes/pkg/kubelet/prober/worker.go index 8578c415d4..60461165bd 100644 --- a/deps/github.com/openshift/kubernetes/pkg/kubelet/prober/worker.go +++ b/deps/github.com/openshift/kubernetes/pkg/kubelet/prober/worker.go @@ -83,6 +83,16 @@ type worker struct { proberDurationUnknownMetricLabels metrics.Labels } +// isInitContainer checks if the worker's container is in the pod's init containers +func (w *worker) isInitContainer() bool { + for _, initContainer := range w.pod.Spec.InitContainers { + if initContainer.Name == w.container.Name { + return true + } + } + return false +} + // Creates and starts a new probe worker. func newWorker( m *manager, @@ -253,12 +263,17 @@ func (w *worker) doProbe(ctx context.Context) (keepGoing bool) { if !w.containerID.IsEmpty() { w.resultsManager.Set(w.containerID, results.Failure, w.pod) } + + isRestartableInitContainer := w.isInitContainer() && + w.container.RestartPolicy != nil && *w.container.RestartPolicy == v1.ContainerRestartPolicyAlways + // Abort if the container will not be restarted. if utilfeature.DefaultFeatureGate.Enabled(features.ContainerRestartRules) { return c.State.Terminated != nil || podutil.IsContainerRestartable(w.pod.Spec, w.container) } return c.State.Terminated == nil || - w.pod.Spec.RestartPolicy != v1.RestartPolicyNever + w.pod.Spec.RestartPolicy != v1.RestartPolicyNever || + isRestartableInitContainer } // Graceful shutdown of the pod. diff --git a/deps/github.com/openshift/kubernetes/pkg/kubelet/prober/worker_test.go b/deps/github.com/openshift/kubernetes/pkg/kubelet/prober/worker_test.go index ec8f8673ec..946f183528 100644 --- a/deps/github.com/openshift/kubernetes/pkg/kubelet/prober/worker_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/kubelet/prober/worker_test.go @@ -37,6 +37,25 @@ import ( func init() { } +// newTestWorkerWithRestartableInitContainer creates a test worker with an init container setup +func newTestWorkerWithRestartableInitContainer(m *manager, probeType probeType) *worker { + pod := getTestPod() + + // Set up init container with restart policy + initContainer := pod.Spec.Containers[0] + initContainer.Name = testContainerName + restartPolicy := v1.ContainerRestartPolicyAlways + initContainer.RestartPolicy = &restartPolicy + + // Move container to init containers and add a regular container + pod.Spec.InitContainers = []v1.Container{initContainer} + pod.Spec.Containers = []v1.Container{{ + Name: "main-container", + }} + + return newWorker(m, probeType, pod, initContainer) +} + func TestDoProbe(t *testing.T) { logger, ctx := ktesting.NewTestContext(t) m := newTestManager() @@ -530,6 +549,72 @@ func TestResultRunOnStartupCheckFailure(t *testing.T) { } } +func TestDoProbe_TerminatedRestartableInitContainerWithRestartPolicyNever(t *testing.T) { + logger, ctx := ktesting.NewTestContext(t) + m := newTestManager() + + // Test restartable init container (sidecar) behavior + w := newTestWorkerWithRestartableInitContainer(m, startup) + + // Set pod restart policy to Never + w.pod.Spec.RestartPolicy = v1.RestartPolicyNever + + // Create terminated status for init container + terminatedStatus := getTestRunningStatus() + terminatedStatus.InitContainerStatuses = []v1.ContainerStatus{{ + Name: testContainerName, + ContainerID: "test://test_container_id", + State: v1.ContainerState{ + Terminated: &v1.ContainerStateTerminated{ + StartedAt: metav1.Now(), + }, + }, + }} + terminatedStatus.ContainerStatuses[0].State.Running = nil + + m.statusManager.SetPodStatus(logger, w.pod, terminatedStatus) + + // Test: Terminated restartable init container with restartPolicy=Always should continue probing + // even when pod has restartPolicy=Never + if !w.doProbe(ctx) { + t.Error("Expected to continue probing for terminated restartable init container with pod restart policy Never") + } + + // Verify result is set to Failure for terminated container + expectResult(t, w, results.Failure, "restartable init container with pod restart policy Never") +} + +func TestDoProbe_TerminatedContainerWithRestartPolicyNever(t *testing.T) { + logger, ctx := ktesting.NewTestContext(t) + m := newTestManager() + + // Test that regular containers (without RestartPolicy) still work as before + w := newTestWorker(m, startup, v1.Probe{}) + + // Regular container without explicit restart policy + w.container.RestartPolicy = nil + + // Set pod restart policy to Never + w.pod.Spec.RestartPolicy = v1.RestartPolicyNever + + // Create terminated status + terminatedStatus := getTestRunningStatus() + terminatedStatus.ContainerStatuses[0].State.Running = nil + terminatedStatus.ContainerStatuses[0].State.Terminated = &v1.ContainerStateTerminated{ + StartedAt: metav1.Now(), + } + + m.statusManager.SetPodStatus(logger, w.pod, terminatedStatus) + + // Should stop probing (existing behavior preserved) + if w.doProbe(ctx) { + t.Error("Expected to stop probing for regular container with pod RestartPolicy=Never") + } + + // Verify result is set to Failure for terminated container + expectResult(t, w, results.Failure, "regular container with pod restart policy Never") +} + func TestLivenessProbeDisabledByStarted(t *testing.T) { logger, ctx := ktesting.NewTestContext(t) m := newTestManager() diff --git a/deps/github.com/openshift/kubernetes/pkg/proxy/util/localdetector.go b/deps/github.com/openshift/kubernetes/pkg/proxy/util/localdetector.go index 6e296b0c71..9e579e8876 100644 --- a/deps/github.com/openshift/kubernetes/pkg/proxy/util/localdetector.go +++ b/deps/github.com/openshift/kubernetes/pkg/proxy/util/localdetector.go @@ -98,8 +98,8 @@ func NewDetectLocalByBridgeInterface(interfaceName string) LocalTrafficDetector return &detectLocal{ ifLocal: []string{"-i", interfaceName}, ifNotLocal: []string{"!", "-i", interfaceName}, - ifLocalNFT: []string{"iif", interfaceName}, - ifNotLocalNFT: []string{"iif", "!=", interfaceName}, + ifLocalNFT: []string{"iifname", interfaceName}, + ifNotLocalNFT: []string{"iifname", "!=", interfaceName}, } } @@ -110,7 +110,7 @@ func NewDetectLocalByInterfaceNamePrefix(interfacePrefix string) LocalTrafficDet return &detectLocal{ ifLocal: []string{"-i", interfacePrefix + "+"}, ifNotLocal: []string{"!", "-i", interfacePrefix + "+"}, - ifLocalNFT: []string{"iif", interfacePrefix + "*"}, - ifNotLocalNFT: []string{"iif", "!=", interfacePrefix + "*"}, + ifLocalNFT: []string{"iifname", interfacePrefix + "*"}, + ifNotLocalNFT: []string{"iifname", "!=", interfacePrefix + "*"}, } } diff --git a/deps/github.com/openshift/kubernetes/pkg/proxy/util/localdetector_test.go b/deps/github.com/openshift/kubernetes/pkg/proxy/util/localdetector_test.go index 473aaeb8ce..0fb3693426 100644 --- a/deps/github.com/openshift/kubernetes/pkg/proxy/util/localdetector_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/proxy/util/localdetector_test.go @@ -105,6 +105,37 @@ func TestDetectLocalByBridgeInterface(t *testing.T) { } } +func TestDetectLocalNFTByBridgeInterface(t *testing.T) { + cases := []struct { + ifaceName string + expectedJumpIfOutput []string + expectedJumpIfNotOutput []string + }{ + { + ifaceName: "eth0", + expectedJumpIfOutput: []string{"iifname", "eth0"}, + expectedJumpIfNotOutput: []string{"iifname", "!=", "eth0"}, + }, + } + for _, c := range cases { + localDetector := NewDetectLocalByBridgeInterface(c.ifaceName) + if !localDetector.IsImplemented() { + t.Error("DetectLocalByBridgeInterface returns false for IsImplemented") + } + + ifLocal := localDetector.IfLocalNFT() + ifNotLocal := localDetector.IfNotLocalNFT() + + if !reflect.DeepEqual(ifLocal, c.expectedJumpIfOutput) { + t.Errorf("IfLocalNFT, expected: '%v', but got: '%v'", c.expectedJumpIfOutput, ifLocal) + } + + if !reflect.DeepEqual(ifNotLocal, c.expectedJumpIfNotOutput) { + t.Errorf("IfNotLocalNFT, expected: '%v', but got: '%v'", c.expectedJumpIfNotOutput, ifNotLocal) + } + } +} + func TestDetectLocalByInterfaceNamePrefix(t *testing.T) { cases := []struct { ifacePrefix string @@ -137,3 +168,36 @@ func TestDetectLocalByInterfaceNamePrefix(t *testing.T) { } } } + +func TestDetectLocalNFTByInterfaceNamePrefix(t *testing.T) { + cases := []struct { + ifacePrefix string + chain string + args []string + expectedJumpIfOutput []string + expectedJumpIfNotOutput []string + }{ + { + ifacePrefix: "eth", + expectedJumpIfOutput: []string{"iifname", "eth*"}, + expectedJumpIfNotOutput: []string{"iifname", "!=", "eth*"}, + }, + } + for _, c := range cases { + localDetector := NewDetectLocalByInterfaceNamePrefix(c.ifacePrefix) + if !localDetector.IsImplemented() { + t.Error("DetectLocalByInterfaceNamePrefix returns false for IsImplemented") + } + + ifLocal := localDetector.IfLocalNFT() + ifNotLocal := localDetector.IfNotLocalNFT() + + if !reflect.DeepEqual(ifLocal, c.expectedJumpIfOutput) { + t.Errorf("IfLocalNFT, expected: '%v', but got: '%v'", c.expectedJumpIfOutput, ifLocal) + } + + if !reflect.DeepEqual(ifNotLocal, c.expectedJumpIfNotOutput) { + t.Errorf("IfNotLocalNFT, expected: '%v', but got: '%v'", c.expectedJumpIfNotOutput, ifNotLocal) + } + } +} diff --git a/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/hns.go b/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/hns.go index d6e425f8b7..80bb208adf 100644 --- a/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/hns.go +++ b/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/hns.go @@ -349,17 +349,21 @@ func (hns hns) getAllLoadBalancers() (map[loadBalancerIdentifier]*loadBalancerIn func (hns hns) getLoadBalancer(endpoints []endpointInfo, flags loadBalancerFlags, sourceVip string, vip string, protocol uint16, internalPort uint16, externalPort uint16, previousLoadBalancers map[loadBalancerIdentifier]*loadBalancerInfo) (*loadBalancerInfo, error) { var id loadBalancerIdentifier vips := []string{} - // Compute hash from backends (endpoint IDs) - hash, err := hashEndpoints(endpoints) - if err != nil { - klog.V(2).ErrorS(err, "Error hashing endpoints", "endpoints", endpoints) - return nil, err + id, lbIdErr := findLoadBalancerID( + endpoints, + vip, + protocol, + internalPort, + externalPort, + ) + + if lbIdErr != nil { + klog.V(2).ErrorS(lbIdErr, "Error hashing endpoints", "endpoints", endpoints) + return nil, lbIdErr } + if len(vip) > 0 { - id = loadBalancerIdentifier{protocol: protocol, internalPort: internalPort, externalPort: externalPort, vip: vip, endpointsHash: hash} vips = append(vips, vip) - } else { - id = loadBalancerIdentifier{protocol: protocol, internalPort: internalPort, externalPort: externalPort, endpointsHash: hash} } if lb, found := previousLoadBalancers[id]; found { diff --git a/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/hns_test.go b/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/hns_test.go index ca436394b0..b859ad639e 100644 --- a/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/hns_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/hns_test.go @@ -39,6 +39,8 @@ const ( epIpv6Address = "192::3" epIpAddressB = "192.168.1.4" epIpAddressRemote = "192.168.2.3" + epIpAddressLocal1 = "192.168.4.4" + epIpAddressLocal2 = "192.168.4.5" epPaAddress = "10.0.0.3" protocol = 6 internalPort = 80 diff --git a/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/proxier.go b/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/proxier.go index f32a5cb4fc..ad3bd26fd6 100644 --- a/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/proxier.go +++ b/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/proxier.go @@ -405,7 +405,7 @@ func (proxier *Proxier) updateTerminatedEndpoints(eps []proxy.Endpoint, isOldEnd func (proxier *Proxier) endpointsMapChange(oldEndpointsMap, newEndpointsMap proxy.EndpointsMap) { // This will optimize remote endpoint and loadbalancer deletion based on the annotation var svcPortMap = make(map[proxy.ServicePortName]bool) - clear(proxier.terminatedEndpoints) + var logLevel klog.Level = 5 for svcPortName, eps := range oldEndpointsMap { logFormattedEndpoints("endpointsMapChange oldEndpointsMap", logLevel, svcPortName, eps) @@ -1233,6 +1233,9 @@ func (proxier *Proxier) syncProxyRules() (retryError error) { return } + // Clear terminated endpoints map + clear(proxier.terminatedEndpoints) + // We assume that if this was called, we really want to sync them, // even if nothing changed in the meantime. In other words, callers are // responsible for detecting no-op changes and not calling this function. @@ -1526,7 +1529,7 @@ func (proxier *Proxier) syncProxyRules() (retryError error) { } if !proxier.requiresUpdateLoadbalancer(svcInfo.hnsID, len(clusterIPEndpoints)) { - proxier.deleteExistingLoadBalancer(hns, svcInfo.winProxyOptimization, &svcInfo.hnsID, svcInfo.ClusterIP().String(), Enum(svcInfo.Protocol()), uint16(svcInfo.targetPort), uint16(svcInfo.Port()), hnsEndpoints, queriedLoadBalancers) + proxier.deleteExistingLoadBalancer(hns, svcInfo.winProxyOptimization, &svcInfo.hnsID, svcInfo.ClusterIP().String(), Enum(svcInfo.Protocol()), uint16(svcInfo.targetPort), uint16(svcInfo.Port()), clusterIPEndpoints, queriedLoadBalancers) if len(clusterIPEndpoints) > 0 { // If all endpoints are terminating, then no need to create Cluster IP LoadBalancer @@ -1784,10 +1787,11 @@ func (proxier *Proxier) syncProxyRules() (retryError error) { klog.V(5).InfoS("Terminated endpoints ready for deletion", "epIP", epIP) if epToDelete := queriedEndpoints[epIP]; epToDelete != nil && epToDelete.hnsID != "" && !epToDelete.IsLocal() { if refCount := proxier.endPointsRefCount.getRefCount(epToDelete.hnsID); refCount == nil || *refCount == 0 { - klog.V(3).InfoS("Deleting unreferenced remote endpoint", "hnsID", epToDelete.hnsID, "IP", epToDelete.ip) err := proxier.hns.deleteEndpoint(epToDelete.hnsID) if err != nil { klog.ErrorS(err, "Deleting unreferenced remote endpoint failed", "hnsID", epToDelete.hnsID) + } else { + klog.V(3).InfoS("Deleting unreferenced remote endpoint succeeded", "hnsID", epToDelete.hnsID, "IP", epToDelete.ip) } } } diff --git a/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/proxier_test.go b/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/proxier_test.go index d6a2a31e2c..aaa39ded01 100644 --- a/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/proxier_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/proxy/winkernel/proxier_test.go @@ -48,15 +48,19 @@ import ( const ( testNodeName = "test-node" testNetwork = "TestNetwork" - ipAddress = "10.0.0.1" prefixLen = 24 macAddress = "00-11-22-33-44-55" + macAddressLocal1 = "00-11-22-33-44-56" + macAddressLocal2 = "00-11-22-33-44-57" destinationPrefix = "192.168.2.0/24" providerAddress = "10.0.0.3" guid = "123ABC" + networkId = "123ABC" endpointGuid1 = "EPID-1" loadbalancerGuid1 = "LBID-1" - endpointLocal = "EP-LOCAL" + loadbalancerGuid2 = "LBID-2" + endpointLocal1 = "EP-LOCAL-1" + endpointLocal2 = "EP-LOCAL-2" endpointGw = "EP-GW" epIpAddressGw = "192.168.2.1" epMacAddressGw = "00-11-22-33-44-66" @@ -413,6 +417,193 @@ func TestDsrNotAppliedToClusterTrafficPolicy(t *testing.T) { } } +// TestClusterIPSvcWithITPLocal tests the following scenarios for a ClusterIP service with InternalTrafficPolicy=Local: +// 1. When a local endpoint is added to the service, the service should continue to use the local endpoints and existing loadbalancer. +// If no existing loadbalancer is present, a new loadbalancer should be created. +// 2. When one more local endpoint is added to the service, the service should delete existing loadbalancer and create a new loadbalancer. +// 3. When a remote endpoint is added to the service, the service should continue to use the local endpoints and existing loadbalancer, +// since it's a InternalTrafficPolicy=Local service. +func TestClusterIPSvcWithITPLocal(t *testing.T) { + proxier := NewFakeProxier(t, "testhost", netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge", true) + if proxier == nil { + t.Fatal("Failed to create proxier") + } + + svcIP := "10.20.30.41" + svcPort := 80 + svcPortName := proxy.ServicePortName{ + NamespacedName: makeNSN("ns1", "svc1"), + Port: "p80", + Protocol: v1.ProtocolTCP, + } + + itpLocal := v1.ServiceInternalTrafficPolicyLocal + + makeServiceMap(proxier, + makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *v1.Service) { + svc.Spec.Type = v1.ServiceTypeClusterIP + svc.Spec.ClusterIP = svcIP + svc.Spec.InternalTrafficPolicy = &itpLocal // Setting the InternalTrafficPolicy to Local + svc.Spec.Ports = []v1.ServicePort{{ + Name: svcPortName.Port, + Port: int32(svcPort), + Protocol: v1.ProtocolTCP, + }} + }), + ) + + populateEndpointSlices(proxier, + makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { + eps.AddressType = discovery.AddressTypeIPv4 + eps.Endpoints = []discovery.Endpoint{ + { + Addresses: []string{epIpAddressLocal1}, // Local Endpoint 1 + }, + } + eps.Ports = []discovery.EndpointPort{{ + Name: ptr.To(svcPortName.Port), + Port: ptr.To(int32(svcPort)), + Protocol: ptr.To(v1.ProtocolTCP), + }} + }), + ) + + hcn := (proxier.hcn).(*fakehcn.HcnMock) + // Populating the endpoint to the cache, since it's a local endpoint and local endpoints are managed by CNI and not KubeProxy + // Populating here marks the endpoint to local + hcn.PopulateQueriedEndpoints(endpointLocal1, networkId, epIpAddressLocal1, macAddressLocal1, prefixLen) + + proxier.setInitialized(true) + + // Test 1: When a local endpoint is added to the service, the service should continue to use the local endpoints and existing loadbalancer. + // If no existing loadbalancer is present, a new loadbalancer should be created. + proxier.syncProxyRules() + + ep := proxier.endpointsMap[svcPortName][0] + epInfo, ok := ep.(*endpointInfo) + assert.True(t, ok, fmt.Sprintf("Failed to cast endpointInfo %q", svcPortName.String())) + assert.NotEmpty(t, epInfo.hnsID, fmt.Sprintf("Expected HNS ID to be set for endpoint %s, but got empty value", epIpAddressRemote)) + + svc := proxier.svcPortMap[svcPortName] + svcInfo, ok := svc.(*serviceInfo) + assert.True(t, ok, "Failed to cast serviceInfo %q", svcPortName.String()) + assert.Equal(t, svcInfo.hnsID, loadbalancerGuid1, fmt.Sprintf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid1)) + lb, err := proxier.hcn.GetLoadBalancerByID(loadbalancerGuid1) + assert.Equal(t, nil, err, fmt.Sprintf("Failed to fetch loadbalancer: %s. Error: %v", loadbalancerGuid1, err)) + assert.NotNil(t, lb, "Loadbalancer object should not be nil") + + // Test 2: When one more local endpoint is added to the service, the service should delete existing loadbalancer and create a new loadbalancer. + + proxier.setInitialized(false) + + proxier.OnEndpointSliceUpdate( + makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { + eps.AddressType = discovery.AddressTypeIPv4 + eps.Endpoints = []discovery.Endpoint{{ + Addresses: []string{epIpAddressLocal1}, + }} + eps.Ports = []discovery.EndpointPort{{ + Name: ptr.To(svcPortName.Port), + Port: ptr.To(int32(svcPort)), + Protocol: ptr.To(v1.ProtocolTCP), + }} + }), + makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { + eps.AddressType = discovery.AddressTypeIPv4 + eps.Endpoints = []discovery.Endpoint{ + { + Addresses: []string{epIpAddressLocal1}, + }, + { + Addresses: []string{epIpAddressLocal2}, // Adding one more local endpoint + }, + } + eps.Ports = []discovery.EndpointPort{{ + Name: ptr.To(svcPortName.Port), + Port: ptr.To(int32(svcPort)), + Protocol: ptr.To(v1.ProtocolTCP), + }} + })) + + proxier.mu.Lock() + proxier.endpointSlicesSynced = true + proxier.mu.Unlock() + + proxier.setInitialized(true) + + // Creating the second local endpoint + hcn.PopulateQueriedEndpoints(endpointLocal2, networkId, epIpAddressLocal2, macAddressLocal2, prefixLen) + // Reinitiating the syncProxyRules to create new loadbalancer with the new local endpoint + proxier.syncProxyRules() + svc = proxier.svcPortMap[svcPortName] + svcInfo, ok = svc.(*serviceInfo) + assert.True(t, ok, "Failed to cast serviceInfo %q", svcPortName.String()) + assert.Equal(t, svcInfo.hnsID, loadbalancerGuid2, fmt.Sprintf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid2)) + lb, err = proxier.hcn.GetLoadBalancerByID(loadbalancerGuid2) + assert.Equal(t, nil, err, fmt.Sprintf("Failed to fetch loadbalancer: %s. Error: %v", loadbalancerGuid2, err)) + assert.NotNil(t, lb, "Loadbalancer object should not be nil") + + lb, _ = proxier.hcn.GetLoadBalancerByID(loadbalancerGuid1) + assert.Nil(t, lb, fmt.Sprintf("Loadbalancer object should be nil: %s", loadbalancerGuid1)) + + // Test 3: When a remote endpoint is added to the service, the service should continue to use the local endpoints and existing loadbalancer, + // since it's a InternalTrafficPolicy=Local service. + + proxier.setInitialized(false) + + proxier.OnEndpointSliceUpdate( + makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { + eps.AddressType = discovery.AddressTypeIPv4 + eps.Endpoints = []discovery.Endpoint{ + { + Addresses: []string{epIpAddressLocal1}, + }, + { + Addresses: []string{epIpAddressLocal2}, + }, + } + eps.Ports = []discovery.EndpointPort{{ + Name: ptr.To(svcPortName.Port), + Port: ptr.To(int32(svcPort)), + Protocol: ptr.To(v1.ProtocolTCP), + }} + }), + makeTestEndpointSlice(svcPortName.Namespace, svcPortName.Name, 1, func(eps *discovery.EndpointSlice) { + eps.AddressType = discovery.AddressTypeIPv4 + eps.Endpoints = []discovery.Endpoint{ + { + Addresses: []string{epIpAddressLocal1}, + }, + { + Addresses: []string{epIpAddressLocal2}, // Adding one more local endpoint + }, + { + Addresses: []string{epIpAddressRemote}, // Adding one more remote endpoint to the slice + }, + } + eps.Ports = []discovery.EndpointPort{{ + Name: ptr.To(svcPortName.Port), + Port: ptr.To(int32(svcPort)), + Protocol: ptr.To(v1.ProtocolTCP), + }} + })) + + proxier.mu.Lock() + proxier.endpointSlicesSynced = true + proxier.mu.Unlock() + + proxier.setInitialized(true) + + proxier.syncProxyRules() + svc = proxier.svcPortMap[svcPortName] + svcInfo, ok = svc.(*serviceInfo) + assert.True(t, ok, "Failed to cast serviceInfo %q", svcPortName.String()) + assert.Equal(t, svcInfo.hnsID, loadbalancerGuid2, fmt.Sprintf("%v does not match %v", svcInfo.hnsID, loadbalancerGuid2)) + lb, err = proxier.hcn.GetLoadBalancerByID(loadbalancerGuid2) + assert.Equal(t, nil, err, fmt.Sprintf("Failed to fetch loadbalancer: %s. Error: %v", loadbalancerGuid2, err)) + assert.NotNil(t, lb, "Loadbalancer object should not be nil") +} + func TestSharedRemoteEndpointDelete(t *testing.T) { proxier := NewFakeProxier(t, testNodeName, netutils.ParseIPSloppy("10.0.0.1"), "L2Bridge", true) if proxier == nil { @@ -1198,7 +1389,7 @@ func TestCreateDsrLoadBalancer(t *testing.T) { hcn := (proxier.hcn).(*fakehcn.HcnMock) proxier.rootHnsEndpointName = endpointGw - hcn.PopulateQueriedEndpoints(endpointLocal, guid, epIpAddressRemote, macAddress, prefixLen) + hcn.PopulateQueriedEndpoints(endpointLocal1, guid, epIpAddressRemote, macAddress, prefixLen) hcn.PopulateQueriedEndpoints(endpointGw, guid, epIpAddressGw, epMacAddressGw, prefixLen) proxier.setInitialized(true) proxier.syncProxyRules() diff --git a/deps/github.com/openshift/kubernetes/pkg/registry/batch/job/strategy.go b/deps/github.com/openshift/kubernetes/pkg/registry/batch/job/strategy.go index 8bde82debf..23f343e754 100644 --- a/deps/github.com/openshift/kubernetes/pkg/registry/batch/job/strategy.go +++ b/deps/github.com/openshift/kubernetes/pkg/registry/batch/job/strategy.go @@ -380,6 +380,11 @@ func getStatusValidationOptions(newJob, oldJob *batch.Job) batchvalidation.JobSt isReadyChanged := !ptr.Equal(oldJob.Status.Ready, newJob.Status.Ready) isTerminatingChanged := !ptr.Equal(oldJob.Status.Terminating, newJob.Status.Terminating) isSuspendedWithZeroCompletions := ptr.Equal(newJob.Spec.Suspend, ptr.To(true)) && ptr.Equal(newJob.Spec.Completions, ptr.To[int32](0)) + // Detect job resume via condition changes (JobSuspended: True -> False) + // This handles the case where the controller updates status after the user has already + // changed spec.suspend=false, which is the scenario from https://github.com/kubernetes/kubernetes/issues/134521 + isJobResuming := batchvalidation.IsConditionTrue(oldJob.Status.Conditions, batch.JobSuspended) && + batchvalidation.IsConditionFalse(newJob.Status.Conditions, batch.JobSuspended) return batchvalidation.JobStatusValidationOptions{ // We allow to decrease the counter for succeeded pods for jobs which @@ -397,7 +402,7 @@ func getStatusValidationOptions(newJob, oldJob *batch.Job) batchvalidation.JobSt RejectFinishedJobWithActivePods: isJobFinishedChanged || isActiveChanged, RejectFinishedJobWithoutStartTime: (isJobFinishedChanged || isStartTimeChanged) && !isSuspendedWithZeroCompletions, RejectFinishedJobWithUncountedTerminatedPods: isJobFinishedChanged || isUncountedTerminatedPodsChanged, - RejectStartTimeUpdateForUnsuspendedJob: isStartTimeChanged, + RejectStartTimeUpdateForUnsuspendedJob: isStartTimeChanged && !isJobResuming, RejectCompletionTimeBeforeStartTime: isStartTimeChanged || isCompletionTimeChanged, RejectMutatingCompletionTime: true, RejectNotCompleteJobWithCompletionTime: isJobCompleteChanged || isCompletionTimeChanged, diff --git a/deps/github.com/openshift/kubernetes/pkg/registry/batch/job/strategy_test.go b/deps/github.com/openshift/kubernetes/pkg/registry/batch/job/strategy_test.go index 1997106a2d..58b4a54044 100644 --- a/deps/github.com/openshift/kubernetes/pkg/registry/batch/job/strategy_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/registry/batch/job/strategy_test.go @@ -2559,6 +2559,33 @@ func TestStatusStrategy_ValidateUpdate(t *testing.T) { {Type: field.ErrorTypeRequired, Field: "status.startTime"}, }, }, + "verify startTime can be updated when resuming job (JobSuspended: True -> False)": { + enableJobManagedBy: true, + job: &batch.Job{ + ObjectMeta: validObjectMeta, + Status: batch.JobStatus{ + StartTime: &now, + Conditions: []batch.JobCondition{ + { + Type: batch.JobSuspended, + Status: api.ConditionTrue, + }, + }, + }, + }, + newJob: &batch.Job{ + ObjectMeta: validObjectMeta, + Status: batch.JobStatus{ + StartTime: &nowPlusMinute, + Conditions: []batch.JobCondition{ + { + Type: batch.JobSuspended, + Status: api.ConditionFalse, + }, + }, + }, + }, + }, "invalid attempt to set completionTime before startTime": { enableJobManagedBy: true, job: &batch.Job{ diff --git a/deps/github.com/openshift/kubernetes/pkg/scheduler/backend/api_dispatcher/api_dispatcher_test.go b/deps/github.com/openshift/kubernetes/pkg/scheduler/backend/api_dispatcher/api_dispatcher_test.go index 0134ec4c4e..d04544f1a7 100644 --- a/deps/github.com/openshift/kubernetes/pkg/scheduler/backend/api_dispatcher/api_dispatcher_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/scheduler/backend/api_dispatcher/api_dispatcher_test.go @@ -22,19 +22,21 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + utilfeature "k8s.io/apiserver/pkg/util/feature" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/fake" + featuregatetesting "k8s.io/component-base/featuregate/testing" "k8s.io/component-base/metrics/testutil" "k8s.io/klog/v2/ktesting" fwk "k8s.io/kube-scheduler/framework" + "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler/metrics" ) -func init() { +func registerAndResetMetrics(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncAPICalls, true) metrics.Register() -} -func resetMetrics() { metrics.AsyncAPICallsTotal.Reset() metrics.AsyncAPICallDuration.Reset() metrics.AsyncAPIPendingCalls.Reset() @@ -100,7 +102,7 @@ func (mac *mockAPICall) IsNoOp() bool { func TestAPIDispatcherLifecycle(t *testing.T) { // Reset all async API metrics - resetMetrics() + registerAndResetMetrics(t) logger, _ := ktesting.NewTestContext(t) diff --git a/deps/github.com/openshift/kubernetes/pkg/scheduler/backend/api_dispatcher/call_queue_test.go b/deps/github.com/openshift/kubernetes/pkg/scheduler/backend/api_dispatcher/call_queue_test.go index 926f3cff75..915ee79708 100644 --- a/deps/github.com/openshift/kubernetes/pkg/scheduler/backend/api_dispatcher/call_queue_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/scheduler/backend/api_dispatcher/call_queue_test.go @@ -106,7 +106,7 @@ func TestCallQueueAdd(t *testing.T) { uid2 := types.UID("uid2") t.Run("First call is added without collision", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) call := &queuedAPICall{ @@ -124,7 +124,7 @@ func TestCallQueueAdd(t *testing.T) { }) t.Run("No-op call is skipped", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) onFinishCh := make(chan error, 1) @@ -149,7 +149,7 @@ func TestCallQueueAdd(t *testing.T) { }) t.Run("Two calls for different objects don't collide", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) call1 := &queuedAPICall{ @@ -176,7 +176,7 @@ func TestCallQueueAdd(t *testing.T) { }) t.Run("New call overwrites less relevant call", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) onFinishCh := make(chan error, 1) @@ -206,7 +206,7 @@ func TestCallQueueAdd(t *testing.T) { }) t.Run("New call is skipped if less relevant", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) onFinishCh := make(chan error, 1) @@ -237,7 +237,7 @@ func TestCallQueueAdd(t *testing.T) { }) t.Run("New call merges with old call and skips if no-op", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) onFinishCh1 := make(chan error, 1) @@ -308,7 +308,7 @@ func TestCallQueuePop(t *testing.T) { uid2 := types.UID("uid2") t.Run("Calls are popped from the queue in FIFO order", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) call1 := &queuedAPICall{ @@ -395,7 +395,7 @@ func TestCallQueueFinalize(t *testing.T) { uid := types.UID("uid") t.Run("Call details are cleared if there is no waiting call", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) call := &queuedAPICall{ @@ -420,7 +420,7 @@ func TestCallQueueFinalize(t *testing.T) { }) t.Run("UID is re-queued if a new call arrived while one was in-flight", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) call1 := &queuedAPICall{ @@ -462,7 +462,7 @@ func TestCallQueueSyncObject(t *testing.T) { uid2 := types.UID("uid2") t.Run("Object is synced with pending call details", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) obj := &metav1.ObjectMeta{ @@ -497,7 +497,7 @@ func TestCallQueueSyncObject(t *testing.T) { }) t.Run("Pending call is canceled if sync results in no-op", func(t *testing.T) { - resetMetrics() + registerAndResetMetrics(t) cq := newCallQueue(mockRelevances) obj := &metav1.ObjectMeta{UID: uid1} diff --git a/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration.go b/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration.go index 9e75df58db..48b9f2fc86 100644 --- a/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration.go +++ b/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration.go @@ -116,8 +116,8 @@ func (pl *TaintToleration) Filter(ctx context.Context, state fwk.CycleState, pod return nil } - errReason := fmt.Sprintf("node(s) had untolerated taint {%s: %s}", taint.Key, taint.Value) - return fwk.NewStatus(fwk.UnschedulableAndUnresolvable, errReason) + klog.FromContext(ctx).V(4).Info("node had untolerated taints", "node", klog.KObj(node), "pod", klog.KObj(pod), "untoleratedTaint", taint) + return fwk.NewStatus(fwk.UnschedulableAndUnresolvable, "node(s) had untolerated taint(s)") } // preScoreState computed at PreScore and used at Score. diff --git a/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration_test.go b/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration_test.go index 058a0ef17b..3af361cc7b 100644 --- a/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration_test.go @@ -283,7 +283,7 @@ func TestTaintTolerationFilter(t *testing.T) { pod: podWithTolerations("pod1", []v1.Toleration{}), node: nodeWithTaints("nodeA", []v1.Taint{{Key: "dedicated", Value: "user1", Effect: "NoSchedule"}}), wantStatus: fwk.NewStatus(fwk.UnschedulableAndUnresolvable, - "node(s) had untolerated taint {dedicated: user1}"), + "node(s) had untolerated taint(s)"), }, { name: "A pod which can be scheduled on a dedicated node assigned to user1 with effect NoSchedule", @@ -295,7 +295,7 @@ func TestTaintTolerationFilter(t *testing.T) { pod: podWithTolerations("pod1", []v1.Toleration{{Key: "dedicated", Operator: "Equal", Value: "user2", Effect: "NoSchedule"}}), node: nodeWithTaints("nodeA", []v1.Taint{{Key: "dedicated", Value: "user1", Effect: "NoSchedule"}}), wantStatus: fwk.NewStatus(fwk.UnschedulableAndUnresolvable, - "node(s) had untolerated taint {dedicated: user1}"), + "node(s) had untolerated taint(s)"), }, { name: "A pod can be scheduled onto the node, with a toleration uses operator Exists that tolerates the taints on the node", @@ -319,7 +319,7 @@ func TestTaintTolerationFilter(t *testing.T) { pod: podWithTolerations("pod1", []v1.Toleration{{Key: "foo", Operator: "Equal", Value: "bar", Effect: "PreferNoSchedule"}}), node: nodeWithTaints("nodeA", []v1.Taint{{Key: "foo", Value: "bar", Effect: "NoSchedule"}}), wantStatus: fwk.NewStatus(fwk.UnschedulableAndUnresolvable, - "node(s) had untolerated taint {foo: bar}"), + "node(s) had untolerated taint(s)"), }, { name: "The pod has a toleration that keys and values match the taint on the node, the effect of toleration is empty, " + diff --git a/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/preemption/preemption.go b/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/preemption/preemption.go index 9bcd91592f..ee98910ef9 100644 --- a/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/preemption/preemption.go +++ b/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/preemption/preemption.go @@ -189,12 +189,12 @@ func NewEvaluator(pluginName string, fh framework.Handle, i Interface, enableAsy } } if err := util.DeletePod(ctx, ev.Handler.ClientSet(), victim); err != nil { - if apierrors.IsNotFound(err) { - logger.V(2).Info("Victim Pod is already deleted", "preemptor", klog.KObj(preemptor), "victim", klog.KObj(victim), "node", c.Name()) - } else { + if !apierrors.IsNotFound(err) { logger.Error(err, "Tried to preempted pod", "pod", klog.KObj(victim), "preemptor", klog.KObj(preemptor)) + return err } - return err + logger.V(2).Info("Victim Pod is already deleted", "preemptor", klog.KObj(preemptor), "victim", klog.KObj(victim), "node", c.Name()) + return nil } logger.V(2).Info("Preemptor Pod preempted victim Pod", "preemptor", klog.KObj(preemptor), "victim", klog.KObj(victim), "node", c.Name()) } @@ -436,14 +436,7 @@ func (ev *Evaluator) prepareCandidate(ctx context.Context, c Candidate, pod *v1. logger := klog.FromContext(ctx) errCh := parallelize.NewErrorChannel() fh.Parallelizer().Until(ctx, len(c.Victims().Pods), func(index int) { - victimPod := c.Victims().Pods[index] - if victimPod.DeletionTimestamp != nil { - // If the victim Pod is already being deleted, we don't have to make another deletion api call. - logger.V(2).Info("Victim Pod is already deleted, skipping the API call for it", "preemptor", klog.KObj(pod), "node", c.Name(), "victim", klog.KObj(victimPod)) - return - } - - if err := ev.PreemptPod(ctx, c, pod, victimPod, pluginName); err != nil && !apierrors.IsNotFound(err) { + if err := ev.PreemptPod(ctx, c, pod, c.Victims().Pods[index], pluginName); err != nil { errCh.SendErrorWithCancel(err, cancel) } }, ev.PluginName) @@ -504,34 +497,11 @@ func (ev *Evaluator) prepareCandidateAsync(c Candidate, pod *v1.Pod, pluginName // Intentionally create a new context, not using a ctx from the scheduling cycle, to create ctx, // because this process could continue even after this scheduling cycle finishes. ctx, cancel := context.WithCancel(context.Background()) - logger := klog.FromContext(ctx) - victimPods := make([]*v1.Pod, 0, len(c.Victims().Pods)) - for _, victim := range c.Victims().Pods { - if victim.DeletionTimestamp != nil { - // If the victim Pod is already being deleted, we don't have to make another deletion api call. - logger.V(2).Info("Victim Pod is already deleted, skipping the API call for it", "preemptor", klog.KObj(pod), "node", c.Name(), "victim", klog.KObj(victim)) - continue - } - victimPods = append(victimPods, victim) - } - if len(victimPods) == 0 { - cancel() - return - } - errCh := parallelize.NewErrorChannel() - // Whether all victim pods are already deleted before making API call. - var allPodsAlreadyDeleted atomic.Bool - allPodsAlreadyDeleted.Store(true) preemptPod := func(index int) { - victim := victimPods[index] - err := ev.PreemptPod(ctx, c, pod, victim, pluginName) - switch { - case err != nil && !apierrors.IsNotFound(err): - // We don't have to handle NotFound error here, because it means the victim Pod is already deleted, and the preemption didn't have to remove it. + victim := c.Victims().Pods[index] + if err := ev.PreemptPod(ctx, c, pod, victim, pluginName); err != nil { errCh.SendErrorWithCancel(err, cancel) - case err == nil: - allPodsAlreadyDeleted.Store(false) } } @@ -539,24 +509,21 @@ func (ev *Evaluator) prepareCandidateAsync(c Candidate, pod *v1.Pod, pluginName ev.preempting.Insert(pod.UID) ev.mu.Unlock() + logger := klog.FromContext(ctx) go func() { startTime := time.Now() result := metrics.GoroutineResultSuccess - defer metrics.PreemptionGoroutinesDuration.WithLabelValues(result).Observe(metrics.SinceInSeconds(startTime)) defer metrics.PreemptionGoroutinesExecutionTotal.WithLabelValues(result).Inc() defer func() { - // When API call isn't successful, the Pod may get stuck in the unschedulable pod pool in the worst case. - // So, we should move the Pod to the activeQ. - if result == metrics.GoroutineResultError || - // When all pods are already deleted (which is very rare, but could happen in theory), - // it's safe to activate the preemptor Pod because it might miss Pod/delete event that requeues the pod. - allPodsAlreadyDeleted.Load() { + if result == metrics.GoroutineResultError { + // When API call isn't successful, the Pod may get stuck in the unschedulable pod pool in the worst case. + // So, we should move the Pod to the activeQ. ev.Handler.Activate(logger, map[string]*v1.Pod{pod.Name: pod}) } }() defer cancel() - logger.V(2).Info("Start the preemption asynchronously", "preemptor", klog.KObj(pod), "node", c.Name(), "numVictims", len(c.Victims().Pods), "numVictimsToDelete", len(victimPods)) + logger.V(2).Info("Start the preemption asynchronously", "preemptor", klog.KObj(pod), "node", c.Name(), "numVictims", len(c.Victims().Pods)) // Lower priority pods nominated to run on this node, may no longer fit on // this node. So, we should remove their nomination. Removing their @@ -569,32 +536,33 @@ func (ev *Evaluator) prepareCandidateAsync(c Candidate, pod *v1.Pod, pluginName // We do not return as this error is not critical. } - if len(victimPods) > 1 { - // We can evict all victims in parallel, but the last one. - // We have to remove the pod from the preempting map before the last one is evicted - // because, otherwise, the pod removal might be notified to the scheduling queue before - // we remove this pod from the preempting map, - // and the pod could end up stucking at the unschedulable pod pool - // by all the pod removal events being ignored. - ev.Handler.Parallelizer().Until(ctx, len(victimPods)-1, preemptPod, ev.PluginName) - if err := errCh.ReceiveError(); err != nil { - utilruntime.HandleErrorWithContext(ctx, err, "Error occurred during async preemption") - result = metrics.GoroutineResultError - } + if len(c.Victims().Pods) == 0 { + ev.mu.Lock() + delete(ev.preempting, pod.UID) + ev.mu.Unlock() + + return + } + + // We can evict all victims in parallel, but the last one. + // We have to remove the pod from the preempting map before the last one is evicted + // because, otherwise, the pod removal might be notified to the scheduling queue before + // we remove this pod from the preempting map, + // and the pod could end up stucking at the unschedulable pod pool + // by all the pod removal events being ignored. + ev.Handler.Parallelizer().Until(ctx, len(c.Victims().Pods)-1, preemptPod, ev.PluginName) + if err := errCh.ReceiveError(); err != nil { + utilruntime.HandleErrorWithContext(ctx, err, "Error occurred during async preemption") + result = metrics.GoroutineResultError } ev.mu.Lock() delete(ev.preempting, pod.UID) ev.mu.Unlock() - err := ev.PreemptPod(ctx, c, pod, victimPods[len(victimPods)-1], pluginName) - switch { - case err != nil && !apierrors.IsNotFound(err): - // We don't have to handle NotFound error here, because it means the victim Pod is already deleted, and the preemption didn't have to remove it. + if err := ev.PreemptPod(ctx, c, pod, c.Victims().Pods[len(c.Victims().Pods)-1], pluginName); err != nil { utilruntime.HandleErrorWithContext(ctx, err, "Error occurred during async preemption") result = metrics.GoroutineResultError - case err == nil: - allPodsAlreadyDeleted.Store(false) } logger.V(2).Info("Async Preemption finished completely", "preemptor", klog.KObj(pod), "node", c.Name(), "result", result) diff --git a/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/preemption/preemption_test.go b/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/preemption/preemption_test.go index 5a37f0df4f..e8b0a80eca 100644 --- a/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/preemption/preemption_test.go +++ b/deps/github.com/openshift/kubernetes/pkg/scheduler/framework/preemption/preemption_test.go @@ -30,7 +30,6 @@ import ( v1 "k8s.io/api/core/v1" policy "k8s.io/api/policy/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -45,12 +44,12 @@ import ( "k8s.io/klog/v2/ktesting" extenderv1 "k8s.io/kube-scheduler/extender/v1" fwk "k8s.io/kube-scheduler/framework" - apicache "k8s.io/kubernetes/pkg/scheduler/backend/api_cache" - apidispatcher "k8s.io/kubernetes/pkg/scheduler/backend/api_dispatcher" + "k8s.io/kubernetes/pkg/scheduler/backend/api_cache" + "k8s.io/kubernetes/pkg/scheduler/backend/api_dispatcher" internalcache "k8s.io/kubernetes/pkg/scheduler/backend/cache" internalqueue "k8s.io/kubernetes/pkg/scheduler/backend/queue" "k8s.io/kubernetes/pkg/scheduler/framework" - apicalls "k8s.io/kubernetes/pkg/scheduler/framework/api_calls" + "k8s.io/kubernetes/pkg/scheduler/framework/api_calls" "k8s.io/kubernetes/pkg/scheduler/framework/parallelize" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultbinder" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/queuesort" @@ -421,10 +420,6 @@ func TestPrepareCandidate(t *testing.T) { Containers([]v1.Container{st.MakeContainer().Name("container1").Obj()}). Obj() - notFoundVictim1 = st.MakePod().Name("not-found-victim").UID("victim1"). - Node(node1Name).SchedulerName(defaultSchedulerName).Priority(midPriority). - Containers([]v1.Container{st.MakeContainer().Name("container1").Obj()}). - Obj() failVictim = st.MakePod().Name("fail-victim").UID("victim1"). Node(node1Name).SchedulerName(defaultSchedulerName).Priority(midPriority). Containers([]v1.Container{st.MakeContainer().Name("container1").Obj()}). @@ -456,12 +451,6 @@ func TestPrepareCandidate(t *testing.T) { errPatchStatusFailed = errors.New("patch pod status failed") ) - victimWithDeletionTimestamp := victim1.DeepCopy() - victimWithDeletionTimestamp.Name = "victim1-with-deletion-timestamp" - victimWithDeletionTimestamp.UID = "victim1-with-deletion-timestamp" - victimWithDeletionTimestamp.DeletionTimestamp = &metav1.Time{Time: time.Now().Add(-100 * time.Second)} - victimWithDeletionTimestamp.Finalizers = []string{"test"} - tests := []struct { name string nodeNames []string @@ -490,8 +479,9 @@ func TestPrepareCandidate(t *testing.T) { testPods: []*v1.Pod{ victim1, }, - nodeNames: []string{node1Name}, - expectedStatus: nil, + nodeNames: []string{node1Name}, + expectedStatus: nil, + expectedPreemptingMap: sets.New(types.UID("preemptor")), }, { name: "one victim without condition", @@ -513,42 +503,6 @@ func TestPrepareCandidate(t *testing.T) { expectedStatus: nil, expectedPreemptingMap: sets.New(types.UID("preemptor")), }, - { - name: "one victim, but victim is already being deleted", - - candidate: &fakeCandidate{ - name: node1Name, - victims: &extenderv1.Victims{ - Pods: []*v1.Pod{ - victimWithDeletionTimestamp, - }, - }, - }, - preemptor: preemptor, - testPods: []*v1.Pod{ - victimWithDeletionTimestamp, - }, - nodeNames: []string{node1Name}, - expectedStatus: nil, - }, - { - name: "one victim, but victim is already deleted", - - candidate: &fakeCandidate{ - name: node1Name, - victims: &extenderv1.Victims{ - Pods: []*v1.Pod{ - notFoundVictim1, - }, - }, - }, - preemptor: preemptor, - testPods: []*v1.Pod{}, - nodeNames: []string{node1Name}, - expectedStatus: nil, - expectedActivatedPods: map[string]*v1.Pod{preemptor.Name: preemptor}, - expectedPreemptingMap: sets.New(types.UID("preemptor")), - }, { name: "one victim with same condition", @@ -709,11 +663,6 @@ func TestPrepareCandidate(t *testing.T) { deletionFailure = true return true, nil, errDeletePodFailed } - // fake clientset does not return an error for not-found pods, so we simulate it here. - if name == "not-found-victim" { - // Simulate a not-found error. - return true, nil, apierrors.NewNotFound(v1.Resource("pods"), name) - } deletedPods.Insert(name) return true, nil, nil @@ -726,10 +675,6 @@ func TestPrepareCandidate(t *testing.T) { patchFailure = true return true, nil, errPatchStatusFailed } - // fake clientset does not return an error for not-found pods, so we simulate it here. - if action.(clienttesting.PatchAction).GetName() == "not-found-victim" { - return true, nil, apierrors.NewNotFound(v1.Resource("pods"), "not-found-victim") - } return true, nil, nil }) diff --git a/deps/github.com/openshift/kubernetes/pkg/volume/csi/csi_attacher.go b/deps/github.com/openshift/kubernetes/pkg/volume/csi/csi_attacher.go index 314fe68a85..c4fd435064 100644 --- a/deps/github.com/openshift/kubernetes/pkg/volume/csi/csi_attacher.go +++ b/deps/github.com/openshift/kubernetes/pkg/volume/csi/csi_attacher.go @@ -252,7 +252,7 @@ func (c *csiAttacher) VolumesAreAttached(specs []*volume.Spec, nodeName types.No } func (c *csiAttacher) GetDeviceMountPath(spec *volume.Spec) (string, error) { - klog.V(4).Info(log("attacher.GetDeviceMountPath(%v)", spec)) + klog.V(4).Info(log("attacher.GetDeviceMountPath for volume(%s)", spec.Name())) deviceMountPath, err := makeDeviceMountPath(c.plugin, spec) if err != nil { return "", errors.New(log("attacher.GetDeviceMountPath failed to make device mount path: %v", err)) diff --git a/deps/github.com/openshift/kubernetes/pkg/volume/plugins.go b/deps/github.com/openshift/kubernetes/pkg/volume/plugins.go index a6426cbd9d..24b661493f 100644 --- a/deps/github.com/openshift/kubernetes/pkg/volume/plugins.go +++ b/deps/github.com/openshift/kubernetes/pkg/volume/plugins.go @@ -997,7 +997,7 @@ func NewPersistentVolumeRecyclerPodTemplate() *v1.Pod { Containers: []v1.Container{ { Name: "pv-recycler", - Image: "registry.k8s.io/build-image/debian-base:bookworm-v1.0.4", + Image: "registry.k8s.io/build-image/debian-base:bookworm-v1.0.6", Command: []string{"/bin/sh"}, Args: []string{"-c", "test -e /scrub && find /scrub -mindepth 1 -delete && test -z \"$(ls -A /scrub)\" || exit 1"}, VolumeMounts: []v1.VolumeMount{ diff --git a/deps/github.com/openshift/kubernetes/pkg/volume/portworx/portworx.go b/deps/github.com/openshift/kubernetes/pkg/volume/portworx/portworx.go index c41f06b3a0..f8d4c348c4 100644 --- a/deps/github.com/openshift/kubernetes/pkg/volume/portworx/portworx.go +++ b/deps/github.com/openshift/kubernetes/pkg/volume/portworx/portworx.go @@ -308,8 +308,9 @@ func (b *portworxVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterAr notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) klog.Infof("Portworx Volume set up. Dir: %s %v %v", dir, !notMnt, err) if err != nil && !os.IsNotExist(err) { - klog.Errorf("Cannot validate mountpoint: %s", dir) - return err + // don't log error details from client calls in events + klog.V(4).Infof("Cannot validate mountpoint %s: %v", dir, err) + return fmt.Errorf("failed to validate mountpoint: see kube-controller-manager.log for details") } if !notMnt { return nil @@ -319,7 +320,9 @@ func (b *portworxVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterAr attachOptions[attachContextKey] = dir attachOptions[attachHostKey] = b.plugin.host.GetHostName() if _, err := b.manager.AttachVolume(b, attachOptions); err != nil { - return err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to attach volume %s: %v", b.volumeID, err) + return fmt.Errorf("failed to attach volume: see kube-controller-manager.log for details") } klog.V(4).Infof("Portworx Volume %s attached", b.volumeID) @@ -329,7 +332,9 @@ func (b *portworxVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterAr } if err := b.manager.MountVolume(b, dir); err != nil { - return err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to mount volume %s: %v", b.volumeID, err) + return fmt.Errorf("failed to mount volume: see kube-controller-manager.log for details") } if !b.readOnly { // Since portworxVolume is in process of being removed from in-tree, we avoid larger refactor to add progress tracking for ownership operation @@ -362,12 +367,16 @@ func (c *portworxVolumeUnmounter) TearDownAt(dir string) error { klog.Infof("Portworx Volume TearDown of %s", dir) if err := c.manager.UnmountVolume(c, dir); err != nil { - return err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to unmount volume %s: %v", c.volumeID, err) + return fmt.Errorf("failed to unmount volume: see kube-controller-manager.log for details") } // Call Portworx Detach Volume. if err := c.manager.DetachVolume(c); err != nil { - return err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to detach volume %s: %v", c.volumeID, err) + return fmt.Errorf("failed to detach volume: see kube-controller-manager.log for details") } return nil @@ -384,7 +393,13 @@ func (d *portworxVolumeDeleter) GetPath() string { } func (d *portworxVolumeDeleter) Delete() error { - return d.manager.DeleteVolume(d) + err := d.manager.DeleteVolume(d) + if err != nil { + // don't log error details from client calls in events + klog.V(4).Infof("Failed to delete volume %s: %v", d.volumeID, err) + return fmt.Errorf("failed to delete volume: see kube-controller-manager.log for details") + } + return nil } type portworxVolumeProvisioner struct { @@ -405,7 +420,9 @@ func (c *portworxVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopo volumeID, sizeGiB, labels, err := c.manager.CreateVolume(c) if err != nil { - return nil, err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to create volume: %v", err) + return nil, fmt.Errorf("failed to create volume: see kube-controller-manager.log for details") } pv := &v1.PersistentVolume{ diff --git a/deps/github.com/openshift/kubernetes/staging/publishing/rules.yaml b/deps/github.com/openshift/kubernetes/staging/publishing/rules.yaml index f9952f7fb5..76723a7c5d 100644 --- a/deps/github.com/openshift/kubernetes/staging/publishing/rules.yaml +++ b/deps/github.com/openshift/kubernetes/staging/publishing/rules.yaml @@ -19,13 +19,13 @@ rules: dirs: - staging/src/k8s.io/apimachinery - name: release-1.33 - go: 1.24.6 + go: 1.24.9 source: branch: release-1.33 dirs: - staging/src/k8s.io/apimachinery - name: release-1.34 - go: 1.24.6 + go: 1.24.9 source: branch: release-1.34 dirs: @@ -60,7 +60,7 @@ rules: dirs: - staging/src/k8s.io/api - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -69,7 +69,7 @@ rules: dirs: - staging/src/k8s.io/api - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -125,7 +125,7 @@ rules: go build -mod=mod ./... go test -mod=mod ./... - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -140,7 +140,7 @@ rules: go build -mod=mod ./... go test -mod=mod ./... - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -184,7 +184,7 @@ rules: dirs: - staging/src/k8s.io/code-generator - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -193,7 +193,7 @@ rules: dirs: - staging/src/k8s.io/code-generator - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -242,7 +242,7 @@ rules: dirs: - staging/src/k8s.io/component-base - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -255,7 +255,7 @@ rules: dirs: - staging/src/k8s.io/component-base - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -309,7 +309,7 @@ rules: dirs: - staging/src/k8s.io/component-helpers - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -322,7 +322,7 @@ rules: dirs: - staging/src/k8s.io/component-helpers - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -364,7 +364,7 @@ rules: dirs: - staging/src/k8s.io/kms - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -373,7 +373,7 @@ rules: dirs: - staging/src/k8s.io/kms - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -435,7 +435,7 @@ rules: dirs: - staging/src/k8s.io/apiserver - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -452,7 +452,7 @@ rules: dirs: - staging/src/k8s.io/apiserver - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -534,7 +534,7 @@ rules: dirs: - staging/src/k8s.io/kube-aggregator - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -555,7 +555,7 @@ rules: dirs: - staging/src/k8s.io/kube-aggregator - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -655,7 +655,7 @@ rules: # assumes GO111MODULE=on go build -mod=mod . - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -681,7 +681,7 @@ rules: # assumes GO111MODULE=on go build -mod=mod . - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -768,7 +768,7 @@ rules: # assumes GO111MODULE=on go build -mod=mod . - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -788,7 +788,7 @@ rules: # assumes GO111MODULE=on go build -mod=mod . - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -878,7 +878,7 @@ rules: required-packages: - k8s.io/code-generator - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -901,7 +901,7 @@ rules: required-packages: - k8s.io/code-generator - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -970,7 +970,7 @@ rules: dirs: - staging/src/k8s.io/metrics - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -985,7 +985,7 @@ rules: dirs: - staging/src/k8s.io/metrics - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -1041,7 +1041,7 @@ rules: dirs: - staging/src/k8s.io/cli-runtime - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.33 @@ -1054,7 +1054,7 @@ rules: dirs: - staging/src/k8s.io/cli-runtime - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.34 @@ -1114,7 +1114,7 @@ rules: dirs: - staging/src/k8s.io/sample-cli-plugin - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.33 @@ -1129,7 +1129,7 @@ rules: dirs: - staging/src/k8s.io/sample-cli-plugin - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.34 @@ -1190,7 +1190,7 @@ rules: dirs: - staging/src/k8s.io/kube-proxy - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -1205,7 +1205,7 @@ rules: dirs: - staging/src/k8s.io/kube-proxy - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -1240,13 +1240,13 @@ rules: dirs: - staging/src/k8s.io/cri-api - name: release-1.33 - go: 1.24.6 + go: 1.24.9 source: branch: release-1.33 dirs: - staging/src/k8s.io/cri-api - name: release-1.34 - go: 1.24.6 + go: 1.24.9 source: branch: release-1.34 dirs: @@ -1305,7 +1305,7 @@ rules: dirs: - staging/src/k8s.io/cri-client - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.33 @@ -1322,7 +1322,7 @@ rules: dirs: - staging/src/k8s.io/cri-client - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.34 @@ -1404,7 +1404,7 @@ rules: dirs: - staging/src/k8s.io/kubelet - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -1425,7 +1425,7 @@ rules: dirs: - staging/src/k8s.io/kubelet - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -1493,7 +1493,7 @@ rules: dirs: - staging/src/k8s.io/kube-scheduler - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -1508,7 +1508,7 @@ rules: dirs: - staging/src/k8s.io/kube-scheduler - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -1582,7 +1582,7 @@ rules: dirs: - staging/src/k8s.io/controller-manager - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.33 @@ -1601,7 +1601,7 @@ rules: dirs: - staging/src/k8s.io/controller-manager - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.34 @@ -1691,7 +1691,7 @@ rules: dirs: - staging/src/k8s.io/cloud-provider - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.33 @@ -1714,7 +1714,7 @@ rules: dirs: - staging/src/k8s.io/cloud-provider - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.34 @@ -1814,7 +1814,7 @@ rules: dirs: - staging/src/k8s.io/kube-controller-manager - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -1839,7 +1839,7 @@ rules: dirs: - staging/src/k8s.io/kube-controller-manager - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -1899,7 +1899,7 @@ rules: dirs: - staging/src/k8s.io/cluster-bootstrap - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -1910,7 +1910,7 @@ rules: dirs: - staging/src/k8s.io/cluster-bootstrap - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -1956,7 +1956,7 @@ rules: dirs: - staging/src/k8s.io/csi-translation-lib - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.33 @@ -1967,7 +1967,7 @@ rules: dirs: - staging/src/k8s.io/csi-translation-lib - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.34 @@ -1998,13 +1998,13 @@ rules: dirs: - staging/src/k8s.io/mount-utils - name: release-1.33 - go: 1.24.6 + go: 1.24.9 source: branch: release-1.33 dirs: - staging/src/k8s.io/mount-utils - name: release-1.34 - go: 1.24.6 + go: 1.24.9 source: branch: release-1.34 dirs: @@ -2081,7 +2081,7 @@ rules: dirs: - staging/src/k8s.io/kubectl - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.33 @@ -2104,7 +2104,7 @@ rules: dirs: - staging/src/k8s.io/kubectl - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.34 @@ -2186,7 +2186,7 @@ rules: dirs: - staging/src/k8s.io/pod-security-admission - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.33 @@ -2205,7 +2205,7 @@ rules: dirs: - staging/src/k8s.io/pod-security-admission - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.34 @@ -2301,7 +2301,7 @@ rules: dirs: - staging/src/k8s.io/dynamic-resource-allocation - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.33 @@ -2326,7 +2326,7 @@ rules: dirs: - staging/src/k8s.io/dynamic-resource-allocation - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: apimachinery branch: release-1.34 @@ -2397,7 +2397,7 @@ rules: dirs: - staging/src/k8s.io/endpointslice - name: release-1.33 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.33 @@ -2412,7 +2412,7 @@ rules: dirs: - staging/src/k8s.io/endpointslice - name: release-1.34 - go: 1.24.6 + go: 1.24.9 dependencies: - repository: api branch: release-1.34 @@ -2440,17 +2440,17 @@ rules: dirs: - staging/src/k8s.io/externaljwt - name: release-1.33 - go: 1.24.6 + go: 1.24.9 source: branch: release-1.33 dirs: - staging/src/k8s.io/externaljwt - name: release-1.34 - go: 1.24.6 + go: 1.24.9 source: branch: release-1.34 dirs: - staging/src/k8s.io/externaljwt recursive-delete-patterns: - '*/.gitattributes' -default-go-version: 1.24.6 +default-go-version: 1.24.9 diff --git a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics_test.go b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics_test.go index 9fa48014dc..b8f7e72315 100644 --- a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics_test.go +++ b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics_test.go @@ -107,9 +107,16 @@ func TestAuthorizerMetrics(t *testing.T) { if service.statusCode == 0 { service.statusCode = 200 } - service.reviewHook = func(*authorizationv1.SubjectAccessReview) { - if scenario.canceledRequest { + + testFinishedCtx, testFinishedCancel := context.WithCancel(context.Background()) + defer testFinishedCancel() + if scenario.canceledRequest { + service.reviewHook = func(*authorizationv1.SubjectAccessReview) { cancel() + // net/http transport still attempts to use a response if it's + // available right when it's handling context cancellation, + // we need to delay the response. + <-testFinishedCtx.Done() } } service.allow = !scenario.authFakeServiceDeny @@ -120,6 +127,9 @@ func TestAuthorizerMetrics(t *testing.T) { return } defer server.Close() + // testFinishedCtx must be cancelled before we close the server, otherwise + // closing the server hangs on an active connection from the listener. + defer testFinishedCancel() fakeAuthzMetrics := &fakeAuthorizerMetrics{} wh, err := newV1Authorizer(server.URL, scenario.clientCert, scenario.clientKey, scenario.clientCA, 0, fakeAuthzMetrics, cel.NewDefaultCompiler(), []apiserver.WebhookMatchCondition{}, "") diff --git a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock.go b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock.go index 5d2054155c..79a748b74d 100644 --- a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock.go +++ b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock.go @@ -77,6 +77,9 @@ func (ll *LeaseLock) Update(ctx context.Context, ler LeaderElectionRecord) error ll.lease.Spec = LeaderElectionRecordToLeaseSpec(&ler) if ll.Labels != nil { + if ll.lease.Labels == nil { + ll.lease.Labels = map[string]string{} + } // Only overwrite the labels that are specifically set for k, v := range ll.Labels { ll.lease.Labels[k] = v diff --git a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock_test.go b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock_test.go index b6d1af532e..f30bcfe284 100644 --- a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock_test.go +++ b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock_test.go @@ -266,7 +266,7 @@ func TestLeaseConversion(t *testing.T) { } } -func TestUpdateWithNilLabels(t *testing.T) { +func TestUpdateWithNilLabelsOnLease(t *testing.T) { setup() // Create initial lease @@ -278,23 +278,33 @@ func TestUpdateWithNilLabels(t *testing.T) { t.Fatalf("Failed to get lease: %v", err) } - leaseLock.lease.Labels = map[string]string{"custom-key": "custom-val"} + leaseLock.lease.Labels = nil - // Update labels - lease, err := leaseLock.Client.Leases(testNamespace).Update(context.Background(), leaseLock.lease, metav1.UpdateOptions{}) - if err != nil { - t.Fatalf("Failed to update lease labels: %v", err) + leaseLock.Labels = map[string]string{"custom-key": "custom-val"} + + // Update should succeed even with nil Labels on the lease itself + if err := leaseLock.Update(context.Background(), testRecord); err != nil { + t.Errorf("Update failed with nil Labels: %v", err) } +} - val, exists := lease.Labels["custom-key"] - if !exists { - t.Error("Label was overidden on the lease") +func TestUpdateWithNilLabelsOnLeaseLock(t *testing.T) { + setup() + + // Create initial lease + if err := leaseLock.Create(context.Background(), testRecord); err != nil { + t.Fatalf("Failed to create lease: %v", err) } - if val != "custom-val" { - t.Errorf("Label value mismatch, got %q want %q", val, "custom-val") + // Get the lease to initialize leaseLock.lease + if _, _, err := leaseLock.Get(context.Background()); err != nil { + t.Fatalf("Failed to get lease: %v", err) } - // Update should succeed even with nil Labels + leaseLock.Labels = nil + + leaseLock.lease.Labels = map[string]string{"custom-key": "custom-val"} + + // Update should succeed even with nil Labels on the leaselock if err := leaseLock.Update(context.Background(), testRecord); err != nil { t.Errorf("Update failed with nil Labels: %v", err) } diff --git a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/util/cert/cert.go b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/util/cert/cert.go index 1220461264..48c78b595e 100644 --- a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/util/cert/cert.go +++ b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/util/cert/cert.go @@ -75,13 +75,15 @@ func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, erro CommonName: cfg.CommonName, Organization: cfg.Organization, }, - DNSNames: []string{cfg.CommonName}, NotBefore: notBefore, NotAfter: now.Add(duration365d * 10).UTC(), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, IsCA: true, } + if len(cfg.CommonName) > 0 { + tmpl.DNSNames = []string{cfg.CommonName} + } certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &tmpl, &tmpl, key.Public(), key) if err != nil { diff --git a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/allocatortesting/allocator_testing.go b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/allocatortesting/allocator_testing.go index dcf2bf02b5..f145e76c5a 100644 --- a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/allocatortesting/allocator_testing.go +++ b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/allocatortesting/allocator_testing.go @@ -87,6 +87,7 @@ const ( claim1 = "claim-1" slice1 = "slice-1" slice2 = "slice-2" + device0 = "device-0" device1 = "device-1" device2 = "device-2" device3 = "device-3" @@ -1989,12 +1990,51 @@ func TestAllocator(t *testing.T, node: node(node1, region1), expectResults: []any{ - allocationResultWithConfig( + allocationResultWithConfigs( localNodeSelector(node1), - driverA, - resourceapi.AllocationConfigSourceClass, - "classAttribute", - deviceAllocationResult(req0, driverA, pool1, device1, false), + objects(deviceAllocationResult(req0, driverA, pool1, device1, false)), + []resourceapi.DeviceAllocationConfiguration{ + { + Source: resourceapi.AllocationConfigSourceClass, + Requests: []string{req0}, + DeviceConfiguration: deviceConfiguration(driverA, "classAttribute"), + }, + }, + ), + }, + }, + "with-class-device-config-with-multiple-request-and-configs": { + claimsToAllocate: objects(claimWithRequests(claim0, []resourceapi.DeviceConstraint{}, request(req0, classA, 1), request(req1, classA, 1), request(req2, classB, 1))), + classes: objects( + classWithConfig(classA, driverA, "classAttribute-A"), + classWithConfig(classB, driverB, "classAttribute-B"), + ), + slices: unwrap( + sliceWithMultipleDevices(slice1, node1, pool1, driverA, 2), + sliceWithOneDevice(slice2, node1, pool1, driverB), + ), + node: node(node1, region1), + + expectResults: []any{ + allocationResultWithConfigs( + localNodeSelector(node1), + objects( + deviceAllocationResult(req0, driverA, pool1, device0, false), + deviceAllocationResult(req1, driverA, pool1, device1, false), + deviceAllocationResult(req2, driverB, pool1, device1, false), + ), + []resourceapi.DeviceAllocationConfiguration{ + { + Source: resourceapi.AllocationConfigSourceClass, + Requests: []string{req0, req1}, + DeviceConfiguration: deviceConfiguration(driverA, "classAttribute-A"), + }, + { + Source: resourceapi.AllocationConfigSourceClass, + Requests: []string{req2}, + DeviceConfiguration: deviceConfiguration(driverB, "classAttribute-B"), + }, + }, ), }, }, @@ -2245,7 +2285,7 @@ func TestAllocator(t *testing.T, []resourceapi.DeviceAllocationConfiguration{ { Source: resourceapi.AllocationConfigSourceClass, - Requests: nil, + Requests: []string{req0SubReq1}, DeviceConfiguration: deviceConfiguration(driverB, "bar"), }, }, diff --git a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go index 84218307c6..6b3c69b791 100644 --- a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go +++ b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go @@ -388,6 +388,11 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } // Populate configs. + + // Each class config gets added only once. + // We need to keep track of which class configs have already been added and at which position in the allocationResult.Devices.Config. + type configRange struct{ start, end int } + configIndexesForClass := make(map[string]configRange) // Key: class name / Value: position of the configs for the class in allocationResult.Devices.Config. for requestIndex := range claim.Spec.Devices.Requests { requestKey := requestIndices{claimIndex: claimIndex, requestIndex: requestIndex} requestData := alloc.requestData[requestKey] @@ -398,15 +403,29 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } class := requestData.class - if class != nil { - for _, config := range class.Spec.Config { - allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ - Source: resourceapi.AllocationConfigSourceClass, - Requests: nil, // All of them... - DeviceConfiguration: config.DeviceConfiguration, - }) + if class == nil { + continue + } + configIndexes, exists := configIndexesForClass[class.Name] + if exists { + // The configs for the class have already been added. + // Just append the request name for the request class. + for i := configIndexes.start; i < configIndexes.end; i++ { + allocationResult.Devices.Config[i].Requests = append(allocationResult.Devices.Config[i].Requests, requestData.requestName()) } + continue } + + // Add all configs for the class once. + initialConfigLen := len(allocationResult.Devices.Config) + for _, config := range class.Spec.Config { + allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ + Source: resourceapi.AllocationConfigSourceClass, + Requests: []string{requestData.requestName()}, + DeviceConfiguration: config.DeviceConfiguration, + }) + } + configIndexesForClass[class.Name] = configRange{start: initialConfigLen, end: len(allocationResult.Devices.Config)} } for _, config := range claim.Spec.Devices.Config { // If Requests are empty, it applies to all. So it can just be included. @@ -646,6 +665,13 @@ type requestData struct { allDevices []deviceWithID } +func (rd *requestData) requestName() string { + if rd.parentRequest != nil { + return fmt.Sprintf("%s/%s", rd.parentRequest.name(), rd.request.name()) + } + return rd.request.name() +} + type deviceWithID struct { *draapi.Device id DeviceID diff --git a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go index d65235e35b..b3b4f7d2c6 100644 --- a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go +++ b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go @@ -295,6 +295,11 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } // Populate configs. + + // Each class config gets added only once. + // We need to keep track of which class configs have already been added and at which position in the allocationResult.Devices.Config. + type configRange struct{ start, end int } + configIndexesForClass := make(map[string]configRange) // Key: class name / Value: position of the configs for the class in allocationResult.Devices.Config. for requestIndex := range claim.Spec.Devices.Requests { requestKey := requestIndices{claimIndex: claimIndex, requestIndex: requestIndex} requestData := alloc.requestData[requestKey] @@ -305,15 +310,29 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } class := requestData.class - if class != nil { - for _, config := range class.Spec.Config { - allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ - Source: resourceapi.AllocationConfigSourceClass, - Requests: nil, // All of them... - DeviceConfiguration: config.DeviceConfiguration, - }) + if class == nil { + continue + } + configIndexes, exists := configIndexesForClass[class.Name] + if exists { + // The configs for the class have already been added. + // Just append the request name for the request class. + for i := configIndexes.start; i < configIndexes.end; i++ { + allocationResult.Devices.Config[i].Requests = append(allocationResult.Devices.Config[i].Requests, requestData.requestName()) } + continue } + + // Add all configs for the class once. + initialConfigLen := len(allocationResult.Devices.Config) + for _, config := range class.Spec.Config { + allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ + Source: resourceapi.AllocationConfigSourceClass, + Requests: []string{requestData.requestName()}, + DeviceConfiguration: config.DeviceConfiguration, + }) + } + configIndexesForClass[class.Name] = configRange{start: initialConfigLen, end: len(allocationResult.Devices.Config)} } for _, config := range claim.Spec.Devices.Config { // If Requests are empty, it applies to all. So it can just be included. @@ -535,6 +554,13 @@ type requestData struct { allDevices []deviceWithID } +func (rd *requestData) requestName() string { + if rd.parentRequest != nil { + return fmt.Sprintf("%s/%s", rd.parentRequest.name(), rd.request.name()) + } + return rd.request.name() +} + type deviceWithID struct { *draapi.Device id DeviceID diff --git a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/stable/allocator_stable.go b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/stable/allocator_stable.go index d5b118e931..54440746b7 100644 --- a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/stable/allocator_stable.go +++ b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation/structured/internal/stable/allocator_stable.go @@ -286,6 +286,11 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } // Populate configs. + + // Each class config gets added only once. + // We need to keep track of which class configs have already been added and at which position in the allocationResult.Devices.Config. + type configRange struct{ start, end int } + configIndexesForClass := make(map[string]configRange) // Key: class name / Value: position of the configs for the class in allocationResult.Devices.Config. for requestIndex := range claim.Spec.Devices.Requests { requestKey := requestIndices{claimIndex: claimIndex, requestIndex: requestIndex} requestData := alloc.requestData[requestKey] @@ -296,15 +301,29 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } class := requestData.class - if class != nil { - for _, config := range class.Spec.Config { - allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ - Source: resourceapi.AllocationConfigSourceClass, - Requests: nil, // All of them... - DeviceConfiguration: config.DeviceConfiguration, - }) + if class == nil { + continue + } + configIndexes, exists := configIndexesForClass[class.Name] + if exists { + // The configs for the class have already been added. + // Just append the request name for the request class. + for i := configIndexes.start; i < configIndexes.end; i++ { + allocationResult.Devices.Config[i].Requests = append(allocationResult.Devices.Config[i].Requests, requestData.requestName()) } + continue } + + // Add all configs for the class once. + initialConfigLen := len(allocationResult.Devices.Config) + for _, config := range class.Spec.Config { + allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ + Source: resourceapi.AllocationConfigSourceClass, + Requests: []string{requestData.requestName()}, + DeviceConfiguration: config.DeviceConfiguration, + }) + } + configIndexesForClass[class.Name] = configRange{start: initialConfigLen, end: len(allocationResult.Devices.Config)} } for _, config := range claim.Spec.Devices.Config { // If Requests are empty, it applies to all. So it can just be included. @@ -517,6 +536,13 @@ type requestData struct { allDevices []deviceWithID } +func (rd *requestData) requestName() string { + if rd.parentRequest != nil { + return fmt.Sprintf("%s/%s", rd.parentRequest.name(), rd.request.name()) + } + return rd.request.name() +} + type deviceWithID struct { *draapi.Device id DeviceID diff --git a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/apiresources/apiresources.go b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/apiresources/apiresources.go index 1959cc1109..9a45cd907d 100644 --- a/deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/apiresources/apiresources.go +++ b/deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubectl/pkg/cmd/apiresources/apiresources.go @@ -229,6 +229,9 @@ func (o *APIResourceOptions) RunAPIResources() error { allResources = append(allResources, apiList) } + if len(allResources) == 0 { + return utilerrors.NewAggregate(errs) + } flatList := &metav1.APIResourceList{ TypeMeta: metav1.TypeMeta{ APIVersion: allResources[0].APIVersion, diff --git a/deps/github.com/openshift/kubernetes/test/compatibility_lifecycle/reference/versioned_feature_list.yaml b/deps/github.com/openshift/kubernetes/test/compatibility_lifecycle/reference/versioned_feature_list.yaml index fd3ca8715f..b1e225f9a8 100644 --- a/deps/github.com/openshift/kubernetes/test/compatibility_lifecycle/reference/versioned_feature_list.yaml +++ b/deps/github.com/openshift/kubernetes/test/compatibility_lifecycle/reference/versioned_feature_list.yaml @@ -1417,7 +1417,7 @@ version: "1.29" - name: SchedulerAsyncAPICalls versionedSpecs: - - default: true + - default: false lockToDefault: false preRelease: Beta version: "1.34" @@ -1633,6 +1633,12 @@ lockToDefault: true preRelease: GA version: "1.32" +- name: StatefulSetSemanticRevisionComparison + versionedSpecs: + - default: true + lockToDefault: false + preRelease: Beta + version: "1.0" - name: StorageCapacityScoring versionedSpecs: - default: false diff --git a/deps/github.com/openshift/kubernetes/test/conformance/image/Makefile b/deps/github.com/openshift/kubernetes/test/conformance/image/Makefile index 17f84faa2f..61a963f635 100644 --- a/deps/github.com/openshift/kubernetes/test/conformance/image/Makefile +++ b/deps/github.com/openshift/kubernetes/test/conformance/image/Makefile @@ -33,7 +33,7 @@ CLUSTER_DIR?=$(shell pwd)/../../../cluster/ # This is defined in root Makefile, but some build contexts do not refer to them KUBE_BASE_IMAGE_REGISTRY?=registry.k8s.io -BASE_IMAGE_VERSION?=bookworm-v1.0.4 +BASE_IMAGE_VERSION?=bookworm-v1.0.6 RUNNERIMAGE?=${KUBE_BASE_IMAGE_REGISTRY}/build-image/debian-base-${ARCH}:${BASE_IMAGE_VERSION} TEMP_DIR:=$(shell mktemp -d -t conformance-XXXXXX) diff --git a/deps/github.com/openshift/kubernetes/test/e2e/common/node/framework/cgroups/cgroups_linux.go b/deps/github.com/openshift/kubernetes/test/e2e/common/node/framework/cgroups/cgroups_linux.go index c77c560d50..c7f3064b50 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/common/node/framework/cgroups/cgroups_linux.go +++ b/deps/github.com/openshift/kubernetes/test/e2e/common/node/framework/cgroups/cgroups_linux.go @@ -17,13 +17,33 @@ limitations under the License. package cgroups import ( + "math" "strconv" - libcontainercgroups "github.com/opencontainers/cgroups" v1 "k8s.io/api/core/v1" kubecm "k8s.io/kubernetes/pkg/kubelet/cm" ) +// convertCPUSharesToCgroupV2Value is copied from ConvertCPUSharesToCgroupV2Value in opencontainers/cgroups. +// https://github.com/opencontainers/cgroups/pull/20/files +func convertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 { + // The value of 0 means "unset". + if cpuShares == 0 { + return 0 + } + if cpuShares <= 2 { + return 1 + } + if cpuShares >= 262144 { + return 10000 + } + l := math.Log2(float64(cpuShares)) + // Quadratic function which fits min, max, and default. + exponent := (l*l+125*l)/612.0 - 7.0/34.0 + + return uint64(math.Ceil(math.Pow(10, exponent))) +} + func getExpectedCPUShares(rr *v1.ResourceRequirements, podOnCgroupv2 bool) []string { // This function is moved out from cgroups.go because opencontainers/cgroups can only be compiled in linux platforms. cpuRequest := rr.Requests.Cpu() @@ -42,7 +62,7 @@ func getExpectedCPUShares(rr *v1.ResourceRequirements, podOnCgroupv2 bool) []str // container runtimes, we check if either the old or the new conversion matches the actual value for now. // TODO: Remove the old conversion once container runtimes are updated. oldConverted := 1 + ((shares-2)*9999)/262142 - converted := libcontainercgroups.ConvertCPUSharesToCgroupV2Value(uint64(shares)) + converted := convertCPUSharesToCgroupV2Value(uint64(shares)) return []string{strconv.FormatInt(oldConverted, 10), strconv.FormatInt(int64(converted), 10)} } else { return []string{strconv.FormatInt(shares, 10)} diff --git a/deps/github.com/openshift/kubernetes/test/e2e/framework/metrics/kubelet_metrics.go b/deps/github.com/openshift/kubernetes/test/e2e/framework/metrics/kubelet_metrics.go index fd0776d1b2..ae7a7e211e 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/framework/metrics/kubelet_metrics.go +++ b/deps/github.com/openshift/kubernetes/test/e2e/framework/metrics/kubelet_metrics.go @@ -33,7 +33,6 @@ import ( ) const ( - proxyTimeout = 2 * time.Minute // dockerOperationsLatencyKey is the key for the operation latency metrics. // Taken from k8s.io/kubernetes/pkg/kubelet/dockershim/metrics dockerOperationsLatencyKey = "docker_operations_duration_seconds" diff --git a/deps/github.com/openshift/kubernetes/test/e2e/framework/metrics/metrics_grabber.go b/deps/github.com/openshift/kubernetes/test/e2e/framework/metrics/metrics_grabber.go index 9919cccd9d..b49889aa23 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/framework/metrics/metrics_grabber.go +++ b/deps/github.com/openshift/kubernetes/test/e2e/framework/metrics/metrics_grabber.go @@ -29,6 +29,7 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" + k8snet "k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -94,7 +95,6 @@ type Grabber struct { // support it. If disabled for a component, the corresponding Grab function // will immediately return an error derived from MetricsGrabbingDisabledError. func NewMetricsGrabber(ctx context.Context, c clientset.Interface, ec clientset.Interface, config *rest.Config, kubelets bool, scheduler bool, controllers bool, apiServer bool, clusterAutoscaler bool, snapshotController bool) (*Grabber, error) { - kubeScheduler := "" kubeControllerManager := "" snapshotControllerManager := "" @@ -213,28 +213,29 @@ func (g *Grabber) grabFromKubeletInternal(ctx context.Context, nodeName string, } func (g *Grabber) getMetricsFromNode(ctx context.Context, nodeName string, kubeletPort int, pathSuffix string) (string, error) { - // There's a problem with timing out during proxy. Wrapping this in a goroutine to prevent deadlock. - finished := make(chan struct{}, 1) + // There's a problem with timing out during proxy. We are going to set a 45 second client timeout, and issue a retry. var err error - var rawOutput []byte - go func() { - rawOutput, err = g.client.CoreV1().RESTClient().Get(). + var output []byte + err = wait.PollUntilContextTimeout(ctx, 15*time.Second, 2*time.Minute, true, func(ctx context.Context) (done bool, retErr error) { + rawOutput, err := g.client.CoreV1().RESTClient().Get(). Resource("nodes"). SubResource("proxy"). Name(fmt.Sprintf("%v:%v", nodeName, kubeletPort)). Suffix(pathSuffix). + Timeout(45 * time.Second). Do(ctx).Raw() - finished <- struct{}{} - }() - select { - case <-time.After(proxyTimeout): - return "", fmt.Errorf("Timed out when waiting for proxy to gather metrics from %v", nodeName) - case <-finished: if err != nil { - return "", err + if k8snet.IsTimeout(err) { + klog.Warningf("Metrics rest call timed out") + return false, nil + } + klog.Warningf("Metrics rest call errored: %v", err) + return false, nil } - return string(rawOutput), nil - } + output = rawOutput + return true, nil + }) + return string(output), err } // GrabFromKubeProxy returns metrics from kube-proxy diff --git a/deps/github.com/openshift/kubernetes/test/e2e/framework/pv/wait.go b/deps/github.com/openshift/kubernetes/test/e2e/framework/pv/wait.go index ebfe227afe..aa94b17081 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/framework/pv/wait.go +++ b/deps/github.com/openshift/kubernetes/test/e2e/framework/pv/wait.go @@ -76,11 +76,16 @@ func WaitForPersistentVolumeClaimModificationFailure(ctx context.Context, c clie desiredClass := ptr.Deref(claim.Spec.VolumeAttributesClassName, "") var match = func(claim *v1.PersistentVolumeClaim) bool { + foundErrorCondition := false for _, condition := range claim.Status.Conditions { - if condition.Type != v1.PersistentVolumeClaimVolumeModifyVolumeError { - return false + if condition.Type == v1.PersistentVolumeClaimVolumeModifyVolumeError { + foundErrorCondition = true } } + // if no error found it must be an error + if !foundErrorCondition { + return false + } // check if claim's current volume attributes class is NOT desired one, and has appropriate ModifyVolumeStatus currentClass := ptr.Deref(claim.Status.CurrentVolumeAttributesClassName, "") diff --git a/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/mutable_csinode_allocatable.go b/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/mutable_csinode_allocatable.go index eccdcdb419..179d2eb2ce 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/mutable_csinode_allocatable.go +++ b/deps/github.com/openshift/kubernetes/test/e2e/storage/csimock/mutable_csinode_allocatable.go @@ -18,7 +18,6 @@ package csimock import ( "context" - "encoding/json" "fmt" "strings" "sync/atomic" @@ -30,17 +29,12 @@ import ( "github.com/onsi/ginkgo/v2" - jsonpatch "gopkg.in/evanphx/json-patch.v4" - storagev1 "k8s.io/api/storage/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/test/e2e/framework" e2epod "k8s.io/kubernetes/test/e2e/framework/pod" - e2evolume "k8s.io/kubernetes/test/e2e/framework/volume" "k8s.io/kubernetes/test/e2e/storage/drivers" storageframework "k8s.io/kubernetes/test/e2e/storage/framework" "k8s.io/kubernetes/test/e2e/storage/utils" @@ -145,9 +139,10 @@ var _ = utils.SIGDescribe("MutableCSINodeAllocatableCount", framework.WithFeatur } opts := drivers.CSIMockDriverOpts{ - Embedded: true, - RegisterDriver: true, - Hooks: hook, + Embedded: true, + EnableMutableCSINodeAllocatableCount: true, + RegisterDriver: true, + Hooks: hook, } driver = drivers.InitMockCSIDriver(opts) cfg = driver.PrepareTest(ctx, f) @@ -173,45 +168,13 @@ var _ = utils.SIGDescribe("MutableCSINodeAllocatableCount", framework.WithFeatur }) f.It("should transition pod to failed state when attachment limit exceeded", func(ctx context.Context) { - _, claim, pod := m.createPod(ctx, pvcReference) + _, _, pod := m.createPod(ctx, pvcReference) if pod == nil { return } - ginkgo.By("Checking if VolumeAttachment was created for the pod") - testConfig := storageframework.ConvertTestConfig(m.config) - attachmentName := e2evolume.GetVolumeAttachmentName(ctx, m.cs, testConfig, m.provisioner, claim.Name, claim.Namespace) - - var va *storagev1.VolumeAttachment - err := wait.PollUntilContextTimeout(ctx, framework.Poll, 30*time.Second, true, func(ctx context.Context) (bool, error) { - var getErr error - va, getErr = m.cs.StorageV1().VolumeAttachments().Get(ctx, attachmentName, metav1.GetOptions{}) - if getErr != nil { - if apierrors.IsNotFound(getErr) { - return false, nil - } - return false, getErr - } - return true, nil - }) - framework.ExpectNoError(err, "VolumeAttachment not created") - - // Patch VolumeAttachment.Status.AttachError.ErrorCode with ResourceExhausted - clone := va.DeepCopy() - clone.Status.Attached = false - errorCode := int32(codes.ResourceExhausted) - clone.Status.AttachError = &storagev1.VolumeError{ - Message: "ResourceExhausted: attachment limit exceeded", - Time: metav1.Now(), - ErrorCode: &errorCode, - } - patch, err := createMergePatch(va, clone) - framework.ExpectNoError(err, "Failed to create merge patch") - _, err = m.cs.StorageV1().VolumeAttachments().Patch(ctx, attachmentName, types.MergePatchType, patch, metav1.PatchOptions{}, "status") - framework.ExpectNoError(err, "Failed to patch VolumeAttachment status") - ginkgo.By("Waiting for Pod to fail with VolumeAttachmentLimitExceeded") - err = e2epod.WaitForPodFailedReason(ctx, m.cs, pod, "VolumeAttachmentLimitExceeded", 4*time.Minute) + err := e2epod.WaitForPodFailedReason(ctx, m.cs, pod, "VolumeAttachmentLimitExceeded", 4*time.Minute) framework.ExpectNoError(err, "Pod did not fail with VolumeAttachmentLimitExceeded") }) }) @@ -245,19 +208,3 @@ func readCSINodeLimit(ctx context.Context, cs clientset.Interface, node, drv str } return 0, fmt.Errorf("driver %q not present on CSINode", drv) } - -func createMergePatch(original, new interface{}) ([]byte, error) { - pvByte, err := json.Marshal(original) - if err != nil { - return nil, err - } - cloneByte, err := json.Marshal(new) - if err != nil { - return nil, err - } - patch, err := jsonpatch.CreateMergePatch(pvByte, cloneByte) - if err != nil { - return nil, err - } - return patch, nil -} diff --git a/deps/github.com/openshift/kubernetes/test/e2e/storage/drivers/csi.go b/deps/github.com/openshift/kubernetes/test/e2e/storage/drivers/csi.go index 6ef88f955d..d1253ddb7a 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/storage/drivers/csi.go +++ b/deps/github.com/openshift/kubernetes/test/e2e/storage/drivers/csi.go @@ -337,25 +337,27 @@ func (h *hostpathCSIDriver) PrepareTest(ctx context.Context, f *framework.Framew // mockCSI type mockCSIDriver struct { - driverInfo storageframework.DriverInfo - manifests []string - podInfo *bool - storageCapacity *bool - attachable bool - attachLimit int - enableTopology bool - enableNodeExpansion bool - hooks Hooks - tokenRequests []storagev1.TokenRequest - requiresRepublish *bool - fsGroupPolicy *storagev1.FSGroupPolicy - enableVolumeMountGroup bool - enableNodeVolumeCondition bool - embedded bool - calls MockCSICalls - embeddedCSIDriver *mockdriver.CSIDriver - enableSELinuxMount *bool - disableControllerExpansion bool + driverInfo storageframework.DriverInfo + manifests []string + podInfo *bool + storageCapacity *bool + attachable bool + attachLimit int + enableTopology bool + enableNodeExpansion bool + hooks Hooks + tokenRequests []storagev1.TokenRequest + requiresRepublish *bool + serviceAccountTokenInSecrets *bool + fsGroupPolicy *storagev1.FSGroupPolicy + enableVolumeMountGroup bool + enableNodeVolumeCondition bool + embedded bool + calls MockCSICalls + embeddedCSIDriver *mockdriver.CSIDriver + enableSELinuxMount *bool + disableControllerExpansion bool + enableMutableCSINodeAllocatableCount bool // Additional values set during PrepareTest clientSet clientset.Interface @@ -389,22 +391,24 @@ type MockCSITestDriver interface { // CSIMockDriverOpts defines options used for csi driver type CSIMockDriverOpts struct { - RegisterDriver bool - DisableAttach bool - PodInfo *bool - StorageCapacity *bool - AttachLimit int - EnableTopology bool - EnableResizing bool - EnableNodeExpansion bool - DisableControllerExpansion bool - EnableSnapshot bool - EnableVolumeMountGroup bool - EnableNodeVolumeCondition bool - TokenRequests []storagev1.TokenRequest - RequiresRepublish *bool - FSGroupPolicy *storagev1.FSGroupPolicy - EnableSELinuxMount *bool + RegisterDriver bool + DisableAttach bool + PodInfo *bool + StorageCapacity *bool + AttachLimit int + EnableTopology bool + EnableResizing bool + EnableNodeExpansion bool + DisableControllerExpansion bool + EnableSnapshot bool + EnableVolumeMountGroup bool + EnableNodeVolumeCondition bool + TokenRequests []storagev1.TokenRequest + ServiceAccountTokenInSecrets *bool + RequiresRepublish *bool + FSGroupPolicy *storagev1.FSGroupPolicy + EnableSELinuxMount *bool + EnableMutableCSINodeAllocatableCount bool // Embedded defines whether the CSI mock driver runs // inside the cluster (false, the default) or just a proxy @@ -546,22 +550,24 @@ func InitMockCSIDriver(driverOpts CSIMockDriverOpts) MockCSITestDriver { storageframework.CapMultiplePVsSameID: true, }, }, - manifests: driverManifests, - podInfo: driverOpts.PodInfo, - storageCapacity: driverOpts.StorageCapacity, - enableTopology: driverOpts.EnableTopology, - attachable: !driverOpts.DisableAttach, - attachLimit: driverOpts.AttachLimit, - enableNodeExpansion: driverOpts.EnableNodeExpansion, - enableNodeVolumeCondition: driverOpts.EnableNodeVolumeCondition, - disableControllerExpansion: driverOpts.DisableControllerExpansion, - tokenRequests: driverOpts.TokenRequests, - requiresRepublish: driverOpts.RequiresRepublish, - fsGroupPolicy: driverOpts.FSGroupPolicy, - enableVolumeMountGroup: driverOpts.EnableVolumeMountGroup, - enableSELinuxMount: driverOpts.EnableSELinuxMount, - embedded: driverOpts.Embedded, - hooks: driverOpts.Hooks, + manifests: driverManifests, + podInfo: driverOpts.PodInfo, + storageCapacity: driverOpts.StorageCapacity, + enableTopology: driverOpts.EnableTopology, + attachable: !driverOpts.DisableAttach, + attachLimit: driverOpts.AttachLimit, + enableNodeExpansion: driverOpts.EnableNodeExpansion, + enableNodeVolumeCondition: driverOpts.EnableNodeVolumeCondition, + disableControllerExpansion: driverOpts.DisableControllerExpansion, + tokenRequests: driverOpts.TokenRequests, + requiresRepublish: driverOpts.RequiresRepublish, + serviceAccountTokenInSecrets: driverOpts.ServiceAccountTokenInSecrets, + fsGroupPolicy: driverOpts.FSGroupPolicy, + enableVolumeMountGroup: driverOpts.EnableVolumeMountGroup, + enableSELinuxMount: driverOpts.EnableSELinuxMount, + enableMutableCSINodeAllocatableCount: driverOpts.EnableMutableCSINodeAllocatableCount, + embedded: driverOpts.Embedded, + hooks: driverOpts.Hooks, } } @@ -717,6 +723,9 @@ func (m *mockCSIDriver) PrepareTest(ctx context.Context, f *framework.Framework) SELinuxMount: m.enableSELinuxMount, Features: map[string][]string{}, } + if m.enableMutableCSINodeAllocatableCount { + o.Features["csi-attacher"] = []string{"MutableCSINodeAllocatableCount=true"} + } err = utils.CreateFromManifests(ctx, f, m.driverNamespace, func(item interface{}) error { if err := utils.PatchCSIDeployment(config.Framework, o, item); err != nil { diff --git a/deps/github.com/openshift/kubernetes/test/e2e/storage/testsuites/base.go b/deps/github.com/openshift/kubernetes/test/e2e/storage/testsuites/base.go index 04b4ac163d..e04c567bd0 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/storage/testsuites/base.go +++ b/deps/github.com/openshift/kubernetes/test/e2e/storage/testsuites/base.go @@ -80,7 +80,6 @@ var CSISuites = append(BaseSuites, return InitCustomEphemeralTestSuite(CSIEphemeralTestPatterns()) }, InitSnapshottableTestSuite, - InitVolumeGroupSnapshottableTestSuite, InitSnapshottableStressTestSuite, InitVolumePerformanceTestSuite, InitPvcDeletionPerformanceTestSuite, diff --git a/deps/github.com/openshift/kubernetes/test/e2e/storage/testsuites/volume_group_snapshottable.go b/deps/github.com/openshift/kubernetes/test/e2e/storage/testsuites/volume_group_snapshottable.go index 0707f557bb..e823442a5c 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/storage/testsuites/volume_group_snapshottable.go +++ b/deps/github.com/openshift/kubernetes/test/e2e/storage/testsuites/volume_group_snapshottable.go @@ -185,17 +185,18 @@ func (s *VolumeGroupSnapshottableTestSuite) DefineTests(driver storageframework. volumeListMap := snapshot.VGSContent.Object["status"].(map[string]interface{}) err = framework.Gomega().Expect(volumeListMap).NotTo(gomega.BeNil()) framework.ExpectNoError(err, "failed to get volume snapshot list") - volumeSnapshotHandlePairList := volumeListMap["volumeSnapshotHandlePairList"].([]interface{}) - err = framework.Gomega().Expect(volumeSnapshotHandlePairList).NotTo(gomega.BeNil()) + volumeSnapshotInfoList := volumeListMap["volumeSnapshotInfoList"].([]interface{}) + err = framework.Gomega().Expect(volumeSnapshotInfoList).NotTo(gomega.BeNil()) framework.ExpectNoError(err, "failed to get volume snapshot list") - err = framework.Gomega().Expect(len(volumeSnapshotHandlePairList)).To(gomega.Equal(groupTest.numVolumes)) + err = framework.Gomega().Expect(len(volumeSnapshotInfoList)).To(gomega.Equal(groupTest.numVolumes)) framework.ExpectNoError(err, "failed to get volume snapshot list") claimSize := groupTest.volumeGroup[0][0].Pvc.Spec.Resources.Requests.Storage().String() - for _, volume := range volumeSnapshotHandlePairList { + for _, info := range volumeSnapshotInfoList { // Create a PVC from the snapshot - volumeHandle := volume.(map[string]interface{})["volumeHandle"].(string) + volumeHandle := info.(map[string]interface{})["volumeHandle"].(string) err = framework.Gomega().Expect(volumeHandle).NotTo(gomega.BeNil()) framework.ExpectNoError(err, "failed to get volume handle from volume") + uid := snapshot.VGS.Object["metadata"].(map[string]interface{})["uid"].(string) err = framework.Gomega().Expect(uid).NotTo(gomega.BeNil()) framework.ExpectNoError(err, "failed to get uuid from content") diff --git a/deps/github.com/openshift/kubernetes/test/e2e/storage/utils/volume_group_snapshot.go b/deps/github.com/openshift/kubernetes/test/e2e/storage/utils/volume_group_snapshot.go index b5515e8792..a3ed602030 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/storage/utils/volume_group_snapshot.go +++ b/deps/github.com/openshift/kubernetes/test/e2e/storage/utils/volume_group_snapshot.go @@ -33,16 +33,16 @@ const ( // VolumeGroupSnapshot is the group snapshot api VolumeGroupSnapshotAPIGroup = "groupsnapshot.storage.k8s.io" // VolumeGroupSnapshotAPIVersion is the group snapshot api version - VolumeGroupSnapshotAPIVersion = "groupsnapshot.storage.k8s.io/v1beta1" + VolumeGroupSnapshotAPIVersion = "groupsnapshot.storage.k8s.io/v1beta2" ) var ( // VolumeGroupSnapshotGVR is GroupVersionResource for volumegroupsnapshots - VolumeGroupSnapshotGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1beta1", Resource: "volumegroupsnapshots"} + VolumeGroupSnapshotGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1beta2", Resource: "volumegroupsnapshots"} // VolumeGroupSnapshotClassGVR is GroupVersionResource for volumegroupsnapshotsclasses - VolumeGroupSnapshotClassGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1beta1", Resource: "volumegroupsnapshotclasses"} - VolumeGroupSnapshotContentGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1beta1", Resource: "volumegroupsnapshotcontents"} + VolumeGroupSnapshotClassGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1beta2", Resource: "volumegroupsnapshotclasses"} + VolumeGroupSnapshotContentGVR = schema.GroupVersionResource{Group: VolumeGroupSnapshotAPIGroup, Version: "v1beta2", Resource: "volumegroupsnapshotcontents"} ) // WaitForVolumeGroupSnapshotReady waits for a VolumeGroupSnapshot to be ready to use or until timeout occurs, whichever comes first. diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml index a06c328d46..7b996dd9c7 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-attacher/rbac.yaml @@ -1,5 +1,5 @@ -# Do not edit, downloaded from https://github.com/kubernetes-csi/external-attacher/raw/v4.6.1/deploy/kubernetes//rbac.yaml -# for csi-driver-host-path release-1.14 +# Do not edit, downloaded from https://github.com/kubernetes-csi/external-attacher/raw/v4.10.0/deploy/kubernetes//rbac.yaml +# for csi-driver-host-path master # by ./update-hostpath.sh # # This YAML file contains all RBAC objects that are necessary to run external diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-health-monitor/external-health-monitor-controller/rbac.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-health-monitor/external-health-monitor-controller/rbac.yaml index 9154a0e0a5..8d91a016fa 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-health-monitor/external-health-monitor-controller/rbac.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-health-monitor/external-health-monitor-controller/rbac.yaml @@ -1,5 +1,5 @@ -# Do not edit, downloaded from https://github.com/kubernetes-csi/external-health-monitor/raw/v0.12.1/deploy/kubernetes/external-health-monitor-controller/rbac.yaml -# for csi-driver-host-path release-1.14 +# Do not edit, downloaded from https://github.com/kubernetes-csi/external-health-monitor/raw/v0.16.0/deploy/kubernetes/external-health-monitor-controller/rbac.yaml +# for csi-driver-host-path master # by ./update-hostpath.sh # # This YAML file contains all RBAC objects that are necessary to run external diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml index d0811b00aa..06bc4a3c71 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-provisioner/rbac.yaml @@ -1,5 +1,5 @@ -# Do not edit, downloaded from https://github.com/kubernetes-csi/external-provisioner/raw/v5.0.1/deploy/kubernetes//rbac.yaml -# for csi-driver-host-path release-1.14 +# Do not edit, downloaded from https://github.com/kubernetes-csi/external-provisioner/raw/v6.0.0/deploy/kubernetes//rbac.yaml +# for csi-driver-host-path master # by ./update-hostpath.sh # # This YAML file contains all RBAC objects that are necessary to run external diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-resizer/rbac.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-resizer/rbac.yaml index afefe5c902..0d051eb765 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-resizer/rbac.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-resizer/rbac.yaml @@ -1,5 +1,5 @@ -# Do not edit, downloaded from https://github.com/kubernetes-csi/external-resizer/raw/v1.11.1/deploy/kubernetes//rbac.yaml -# for csi-driver-host-path release-1.14 +# Do not edit, downloaded from https://github.com/kubernetes-csi/external-resizer/raw/v2.0.0/deploy/kubernetes//rbac.yaml +# for csi-driver-host-path master # by ./update-hostpath.sh # # This YAML file contains all RBAC objects that are necessary to run external @@ -46,7 +46,6 @@ rules: - apiGroups: [""] resources: ["events"] verbs: ["list", "watch", "create", "update", "patch"] - # only required if enabling the alpha volume modify feature - apiGroups: ["storage.k8s.io"] resources: ["volumeattributesclasses"] verbs: ["get", "list", "watch"] diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/csi-snapshotter/rbac-csi-snapshotter.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/csi-snapshotter/rbac-csi-snapshotter.yaml index b02de9fdfe..3fcb9f541f 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/csi-snapshotter/rbac-csi-snapshotter.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/csi-snapshotter/rbac-csi-snapshotter.yaml @@ -1,5 +1,5 @@ -# Do not edit, downloaded from https://github.com/kubernetes-csi/external-snapshotter/raw/v8.0.1/deploy/kubernetes/csi-snapshotter/rbac-csi-snapshotter.yaml -# for csi-driver-host-path release-1.14 +# Do not edit, downloaded from https://github.com/kubernetes-csi/external-snapshotter/raw/v8.4.0/deploy/kubernetes/csi-snapshotter/rbac-csi-snapshotter.yaml +# for csi-driver-host-path master # by ./update-hostpath.sh # # Together with the RBAC file for external-provisioner, this YAML file @@ -38,12 +38,9 @@ rules: - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotclasses"] verbs: ["get", "list", "watch"] - - apiGroups: ["snapshot.storage.k8s.io"] - resources: ["volumesnapshots"] - verbs: ["get", "list", "watch", "update", "patch", "create"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotcontents"] - verbs: ["get", "list", "watch", "update", "patch", "create"] + verbs: ["get", "list", "watch", "update", "patch"] - apiGroups: ["snapshot.storage.k8s.io"] resources: ["volumesnapshotcontents/status"] verbs: ["update", "patch"] diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml index e552f81b57..81299d5ecf 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotclasses.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1150" + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1337" controller-gen.kubebuilder.io/version: v0.15.0 name: volumegroupsnapshotclasses.groupsnapshot.storage.k8s.io spec: @@ -31,6 +31,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date + deprecated: true name: v1beta1 schema: openAPIV3Schema: @@ -90,5 +91,88 @@ spec: - driver type: object served: true + storage: false + subresources: {} + - additionalPrinterColumns: + - jsonPath: .driver + name: Driver + type: string + - description: Determines whether a VolumeGroupSnapshotContent created through + the VolumeGroupSnapshotClass should be deleted when its bound VolumeGroupSnapshot + is deleted. + jsonPath: .deletionPolicy + name: DeletionPolicy + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta2 + schema: + openAPIV3Schema: + description: |- + VolumeGroupSnapshotClass specifies parameters that a underlying storage system + uses when creating a volume group snapshot. A specific VolumeGroupSnapshotClass + is used by specifying its name in a VolumeGroupSnapshot object. + VolumeGroupSnapshotClasses are non-namespaced. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + deletionPolicy: + description: |- + DeletionPolicy determines whether a VolumeGroupSnapshotContent created + through the VolumeGroupSnapshotClass should be deleted when its bound + VolumeGroupSnapshot is deleted. + Supported values are "Retain" and "Delete". + "Retain" means that the VolumeGroupSnapshotContent and its physical group + snapshot on underlying storage system are kept. + "Delete" means that the VolumeGroupSnapshotContent and its physical group + snapshot on underlying storage system are deleted. + Required. + enum: + - Delete + - Retain + type: string + x-kubernetes-validations: + - message: deletionPolicy is immutable once set + rule: self == oldSelf + driver: + description: |- + Driver is the name of the storage driver expected to handle this VolumeGroupSnapshotClass. + Required. + type: string + x-kubernetes-validations: + - message: driver is immutable once set + rule: self == oldSelf + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + parameters: + additionalProperties: + type: string + description: |- + Parameters is a key-value map with storage driver specific parameters for + creating group snapshots. + These values are opaque to Kubernetes and are passed directly to the driver. + type: object + x-kubernetes-validations: + - message: parameters are immutable once set + rule: self == oldSelf + required: + - deletionPolicy + - driver + type: object + served: true storage: true subresources: {} diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotcontents.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotcontents.yaml index a6d15d8adc..235198ac49 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotcontents.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshotcontents.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1150" + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1337" controller-gen.kubebuilder.io/version: v0.15.0 name: volumegroupsnapshotcontents.groupsnapshot.storage.k8s.io spec: @@ -17,6 +17,15 @@ spec: - vgscs singular: volumegroupsnapshotcontent scope: Cluster + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1"] + clientConfig: + service: + namespace: default + name: snapshot-conversion-webhook-service + path: /convert versions: - additionalPrinterColumns: - description: Indicates if all the individual snapshots in the group are ready @@ -53,6 +62,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date + deprecated: true name: v1beta1 schema: openAPIV3Schema: @@ -319,6 +329,333 @@ spec: - spec type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Indicates if all the individual snapshots in the group are ready + to be used to restore a group of volumes. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: Determines whether this VolumeGroupSnapshotContent and its physical + group snapshot on the underlying storage system should be deleted when its + bound VolumeGroupSnapshot is deleted. + jsonPath: .spec.deletionPolicy + name: DeletionPolicy + type: string + - description: Name of the CSI driver used to create the physical group snapshot + on the underlying storage system. + jsonPath: .spec.driver + name: Driver + type: string + - description: Name of the VolumeGroupSnapshotClass from which this group snapshot + was (or will be) created. + jsonPath: .spec.volumeGroupSnapshotClassName + name: VolumeGroupSnapshotClass + type: string + - description: Namespace of the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent + object is bound. + jsonPath: .spec.volumeGroupSnapshotRef.namespace + name: VolumeGroupSnapshotNamespace + type: string + - description: Name of the VolumeGroupSnapshot object to which this VolumeGroupSnapshotContent + object is bound. + jsonPath: .spec.volumeGroupSnapshotRef.name + name: VolumeGroupSnapshot + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta2 + schema: + openAPIV3Schema: + description: |- + VolumeGroupSnapshotContent represents the actual "on-disk" group snapshot object + in the underlying storage system + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + Spec defines properties of a VolumeGroupSnapshotContent created by the underlying storage system. + Required. + properties: + deletionPolicy: + description: |- + DeletionPolicy determines whether this VolumeGroupSnapshotContent and the + physical group snapshot on the underlying storage system should be deleted + when the bound VolumeGroupSnapshot is deleted. + Supported values are "Retain" and "Delete". + "Retain" means that the VolumeGroupSnapshotContent and its physical group + snapshot on underlying storage system are kept. + "Delete" means that the VolumeGroupSnapshotContent and its physical group + snapshot on underlying storage system are deleted. + For dynamically provisioned group snapshots, this field will automatically + be filled in by the CSI snapshotter sidecar with the "DeletionPolicy" field + defined in the corresponding VolumeGroupSnapshotClass. + For pre-existing snapshots, users MUST specify this field when creating the + VolumeGroupSnapshotContent object. + Required. + enum: + - Delete + - Retain + type: string + driver: + description: |- + Driver is the name of the CSI driver used to create the physical group snapshot on + the underlying storage system. + This MUST be the same as the name returned by the CSI GetPluginName() call for + that driver. + Required. + type: string + x-kubernetes-validations: + - message: driver is immutable once set + rule: self == oldSelf + source: + description: |- + Source specifies whether the snapshot is (or should be) dynamically provisioned + or already exists, and just requires a Kubernetes object representation. + This field is immutable after creation. + Required. + properties: + groupSnapshotHandles: + description: |- + GroupSnapshotHandles specifies the CSI "group_snapshot_id" of a pre-existing + group snapshot and a list of CSI "snapshot_id" of pre-existing snapshots + on the underlying storage system for which a Kubernetes object + representation was (or should be) created. + This field is immutable. + properties: + volumeGroupSnapshotHandle: + description: |- + VolumeGroupSnapshotHandle specifies the CSI "group_snapshot_id" of a pre-existing + group snapshot on the underlying storage system for which a Kubernetes object + representation was (or should be) created. + This field is immutable. + Required. + type: string + volumeSnapshotHandles: + description: |- + VolumeSnapshotHandles is a list of CSI "snapshot_id" of pre-existing + snapshots on the underlying storage system for which Kubernetes objects + representation were (or should be) created. + This field is immutable. + Required. + items: + type: string + type: array + required: + - volumeGroupSnapshotHandle + - volumeSnapshotHandles + type: object + x-kubernetes-validations: + - message: groupSnapshotHandles is immutable + rule: self == oldSelf + volumeHandles: + description: |- + VolumeHandles is a list of volume handles on the backend to be snapshotted + together. It is specified for dynamic provisioning of the VolumeGroupSnapshot. + This field is immutable. + items: + type: string + type: array + x-kubernetes-validations: + - message: volumeHandles is immutable + rule: self == oldSelf + type: object + x-kubernetes-validations: + - message: volumeHandles is required once set + rule: '!has(oldSelf.volumeHandles) || has(self.volumeHandles)' + - message: groupSnapshotHandles is required once set + rule: '!has(oldSelf.groupSnapshotHandles) || has(self.groupSnapshotHandles)' + - message: exactly one of volumeHandles and groupSnapshotHandles must + be set + rule: (has(self.volumeHandles) && !has(self.groupSnapshotHandles)) + || (!has(self.volumeHandles) && has(self.groupSnapshotHandles)) + volumeGroupSnapshotClassName: + description: |- + VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass from + which this group snapshot was (or will be) created. + Note that after provisioning, the VolumeGroupSnapshotClass may be deleted or + recreated with different set of values, and as such, should not be referenced + post-snapshot creation. + For dynamic provisioning, this field must be set. + This field may be unset for pre-provisioned snapshots. + type: string + x-kubernetes-validations: + - message: volumeGroupSnapshotClassName is immutable once set + rule: self == oldSelf + volumeGroupSnapshotRef: + description: |- + VolumeGroupSnapshotRef specifies the VolumeGroupSnapshot object to which this + VolumeGroupSnapshotContent object is bound. + VolumeGroupSnapshot.Spec.VolumeGroupSnapshotContentName field must reference to + this VolumeGroupSnapshotContent's name for the bidirectional binding to be valid. + For a pre-existing VolumeGroupSnapshotContent object, name and namespace of the + VolumeGroupSnapshot object MUST be provided for binding to happen. + This field is immutable after creation. + Required. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: both volumeGroupSnapshotRef.name and volumeGroupSnapshotRef.namespace + must be set + rule: has(self.name) && has(self.__namespace__) + - message: volumeGroupSnapshotRef.name and volumeGroupSnapshotRef.namespace + are immutable + rule: self.name == oldSelf.name && self.__namespace__ == oldSelf.__namespace__ + - message: volumeGroupSnapshotRef.uid is immutable once set + rule: '!has(oldSelf.uid) || (has(self.uid) && self.uid == oldSelf.uid)' + required: + - deletionPolicy + - driver + - source + - volumeGroupSnapshotRef + type: object + status: + description: status represents the current information of a group snapshot. + properties: + creationTime: + description: |- + CreationTime is the timestamp when the point-in-time group snapshot is taken + by the underlying storage system. + If not specified, it indicates the creation time is unknown. + If not specified, it means the readiness of a group snapshot is unknown. + This field is the source for the CreationTime field in VolumeGroupSnapshotStatus + format: date-time + type: string + error: + description: |- + Error is the last observed error during group snapshot creation, if any. + Upon success after retry, this error field will be cleared. + properties: + message: + description: |- + message is a string detailing the encountered error during snapshot + creation if specified. + NOTE: message may be logged, and it should not contain sensitive + information. + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: |- + ReadyToUse indicates if all the individual snapshots in the group are ready to be + used to restore a group of volumes. + ReadyToUse becomes true when ReadyToUse of all individual snapshots become true. + type: boolean + volumeGroupSnapshotHandle: + description: |- + VolumeGroupSnapshotHandle is a unique id returned by the CSI driver + to identify the VolumeGroupSnapshot on the storage system. + If a storage system does not provide such an id, the + CSI driver can choose to return the VolumeGroupSnapshot name. + type: string + x-kubernetes-validations: + - message: volumeGroupSnapshotHandle is immutable once set + rule: self == oldSelf + volumeSnapshotInfoList: + description: |- + This field is introduced in v1beta2 + It is replacing VolumeSnapshotHandlePairList + VolumeSnapshotInfoList is a list of snapshot information returned by + by the CSI driver to identify snapshots on the storage system. + items: + description: |- + The VolumeSnapshotInfo struct is added in v1beta2 + VolumeSnapshotInfo contains information for a snapshot + properties: + creationTime: + description: |- + creationTime is the timestamp when the point-in-time snapshot is taken + by the underlying storage system. + format: int64 + type: integer + readyToUse: + description: ReadyToUse indicates if the snapshot is ready to + be used to restore a volume. + type: boolean + restoreSize: + description: |- + RestoreSize represents the minimum size of volume required to create a volume + from this snapshot. + format: int64 + type: integer + snapshotHandle: + description: SnapshotHandle is the CSI "snapshot_id" of this + snapshot on the underlying storage system. + type: string + volumeHandle: + description: |- + VolumeHandle specifies the CSI "volume_id" of the volume from which this snapshot + was taken from. + type: string + type: object + type: array + type: object + required: + - spec + type: object + served: true storage: true subresources: status: {} diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml index 145d1211df..3f8c4909aa 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/groupsnapshot.storage.k8s.io_volumegroupsnapshots.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1150" + api-approved.kubernetes.io: "https://github.com/kubernetes-csi/external-snapshotter/pull/1337" controller-gen.kubebuilder.io/version: v0.15.0 name: volumegroupsnapshots.groupsnapshot.storage.k8s.io spec: @@ -43,6 +43,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date + deprecated: true name: v1beta1 schema: openAPIV3Schema: @@ -234,6 +235,226 @@ spec: - spec type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Indicates if all the individual snapshots in the group are ready + to be used to restore a group of volumes. + jsonPath: .status.readyToUse + name: ReadyToUse + type: boolean + - description: The name of the VolumeGroupSnapshotClass requested by the VolumeGroupSnapshot. + jsonPath: .spec.volumeGroupSnapshotClassName + name: VolumeGroupSnapshotClass + type: string + - description: Name of the VolumeGroupSnapshotContent object to which the VolumeGroupSnapshot + object intends to bind to. Please note that verification of binding actually + requires checking both VolumeGroupSnapshot and VolumeGroupSnapshotContent + to ensure both are pointing at each other. Binding MUST be verified prior + to usage of this object. + jsonPath: .status.boundVolumeGroupSnapshotContentName + name: VolumeGroupSnapshotContent + type: string + - description: Timestamp when the point-in-time group snapshot was taken by the + underlying storage system. + jsonPath: .status.creationTime + name: CreationTime + type: date + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta2 + schema: + openAPIV3Schema: + description: |- + VolumeGroupSnapshot is a user's request for creating either a point-in-time + group snapshot or binding to a pre-existing group snapshot. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + Spec defines the desired characteristics of a group snapshot requested by a user. + Required. + properties: + source: + description: |- + Source specifies where a group snapshot will be created from. + This field is immutable after creation. + Required. + properties: + selector: + description: |- + Selector is a label query over persistent volume claims that are to be + grouped together for snapshotting. + This labelSelector will be used to match the label added to a PVC. + If the label is added or removed to a volume after a group snapshot + is created, the existing group snapshots won't be modified. + Once a VolumeGroupSnapshotContent is created and the sidecar starts to process + it, the volume list will not change with retries. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + x-kubernetes-validations: + - message: selector is immutable + rule: self == oldSelf + volumeGroupSnapshotContentName: + description: |- + VolumeGroupSnapshotContentName specifies the name of a pre-existing VolumeGroupSnapshotContent + object representing an existing volume group snapshot. + This field should be set if the volume group snapshot already exists and + only needs a representation in Kubernetes. + This field is immutable. + type: string + x-kubernetes-validations: + - message: volumeGroupSnapshotContentName is immutable + rule: self == oldSelf + type: object + x-kubernetes-validations: + - message: selector is required once set + rule: '!has(oldSelf.selector) || has(self.selector)' + - message: volumeGroupSnapshotContentName is required once set + rule: '!has(oldSelf.volumeGroupSnapshotContentName) || has(self.volumeGroupSnapshotContentName)' + - message: exactly one of selector and volumeGroupSnapshotContentName + must be set + rule: (has(self.selector) && !has(self.volumeGroupSnapshotContentName)) + || (!has(self.selector) && has(self.volumeGroupSnapshotContentName)) + volumeGroupSnapshotClassName: + description: |- + VolumeGroupSnapshotClassName is the name of the VolumeGroupSnapshotClass + requested by the VolumeGroupSnapshot. + VolumeGroupSnapshotClassName may be left nil to indicate that the default + class will be used. + Empty string is not allowed for this field. + type: string + x-kubernetes-validations: + - message: volumeGroupSnapshotClassName must not be the empty string + when set + rule: size(self) > 0 + required: + - source + type: object + status: + description: |- + Status represents the current information of a group snapshot. + Consumers must verify binding between VolumeGroupSnapshot and + VolumeGroupSnapshotContent objects is successful (by validating that both + VolumeGroupSnapshot and VolumeGroupSnapshotContent point to each other) before + using this object. + properties: + boundVolumeGroupSnapshotContentName: + description: |- + BoundVolumeGroupSnapshotContentName is the name of the VolumeGroupSnapshotContent + object to which this VolumeGroupSnapshot object intends to bind to. + If not specified, it indicates that the VolumeGroupSnapshot object has not + been successfully bound to a VolumeGroupSnapshotContent object yet. + NOTE: To avoid possible security issues, consumers must verify binding between + VolumeGroupSnapshot and VolumeGroupSnapshotContent objects is successful + (by validating that both VolumeGroupSnapshot and VolumeGroupSnapshotContent + point at each other) before using this object. + type: string + x-kubernetes-validations: + - message: boundVolumeGroupSnapshotContentName is immutable once set + rule: self == oldSelf + creationTime: + description: |- + CreationTime is the timestamp when the point-in-time group snapshot is taken + by the underlying storage system. + If not specified, it may indicate that the creation time of the group snapshot + is unknown. + This field is updated based on the CreationTime field in VolumeGroupSnapshotContentStatus + format: date-time + type: string + error: + description: |- + Error is the last observed error during group snapshot creation, if any. + This field could be helpful to upper level controllers (i.e., application + controller) to decide whether they should continue on waiting for the group + snapshot to be created based on the type of error reported. + The snapshot controller will keep retrying when an error occurs during the + group snapshot creation. Upon success, this error field will be cleared. + properties: + message: + description: |- + message is a string detailing the encountered error during snapshot + creation if specified. + NOTE: message may be logged, and it should not contain sensitive + information. + type: string + time: + description: time is the timestamp when the error was encountered. + format: date-time + type: string + type: object + readyToUse: + description: |- + ReadyToUse indicates if all the individual snapshots in the group are ready + to be used to restore a group of volumes. + ReadyToUse becomes true when ReadyToUse of all individual snapshots become true. + If not specified, it means the readiness of a group snapshot is unknown. + type: boolean + type: object + required: + - spec + type: object + served: true storage: true subresources: status: {} diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/volume-group-snapshots/csi-hostpath-plugin.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/volume-group-snapshots/csi-hostpath-plugin.yaml index 35dc8c4b29..4bedcf6e3c 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/volume-group-snapshots/csi-hostpath-plugin.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/volume-group-snapshots/csi-hostpath-plugin.yaml @@ -354,7 +354,7 @@ spec: name: socket-dir - name: csi-snapshotter - image: registry.k8s.io/sig-storage/csi-snapshotter:v8.3.0 + image: registry.k8s.io/sig-storage/csi-snapshotter:v8.4.0 args: - -v=5 - --csi-address=/csi/csi.sock diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/volume-group-snapshots/run_group_snapshot_e2e.sh b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/volume-group-snapshots/run_group_snapshot_e2e.sh index f62b40d848..9791f9b070 100755 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/volume-group-snapshots/run_group_snapshot_e2e.sh +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/external-snapshotter/volume-group-snapshots/run_group_snapshot_e2e.sh @@ -266,13 +266,12 @@ run_tests() { export KUBE_CONTAINER_RUNTIME=remote export KUBE_CONTAINER_RUNTIME_ENDPOINT=unix:///run/containerd/containerd.sock export KUBE_CONTAINER_RUNTIME_NAME=containerd - export SNAPSHOTTER_VERSION="${SNAPSHOTTER_VERSION:-v8.3.0}" + export SNAPSHOTTER_VERSION="${SNAPSHOTTER_VERSION:-v8.4.0}" echo "SNAPSHOTTER_VERSION is $SNAPSHOTTER_VERSION" - # ginkgo can take forever to exit, so we run it in the background and save the - # PID, bash will not run traps while waiting on a process, but it will while - # running a builtin like `wait`, saving the PID also allows us to forward the - # interrupt - + + # Enable VolumeGroupSnapshot tests in csi-driver-hostpath + export CSI_PROW_ENABLE_GROUP_SNAPSHOT=true + kubectl apply -f ./cluster/addons/volumesnapshots/crd/snapshot.storage.k8s.io_volumesnapshotclasses.yaml || exit 1 kubectl apply -f ./cluster/addons/volumesnapshots/crd/snapshot.storage.k8s.io_volumesnapshotcontents.yaml || exit 1 kubectl apply -f ./cluster/addons/volumesnapshots/crd/snapshot.storage.k8s.io_volumesnapshots.yaml || exit 1 @@ -287,6 +286,10 @@ sed "s|image: registry.k8s.io/sig-storage/snapshot-controller:.*|image: registry kubectl apply -f - || exit 1 + # ginkgo can take forever to exit, so we run it in the background and save the + # PID, bash will not run traps while waiting on a process, but it will while + # running a builtin like `wait`, saving the PID also allows us to forward the + # interrupt ./hack/ginkgo-e2e.sh \ '--provider=skeleton' "--num-nodes=${NUM_NODES}" \ "--ginkgo.focus=${FOCUS}" "--ginkgo.skip=${SKIP}" "--ginkgo.label-filter=${LABEL_FILTER}" \ diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/README.md b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/README.md index 2a53faceae..6b662f547b 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/README.md +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/README.md @@ -1,4 +1,4 @@ The files in this directory are exact copies of "kubernetes-latest" in -https://github.com/kubernetes-csi/csi-driver-host-path/tree/release-1.14/deploy/ +https://github.com/kubernetes-csi/csi-driver-host-path/tree/master/deploy/ Do not edit manually. Run ./update-hostpath.sh to refresh the content. diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-plugin.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-plugin.yaml index a5af9814a8..d2e97779bd 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-plugin.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-plugin.yaml @@ -1,4 +1,4 @@ -# All of the individual sidecar RBAC roles get bound + # All of the individual sidecar RBAC roles get bound # to this account. kind: ServiceAccount apiVersion: v1 @@ -102,6 +102,24 @@ subjects: namespace: default --- apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/instance: hostpath.csi.k8s.io + app.kubernetes.io/part-of: csi-driver-host-path + app.kubernetes.io/name: csi-hostpathplugin + app.kubernetes.io/component: snapshot-metadata-cluster-role + name: csi-hostpathplugin-snapshot-metadata-cluster-role +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: external-snapshot-metadata-runner +subjects: +- kind: ServiceAccount + name: csi-hostpathplugin-sa + namespace: default +--- +apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: @@ -219,12 +237,13 @@ spec: serviceAccountName: csi-hostpathplugin-sa containers: - name: hostpath - image: registry.k8s.io/sig-storage/hostpathplugin:v1.16.1 + image: registry.k8s.io/sig-storage/hostpathplugin:v1.17.0 args: - "--drivername=hostpath.csi.k8s.io" - "--v=5" - "--endpoint=$(CSI_ENDPOINT)" - "--nodeid=$(KUBE_NODE_NAME)" + # end hostpath args env: - name: CSI_ENDPOINT value: unix:///csi/csi.sock @@ -262,7 +281,7 @@ spec: name: dev-dir - name: csi-external-health-monitor-controller - image: registry.k8s.io/sig-storage/csi-external-health-monitor-controller:v0.12.1 + image: registry.k8s.io/sig-storage/csi-external-health-monitor-controller:v0.16.0 args: - "--v=5" - "--csi-address=$(ADDRESS)" @@ -324,7 +343,7 @@ spec: name: socket-dir - name: csi-provisioner - image: registry.k8s.io/sig-storage/csi-provisioner:v5.1.0 + image: registry.k8s.io/sig-storage/csi-provisioner:v6.0.0 args: - -v=5 - --csi-address=/csi/csi.sock @@ -340,7 +359,7 @@ spec: name: socket-dir - name: csi-resizer - image: registry.k8s.io/sig-storage/csi-resizer:v1.13.1 + image: registry.k8s.io/sig-storage/csi-resizer:v2.0.0 args: - -v=5 - -csi-address=/csi/csi.sock @@ -354,7 +373,7 @@ spec: name: socket-dir - name: csi-snapshotter - image: registry.k8s.io/sig-storage/csi-snapshotter:v8.3.0 + image: registry.k8s.io/sig-storage/csi-snapshotter:v8.4.0 args: - -v=5 - --csi-address=/csi/csi.sock @@ -367,6 +386,8 @@ spec: - mountPath: /csi name: socket-dir + # end csi containers + volumes: - hostPath: path: /var/lib/kubelet/plugins/csi-hostpath @@ -394,3 +415,4 @@ spec: path: /dev type: Directory name: dev-dir + # end csi volumes diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-testing.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-testing.yaml index 494f2aacc2..19c9888eec 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-testing.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/hostpath/hostpath/csi-hostpath-testing.yaml @@ -66,7 +66,7 @@ spec: topologyKey: kubernetes.io/hostname containers: - name: socat - image: registry.k8s.io/sig-storage/hostpathplugin:v1.16.1 + image: registry.k8s.io/sig-storage/hostpathplugin:v1.15.0 command: - socat args: diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-attacher.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-attacher.yaml index 9716caaad8..f2f7850f08 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-attacher.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-attacher.yaml @@ -15,7 +15,7 @@ spec: serviceAccountName: csi-mock containers: - name: csi-attacher - image: registry.k8s.io/sig-storage/csi-attacher:v4.8.0 + image: registry.k8s.io/sig-storage/csi-attacher:v4.10.0 args: - --v=5 - --csi-address=$(ADDRESS) diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-resizer.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-resizer.yaml index c2f7d07774..0133796e72 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-resizer.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-resizer.yaml @@ -15,7 +15,7 @@ spec: serviceAccountName: csi-mock containers: - name: csi-resizer - image: registry.k8s.io/sig-storage/csi-resizer:v1.13.1 + image: registry.k8s.io/sig-storage/csi-resizer:v2.0.0 args: - "--v=5" - "--csi-address=$(ADDRESS)" diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-snapshotter.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-snapshotter.yaml index cf5bbba29a..15c4bb5230 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-snapshotter.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver-snapshotter.yaml @@ -15,7 +15,7 @@ spec: serviceAccountName: csi-mock containers: - name: csi-snapshotter - image: registry.k8s.io/sig-storage/csi-snapshotter:v8.3.0 + image: registry.k8s.io/sig-storage/csi-snapshotter:v8.4.0 args: - "--v=5" - "--csi-address=$(ADDRESS)" diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver.yaml index 21b3d73398..fbac7b5fb3 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-driver.yaml @@ -15,7 +15,7 @@ spec: serviceAccountName: csi-mock containers: - name: csi-provisioner - image: registry.k8s.io/sig-storage/csi-provisioner:v5.1.0 + image: registry.k8s.io/sig-storage/csi-provisioner:v6.0.0 args: - "--csi-address=$(ADDRESS)" # Topology support is needed for the pod rescheduling test @@ -34,7 +34,7 @@ spec: - mountPath: /csi name: socket-dir - name: driver-registrar - image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0 + image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.15.0 args: - --v=5 - --csi-address=/csi/csi.sock @@ -53,7 +53,7 @@ spec: - mountPath: /registration name: registration-dir - name: mock - image: registry.k8s.io/sig-storage/hostpathplugin:v1.16.1 + image: registry.k8s.io/sig-storage/hostpathplugin:v1.17.0 args: - "--drivername=mock.storage.k8s.io" - "--nodeid=$(KUBE_NODE_NAME)" diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-proxy.yaml b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-proxy.yaml index a267f4f592..0530c9a472 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-proxy.yaml +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/mock/csi-mock-proxy.yaml @@ -15,7 +15,7 @@ spec: serviceAccountName: csi-mock containers: - name: csi-provisioner - image: registry.k8s.io/sig-storage/csi-provisioner:v5.1.0 + image: registry.k8s.io/sig-storage/csi-provisioner:v6.0.0 args: - "--csi-address=$(ADDRESS)" # Topology support is needed for the pod rescheduling test @@ -35,7 +35,7 @@ spec: - mountPath: /csi name: socket-dir - name: driver-registrar - image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.13.0 + image: registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.15.0 args: - --v=5 - --csi-address=/csi/csi.sock @@ -53,7 +53,7 @@ spec: - mountPath: /registration name: registration-dir - name: mock - image: registry.k8s.io/sig-storage/hostpathplugin:v1.16.1 + image: registry.k8s.io/sig-storage/hostpathplugin:v1.17.0 args: - -v=5 - -nodeid=$(KUBE_NODE_NAME) diff --git a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/update-hostpath.sh b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/update-hostpath.sh index 122de0d18b..cf9ec057b4 100755 --- a/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/update-hostpath.sh +++ b/deps/github.com/openshift/kubernetes/test/e2e/testing-manifests/storage-csi/update-hostpath.sh @@ -37,7 +37,7 @@ set -xe cd "$(dirname "$0")" # Remove stale files. -rm -rf external-attacher external-provisioner external-resizer external-snapshotter external-health-monitor hostpath csi-driver-host-path +rm -rf external-attacher external-provisioner external-resizer external-snapshotter/csi-snapshotter external-health-monitor hostpath csi-driver-host-path # Check out desired release. git clone https://github.com/kubernetes-csi/csi-driver-host-path.git @@ -127,6 +127,10 @@ for image in $images; do path="csi-snapshotter" rbac="rbac-csi-snapshotter.yaml" ;; + external-snapshot-metadata) + # Another special case. There is no e2e test that needs the RBAC manifest + it's on an unusual place. + continue + ;; esac ;; esac @@ -137,5 +141,12 @@ done grep -r image: hostpath/hostpath/csi-hostpath-plugin.yaml | while read -r image; do version=$(echo "$image" | sed -e 's/.*:\(.*\)/\1/') image=$(echo "$image" | sed -e 's/.*image: \([^:]*\).*/\1/') - sed -i '' -e "s;$image:.*;$image:$version;" mock/*.yaml + + if sed --version >/dev/null 2>&1; then + # GNU sed, `-i ''` fails + sed -i -e "s;$image:.*;$image:$version;" mock/*.yaml + else + # BSD sed (macOS) + sed -i '' -e "s;$image:.*;$image:$version;" mock/*.yaml + fi done diff --git a/deps/github.com/openshift/kubernetes/test/e2e_node/container_lifecycle_test.go b/deps/github.com/openshift/kubernetes/test/e2e_node/container_lifecycle_test.go index 8362c3000b..6c99596dc7 100644 --- a/deps/github.com/openshift/kubernetes/test/e2e_node/container_lifecycle_test.go +++ b/deps/github.com/openshift/kubernetes/test/e2e_node/container_lifecycle_test.go @@ -5906,7 +5906,113 @@ var _ = SIGDescribe(feature.SidecarContainers, "Containers Lifecycle", func() { }) }) }) + }) + + ginkgo.When("A restartable init container with startup probe fails initially", func() { + ginkgo.It("should continue probing and allow regular container to start after the restartable init container recovers", func(ctx context.Context) { + restartableInit := "buggy-restartable-init" + regularContainer := "regular-container" + + restartPolicyAlways := v1.ContainerRestartPolicyAlways + + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "restartable-init-startup-probe-fix", + }, + Spec: v1.PodSpec{ + RestartPolicy: v1.RestartPolicyNever, + InitContainers: []v1.Container{{ + Name: restartableInit, + Image: busyboxImage, + RestartPolicy: &restartPolicyAlways, + Command: []string{"sh", "-c", ` +if [ ! -f /persistent/first_run_done ]; then + echo 'First run: creating marker and exiting with 1' + touch /persistent/first_run_done + exit 1 +else + echo 'Second run: marker found, running as sidecar' + sleep 120 +fi`}, + StartupProbe: &v1.Probe{ + InitialDelaySeconds: 3, + PeriodSeconds: 2, + FailureThreshold: 10, + ProbeHandler: v1.ProbeHandler{ + Exec: &v1.ExecAction{ + Command: []string{"/bin/true"}, + }, + }, + }, + }}, + Containers: []v1.Container{{ + Name: regularContainer, + Image: imageutils.GetPauseImageName(), + StartupProbe: &v1.Probe{ + InitialDelaySeconds: 5, + PeriodSeconds: 5, + ProbeHandler: v1.ProbeHandler{ + Exec: &v1.ExecAction{ + Command: []string{"/bin/true"}, + }, + }, + }, + }}, + }, + } + + preparePod(pod) + client := e2epod.NewPodClient(f) + pod = client.Create(ctx, pod) + + ginkgo.By("Waiting for init container to fail and restart at least once") + framework.ExpectNoError( + e2epod.WaitForPodCondition(ctx, f.ClientSet, pod.Namespace, pod.Name, + "restartable init restarted", 90*time.Second, + func(p *v1.Pod) (bool, error) { + for _, st := range p.Status.InitContainerStatuses { + if st.Name == restartableInit && st.RestartCount > 0 { + framework.Logf("Init container %s has restarted %d times", restartableInit, st.RestartCount) + return true, nil + } + } + return false, nil + }), + ) + + ginkgo.By("Waiting for init container to be running after restart") + framework.ExpectNoError( + e2epod.WaitForPodCondition(ctx, f.ClientSet, pod.Namespace, pod.Name, + "restartable init running", 90*time.Second, + func(p *v1.Pod) (bool, error) { + for _, st := range p.Status.InitContainerStatuses { + if st.Name == restartableInit && st.State.Running != nil { + framework.Logf("Init container %s is now running", restartableInit) + return true, nil + } + } + return false, nil + }), + ) + + ginkgo.By("Waiting for regular container to start") + framework.ExpectNoError( + e2epod.WaitForPodCondition(ctx, f.ClientSet, pod.Namespace, pod.Name, + "regular container running", 120*time.Second, + func(p *v1.Pod) (bool, error) { + for _, st := range p.Status.ContainerStatuses { + if st.Name == regularContainer && st.State.Running != nil { + framework.Logf("Regular container %s is running", regularContainer) + return true, nil + } + } + return false, nil + }), + ) + }) + }) + }) var _ = SIGDescribe(feature.SidecarContainers, framework.WithSerial(), "Containers Lifecycle", func() { diff --git a/deps/github.com/openshift/kubernetes/test/images/nonroot/BASEIMAGE b/deps/github.com/openshift/kubernetes/test/images/nonroot/BASEIMAGE index 5c683ef4c6..b0a0270b00 100644 --- a/deps/github.com/openshift/kubernetes/test/images/nonroot/BASEIMAGE +++ b/deps/github.com/openshift/kubernetes/test/images/nonroot/BASEIMAGE @@ -1,7 +1,7 @@ -linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.4 -linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.4 -linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.4 -linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.4 -linux/s390x=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.4 +linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.6 +linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.6 +linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.6 +linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.6 +linux/s390x=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.6 windows/amd64/1809=mcr.microsoft.com/windows/nanoserver:1809 windows/amd64/ltsc2022=mcr.microsoft.com/windows/nanoserver:ltsc2022 diff --git a/deps/github.com/openshift/kubernetes/test/images/pets/peer-finder/BASEIMAGE b/deps/github.com/openshift/kubernetes/test/images/pets/peer-finder/BASEIMAGE index 880445d9c1..8b900d2f41 100644 --- a/deps/github.com/openshift/kubernetes/test/images/pets/peer-finder/BASEIMAGE +++ b/deps/github.com/openshift/kubernetes/test/images/pets/peer-finder/BASEIMAGE @@ -1,5 +1,5 @@ -linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.4 -linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.4 -linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.4 -linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.4 -linux/s390x=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.4 +linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.6 +linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.6 +linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.6 +linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.6 +linux/s390x=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.6 diff --git a/deps/github.com/openshift/kubernetes/test/images/pets/zookeeper-installer/BASEIMAGE b/deps/github.com/openshift/kubernetes/test/images/pets/zookeeper-installer/BASEIMAGE index 1e453bde46..afc96c3e30 100644 --- a/deps/github.com/openshift/kubernetes/test/images/pets/zookeeper-installer/BASEIMAGE +++ b/deps/github.com/openshift/kubernetes/test/images/pets/zookeeper-installer/BASEIMAGE @@ -1,4 +1,4 @@ -linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.4 -linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.4 -linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.4 -linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.4 +linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.6 +linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.6 +linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.6 +linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.6 diff --git a/deps/github.com/openshift/kubernetes/test/images/regression-issue-74839/BASEIMAGE b/deps/github.com/openshift/kubernetes/test/images/regression-issue-74839/BASEIMAGE index 880445d9c1..8b900d2f41 100644 --- a/deps/github.com/openshift/kubernetes/test/images/regression-issue-74839/BASEIMAGE +++ b/deps/github.com/openshift/kubernetes/test/images/regression-issue-74839/BASEIMAGE @@ -1,5 +1,5 @@ -linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.4 -linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.4 -linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.4 -linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.4 -linux/s390x=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.4 +linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.6 +linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.6 +linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.6 +linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.6 +linux/s390x=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.6 diff --git a/deps/github.com/openshift/kubernetes/test/images/resource-consumer/BASEIMAGE b/deps/github.com/openshift/kubernetes/test/images/resource-consumer/BASEIMAGE index 5c683ef4c6..b0a0270b00 100644 --- a/deps/github.com/openshift/kubernetes/test/images/resource-consumer/BASEIMAGE +++ b/deps/github.com/openshift/kubernetes/test/images/resource-consumer/BASEIMAGE @@ -1,7 +1,7 @@ -linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.4 -linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.4 -linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.4 -linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.4 -linux/s390x=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.4 +linux/amd64=registry.k8s.io/build-image/debian-base-amd64:bookworm-v1.0.6 +linux/arm=registry.k8s.io/build-image/debian-base-arm:bookworm-v1.0.6 +linux/arm64=registry.k8s.io/build-image/debian-base-arm64:bookworm-v1.0.6 +linux/ppc64le=registry.k8s.io/build-image/debian-base-ppc64le:bookworm-v1.0.6 +linux/s390x=registry.k8s.io/build-image/debian-base-s390x:bookworm-v1.0.6 windows/amd64/1809=mcr.microsoft.com/windows/nanoserver:1809 windows/amd64/ltsc2022=mcr.microsoft.com/windows/nanoserver:ltsc2022 diff --git a/deps/github.com/openshift/kubernetes/test/integration/apimachinery/apply/apply_test.go b/deps/github.com/openshift/kubernetes/test/integration/apimachinery/apply/apply_test.go index ce51b5299a..0d6caed004 100644 --- a/deps/github.com/openshift/kubernetes/test/integration/apimachinery/apply/apply_test.go +++ b/deps/github.com/openshift/kubernetes/test/integration/apimachinery/apply/apply_test.go @@ -83,12 +83,20 @@ func testOptionalListMapKey(tCtx ktesting.TContext) { requireManagedFields := func(what string, obj *unstructured.Unstructured, expectedManagedFields any) { tCtx.Helper() actualManagedFields, _, _ := unstructured.NestedFieldCopy(obj.Object, "metadata", "managedFields") - // Strip non-deterministic time. if actualManagedFields != nil { managers := actualManagedFields.([]any) for i := range managers { + // Strip non-deterministic time. unstructured.RemoveNestedField(managers[i].(map[string]any), "time") } + // Sort by manager. There should be at most one entry per manager, so + // no need for a tie breaker. Semantically the order is irrelevant, + // so we don't need to expect a specific one here. + // + // The order turned out to be non-deterministic (test flake!) without this. + slices.SortFunc(managers, func(a, b any) int { + return strings.Compare(a.(map[string]any)["manager"].(string), b.(map[string]any)["manager"].(string)) + }) } require.Equal(tCtx, dump(expectedManagedFields), dump(actualManagedFields), "%s:\n%s", what, dump(obj)) } diff --git a/deps/github.com/openshift/kubernetes/test/integration/auth/auth_test.go b/deps/github.com/openshift/kubernetes/test/integration/auth/auth_test.go index 3641b7e4ae..d80b049d07 100644 --- a/deps/github.com/openshift/kubernetes/test/integration/auth/auth_test.go +++ b/deps/github.com/openshift/kubernetes/test/integration/auth/auth_test.go @@ -41,10 +41,9 @@ import ( "testing" "time" - utiltesting "k8s.io/client-go/util/testing" - "github.com/google/go-cmp/cmp" + authenticationv1 "k8s.io/api/authentication/v1" authenticationv1beta1 "k8s.io/api/authentication/v1beta1" certificatesv1 "k8s.io/api/certificates/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -65,6 +64,7 @@ import ( "k8s.io/client-go/rest" v1 "k8s.io/client-go/tools/clientcmd/api/v1" resttransport "k8s.io/client-go/transport" + utiltesting "k8s.io/client-go/util/testing" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing" "k8s.io/kubernetes/pkg/apis/autoscaling" @@ -1567,3 +1567,48 @@ func newTestWebhookTokenAuthServer() *httptest.Server { server.Start() return server } + +func TestSloppySANCertificates(t *testing.T) { + tCtx := ktesting.Init(t) + _, kubeConfig, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{ + ModifyServerRunOptions: func(opts *options.ServerRunOptions) { + // append to opts.Authentication.ClientCert.ClientCA + fmt.Println(opts.Authentication.ClientCert.ClientCA) + caData, err := os.ReadFile(opts.Authentication.ClientCert.ClientCA) + if err != nil { + t.Fatal(err) + } + sloppyCAData, err := os.ReadFile("testdata/sloppy-san-root.pem") + if err != nil { + t.Fatal(err) + } + err = os.WriteFile(opts.Authentication.ClientCert.ClientCA, []byte(string(caData)+"\n"+string(sloppyCAData)), os.FileMode(0644)) + if err != nil { + t.Fatal(err) + } + }, + }) + defer tearDownFn() + + var err error + kubeConfig = rest.AnonymousClientConfig(kubeConfig) + kubeConfig.CertData, err = os.ReadFile("testdata/sloppy-san-client.pem") + if err != nil { + t.Fatal(err) + } + kubeConfig.KeyData, err = os.ReadFile("testdata/sloppy-san-client-key.pem") + if err != nil { + t.Fatal(err) + } + c, err := clientset.NewForConfig(kubeConfig) + if err != nil { + t.Fatal(err) + } + r, err := c.AuthenticationV1().SelfSubjectReviews().Create(tCtx, &authenticationv1.SelfSubjectReview{}, metav1.CreateOptions{}) + if err != nil { + t.Fatal(err) + } + if r.Status.UserInfo.Username != "sloppy-san-client" { + t.Fatalf("expected sloppy-san-client, got %#v", r.Status.UserInfo) + } +} diff --git a/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/README.md b/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/README.md new file mode 100644 index 0000000000..a78ddfbd05 --- /dev/null +++ b/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/README.md @@ -0,0 +1 @@ +Keys in this directory are generated for testing purposes only. diff --git a/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-client-key.pem b/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-client-key.pem new file mode 100644 index 0000000000..b6d0a3a7c8 --- /dev/null +++ b/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-client-key.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEILndj5ixo79V24VqIlvSS0J5rwQyklP4+D+rAAjO763loAoGCCqGSM49 +AwEHoUQDQgAEXMW9sg8iyagwwhlJ94p0brB5NqSYIytoj18bs6xPZ3UqEZo5BhXi +2m2Cx8althrzoXbMIGr+ALUWDgKk7BVuSg== +-----END EC PRIVATE KEY----- diff --git a/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-client.pem b/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-client.pem new file mode 100644 index 0000000000..8627574055 --- /dev/null +++ b/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-client.pem @@ -0,0 +1,65 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 6084561304482469822 (0x5470b444dfc3d7be) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=sloppy-san-root + Validity + Not Before: Oct 14 00:20:19 2025 GMT + Not After : Sep 20 00:20:19 2125 GMT + Subject: CN=sloppy-san-client + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:5c:c5:bd:b2:0f:22:c9:a8:30:c2:19:49:f7:8a: + 74:6e:b0:79:36:a4:98:23:2b:68:8f:5f:1b:b3:ac: + 4f:67:75:2a:11:9a:39:06:15:e2:da:6d:82:c7:c6: + a5:b6:1a:f3:a1:76:cc:20:6a:fe:00:b5:16:0e:02: + a4:ec:15:6e:4a + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 Extended Key Usage: + TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:FALSE + X509v3 Authority Key Identifier: + 9A:A1:A8:3C:30:1B:EC:1F:B2:1F:10:0E:0C:42:A8:2A:B8:97:9A:8E + X509v3 Subject Alternative Name: + DNS:, DNS:example.com., email:not-an-email + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 96:bc:48:3c:aa:f6:8c:e4:a4:b5:40:6d:fe:20:1b:60:40:12: + e9:f5:58:94:0e:0d:dc:6d:a3:83:ae:3d:05:3b:64:1a:f4:c0: + 23:c9:0d:63:02:ea:c2:f4:e8:bc:88:20:8e:2e:bb:f0:79:32: + cc:0a:59:e2:17:6f:63:aa:5e:b8:0d:54:15:2f:5c:eb:08:7e: + eb:fe:31:62:b1:e5:da:88:dc:be:9e:20:01:f1:73:40:8d:13: + 55:36:aa:2e:58:13:b4:85:aa:63:30:2c:47:a4:95:61:33:f3: + 31:c7:f8:91:d1:18:3c:65:a8:fb:a4:8f:dc:51:8e:9a:d5:dc: + eb:04:b5:b1:f9:82:f5:ff:4a:7b:27:b3:3e:8e:59:30:93:57: + 7d:f2:b4:af:94:39:2b:b9:0d:c1:e5:94:0f:8d:83:03:74:e5: + 6f:38:cd:ee:df:1b:5d:64:48:b9:05:27:5f:09:12:c8:03:96: + 36:0d:d4:19:5b:be:76:ea:7d:f3:20:08:2a:b4:c6:92:63:41: + 44:d8:2c:b1:b8:71:7c:a9:1f:26:d7:99:04:d4:9b:a6:4b:a4: + fa:ef:b2:a9:f5:e7:af:53:4b:de:00:45:5c:5b:f0:2a:1a:bc: + 40:2f:97:ca:fb:9c:53:a8:16:46:89:a0:f9:43:45:47:de:3e: + 09:8e:a6:22 +-----BEGIN CERTIFICATE----- +MIICbjCCAVagAwIBAgIIVHC0RN/D174wDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UE +AxMPc2xvcHB5LXNhbi1yb290MCAXDTI1MTAxNDAwMjAxOVoYDzIxMjUwOTIwMDAy +MDE5WjAcMRowGAYDVQQDExFzbG9wcHktc2FuLWNsaWVudDBZMBMGByqGSM49AgEG +CCqGSM49AwEHA0IABFzFvbIPIsmoMMIZSfeKdG6weTakmCMraI9fG7OsT2d1KhGa +OQYV4tptgsfGpbYa86F2zCBq/gC1Fg4CpOwVbkqjfzB9MA4GA1UdDwEB/wQEAwIF +oDATBgNVHSUEDDAKBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaA +FJqhqDwwG+wfsh8QDgxCqCq4l5qOMCcGA1UdEQQgMB6CAIIMZXhhbXBsZS5jb20u +gQxub3QtYW4tZW1haWwwDQYJKoZIhvcNAQELBQADggEBAJa8SDyq9ozkpLVAbf4g +G2BAEun1WJQODdxto4OuPQU7ZBr0wCPJDWMC6sL06LyIII4uu/B5MswKWeIXb2Oq +XrgNVBUvXOsIfuv+MWKx5dqI3L6eIAHxc0CNE1U2qi5YE7SFqmMwLEeklWEz8zHH ++JHRGDxlqPukj9xRjprV3OsEtbH5gvX/Snsnsz6OWTCTV33ytK+UOSu5DcHllA+N +gwN05W84ze7fG11kSLkFJ18JEsgDljYN1BlbvnbqffMgCCq0xpJjQUTYLLG4cXyp +HybXmQTUm6ZLpPrvsqn1569TS94ARVxb8CoavEAvl8r7nFOoFkaJoPlDRUfePgmO +piI= +-----END CERTIFICATE----- diff --git a/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-root.pem b/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-root.pem new file mode 100644 index 0000000000..54386e1487 --- /dev/null +++ b/deps/github.com/openshift/kubernetes/test/integration/auth/testdata/sloppy-san-root.pem @@ -0,0 +1,78 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 2937139693522916239 (0x28c2d0fd5822138f) + Signature Algorithm: sha256WithRSAEncryption + Issuer: CN=sloppy-san-root + Validity + Not Before: Oct 14 00:20:19 2025 GMT + Not After : Sep 20 00:20:19 2125 GMT + Subject: CN=sloppy-san-root + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:9e:00:38:70:8d:a7:9c:fd:89:e4:33:f9:7e:e3: + 99:1f:19:69:a9:a3:7c:ca:8e:f4:52:ef:c8:a8:3d: + fc:6c:08:95:8b:14:f9:d9:a2:2b:25:7c:15:8e:aa: + a9:ec:19:fe:62:9f:18:33:12:72:b0:2f:37:b6:de: + d0:24:fe:19:ef:78:93:b7:7d:7a:44:46:4c:14:bd: + d7:23:a7:fc:44:43:6d:f9:29:f8:79:2a:61:fc:1f: + d4:79:49:19:53:5b:6d:5a:66:cd:59:a9:2b:38:c7: + c5:38:96:b8:12:36:c5:60:d8:dc:ea:86:df:9a:cd: + 50:95:be:5f:1a:38:67:dc:bf:67:24:5e:ed:06:79: + 32:b5:19:bd:11:ec:ff:61:b7:e2:32:05:8d:b6:c9: + 12:ba:92:7c:2a:9e:26:71:b2:d0:85:95:9d:68:79: + d0:3e:e5:8b:ac:e8:e4:22:6d:79:a3:77:58:01:72: + f9:67:7d:d8:5e:7f:5c:56:45:31:36:8e:f5:be:48: + c4:66:f1:14:ed:38:43:ae:5f:cc:20:66:7b:48:df: + 78:d5:f4:4f:67:2a:d4:ee:7b:36:d2:c1:5f:d1:3b: + e4:bb:31:0f:94:0c:19:f7:17:99:99:04:eb:b7:b4: + 34:6c:f9:0b:8c:61:e9:a5:5b:50:62:f7:24:51:25: + 3d:43 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Key Encipherment, Certificate Sign + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Subject Key Identifier: + 9A:A1:A8:3C:30:1B:EC:1F:B2:1F:10:0E:0C:42:A8:2A:B8:97:9A:8E + X509v3 Subject Alternative Name: + DNS:, DNS:example.com. + Signature Algorithm: sha256WithRSAEncryption + Signature Value: + 4d:4f:ef:47:a0:41:96:9a:e0:98:e3:e6:5e:4f:70:6a:b1:16: + 3c:10:8b:f9:2b:12:57:58:28:88:a4:1a:e8:4c:a4:be:a0:c1: + ad:07:95:dd:d9:bc:db:a9:db:31:5f:42:30:60:19:e2:28:fb: + 72:78:91:a7:83:e7:bd:0f:52:b8:2b:fe:d0:0e:03:64:0e:08: + 8b:62:b9:bc:30:1d:76:86:42:a6:fe:f0:55:0d:3c:16:97:32: + 3a:9f:1a:0e:5b:01:68:9d:37:76:d5:ed:a8:e5:e6:1b:7d:ff: + b2:e3:c0:a0:8f:cb:2f:98:e5:6b:e5:b6:ef:fe:a4:c4:f8:33: + 6f:e1:90:89:16:69:58:c8:ca:95:99:d1:84:8e:0e:83:ed:a7: + ae:ac:4e:32:7e:72:95:fa:ce:3f:62:ae:06:57:40:b2:bf:79: + 8f:b2:f6:69:07:ee:d8:7c:70:b0:52:8d:f6:08:f9:de:a8:6a: + 90:77:6a:65:52:67:82:98:32:68:66:4d:8e:6b:a8:dd:b5:3c: + a7:fe:b4:98:d0:69:70:1b:60:60:1b:10:30:88:5c:9b:f0:6b: + 9e:52:47:2f:83:7d:77:e3:e2:af:a5:fb:de:65:91:51:0f:27: + b2:34:25:8f:97:55:ee:11:d0:d1:4e:8f:7a:cf:9f:7d:8e:e6: + 27:24:61:cf +-----BEGIN CERTIFICATE----- +MIIDFTCCAf2gAwIBAgIIKMLQ/VgiE48wDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UE +AxMPc2xvcHB5LXNhbi1yb290MCAXDTI1MTAxNDAwMjAxOVoYDzIxMjUwOTIwMDAy +MDE5WjAaMRgwFgYDVQQDEw9zbG9wcHktc2FuLXJvb3QwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCeADhwjaec/YnkM/l+45kfGWmpo3zKjvRS78ioPfxs +CJWLFPnZoislfBWOqqnsGf5inxgzEnKwLze23tAk/hnveJO3fXpERkwUvdcjp/xE +Q235Kfh5KmH8H9R5SRlTW21aZs1ZqSs4x8U4lrgSNsVg2Nzqht+azVCVvl8aOGfc +v2ckXu0GeTK1Gb0R7P9ht+IyBY22yRK6knwqniZxstCFlZ1oedA+5Yus6OQibXmj +d1gBcvlnfdhef1xWRTE2jvW+SMRm8RTtOEOuX8wgZntI33jV9E9nKtTuezbSwV/R +O+S7MQ+UDBn3F5mZBOu3tDRs+QuMYemlW1Bi9yRRJT1DAgMBAAGjXTBbMA4GA1Ud +DwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSaoag8MBvsH7If +EA4MQqgquJeajjAZBgNVHREEEjAQggCCDGV4YW1wbGUuY29tLjANBgkqhkiG9w0B +AQsFAAOCAQEATU/vR6BBlprgmOPmXk9warEWPBCL+SsSV1goiKQa6EykvqDBrQeV +3dm826nbMV9CMGAZ4ij7cniRp4PnvQ9SuCv+0A4DZA4Ii2K5vDAddoZCpv7wVQ08 +FpcyOp8aDlsBaJ03dtXtqOXmG33/suPAoI/LL5jla+W27/6kxPgzb+GQiRZpWMjK +lZnRhI4Og+2nrqxOMn5ylfrOP2KuBldAsr95j7L2aQfu2HxwsFKN9gj53qhqkHdq +ZVJngpgyaGZNjmuo3bU8p/60mNBpcBtgYBsQMIhcm/BrnlJHL4N9d+Pir6X73mWR +UQ8nsjQlj5dV7hHQ0U6Pes+ffY7mJyRhzw== +-----END CERTIFICATE----- diff --git a/deps/github.com/openshift/kubernetes/test/integration/job/job_test.go b/deps/github.com/openshift/kubernetes/test/integration/job/job_test.go index 8e8e2aa9ef..3e0bee1d26 100644 --- a/deps/github.com/openshift/kubernetes/test/integration/job/job_test.go +++ b/deps/github.com/openshift/kubernetes/test/integration/job/job_test.go @@ -4091,6 +4091,85 @@ func TestSuspendJob(t *testing.T) { } } +// TestStartTimeUpdateOnResume verifies that the job controller can update startTime +// when resuming a suspended job (https://github.com/kubernetes/kubernetes/issues/134521). +func TestStartTimeUpdateOnResume(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.JobManagedBy, true) + + closeFn, restConfig, clientSet, ns := setup(t, "suspend-starttime-validation") + t.Cleanup(closeFn) + ctx, cancel := startJobControllerAndWaitForCaches(t, restConfig) + t.Cleanup(cancel) + + job, err := createJobWithDefaults(ctx, clientSet, ns.Name, &batchv1.Job{ + Spec: batchv1.JobSpec{ + Parallelism: ptr.To[int32](1), + Completions: ptr.To[int32](2), + Suspend: ptr.To(false), + }, + }) + if err != nil { + t.Fatalf("Failed to create Job: %v", err) + } + + validateJobsPodsStatusOnly(ctx, t, clientSet, job, podsByStatus{ + Active: 1, + Ready: ptr.To[int32](0), + Terminating: ptr.To[int32](0), + }) + + job, err = clientSet.BatchV1().Jobs(ns.Name).Get(ctx, job.Name, metav1.GetOptions{}) + if err != nil { + t.Fatalf("Failed to get Job: %v", err) + } + if job.Status.StartTime == nil { + t.Fatalf("Job startTime was not set") + } + + job.Spec.Suspend = ptr.To(true) + job, err = clientSet.BatchV1().Jobs(ns.Name).Update(ctx, job, metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("Failed to suspend Job: %v", err) + } + + validateJobsPodsStatusOnly(ctx, t, clientSet, job, podsByStatus{ + Active: 0, + Ready: ptr.To[int32](0), + Terminating: ptr.To[int32](0), + }) + + job, err = clientSet.BatchV1().Jobs(ns.Name).Get(ctx, job.Name, metav1.GetOptions{}) + if err != nil { + t.Fatalf("Failed to get Job: %v", err) + } + if getJobConditionStatus(ctx, job, batchv1.JobSuspended) != v1.ConditionTrue { + t.Fatalf("JobSuspended condition was not set to True") + } + + job.Spec.Suspend = ptr.To(false) + job, err = clientSet.BatchV1().Jobs(ns.Name).Update(ctx, job, metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("Failed to resume Job: %v", err) + } + + validateJobsPodsStatusOnly(ctx, t, clientSet, job, podsByStatus{ + Active: 1, + Ready: ptr.To[int32](0), + Terminating: ptr.To[int32](0), + }) + + job, err = clientSet.BatchV1().Jobs(ns.Name).Get(ctx, job.Name, metav1.GetOptions{}) + if err != nil { + t.Fatalf("Failed to get Job: %v", err) + } + if getJobConditionStatus(ctx, job, batchv1.JobSuspended) != v1.ConditionFalse { + t.Error("JobSuspended condition was not set to False") + } + if job.Status.StartTime == nil { + t.Error("Job startTime was not set after resume") + } +} + // TestSuspendJobWithZeroCompletions verifies the suspended Job with // completions=0 is marked as Complete. func TestSuspendJobWithZeroCompletions(t *testing.T) { diff --git a/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/misc/main_test.go b/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/misc/main_test.go new file mode 100644 index 0000000000..3dd88c34eb --- /dev/null +++ b/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/misc/main_test.go @@ -0,0 +1,27 @@ +/* +Copyright 2017 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 miscpreemption + +import ( + "testing" + + "k8s.io/kubernetes/test/integration/framework" +) + +func TestMain(m *testing.M) { + framework.EtcdMain(m.Run) +} diff --git a/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/misc/miscpreemption_test.go b/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/misc/miscpreemption_test.go new file mode 100644 index 0000000000..805ecd104a --- /dev/null +++ b/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/misc/miscpreemption_test.go @@ -0,0 +1,1238 @@ +/* +Copyright 2017 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 miscpreemption + +import ( + "fmt" + "testing" + "time" + + v1 "k8s.io/api/core/v1" + policy "k8s.io/api/policy/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/wait" + utilfeature "k8s.io/apiserver/pkg/util/feature" + "k8s.io/client-go/informers" + clientset "k8s.io/client-go/kubernetes" + restclient "k8s.io/client-go/rest" + featuregatetesting "k8s.io/component-base/featuregate/testing" + "k8s.io/component-helpers/storage/volume" + "k8s.io/klog/v2" + configv1 "k8s.io/kube-scheduler/config/v1" + podutil "k8s.io/kubernetes/pkg/api/v1/pod" + "k8s.io/kubernetes/pkg/apis/scheduling" + "k8s.io/kubernetes/pkg/features" + "k8s.io/kubernetes/pkg/scheduler" + configtesting "k8s.io/kubernetes/pkg/scheduler/apis/config/testing" + "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumerestrictions" + st "k8s.io/kubernetes/pkg/scheduler/testing" + "k8s.io/kubernetes/plugin/pkg/admission/priority" + testutils "k8s.io/kubernetes/test/integration/util" + "k8s.io/utils/ptr" +) + +// imported from testutils +var ( + initPausePod = testutils.InitPausePod + createNode = testutils.CreateNode + createPausePod = testutils.CreatePausePod + runPausePod = testutils.RunPausePod + initTest = testutils.InitTestSchedulerWithNS + initTestDisablePreemption = testutils.InitTestDisablePreemption + initDisruptionController = testutils.InitDisruptionController + waitCachedPodsStable = testutils.WaitCachedPodsStable + podIsGettingEvicted = testutils.PodIsGettingEvicted + podUnschedulable = testutils.PodUnschedulable + waitForPDBsStable = testutils.WaitForPDBsStable + waitForPodToScheduleWithTimeout = testutils.WaitForPodToScheduleWithTimeout + waitForPodUnschedulable = testutils.WaitForPodUnschedulable +) + +var lowPriority, mediumPriority, highPriority = int32(100), int32(200), int32(300) + +// TestNonPreemption tests NonPreempt option of PriorityClass of scheduler works as expected. +func TestNonPreemption(t *testing.T) { + var preemptNever = v1.PreemptNever + // Initialize scheduler. + testCtx := initTest(t, "non-preemption") + cs := testCtx.ClientSet + tests := []struct { + name string + PreemptionPolicy *v1.PreemptionPolicy + }{ + { + name: "pod preemption will happen", + PreemptionPolicy: nil, + }, + { + name: "pod preemption will not happen", + PreemptionPolicy: &preemptNever, + }, + } + victim := initPausePod(&testutils.PausePodConfig{ + Name: "victim-pod", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(400, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, + }, + }) + + preemptor := initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, + }, + }) + + // Create a node with some resources + nodeRes := map[v1.ResourceName]string{ + v1.ResourcePods: "32", + v1.ResourceCPU: "500m", + v1.ResourceMemory: "500", + } + _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) + if err != nil { + t.Fatalf("Error creating nodes: %v", err) + } + + for _, asyncPreemptionEnabled := range []bool{true, false} { + for _, test := range tests { + t.Run(fmt.Sprintf("%s (Async preemption enabled: %v)", test.name, asyncPreemptionEnabled), func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) + + defer testutils.CleanupPods(testCtx.Ctx, cs, t, []*v1.Pod{preemptor, victim}) + preemptor.Spec.PreemptionPolicy = test.PreemptionPolicy + victimPod, err := createPausePod(cs, victim) + if err != nil { + t.Fatalf("Error while creating victim: %v", err) + } + if err := waitForPodToScheduleWithTimeout(testCtx.Ctx, cs, victimPod, 5*time.Second); err != nil { + t.Fatalf("victim %v should be become scheduled", victimPod.Name) + } + + preemptorPod, err := createPausePod(cs, preemptor) + if err != nil { + t.Fatalf("Error while creating preemptor: %v", err) + } + + err = testutils.WaitForNominatedNodeNameWithTimeout(testCtx.Ctx, cs, preemptorPod, 5*time.Second) + // test.PreemptionPolicy == nil means we expect the preemptor to be nominated. + expect := test.PreemptionPolicy == nil + // err == nil indicates the preemptor is indeed nominated. + got := err == nil + if got != expect { + t.Errorf("Expect preemptor to be nominated=%v, but got=%v", expect, got) + } + }) + } + } +} + +// TestDisablePreemption tests disable pod preemption of scheduler works as expected. +func TestDisablePreemption(t *testing.T) { + // Initialize scheduler, and disable preemption. + testCtx := initTestDisablePreemption(t, "disable-preemption") + cs := testCtx.ClientSet + + tests := []struct { + name string + existingPods []*v1.Pod + pod *v1.Pod + }{ + { + name: "pod preemption will not happen", + existingPods: []*v1.Pod{ + initPausePod(&testutils.PausePodConfig{ + Name: "victim-pod", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(400, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, + }, + }), + }, + pod: initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, + }, + }), + }, + } + + // Create a node with some resources + nodeRes := map[v1.ResourceName]string{ + v1.ResourcePods: "32", + v1.ResourceCPU: "500m", + v1.ResourceMemory: "500", + } + _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) + if err != nil { + t.Fatalf("Error creating nodes: %v", err) + } + + for _, asyncPreemptionEnabled := range []bool{true, false} { + for _, test := range tests { + t.Run(fmt.Sprintf("%s (Async preemption enabled: %v)", test.name, asyncPreemptionEnabled), func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) + + pods := make([]*v1.Pod, len(test.existingPods)) + // Create and run existingPods. + for i, p := range test.existingPods { + pods[i], err = runPausePod(cs, p) + if err != nil { + t.Fatalf("Test [%v]: Error running pause pod: %v", test.name, err) + } + } + // Create the "pod". + preemptor, err := createPausePod(cs, test.pod) + if err != nil { + t.Errorf("Error while creating high priority pod: %v", err) + } + // Ensure preemptor should keep unschedulable. + if err := waitForPodUnschedulable(testCtx.Ctx, cs, preemptor); err != nil { + t.Errorf("Preemptor %v should not become scheduled", preemptor.Name) + } + + // Ensure preemptor should not be nominated. + if err := testutils.WaitForNominatedNodeNameWithTimeout(testCtx.Ctx, cs, preemptor, 5*time.Second); err == nil { + t.Errorf("Preemptor %v should not be nominated", preemptor.Name) + } + + // Cleanup + pods = append(pods, preemptor) + testutils.CleanupPods(testCtx.Ctx, cs, t, pods) + }) + } + } +} + +// This test verifies that system critical priorities are created automatically and resolved properly. +func TestPodPriorityResolution(t *testing.T) { + admission := priority.NewPlugin() + testCtx := testutils.InitTestScheduler(t, testutils.InitTestAPIServer(t, "preemption", admission)) + cs := testCtx.ClientSet + + // Build clientset and informers for controllers. + externalClientConfig := restclient.CopyConfig(testCtx.KubeConfig) + externalClientConfig.QPS = -1 + externalClientset := clientset.NewForConfigOrDie(externalClientConfig) + externalInformers := informers.NewSharedInformerFactory(externalClientset, time.Second) + admission.SetExternalKubeClientSet(externalClientset) + admission.SetExternalKubeInformerFactory(externalInformers) + + // Waiting for all controllers to sync + testutils.SyncSchedulerInformerFactory(testCtx) + externalInformers.Start(testCtx.Ctx.Done()) + externalInformers.WaitForCacheSync(testCtx.Ctx.Done()) + + // Run all controllers + go testCtx.Scheduler.Run(testCtx.Ctx) + + tests := []struct { + Name string + PriorityClass string + Pod *v1.Pod + ExpectedPriority int32 + ExpectedError error + }{ + { + Name: "SystemNodeCritical priority class", + PriorityClass: scheduling.SystemNodeCritical, + ExpectedPriority: scheduling.SystemCriticalPriority + 1000, + Pod: initPausePod(&testutils.PausePodConfig{ + Name: fmt.Sprintf("pod1-%v", scheduling.SystemNodeCritical), + Namespace: metav1.NamespaceSystem, + PriorityClassName: scheduling.SystemNodeCritical, + }), + }, + { + Name: "SystemClusterCritical priority class", + PriorityClass: scheduling.SystemClusterCritical, + ExpectedPriority: scheduling.SystemCriticalPriority, + Pod: initPausePod(&testutils.PausePodConfig{ + Name: fmt.Sprintf("pod2-%v", scheduling.SystemClusterCritical), + Namespace: metav1.NamespaceSystem, + PriorityClassName: scheduling.SystemClusterCritical, + }), + }, + { + Name: "Invalid priority class should result in error", + PriorityClass: "foo", + ExpectedPriority: scheduling.SystemCriticalPriority, + Pod: initPausePod(&testutils.PausePodConfig{ + Name: fmt.Sprintf("pod3-%v", scheduling.SystemClusterCritical), + Namespace: metav1.NamespaceSystem, + PriorityClassName: "foo", + }), + ExpectedError: fmt.Errorf("failed to create pause pod: pods \"pod3-system-cluster-critical\" is forbidden: no PriorityClass with name foo was found"), + }, + } + + // Create a node with some resources + nodeRes := map[v1.ResourceName]string{ + v1.ResourcePods: "32", + v1.ResourceCPU: "500m", + v1.ResourceMemory: "500", + } + _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) + if err != nil { + t.Fatalf("Error creating nodes: %v", err) + } + + pods := make([]*v1.Pod, 0, len(tests)) + for _, asyncPreemptionEnabled := range []bool{true, false} { + for _, test := range tests { + t.Run(fmt.Sprintf("%s (Async preemption enabled: %v)", test.Name, asyncPreemptionEnabled), func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) + + pod, err := runPausePod(cs, test.Pod) + if err != nil { + if test.ExpectedError == nil { + t.Fatalf("Test [PodPriority/%v]: Error running pause pod: %v", test.PriorityClass, err) + } + if err.Error() != test.ExpectedError.Error() { + t.Fatalf("Test [PodPriority/%v]: Expected error %v but got error %v", test.PriorityClass, test.ExpectedError, err) + } + return + } + pods = append(pods, pod) + if pod.Spec.Priority != nil { + if *pod.Spec.Priority != test.ExpectedPriority { + t.Errorf("Expected pod %v to have priority %v but was %v", pod.Name, test.ExpectedPriority, pod.Spec.Priority) + } + } else { + t.Errorf("Expected pod %v to have priority %v but was nil", pod.Name, test.PriorityClass) + } + testutils.CleanupPods(testCtx.Ctx, cs, t, pods) + }) + } + } + testutils.CleanupNodes(cs, t) +} + +func mkPriorityPodWithGrace(tc *testutils.TestContext, name string, priority int32, grace int64) *v1.Pod { + defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(100, resource.DecimalSI)}, + } + pod := initPausePod(&testutils.PausePodConfig{ + Name: name, + Namespace: tc.NS.Name, + Priority: &priority, + Labels: map[string]string{"pod": name}, + Resources: defaultPodRes, + }) + pod.Spec.TerminationGracePeriodSeconds = &grace + return pod +} + +// This test ensures that while the preempting pod is waiting for the victims to +// terminate, other pending lower priority pods are not scheduled in the room created +// after preemption and while the higher priority pods is not scheduled yet. +func TestPreemptionStarvation(t *testing.T) { + // Initialize scheduler. + testCtx := initTest(t, "preemption") + cs := testCtx.ClientSet + + tests := []struct { + name string + numExistingPod int + numExpectedPending int + preemptor *v1.Pod + }{ + { + // This test ensures that while the preempting pod is waiting for the victims + // terminate, other lower priority pods are not scheduled in the room created + // after preemption and while the higher priority pods is not scheduled yet. + name: "starvation test: higher priority pod is scheduled before the lower priority ones", + numExistingPod: 10, + numExpectedPending: 5, + preemptor: initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, + }, + }), + }, + } + + // Create a node with some resources + nodeRes := map[v1.ResourceName]string{ + v1.ResourcePods: "32", + v1.ResourceCPU: "500m", + v1.ResourceMemory: "500", + } + _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) + if err != nil { + t.Fatalf("Error creating nodes: %v", err) + } + + for _, asyncPreemptionEnabled := range []bool{true, false} { + for _, clearingNominatedNodeNameAfterBinding := range []bool{true, false} { + for _, test := range tests { + t.Run(fmt.Sprintf("%s (Async preemption enabled: %v, ClearingNominatedNodeNameAfterBinding: %v)", test.name, asyncPreemptionEnabled, clearingNominatedNodeNameAfterBinding), func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ClearingNominatedNodeNameAfterBinding, clearingNominatedNodeNameAfterBinding) + + pendingPods := make([]*v1.Pod, test.numExpectedPending) + numRunningPods := test.numExistingPod - test.numExpectedPending + runningPods := make([]*v1.Pod, numRunningPods) + // Create and run existingPods. + for i := 0; i < numRunningPods; i++ { + runningPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(testCtx, fmt.Sprintf("rpod-%v", i), mediumPriority, 0)) + if err != nil { + t.Fatalf("Error creating pause pod: %v", err) + } + } + // make sure that runningPods are all scheduled. + for _, p := range runningPods { + if err := testutils.WaitForPodToSchedule(testCtx.Ctx, cs, p); err != nil { + t.Fatalf("Pod %v/%v didn't get scheduled: %v", p.Namespace, p.Name, err) + } + } + // Create pending pods. + for i := 0; i < test.numExpectedPending; i++ { + pendingPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(testCtx, fmt.Sprintf("ppod-%v", i), mediumPriority, 0)) + if err != nil { + t.Fatalf("Error creating pending pod: %v", err) + } + } + // Make sure that all pending pods are being marked unschedulable. + for _, p := range pendingPods { + if err := wait.PollUntilContextTimeout(testCtx.Ctx, 100*time.Millisecond, wait.ForeverTestTimeout, false, + podUnschedulable(cs, p.Namespace, p.Name)); err != nil { + t.Errorf("Pod %v/%v didn't get marked unschedulable: %v", p.Namespace, p.Name, err) + } + } + // Create the preemptor. + preemptor, err := createPausePod(cs, test.preemptor) + if err != nil { + t.Errorf("Error while creating the preempting pod: %v", err) + } + + // Make sure that preemptor is scheduled after preemptions. + if err := testutils.WaitForPodToScheduleWithTimeout(testCtx.Ctx, cs, preemptor, 60*time.Second); err != nil { + t.Errorf("Preemptor pod %v didn't get scheduled: %v", preemptor.Name, err) + } + + // Check if .status.nominatedNodeName of the preemptor pod gets set when feature gate is disabled. + // This test always expects preemption to occur since numExistingPod (10) fills the node completely. + if !clearingNominatedNodeNameAfterBinding { + if err := testutils.WaitForNominatedNodeName(testCtx.Ctx, cs, preemptor); err != nil { + t.Errorf(".status.nominatedNodeName was not set for pod %v/%v: %v", preemptor.Namespace, preemptor.Name, err) + } + } + // Cleanup + klog.Info("Cleaning up all pods...") + allPods := pendingPods + allPods = append(allPods, runningPods...) + allPods = append(allPods, preemptor) + testutils.CleanupPods(testCtx.Ctx, cs, t, allPods) + }) + } + } + } +} + +// TestPreemptionRaces tests that other scheduling events and operations do not +// race with the preemption process. +func TestPreemptionRaces(t *testing.T) { + // Initialize scheduler. + testCtx := initTest(t, "preemption-race") + cs := testCtx.ClientSet + + tests := []struct { + name string + numInitialPods int // Pods created and executed before running preemptor + numAdditionalPods int // Pods created after creating the preemptor + numRepetitions int // Repeat the tests to check races + preemptor *v1.Pod + }{ + { + // This test ensures that while the preempting pod is waiting for the victims + // terminate, other lower priority pods are not scheduled in the room created + // after preemption and while the higher priority pods is not scheduled yet. + name: "ensures that other pods are not scheduled while preemptor is being marked as nominated (issue #72124)", + numInitialPods: 2, + numAdditionalPods: 20, + numRepetitions: 5, + preemptor: initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(4900, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(4900, resource.DecimalSI)}, + }, + }), + }, + } + + // Create a node with some resources + nodeRes := map[v1.ResourceName]string{ + v1.ResourcePods: "100", + v1.ResourceCPU: "5000m", + v1.ResourceMemory: "5000", + } + _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) + if err != nil { + t.Fatalf("Error creating nodes: %v", err) + } + + for _, asyncPreemptionEnabled := range []bool{true, false} { + for _, clearingNominatedNodeNameAfterBinding := range []bool{true, false} { + for _, test := range tests { + t.Run(fmt.Sprintf("%s (Async preemption enabled: %v, ClearingNominatedNodeNameAfterBinding: %v)", test.name, asyncPreemptionEnabled, clearingNominatedNodeNameAfterBinding), func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ClearingNominatedNodeNameAfterBinding, clearingNominatedNodeNameAfterBinding) + + if test.numRepetitions <= 0 { + test.numRepetitions = 1 + } + for n := 0; n < test.numRepetitions; n++ { + initialPods := make([]*v1.Pod, test.numInitialPods) + additionalPods := make([]*v1.Pod, test.numAdditionalPods) + // Create and run existingPods. + for i := 0; i < test.numInitialPods; i++ { + initialPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(testCtx, fmt.Sprintf("rpod-%v", i), mediumPriority, 0)) + if err != nil { + t.Fatalf("Error creating pause pod: %v", err) + } + } + // make sure that initial Pods are all scheduled. + for _, p := range initialPods { + if err := testutils.WaitForPodToSchedule(testCtx.Ctx, cs, p); err != nil { + t.Fatalf("Pod %v/%v didn't get scheduled: %v", p.Namespace, p.Name, err) + } + } + // Create the preemptor. + klog.Info("Creating the preemptor pod...") + preemptor, err := createPausePod(cs, test.preemptor) + if err != nil { + t.Errorf("Error while creating the preempting pod: %v", err) + } + + klog.Info("Creating additional pods...") + for i := 0; i < test.numAdditionalPods; i++ { + additionalPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(testCtx, fmt.Sprintf("ppod-%v", i), mediumPriority, 0)) + if err != nil { + t.Fatalf("Error creating pending pod: %v", err) + } + } + // Make sure that preemptor is scheduled after preemptions. + if err := testutils.WaitForPodToScheduleWithTimeout(testCtx.Ctx, cs, preemptor, 60*time.Second); err != nil { + t.Errorf("Preemptor pod %v didn't get scheduled: %v", preemptor.Name, err) + } + + // Check that the preemptor pod gets nominated node name when feature gate is disabled. + if !clearingNominatedNodeNameAfterBinding { + if err := testutils.WaitForNominatedNodeName(testCtx.Ctx, cs, preemptor); err != nil { + t.Errorf(".status.nominatedNodeName was not set for pod %v/%v: %v", preemptor.Namespace, preemptor.Name, err) + } + } + + klog.Info("Check unschedulable pods still exists and were never scheduled...") + for _, p := range additionalPods { + pod, err := cs.CoreV1().Pods(p.Namespace).Get(testCtx.Ctx, p.Name, metav1.GetOptions{}) + if err != nil { + t.Errorf("Error in getting Pod %v/%v info: %v", p.Namespace, p.Name, err) + } + if len(pod.Spec.NodeName) > 0 { + t.Errorf("Pod %v/%v is already scheduled", p.Namespace, p.Name) + } + _, cond := podutil.GetPodCondition(&pod.Status, v1.PodScheduled) + if cond != nil && cond.Status != v1.ConditionFalse { + t.Errorf("Pod %v/%v is no longer unschedulable: %v", p.Namespace, p.Name, err) + } + } + // Cleanup + klog.Info("Cleaning up all pods...") + allPods := additionalPods + allPods = append(allPods, initialPods...) + allPods = append(allPods, preemptor) + testutils.CleanupPods(testCtx.Ctx, cs, t, allPods) + } + }) + } + } + } +} + +func mkMinAvailablePDB(name, namespace string, uid types.UID, minAvailable int, matchLabels map[string]string) *policy.PodDisruptionBudget { + intMinAvailable := intstr.FromInt32(int32(minAvailable)) + return &policy.PodDisruptionBudget{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: policy.PodDisruptionBudgetSpec{ + MinAvailable: &intMinAvailable, + Selector: &metav1.LabelSelector{MatchLabels: matchLabels}, + }, + } +} + +func addPodConditionReady(pod *v1.Pod) { + pod.Status = v1.PodStatus{ + Phase: v1.PodRunning, + Conditions: []v1.PodCondition{ + { + Type: v1.PodReady, + Status: v1.ConditionTrue, + }, + }, + } +} + +// TestPDBInPreemption tests PodDisruptionBudget support in preemption. +func TestPDBInPreemption(t *testing.T) { + // Initialize scheduler. + testCtx := initTest(t, "preemption-pdb") + cs := testCtx.ClientSet + + initDisruptionController(t, testCtx) + + defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(100, resource.DecimalSI)}, + } + defaultNodeRes := map[v1.ResourceName]string{ + v1.ResourcePods: "32", + v1.ResourceCPU: "500m", + v1.ResourceMemory: "500", + } + + tests := []struct { + name string + nodeCnt int + pdbs []*policy.PodDisruptionBudget + pdbPodNum []int32 + existingPods []*v1.Pod + pod *v1.Pod + preemptedPodIndexes map[int]struct{} + }{ + { + name: "A non-PDB violating pod is preempted despite its higher priority", + nodeCnt: 1, + pdbs: []*policy.PodDisruptionBudget{ + mkMinAvailablePDB("pdb-1", testCtx.NS.Name, types.UID("pdb-1-uid"), 2, map[string]string{"foo": "bar"}), + }, + pdbPodNum: []int32{2}, + existingPods: []*v1.Pod{ + initPausePod(&testutils.PausePodConfig{ + Name: "low-pod1", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: defaultPodRes, + Labels: map[string]string{"foo": "bar"}, + }), + initPausePod(&testutils.PausePodConfig{ + Name: "low-pod2", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: defaultPodRes, + Labels: map[string]string{"foo": "bar"}, + }), + initPausePod(&testutils.PausePodConfig{ + Name: "mid-pod3", + Namespace: testCtx.NS.Name, + Priority: &mediumPriority, + Resources: defaultPodRes, + }), + }, + pod: initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, + }, + }), + preemptedPodIndexes: map[int]struct{}{2: {}}, + }, + { + name: "A node without any PDB violating pods is preferred for preemption", + nodeCnt: 2, + pdbs: []*policy.PodDisruptionBudget{ + mkMinAvailablePDB("pdb-1", testCtx.NS.Name, types.UID("pdb-1-uid"), 2, map[string]string{"foo": "bar"}), + }, + pdbPodNum: []int32{1}, + existingPods: []*v1.Pod{ + initPausePod(&testutils.PausePodConfig{ + Name: "low-pod1", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: defaultPodRes, + NodeName: "node-1", + Labels: map[string]string{"foo": "bar"}, + }), + initPausePod(&testutils.PausePodConfig{ + Name: "mid-pod2", + Namespace: testCtx.NS.Name, + Priority: &mediumPriority, + NodeName: "node-2", + Resources: defaultPodRes, + }), + }, + pod: initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, + }, + }), + preemptedPodIndexes: map[int]struct{}{1: {}}, + }, + { + name: "A node with fewer PDB violating pods is preferred for preemption", + nodeCnt: 3, + pdbs: []*policy.PodDisruptionBudget{ + mkMinAvailablePDB("pdb-1", testCtx.NS.Name, types.UID("pdb-1-uid"), 2, map[string]string{"foo1": "bar"}), + mkMinAvailablePDB("pdb-2", testCtx.NS.Name, types.UID("pdb-2-uid"), 2, map[string]string{"foo2": "bar"}), + }, + pdbPodNum: []int32{1, 5}, + existingPods: []*v1.Pod{ + initPausePod(&testutils.PausePodConfig{ + Name: "low-pod1", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: defaultPodRes, + NodeName: "node-1", + Labels: map[string]string{"foo1": "bar"}, + }), + initPausePod(&testutils.PausePodConfig{ + Name: "mid-pod1", + Namespace: testCtx.NS.Name, + Priority: &mediumPriority, + Resources: defaultPodRes, + NodeName: "node-1", + }), + initPausePod(&testutils.PausePodConfig{ + Name: "low-pod2", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: defaultPodRes, + NodeName: "node-2", + Labels: map[string]string{"foo2": "bar"}, + }), + initPausePod(&testutils.PausePodConfig{ + Name: "mid-pod2", + Namespace: testCtx.NS.Name, + Priority: &mediumPriority, + Resources: defaultPodRes, + NodeName: "node-2", + Labels: map[string]string{"foo2": "bar"}, + }), + initPausePod(&testutils.PausePodConfig{ + Name: "low-pod4", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: defaultPodRes, + NodeName: "node-3", + Labels: map[string]string{"foo2": "bar"}, + }), + initPausePod(&testutils.PausePodConfig{ + Name: "low-pod5", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: defaultPodRes, + NodeName: "node-3", + Labels: map[string]string{"foo2": "bar"}, + }), + initPausePod(&testutils.PausePodConfig{ + Name: "low-pod6", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Resources: defaultPodRes, + NodeName: "node-3", + Labels: map[string]string{"foo2": "bar"}, + }), + }, + pod: initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(400, resource.DecimalSI)}, + }, + }), + // The third node is chosen because PDB is not violated for node 3 and the victims have lower priority than node-2. + preemptedPodIndexes: map[int]struct{}{4: {}, 5: {}, 6: {}}, + }, + } + + for _, asyncPreemptionEnabled := range []bool{true, false} { + for _, clearingNominatedNodeNameAfterBinding := range []bool{true, false} { + for _, test := range tests { + t.Run(fmt.Sprintf("%s (Async preemption enabled: %v, ClearingNominatedNodeNameAfterBinding: %v)", test.name, asyncPreemptionEnabled, clearingNominatedNodeNameAfterBinding), func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ClearingNominatedNodeNameAfterBinding, clearingNominatedNodeNameAfterBinding) + + for i := 1; i <= test.nodeCnt; i++ { + nodeName := fmt.Sprintf("node-%v", i) + _, err := createNode(cs, st.MakeNode().Name(nodeName).Capacity(defaultNodeRes).Obj()) + if err != nil { + t.Fatalf("Error creating node %v: %v", nodeName, err) + } + } + + pods := make([]*v1.Pod, len(test.existingPods)) + var err error + // Create and run existingPods. + for i, p := range test.existingPods { + if pods[i], err = runPausePod(cs, p); err != nil { + t.Fatalf("Test [%v]: Error running pause pod: %v", test.name, err) + } + // Add pod condition ready so that PDB is updated. + addPodConditionReady(p) + if _, err := testCtx.ClientSet.CoreV1().Pods(testCtx.NS.Name).UpdateStatus(testCtx.Ctx, p, metav1.UpdateOptions{}); err != nil { + t.Fatal(err) + } + } + // Wait for Pods to be stable in scheduler cache. + if err := waitCachedPodsStable(testCtx, test.existingPods); err != nil { + t.Fatalf("Not all pods are stable in the cache: %v", err) + } + + // Create PDBs. + for _, pdb := range test.pdbs { + _, err := testCtx.ClientSet.PolicyV1().PodDisruptionBudgets(testCtx.NS.Name).Create(testCtx.Ctx, pdb, metav1.CreateOptions{}) + if err != nil { + t.Fatalf("Failed to create PDB: %v", err) + } + } + // Wait for PDBs to become stable. + if err := waitForPDBsStable(testCtx, test.pdbs, test.pdbPodNum); err != nil { + t.Fatalf("Not all pdbs are stable in the cache: %v", err) + } + + // Create the "pod". + preemptor, err := createPausePod(cs, test.pod) + if err != nil { + t.Errorf("Error while creating high priority pod: %v", err) + } + // Wait for preemption of pods and make sure the other ones are not preempted. + for i, p := range pods { + if _, found := test.preemptedPodIndexes[i]; found { + if err = wait.PollUntilContextTimeout(testCtx.Ctx, time.Second, wait.ForeverTestTimeout, false, + podIsGettingEvicted(cs, p.Namespace, p.Name)); err != nil { + t.Errorf("Test [%v]: Pod %v/%v is not getting evicted.", test.name, p.Namespace, p.Name) + } + } else { + if p.DeletionTimestamp != nil { + t.Errorf("Test [%v]: Didn't expect pod %v/%v to get preempted.", test.name, p.Namespace, p.Name) + } + } + } + // Also check if .status.nominatedNodeName of the preemptor pod gets set. + if len(test.preemptedPodIndexes) > 0 && !clearingNominatedNodeNameAfterBinding { + if err := testutils.WaitForNominatedNodeName(testCtx.Ctx, cs, preemptor); err != nil { + t.Errorf("Test [%v]: .status.nominatedNodeName was not set for pod %v/%v: %v", test.name, preemptor.Namespace, preemptor.Name, err) + } + } + + // Cleanup + pods = append(pods, preemptor) + testutils.CleanupPods(testCtx.Ctx, cs, t, pods) + if err := cs.PolicyV1().PodDisruptionBudgets(testCtx.NS.Name).DeleteCollection(testCtx.Ctx, metav1.DeleteOptions{}, metav1.ListOptions{}); err != nil { + t.Errorf("error while deleting PDBs, error: %v", err) + } + if err := cs.CoreV1().Nodes().DeleteCollection(testCtx.Ctx, metav1.DeleteOptions{}, metav1.ListOptions{}); err != nil { + t.Errorf("error whiling deleting nodes, error: %v", err) + } + }) + } + } + } +} + +// TestReadWriteOncePodPreemption tests preemption scenarios for pods with +// ReadWriteOncePod PVCs. +func TestReadWriteOncePodPreemption(t *testing.T) { + cfg := configtesting.V1ToInternalWithDefaults(t, configv1.KubeSchedulerConfiguration{ + Profiles: []configv1.KubeSchedulerProfile{{ + SchedulerName: ptr.To(v1.DefaultSchedulerName), + Plugins: &configv1.Plugins{ + Filter: configv1.PluginSet{ + Enabled: []configv1.Plugin{ + {Name: volumerestrictions.Name}, + }, + }, + PreFilter: configv1.PluginSet{ + Enabled: []configv1.Plugin{ + {Name: volumerestrictions.Name}, + }, + }, + }, + }}, + }) + + testCtx := testutils.InitTestSchedulerWithOptions(t, + testutils.InitTestAPIServer(t, "preemption", nil), + 0, + scheduler.WithProfiles(cfg.Profiles...)) + testutils.SyncSchedulerInformerFactory(testCtx) + go testCtx.Scheduler.Run(testCtx.Ctx) + + cs := testCtx.ClientSet + + storage := v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}} + volType := v1.HostPathDirectoryOrCreate + pv1 := st.MakePersistentVolume(). + Name("pv-with-read-write-once-pod-1"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Capacity(storage.Requests). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/mnt1", Type: &volType}). + Obj() + pvc1 := st.MakePersistentVolumeClaim(). + Name("pvc-with-read-write-once-pod-1"). + Namespace(testCtx.NS.Name). + // Annotation and volume name required for PVC to be considered bound. + Annotation(volume.AnnBindCompleted, "true"). + VolumeName(pv1.Name). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(storage). + Obj() + pv2 := st.MakePersistentVolume(). + Name("pv-with-read-write-once-pod-2"). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Capacity(storage.Requests). + HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/mnt2", Type: &volType}). + Obj() + pvc2 := st.MakePersistentVolumeClaim(). + Name("pvc-with-read-write-once-pod-2"). + Namespace(testCtx.NS.Name). + // Annotation and volume name required for PVC to be considered bound. + Annotation(volume.AnnBindCompleted, "true"). + VolumeName(pv2.Name). + AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). + Resources(storage). + Obj() + + tests := []struct { + name string + init func() error + existingPods []*v1.Pod + pod *v1.Pod + unresolvable bool + preemptedPodIndexes map[int]struct{} + cleanup func() error + }{ + { + name: "preempt single pod", + init: func() error { + _, err := testutils.CreatePV(cs, pv1) + if err != nil { + return fmt.Errorf("cannot create pv: %w", err) + } + _, err = testutils.CreatePVC(cs, pvc1) + if err != nil { + return fmt.Errorf("cannot create pvc: %w", err) + } + return nil + }, + existingPods: []*v1.Pod{ + initPausePod(&testutils.PausePodConfig{ + Name: "victim-pod", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Volumes: []v1.Volume{{ + Name: "volume", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc1.Name, + }, + }, + }}, + }), + }, + pod: initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Volumes: []v1.Volume{{ + Name: "volume", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc1.Name, + }, + }, + }}, + }), + preemptedPodIndexes: map[int]struct{}{0: {}}, + cleanup: func() error { + if err := testutils.DeletePVC(cs, pvc1.Name, pvc1.Namespace); err != nil { + return fmt.Errorf("cannot delete pvc: %w", err) + } + if err := testutils.DeletePV(cs, pv1.Name); err != nil { + return fmt.Errorf("cannot delete pv: %w", err) + } + return nil + }, + }, + { + name: "preempt two pods", + init: func() error { + for _, pv := range []*v1.PersistentVolume{pv1, pv2} { + _, err := testutils.CreatePV(cs, pv) + if err != nil { + return fmt.Errorf("cannot create pv: %w", err) + } + } + for _, pvc := range []*v1.PersistentVolumeClaim{pvc1, pvc2} { + _, err := testutils.CreatePVC(cs, pvc) + if err != nil { + return fmt.Errorf("cannot create pvc: %w", err) + } + } + return nil + }, + existingPods: []*v1.Pod{ + initPausePod(&testutils.PausePodConfig{ + Name: "victim-pod-1", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Volumes: []v1.Volume{{ + Name: "volume", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc1.Name, + }, + }, + }}, + }), + initPausePod(&testutils.PausePodConfig{ + Name: "victim-pod-2", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Volumes: []v1.Volume{{ + Name: "volume", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc2.Name, + }, + }, + }}, + }), + }, + pod: initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Volumes: []v1.Volume{ + { + Name: "volume-1", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc1.Name, + }, + }, + }, + { + Name: "volume-2", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc2.Name, + }, + }, + }, + }, + }), + preemptedPodIndexes: map[int]struct{}{0: {}, 1: {}}, + cleanup: func() error { + for _, pvc := range []*v1.PersistentVolumeClaim{pvc1, pvc2} { + if err := testutils.DeletePVC(cs, pvc.Name, pvc.Namespace); err != nil { + return fmt.Errorf("cannot delete pvc: %w", err) + } + } + for _, pv := range []*v1.PersistentVolume{pv1, pv2} { + if err := testutils.DeletePV(cs, pv.Name); err != nil { + return fmt.Errorf("cannot delete pv: %w", err) + } + } + return nil + }, + }, + { + name: "preempt single pod with two volumes", + init: func() error { + for _, pv := range []*v1.PersistentVolume{pv1, pv2} { + _, err := testutils.CreatePV(cs, pv) + if err != nil { + return fmt.Errorf("cannot create pv: %w", err) + } + } + for _, pvc := range []*v1.PersistentVolumeClaim{pvc1, pvc2} { + _, err := testutils.CreatePVC(cs, pvc) + if err != nil { + return fmt.Errorf("cannot create pvc: %w", err) + } + } + return nil + }, + existingPods: []*v1.Pod{ + initPausePod(&testutils.PausePodConfig{ + Name: "victim-pod", + Namespace: testCtx.NS.Name, + Priority: &lowPriority, + Volumes: []v1.Volume{ + { + Name: "volume-1", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc1.Name, + }, + }, + }, + { + Name: "volume-2", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc2.Name, + }, + }, + }, + }, + }), + }, + pod: initPausePod(&testutils.PausePodConfig{ + Name: "preemptor-pod", + Namespace: testCtx.NS.Name, + Priority: &highPriority, + Volumes: []v1.Volume{ + { + Name: "volume-1", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc1.Name, + }, + }, + }, + { + Name: "volume-2", + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc2.Name, + }, + }, + }, + }, + }), + preemptedPodIndexes: map[int]struct{}{0: {}}, + cleanup: func() error { + for _, pvc := range []*v1.PersistentVolumeClaim{pvc1, pvc2} { + if err := testutils.DeletePVC(cs, pvc.Name, pvc.Namespace); err != nil { + return fmt.Errorf("cannot delete pvc: %w", err) + } + } + for _, pv := range []*v1.PersistentVolume{pv1, pv2} { + if err := testutils.DeletePV(cs, pv.Name); err != nil { + return fmt.Errorf("cannot delete pv: %w", err) + } + } + return nil + }, + }, + } + + // Create a node with some resources and a label. + nodeRes := map[v1.ResourceName]string{ + v1.ResourcePods: "32", + v1.ResourceCPU: "500m", + v1.ResourceMemory: "500", + } + nodeObject := st.MakeNode().Name("node1").Capacity(nodeRes).Label("node", "node1").Obj() + if _, err := createNode(cs, nodeObject); err != nil { + t.Fatalf("Error creating node: %v", err) + } + + for _, asyncPreemptionEnabled := range []bool{true, false} { + for _, clearingNominatedNodeNameAfterBinding := range []bool{true, false} { + for _, test := range tests { + t.Run(fmt.Sprintf("%s (Async preemption enabled: %v, ClearingNominatedNodeNameAfterBinding: %v)", test.name, asyncPreemptionEnabled, clearingNominatedNodeNameAfterBinding), func(t *testing.T) { + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ClearingNominatedNodeNameAfterBinding, clearingNominatedNodeNameAfterBinding) + + if err := test.init(); err != nil { + t.Fatalf("Error while initializing test: %v", err) + } + + pods := make([]*v1.Pod, len(test.existingPods)) + t.Cleanup(func() { + testutils.CleanupPods(testCtx.Ctx, cs, t, pods) + if err := test.cleanup(); err != nil { + t.Errorf("Error cleaning up test: %v", err) + } + }) + // Create and run existingPods. + for i, p := range test.existingPods { + var err error + pods[i], err = runPausePod(cs, p) + if err != nil { + t.Fatalf("Error running pause pod: %v", err) + } + } + // Create the "pod". + preemptor, err := createPausePod(cs, test.pod) + if err != nil { + t.Errorf("Error while creating high priority pod: %v", err) + } + pods = append(pods, preemptor) + // Wait for preemption of pods and make sure the other ones are not preempted. + for i, p := range pods { + if _, found := test.preemptedPodIndexes[i]; found { + if err = wait.PollUntilContextTimeout(testCtx.Ctx, time.Second, wait.ForeverTestTimeout, false, + podIsGettingEvicted(cs, p.Namespace, p.Name)); err != nil { + t.Errorf("Pod %v/%v is not getting evicted.", p.Namespace, p.Name) + } + } else { + if p.DeletionTimestamp != nil { + t.Errorf("Didn't expect pod %v to get preempted.", p.Name) + } + } + } + // Also check that the preemptor pod gets the NominatedNodeName field set. + if len(test.preemptedPodIndexes) > 0 && !clearingNominatedNodeNameAfterBinding { + if err := testutils.WaitForNominatedNodeName(testCtx.Ctx, cs, preemptor); err != nil { + t.Errorf("NominatedNodeName field was not set for pod %v: %v", preemptor.Name, err) + } + } + }) + } + } + } +} diff --git a/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/nominatednodename/nominatednodename_test.go b/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/nominatednodename/nominatednodename_test.go index 00fcbbf838..38cf9706c6 100644 --- a/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/nominatednodename/nominatednodename_test.go +++ b/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/nominatednodename/nominatednodename_test.go @@ -119,10 +119,10 @@ func TestNominatedNode(t *testing.T) { st.MakePod().Name("low-4").Priority(lowPriority).Req(map[v1.ResourceName]string{v1.ResourceCPU: "1"}).Obj(), }, { - st.MakePod().Name("medium").Priority(mediumPriority).Req(map[v1.ResourceName]string{v1.ResourceCPU: "3"}).Obj(), + st.MakePod().Name("medium").Priority(mediumPriority).Req(map[v1.ResourceName]string{v1.ResourceCPU: "4"}).Obj(), }, { - st.MakePod().Name("high").Priority(highPriority).Req(map[v1.ResourceName]string{v1.ResourceCPU: "4"}).Obj(), + st.MakePod().Name("high").Priority(highPriority).Req(map[v1.ResourceName]string{v1.ResourceCPU: "3"}).Obj(), }, }, postChecks: []func(ctx context.Context, cs clientset.Interface, pod *v1.Pod) error{ @@ -130,7 +130,6 @@ func TestNominatedNode(t *testing.T) { testutils.WaitForNominatedNodeName, testutils.WaitForNominatedNodeName, }, - podNamesToDelete: []string{"low-1", "low-2", "low-3", "low-4"}, expectNilNominatedNodeName: true, }, { diff --git a/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/preemption_test.go b/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/preemption_test.go index 4c1535c148..18d71c4924 100644 --- a/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/preemption_test.go +++ b/deps/github.com/openshift/kubernetes/test/integration/scheduler/preemption/preemption_test.go @@ -25,24 +25,16 @@ import ( "time" v1 "k8s.io/api/core/v1" - policy "k8s.io/api/policy/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/wait" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/client-go/informers" - clientset "k8s.io/client-go/kubernetes" - restclient "k8s.io/client-go/rest" featuregatetesting "k8s.io/component-base/featuregate/testing" - "k8s.io/component-helpers/storage/volume" "k8s.io/klog/v2" configv1 "k8s.io/kube-scheduler/config/v1" fwk "k8s.io/kube-scheduler/framework" podutil "k8s.io/kubernetes/pkg/api/v1/pod" - "k8s.io/kubernetes/pkg/apis/scheduling" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/scheduler" "k8s.io/kubernetes/pkg/scheduler/apis/config" @@ -52,11 +44,9 @@ import ( "k8s.io/kubernetes/pkg/scheduler/framework/plugins/defaultpreemption" plfeature "k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature" "k8s.io/kubernetes/pkg/scheduler/framework/plugins/names" - "k8s.io/kubernetes/pkg/scheduler/framework/plugins/volumerestrictions" "k8s.io/kubernetes/pkg/scheduler/framework/preemption" frameworkruntime "k8s.io/kubernetes/pkg/scheduler/framework/runtime" st "k8s.io/kubernetes/pkg/scheduler/testing" - "k8s.io/kubernetes/plugin/pkg/admission/priority" testutils "k8s.io/kubernetes/test/integration/util" "k8s.io/kubernetes/test/utils/ktesting" "k8s.io/utils/ptr" @@ -64,19 +54,11 @@ import ( // imported from testutils var ( - initPausePod = testutils.InitPausePod - createNode = testutils.CreateNode - createPausePod = testutils.CreatePausePod - runPausePod = testutils.RunPausePod - initTest = testutils.InitTestSchedulerWithNS - initTestDisablePreemption = testutils.InitTestDisablePreemption - initDisruptionController = testutils.InitDisruptionController - waitCachedPodsStable = testutils.WaitCachedPodsStable - podIsGettingEvicted = testutils.PodIsGettingEvicted - podUnschedulable = testutils.PodUnschedulable - waitForPDBsStable = testutils.WaitForPDBsStable - waitForPodToScheduleWithTimeout = testutils.WaitForPodToScheduleWithTimeout - waitForPodUnschedulable = testutils.WaitForPodUnschedulable + initPausePod = testutils.InitPausePod + createNode = testutils.CreateNode + createPausePod = testutils.CreatePausePod + runPausePod = testutils.RunPausePod + podIsGettingEvicted = testutils.PodIsGettingEvicted ) const filterPluginName = "filter-plugin" @@ -462,7 +444,7 @@ func TestPreemption(t *testing.T) { // Wait for preemption of pods and make sure the other ones are not preempted. for i, p := range pods { if _, found := test.preemptedPodIndexes[i]; found { - if err = wait.PollUntilContextTimeout(testCtx.Ctx, time.Second, wait.ForeverTestTimeout, false, + if err = wait.PollUntilContextTimeout(testCtx.Ctx, 200*time.Millisecond, wait.ForeverTestTimeout, false, podIsGettingEvicted(cs, p.Namespace, p.Name)); err != nil { t.Errorf("Pod %v/%v is not getting evicted.", p.Namespace, p.Name) } @@ -1006,1173 +988,3 @@ func podInUnschedulablePodPool(t *testing.T, queue queue.SchedulingQueue, podNam } return false } - -// TestNonPreemption tests NonPreempt option of PriorityClass of scheduler works as expected. -func TestNonPreemption(t *testing.T) { - var preemptNever = v1.PreemptNever - // Initialize scheduler. - testCtx := initTest(t, "non-preemption") - cs := testCtx.ClientSet - tests := []struct { - name string - PreemptionPolicy *v1.PreemptionPolicy - }{ - { - name: "pod preemption will happen", - PreemptionPolicy: nil, - }, - { - name: "pod preemption will not happen", - PreemptionPolicy: &preemptNever, - }, - } - victim := initPausePod(&testutils.PausePodConfig{ - Name: "victim-pod", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(400, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, - }, - }) - - preemptor := initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, - }, - }) - - // Create a node with some resources - nodeRes := map[v1.ResourceName]string{ - v1.ResourcePods: "32", - v1.ResourceCPU: "500m", - v1.ResourceMemory: "500", - } - _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) - if err != nil { - t.Fatalf("Error creating nodes: %v", err) - } - - for _, asyncPreemptionEnabled := range []bool{true, false} { - for _, test := range tests { - t.Run(fmt.Sprintf("%s (Async preemption enabled: %v)", test.name, asyncPreemptionEnabled), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) - - defer testutils.CleanupPods(testCtx.Ctx, cs, t, []*v1.Pod{preemptor, victim}) - preemptor.Spec.PreemptionPolicy = test.PreemptionPolicy - victimPod, err := createPausePod(cs, victim) - if err != nil { - t.Fatalf("Error while creating victim: %v", err) - } - if err := waitForPodToScheduleWithTimeout(testCtx.Ctx, cs, victimPod, 5*time.Second); err != nil { - t.Fatalf("victim %v should be become scheduled", victimPod.Name) - } - - preemptorPod, err := createPausePod(cs, preemptor) - if err != nil { - t.Fatalf("Error while creating preemptor: %v", err) - } - - err = testutils.WaitForNominatedNodeNameWithTimeout(testCtx.Ctx, cs, preemptorPod, 5*time.Second) - // test.PreemptionPolicy == nil means we expect the preemptor to be nominated. - expect := test.PreemptionPolicy == nil - // err == nil indicates the preemptor is indeed nominated. - got := err == nil - if got != expect { - t.Errorf("Expect preemptor to be nominated=%v, but got=%v", expect, got) - } - }) - } - } -} - -// TestDisablePreemption tests disable pod preemption of scheduler works as expected. -func TestDisablePreemption(t *testing.T) { - // Initialize scheduler, and disable preemption. - testCtx := initTestDisablePreemption(t, "disable-preemption") - cs := testCtx.ClientSet - - tests := []struct { - name string - existingPods []*v1.Pod - pod *v1.Pod - }{ - { - name: "pod preemption will not happen", - existingPods: []*v1.Pod{ - initPausePod(&testutils.PausePodConfig{ - Name: "victim-pod", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(400, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, - }, - }), - }, - pod: initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, - }, - }), - }, - } - - // Create a node with some resources - nodeRes := map[v1.ResourceName]string{ - v1.ResourcePods: "32", - v1.ResourceCPU: "500m", - v1.ResourceMemory: "500", - } - _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) - if err != nil { - t.Fatalf("Error creating nodes: %v", err) - } - - for _, asyncPreemptionEnabled := range []bool{true, false} { - for _, test := range tests { - t.Run(fmt.Sprintf("%s (Async preemption enabled: %v)", test.name, asyncPreemptionEnabled), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) - - pods := make([]*v1.Pod, len(test.existingPods)) - // Create and run existingPods. - for i, p := range test.existingPods { - pods[i], err = runPausePod(cs, p) - if err != nil { - t.Fatalf("Test [%v]: Error running pause pod: %v", test.name, err) - } - } - // Create the "pod". - preemptor, err := createPausePod(cs, test.pod) - if err != nil { - t.Errorf("Error while creating high priority pod: %v", err) - } - // Ensure preemptor should keep unschedulable. - if err := waitForPodUnschedulable(testCtx.Ctx, cs, preemptor); err != nil { - t.Errorf("Preemptor %v should not become scheduled", preemptor.Name) - } - - // Ensure preemptor should not be nominated. - if err := testutils.WaitForNominatedNodeNameWithTimeout(testCtx.Ctx, cs, preemptor, 5*time.Second); err == nil { - t.Errorf("Preemptor %v should not be nominated", preemptor.Name) - } - - // Cleanup - pods = append(pods, preemptor) - testutils.CleanupPods(testCtx.Ctx, cs, t, pods) - }) - } - } -} - -// This test verifies that system critical priorities are created automatically and resolved properly. -func TestPodPriorityResolution(t *testing.T) { - admission := priority.NewPlugin() - testCtx := testutils.InitTestScheduler(t, testutils.InitTestAPIServer(t, "preemption", admission)) - cs := testCtx.ClientSet - - // Build clientset and informers for controllers. - externalClientConfig := restclient.CopyConfig(testCtx.KubeConfig) - externalClientConfig.QPS = -1 - externalClientset := clientset.NewForConfigOrDie(externalClientConfig) - externalInformers := informers.NewSharedInformerFactory(externalClientset, time.Second) - admission.SetExternalKubeClientSet(externalClientset) - admission.SetExternalKubeInformerFactory(externalInformers) - - // Waiting for all controllers to sync - testutils.SyncSchedulerInformerFactory(testCtx) - externalInformers.Start(testCtx.Ctx.Done()) - externalInformers.WaitForCacheSync(testCtx.Ctx.Done()) - - // Run all controllers - go testCtx.Scheduler.Run(testCtx.Ctx) - - tests := []struct { - Name string - PriorityClass string - Pod *v1.Pod - ExpectedPriority int32 - ExpectedError error - }{ - { - Name: "SystemNodeCritical priority class", - PriorityClass: scheduling.SystemNodeCritical, - ExpectedPriority: scheduling.SystemCriticalPriority + 1000, - Pod: initPausePod(&testutils.PausePodConfig{ - Name: fmt.Sprintf("pod1-%v", scheduling.SystemNodeCritical), - Namespace: metav1.NamespaceSystem, - PriorityClassName: scheduling.SystemNodeCritical, - }), - }, - { - Name: "SystemClusterCritical priority class", - PriorityClass: scheduling.SystemClusterCritical, - ExpectedPriority: scheduling.SystemCriticalPriority, - Pod: initPausePod(&testutils.PausePodConfig{ - Name: fmt.Sprintf("pod2-%v", scheduling.SystemClusterCritical), - Namespace: metav1.NamespaceSystem, - PriorityClassName: scheduling.SystemClusterCritical, - }), - }, - { - Name: "Invalid priority class should result in error", - PriorityClass: "foo", - ExpectedPriority: scheduling.SystemCriticalPriority, - Pod: initPausePod(&testutils.PausePodConfig{ - Name: fmt.Sprintf("pod3-%v", scheduling.SystemClusterCritical), - Namespace: metav1.NamespaceSystem, - PriorityClassName: "foo", - }), - ExpectedError: fmt.Errorf("failed to create pause pod: pods \"pod3-system-cluster-critical\" is forbidden: no PriorityClass with name foo was found"), - }, - } - - // Create a node with some resources - nodeRes := map[v1.ResourceName]string{ - v1.ResourcePods: "32", - v1.ResourceCPU: "500m", - v1.ResourceMemory: "500", - } - _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) - if err != nil { - t.Fatalf("Error creating nodes: %v", err) - } - - pods := make([]*v1.Pod, 0, len(tests)) - for _, asyncPreemptionEnabled := range []bool{true, false} { - for _, test := range tests { - t.Run(fmt.Sprintf("%s (Async preemption enabled: %v)", test.Name, asyncPreemptionEnabled), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) - - pod, err := runPausePod(cs, test.Pod) - if err != nil { - if test.ExpectedError == nil { - t.Fatalf("Test [PodPriority/%v]: Error running pause pod: %v", test.PriorityClass, err) - } - if err.Error() != test.ExpectedError.Error() { - t.Fatalf("Test [PodPriority/%v]: Expected error %v but got error %v", test.PriorityClass, test.ExpectedError, err) - } - return - } - pods = append(pods, pod) - if pod.Spec.Priority != nil { - if *pod.Spec.Priority != test.ExpectedPriority { - t.Errorf("Expected pod %v to have priority %v but was %v", pod.Name, test.ExpectedPriority, pod.Spec.Priority) - } - } else { - t.Errorf("Expected pod %v to have priority %v but was nil", pod.Name, test.PriorityClass) - } - testutils.CleanupPods(testCtx.Ctx, cs, t, pods) - }) - } - } - testutils.CleanupNodes(cs, t) -} - -func mkPriorityPodWithGrace(tc *testutils.TestContext, name string, priority int32, grace int64) *v1.Pod { - defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(100, resource.DecimalSI)}, - } - pod := initPausePod(&testutils.PausePodConfig{ - Name: name, - Namespace: tc.NS.Name, - Priority: &priority, - Labels: map[string]string{"pod": name}, - Resources: defaultPodRes, - }) - pod.Spec.TerminationGracePeriodSeconds = &grace - return pod -} - -// This test ensures that while the preempting pod is waiting for the victims to -// terminate, other pending lower priority pods are not scheduled in the room created -// after preemption and while the higher priority pods is not scheduled yet. -func TestPreemptionStarvation(t *testing.T) { - // Initialize scheduler. - testCtx := initTest(t, "preemption") - cs := testCtx.ClientSet - - tests := []struct { - name string - numExistingPod int - numExpectedPending int - preemptor *v1.Pod - }{ - { - // This test ensures that while the preempting pod is waiting for the victims - // terminate, other lower priority pods are not scheduled in the room created - // after preemption and while the higher priority pods is not scheduled yet. - name: "starvation test: higher priority pod is scheduled before the lower priority ones", - numExistingPod: 10, - numExpectedPending: 5, - preemptor: initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, - }, - }), - }, - } - - // Create a node with some resources - nodeRes := map[v1.ResourceName]string{ - v1.ResourcePods: "32", - v1.ResourceCPU: "500m", - v1.ResourceMemory: "500", - } - _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) - if err != nil { - t.Fatalf("Error creating nodes: %v", err) - } - - for _, asyncPreemptionEnabled := range []bool{true, false} { - for _, clearingNominatedNodeNameAfterBinding := range []bool{true, false} { - for _, test := range tests { - t.Run(fmt.Sprintf("%s (Async preemption enabled: %v, ClearingNominatedNodeNameAfterBinding: %v)", test.name, asyncPreemptionEnabled, clearingNominatedNodeNameAfterBinding), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ClearingNominatedNodeNameAfterBinding, clearingNominatedNodeNameAfterBinding) - - pendingPods := make([]*v1.Pod, test.numExpectedPending) - numRunningPods := test.numExistingPod - test.numExpectedPending - runningPods := make([]*v1.Pod, numRunningPods) - // Create and run existingPods. - for i := 0; i < numRunningPods; i++ { - runningPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(testCtx, fmt.Sprintf("rpod-%v", i), mediumPriority, 0)) - if err != nil { - t.Fatalf("Error creating pause pod: %v", err) - } - } - // make sure that runningPods are all scheduled. - for _, p := range runningPods { - if err := testutils.WaitForPodToSchedule(testCtx.Ctx, cs, p); err != nil { - t.Fatalf("Pod %v/%v didn't get scheduled: %v", p.Namespace, p.Name, err) - } - } - // Create pending pods. - for i := 0; i < test.numExpectedPending; i++ { - pendingPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(testCtx, fmt.Sprintf("ppod-%v", i), mediumPriority, 0)) - if err != nil { - t.Fatalf("Error creating pending pod: %v", err) - } - } - // Make sure that all pending pods are being marked unschedulable. - for _, p := range pendingPods { - if err := wait.PollUntilContextTimeout(testCtx.Ctx, 100*time.Millisecond, wait.ForeverTestTimeout, false, - podUnschedulable(cs, p.Namespace, p.Name)); err != nil { - t.Errorf("Pod %v/%v didn't get marked unschedulable: %v", p.Namespace, p.Name, err) - } - } - // Create the preemptor. - preemptor, err := createPausePod(cs, test.preemptor) - if err != nil { - t.Errorf("Error while creating the preempting pod: %v", err) - } - - // Make sure that preemptor is scheduled after preemptions. - if err := testutils.WaitForPodToScheduleWithTimeout(testCtx.Ctx, cs, preemptor, 60*time.Second); err != nil { - t.Errorf("Preemptor pod %v didn't get scheduled: %v", preemptor.Name, err) - } - - // Check if .status.nominatedNodeName of the preemptor pod gets set when feature gate is disabled. - // This test always expects preemption to occur since numExistingPod (10) fills the node completely. - if !clearingNominatedNodeNameAfterBinding { - if err := testutils.WaitForNominatedNodeName(testCtx.Ctx, cs, preemptor); err != nil { - t.Errorf(".status.nominatedNodeName was not set for pod %v/%v: %v", preemptor.Namespace, preemptor.Name, err) - } - } - // Cleanup - klog.Info("Cleaning up all pods...") - allPods := pendingPods - allPods = append(allPods, runningPods...) - allPods = append(allPods, preemptor) - testutils.CleanupPods(testCtx.Ctx, cs, t, allPods) - }) - } - } - } -} - -// TestPreemptionRaces tests that other scheduling events and operations do not -// race with the preemption process. -func TestPreemptionRaces(t *testing.T) { - // Initialize scheduler. - testCtx := initTest(t, "preemption-race") - cs := testCtx.ClientSet - - tests := []struct { - name string - numInitialPods int // Pods created and executed before running preemptor - numAdditionalPods int // Pods created after creating the preemptor - numRepetitions int // Repeat the tests to check races - preemptor *v1.Pod - }{ - { - // This test ensures that while the preempting pod is waiting for the victims - // terminate, other lower priority pods are not scheduled in the room created - // after preemption and while the higher priority pods is not scheduled yet. - name: "ensures that other pods are not scheduled while preemptor is being marked as nominated (issue #72124)", - numInitialPods: 2, - numAdditionalPods: 20, - numRepetitions: 5, - preemptor: initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(4900, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(4900, resource.DecimalSI)}, - }, - }), - }, - } - - // Create a node with some resources - nodeRes := map[v1.ResourceName]string{ - v1.ResourcePods: "100", - v1.ResourceCPU: "5000m", - v1.ResourceMemory: "5000", - } - _, err := createNode(testCtx.ClientSet, st.MakeNode().Name("node1").Capacity(nodeRes).Obj()) - if err != nil { - t.Fatalf("Error creating nodes: %v", err) - } - - for _, asyncPreemptionEnabled := range []bool{true, false} { - for _, clearingNominatedNodeNameAfterBinding := range []bool{true, false} { - for _, test := range tests { - t.Run(fmt.Sprintf("%s (Async preemption enabled: %v, ClearingNominatedNodeNameAfterBinding: %v)", test.name, asyncPreemptionEnabled, clearingNominatedNodeNameAfterBinding), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ClearingNominatedNodeNameAfterBinding, clearingNominatedNodeNameAfterBinding) - - if test.numRepetitions <= 0 { - test.numRepetitions = 1 - } - for n := 0; n < test.numRepetitions; n++ { - initialPods := make([]*v1.Pod, test.numInitialPods) - additionalPods := make([]*v1.Pod, test.numAdditionalPods) - // Create and run existingPods. - for i := 0; i < test.numInitialPods; i++ { - initialPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(testCtx, fmt.Sprintf("rpod-%v", i), mediumPriority, 0)) - if err != nil { - t.Fatalf("Error creating pause pod: %v", err) - } - } - // make sure that initial Pods are all scheduled. - for _, p := range initialPods { - if err := testutils.WaitForPodToSchedule(testCtx.Ctx, cs, p); err != nil { - t.Fatalf("Pod %v/%v didn't get scheduled: %v", p.Namespace, p.Name, err) - } - } - // Create the preemptor. - klog.Info("Creating the preemptor pod...") - preemptor, err := createPausePod(cs, test.preemptor) - if err != nil { - t.Errorf("Error while creating the preempting pod: %v", err) - } - - klog.Info("Creating additional pods...") - for i := 0; i < test.numAdditionalPods; i++ { - additionalPods[i], err = createPausePod(cs, mkPriorityPodWithGrace(testCtx, fmt.Sprintf("ppod-%v", i), mediumPriority, 0)) - if err != nil { - t.Fatalf("Error creating pending pod: %v", err) - } - } - // Make sure that preemptor is scheduled after preemptions. - if err := testutils.WaitForPodToScheduleWithTimeout(testCtx.Ctx, cs, preemptor, 60*time.Second); err != nil { - t.Errorf("Preemptor pod %v didn't get scheduled: %v", preemptor.Name, err) - } - - // Check that the preemptor pod gets nominated node name when feature gate is disabled. - if !clearingNominatedNodeNameAfterBinding { - if err := testutils.WaitForNominatedNodeName(testCtx.Ctx, cs, preemptor); err != nil { - t.Errorf(".status.nominatedNodeName was not set for pod %v/%v: %v", preemptor.Namespace, preemptor.Name, err) - } - } - - klog.Info("Check unschedulable pods still exists and were never scheduled...") - for _, p := range additionalPods { - pod, err := cs.CoreV1().Pods(p.Namespace).Get(testCtx.Ctx, p.Name, metav1.GetOptions{}) - if err != nil { - t.Errorf("Error in getting Pod %v/%v info: %v", p.Namespace, p.Name, err) - } - if len(pod.Spec.NodeName) > 0 { - t.Errorf("Pod %v/%v is already scheduled", p.Namespace, p.Name) - } - _, cond := podutil.GetPodCondition(&pod.Status, v1.PodScheduled) - if cond != nil && cond.Status != v1.ConditionFalse { - t.Errorf("Pod %v/%v is no longer unschedulable: %v", p.Namespace, p.Name, err) - } - } - // Cleanup - klog.Info("Cleaning up all pods...") - allPods := additionalPods - allPods = append(allPods, initialPods...) - allPods = append(allPods, preemptor) - testutils.CleanupPods(testCtx.Ctx, cs, t, allPods) - } - }) - } - } - } -} - -func mkMinAvailablePDB(name, namespace string, uid types.UID, minAvailable int, matchLabels map[string]string) *policy.PodDisruptionBudget { - intMinAvailable := intstr.FromInt32(int32(minAvailable)) - return &policy.PodDisruptionBudget{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Spec: policy.PodDisruptionBudgetSpec{ - MinAvailable: &intMinAvailable, - Selector: &metav1.LabelSelector{MatchLabels: matchLabels}, - }, - } -} - -func addPodConditionReady(pod *v1.Pod) { - pod.Status = v1.PodStatus{ - Phase: v1.PodRunning, - Conditions: []v1.PodCondition{ - { - Type: v1.PodReady, - Status: v1.ConditionTrue, - }, - }, - } -} - -// TestPDBInPreemption tests PodDisruptionBudget support in preemption. -func TestPDBInPreemption(t *testing.T) { - // Initialize scheduler. - testCtx := initTest(t, "preemption-pdb") - cs := testCtx.ClientSet - - initDisruptionController(t, testCtx) - - defaultPodRes := &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(100, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(100, resource.DecimalSI)}, - } - defaultNodeRes := map[v1.ResourceName]string{ - v1.ResourcePods: "32", - v1.ResourceCPU: "500m", - v1.ResourceMemory: "500", - } - - tests := []struct { - name string - nodeCnt int - pdbs []*policy.PodDisruptionBudget - pdbPodNum []int32 - existingPods []*v1.Pod - pod *v1.Pod - preemptedPodIndexes map[int]struct{} - }{ - { - name: "A non-PDB violating pod is preempted despite its higher priority", - nodeCnt: 1, - pdbs: []*policy.PodDisruptionBudget{ - mkMinAvailablePDB("pdb-1", testCtx.NS.Name, types.UID("pdb-1-uid"), 2, map[string]string{"foo": "bar"}), - }, - pdbPodNum: []int32{2}, - existingPods: []*v1.Pod{ - initPausePod(&testutils.PausePodConfig{ - Name: "low-pod1", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: defaultPodRes, - Labels: map[string]string{"foo": "bar"}, - }), - initPausePod(&testutils.PausePodConfig{ - Name: "low-pod2", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: defaultPodRes, - Labels: map[string]string{"foo": "bar"}, - }), - initPausePod(&testutils.PausePodConfig{ - Name: "mid-pod3", - Namespace: testCtx.NS.Name, - Priority: &mediumPriority, - Resources: defaultPodRes, - }), - }, - pod: initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(300, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, - }, - }), - preemptedPodIndexes: map[int]struct{}{2: {}}, - }, - { - name: "A node without any PDB violating pods is preferred for preemption", - nodeCnt: 2, - pdbs: []*policy.PodDisruptionBudget{ - mkMinAvailablePDB("pdb-1", testCtx.NS.Name, types.UID("pdb-1-uid"), 2, map[string]string{"foo": "bar"}), - }, - pdbPodNum: []int32{1}, - existingPods: []*v1.Pod{ - initPausePod(&testutils.PausePodConfig{ - Name: "low-pod1", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: defaultPodRes, - NodeName: "node-1", - Labels: map[string]string{"foo": "bar"}, - }), - initPausePod(&testutils.PausePodConfig{ - Name: "mid-pod2", - Namespace: testCtx.NS.Name, - Priority: &mediumPriority, - NodeName: "node-2", - Resources: defaultPodRes, - }), - }, - pod: initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(200, resource.DecimalSI)}, - }, - }), - preemptedPodIndexes: map[int]struct{}{1: {}}, - }, - { - name: "A node with fewer PDB violating pods is preferred for preemption", - nodeCnt: 3, - pdbs: []*policy.PodDisruptionBudget{ - mkMinAvailablePDB("pdb-1", testCtx.NS.Name, types.UID("pdb-1-uid"), 2, map[string]string{"foo1": "bar"}), - mkMinAvailablePDB("pdb-2", testCtx.NS.Name, types.UID("pdb-2-uid"), 2, map[string]string{"foo2": "bar"}), - }, - pdbPodNum: []int32{1, 5}, - existingPods: []*v1.Pod{ - initPausePod(&testutils.PausePodConfig{ - Name: "low-pod1", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: defaultPodRes, - NodeName: "node-1", - Labels: map[string]string{"foo1": "bar"}, - }), - initPausePod(&testutils.PausePodConfig{ - Name: "mid-pod1", - Namespace: testCtx.NS.Name, - Priority: &mediumPriority, - Resources: defaultPodRes, - NodeName: "node-1", - }), - initPausePod(&testutils.PausePodConfig{ - Name: "low-pod2", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: defaultPodRes, - NodeName: "node-2", - Labels: map[string]string{"foo2": "bar"}, - }), - initPausePod(&testutils.PausePodConfig{ - Name: "mid-pod2", - Namespace: testCtx.NS.Name, - Priority: &mediumPriority, - Resources: defaultPodRes, - NodeName: "node-2", - Labels: map[string]string{"foo2": "bar"}, - }), - initPausePod(&testutils.PausePodConfig{ - Name: "low-pod4", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: defaultPodRes, - NodeName: "node-3", - Labels: map[string]string{"foo2": "bar"}, - }), - initPausePod(&testutils.PausePodConfig{ - Name: "low-pod5", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: defaultPodRes, - NodeName: "node-3", - Labels: map[string]string{"foo2": "bar"}, - }), - initPausePod(&testutils.PausePodConfig{ - Name: "low-pod6", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Resources: defaultPodRes, - NodeName: "node-3", - Labels: map[string]string{"foo2": "bar"}, - }), - }, - pod: initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Resources: &v1.ResourceRequirements{Requests: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(500, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(400, resource.DecimalSI)}, - }, - }), - // The third node is chosen because PDB is not violated for node 3 and the victims have lower priority than node-2. - preemptedPodIndexes: map[int]struct{}{4: {}, 5: {}, 6: {}}, - }, - } - - for _, asyncPreemptionEnabled := range []bool{true, false} { - for _, clearingNominatedNodeNameAfterBinding := range []bool{true, false} { - for _, test := range tests { - t.Run(fmt.Sprintf("%s (Async preemption enabled: %v, ClearingNominatedNodeNameAfterBinding: %v)", test.name, asyncPreemptionEnabled, clearingNominatedNodeNameAfterBinding), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ClearingNominatedNodeNameAfterBinding, clearingNominatedNodeNameAfterBinding) - - for i := 1; i <= test.nodeCnt; i++ { - nodeName := fmt.Sprintf("node-%v", i) - _, err := createNode(cs, st.MakeNode().Name(nodeName).Capacity(defaultNodeRes).Obj()) - if err != nil { - t.Fatalf("Error creating node %v: %v", nodeName, err) - } - } - - pods := make([]*v1.Pod, len(test.existingPods)) - var err error - // Create and run existingPods. - for i, p := range test.existingPods { - if pods[i], err = runPausePod(cs, p); err != nil { - t.Fatalf("Test [%v]: Error running pause pod: %v", test.name, err) - } - // Add pod condition ready so that PDB is updated. - addPodConditionReady(p) - if _, err := testCtx.ClientSet.CoreV1().Pods(testCtx.NS.Name).UpdateStatus(testCtx.Ctx, p, metav1.UpdateOptions{}); err != nil { - t.Fatal(err) - } - } - // Wait for Pods to be stable in scheduler cache. - if err := waitCachedPodsStable(testCtx, test.existingPods); err != nil { - t.Fatalf("Not all pods are stable in the cache: %v", err) - } - - // Create PDBs. - for _, pdb := range test.pdbs { - _, err := testCtx.ClientSet.PolicyV1().PodDisruptionBudgets(testCtx.NS.Name).Create(testCtx.Ctx, pdb, metav1.CreateOptions{}) - if err != nil { - t.Fatalf("Failed to create PDB: %v", err) - } - } - // Wait for PDBs to become stable. - if err := waitForPDBsStable(testCtx, test.pdbs, test.pdbPodNum); err != nil { - t.Fatalf("Not all pdbs are stable in the cache: %v", err) - } - - // Create the "pod". - preemptor, err := createPausePod(cs, test.pod) - if err != nil { - t.Errorf("Error while creating high priority pod: %v", err) - } - // Wait for preemption of pods and make sure the other ones are not preempted. - for i, p := range pods { - if _, found := test.preemptedPodIndexes[i]; found { - if err = wait.PollUntilContextTimeout(testCtx.Ctx, time.Second, wait.ForeverTestTimeout, false, - podIsGettingEvicted(cs, p.Namespace, p.Name)); err != nil { - t.Errorf("Test [%v]: Pod %v/%v is not getting evicted.", test.name, p.Namespace, p.Name) - } - } else { - if p.DeletionTimestamp != nil { - t.Errorf("Test [%v]: Didn't expect pod %v/%v to get preempted.", test.name, p.Namespace, p.Name) - } - } - } - // Also check if .status.nominatedNodeName of the preemptor pod gets set. - if len(test.preemptedPodIndexes) > 0 && !clearingNominatedNodeNameAfterBinding { - if err := testutils.WaitForNominatedNodeName(testCtx.Ctx, cs, preemptor); err != nil { - t.Errorf("Test [%v]: .status.nominatedNodeName was not set for pod %v/%v: %v", test.name, preemptor.Namespace, preemptor.Name, err) - } - } - - // Cleanup - pods = append(pods, preemptor) - testutils.CleanupPods(testCtx.Ctx, cs, t, pods) - if err := cs.PolicyV1().PodDisruptionBudgets(testCtx.NS.Name).DeleteCollection(testCtx.Ctx, metav1.DeleteOptions{}, metav1.ListOptions{}); err != nil { - t.Errorf("error while deleting PDBs, error: %v", err) - } - if err := cs.CoreV1().Nodes().DeleteCollection(testCtx.Ctx, metav1.DeleteOptions{}, metav1.ListOptions{}); err != nil { - t.Errorf("error whiling deleting nodes, error: %v", err) - } - }) - } - } - } -} - -// TestReadWriteOncePodPreemption tests preemption scenarios for pods with -// ReadWriteOncePod PVCs. -func TestReadWriteOncePodPreemption(t *testing.T) { - cfg := configtesting.V1ToInternalWithDefaults(t, configv1.KubeSchedulerConfiguration{ - Profiles: []configv1.KubeSchedulerProfile{{ - SchedulerName: ptr.To(v1.DefaultSchedulerName), - Plugins: &configv1.Plugins{ - Filter: configv1.PluginSet{ - Enabled: []configv1.Plugin{ - {Name: volumerestrictions.Name}, - }, - }, - PreFilter: configv1.PluginSet{ - Enabled: []configv1.Plugin{ - {Name: volumerestrictions.Name}, - }, - }, - }, - }}, - }) - - testCtx := testutils.InitTestSchedulerWithOptions(t, - testutils.InitTestAPIServer(t, "preemption", nil), - 0, - scheduler.WithProfiles(cfg.Profiles...)) - testutils.SyncSchedulerInformerFactory(testCtx) - go testCtx.Scheduler.Run(testCtx.Ctx) - - cs := testCtx.ClientSet - - storage := v1.VolumeResourceRequirements{Requests: v1.ResourceList{v1.ResourceStorage: resource.MustParse("1Mi")}} - volType := v1.HostPathDirectoryOrCreate - pv1 := st.MakePersistentVolume(). - Name("pv-with-read-write-once-pod-1"). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). - Capacity(storage.Requests). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/mnt1", Type: &volType}). - Obj() - pvc1 := st.MakePersistentVolumeClaim(). - Name("pvc-with-read-write-once-pod-1"). - Namespace(testCtx.NS.Name). - // Annotation and volume name required for PVC to be considered bound. - Annotation(volume.AnnBindCompleted, "true"). - VolumeName(pv1.Name). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). - Resources(storage). - Obj() - pv2 := st.MakePersistentVolume(). - Name("pv-with-read-write-once-pod-2"). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). - Capacity(storage.Requests). - HostPathVolumeSource(&v1.HostPathVolumeSource{Path: "/mnt2", Type: &volType}). - Obj() - pvc2 := st.MakePersistentVolumeClaim(). - Name("pvc-with-read-write-once-pod-2"). - Namespace(testCtx.NS.Name). - // Annotation and volume name required for PVC to be considered bound. - Annotation(volume.AnnBindCompleted, "true"). - VolumeName(pv2.Name). - AccessModes([]v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}). - Resources(storage). - Obj() - - tests := []struct { - name string - init func() error - existingPods []*v1.Pod - pod *v1.Pod - unresolvable bool - preemptedPodIndexes map[int]struct{} - cleanup func() error - }{ - { - name: "preempt single pod", - init: func() error { - _, err := testutils.CreatePV(cs, pv1) - if err != nil { - return fmt.Errorf("cannot create pv: %v", err) - } - _, err = testutils.CreatePVC(cs, pvc1) - if err != nil { - return fmt.Errorf("cannot create pvc: %v", err) - } - return nil - }, - existingPods: []*v1.Pod{ - initPausePod(&testutils.PausePodConfig{ - Name: "victim-pod", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Volumes: []v1.Volume{{ - Name: "volume", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc1.Name, - }, - }, - }}, - }), - }, - pod: initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Volumes: []v1.Volume{{ - Name: "volume", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc1.Name, - }, - }, - }}, - }), - preemptedPodIndexes: map[int]struct{}{0: {}}, - cleanup: func() error { - if err := testutils.DeletePVC(cs, pvc1.Name, pvc1.Namespace); err != nil { - return fmt.Errorf("cannot delete pvc: %v", err) - } - if err := testutils.DeletePV(cs, pv1.Name); err != nil { - return fmt.Errorf("cannot delete pv: %v", err) - } - return nil - }, - }, - { - name: "preempt two pods", - init: func() error { - for _, pv := range []*v1.PersistentVolume{pv1, pv2} { - _, err := testutils.CreatePV(cs, pv) - if err != nil { - return fmt.Errorf("cannot create pv: %v", err) - } - } - for _, pvc := range []*v1.PersistentVolumeClaim{pvc1, pvc2} { - _, err := testutils.CreatePVC(cs, pvc) - if err != nil { - return fmt.Errorf("cannot create pvc: %v", err) - } - } - return nil - }, - existingPods: []*v1.Pod{ - initPausePod(&testutils.PausePodConfig{ - Name: "victim-pod-1", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Volumes: []v1.Volume{{ - Name: "volume", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc1.Name, - }, - }, - }}, - }), - initPausePod(&testutils.PausePodConfig{ - Name: "victim-pod-2", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Volumes: []v1.Volume{{ - Name: "volume", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc2.Name, - }, - }, - }}, - }), - }, - pod: initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Volumes: []v1.Volume{ - { - Name: "volume-1", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc1.Name, - }, - }, - }, - { - Name: "volume-2", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc2.Name, - }, - }, - }, - }, - }), - preemptedPodIndexes: map[int]struct{}{0: {}, 1: {}}, - cleanup: func() error { - for _, pvc := range []*v1.PersistentVolumeClaim{pvc1, pvc2} { - if err := testutils.DeletePVC(cs, pvc.Name, pvc.Namespace); err != nil { - return fmt.Errorf("cannot delete pvc: %v", err) - } - } - for _, pv := range []*v1.PersistentVolume{pv1, pv2} { - if err := testutils.DeletePV(cs, pv.Name); err != nil { - return fmt.Errorf("cannot delete pv: %v", err) - } - } - return nil - }, - }, - { - name: "preempt single pod with two volumes", - init: func() error { - for _, pv := range []*v1.PersistentVolume{pv1, pv2} { - _, err := testutils.CreatePV(cs, pv) - if err != nil { - return fmt.Errorf("cannot create pv: %v", err) - } - } - for _, pvc := range []*v1.PersistentVolumeClaim{pvc1, pvc2} { - _, err := testutils.CreatePVC(cs, pvc) - if err != nil { - return fmt.Errorf("cannot create pvc: %v", err) - } - } - return nil - }, - existingPods: []*v1.Pod{ - initPausePod(&testutils.PausePodConfig{ - Name: "victim-pod", - Namespace: testCtx.NS.Name, - Priority: &lowPriority, - Volumes: []v1.Volume{ - { - Name: "volume-1", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc1.Name, - }, - }, - }, - { - Name: "volume-2", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc2.Name, - }, - }, - }, - }, - }), - }, - pod: initPausePod(&testutils.PausePodConfig{ - Name: "preemptor-pod", - Namespace: testCtx.NS.Name, - Priority: &highPriority, - Volumes: []v1.Volume{ - { - Name: "volume-1", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc1.Name, - }, - }, - }, - { - Name: "volume-2", - VolumeSource: v1.VolumeSource{ - PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: pvc2.Name, - }, - }, - }, - }, - }), - preemptedPodIndexes: map[int]struct{}{0: {}}, - cleanup: func() error { - for _, pvc := range []*v1.PersistentVolumeClaim{pvc1, pvc2} { - if err := testutils.DeletePVC(cs, pvc.Name, pvc.Namespace); err != nil { - return fmt.Errorf("cannot delete pvc: %v", err) - } - } - for _, pv := range []*v1.PersistentVolume{pv1, pv2} { - if err := testutils.DeletePV(cs, pv.Name); err != nil { - return fmt.Errorf("cannot delete pv: %v", err) - } - } - return nil - }, - }, - } - - // Create a node with some resources and a label. - nodeRes := map[v1.ResourceName]string{ - v1.ResourcePods: "32", - v1.ResourceCPU: "500m", - v1.ResourceMemory: "500", - } - nodeObject := st.MakeNode().Name("node1").Capacity(nodeRes).Label("node", "node1").Obj() - if _, err := createNode(cs, nodeObject); err != nil { - t.Fatalf("Error creating node: %v", err) - } - - for _, asyncPreemptionEnabled := range []bool{true, false} { - for _, clearingNominatedNodeNameAfterBinding := range []bool{true, false} { - for _, test := range tests { - t.Run(fmt.Sprintf("%s (Async preemption enabled: %v, ClearingNominatedNodeNameAfterBinding: %v)", test.name, asyncPreemptionEnabled, clearingNominatedNodeNameAfterBinding), func(t *testing.T) { - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SchedulerAsyncPreemption, asyncPreemptionEnabled) - featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ClearingNominatedNodeNameAfterBinding, clearingNominatedNodeNameAfterBinding) - - if err := test.init(); err != nil { - t.Fatalf("Error while initializing test: %v", err) - } - - pods := make([]*v1.Pod, len(test.existingPods)) - t.Cleanup(func() { - testutils.CleanupPods(testCtx.Ctx, cs, t, pods) - if err := test.cleanup(); err != nil { - t.Errorf("Error cleaning up test: %v", err) - } - }) - // Create and run existingPods. - for i, p := range test.existingPods { - var err error - pods[i], err = runPausePod(cs, p) - if err != nil { - t.Fatalf("Error running pause pod: %v", err) - } - } - // Create the "pod". - preemptor, err := createPausePod(cs, test.pod) - if err != nil { - t.Errorf("Error while creating high priority pod: %v", err) - } - pods = append(pods, preemptor) - // Wait for preemption of pods and make sure the other ones are not preempted. - for i, p := range pods { - if _, found := test.preemptedPodIndexes[i]; found { - if err = wait.PollUntilContextTimeout(testCtx.Ctx, time.Second, wait.ForeverTestTimeout, false, - podIsGettingEvicted(cs, p.Namespace, p.Name)); err != nil { - t.Errorf("Pod %v/%v is not getting evicted.", p.Namespace, p.Name) - } - } else { - if p.DeletionTimestamp != nil { - t.Errorf("Didn't expect pod %v to get preempted.", p.Name) - } - } - } - // Also check that the preemptor pod gets the NominatedNodeName field set. - if len(test.preemptedPodIndexes) > 0 && !clearingNominatedNodeNameAfterBinding { - if err := testutils.WaitForNominatedNodeName(testCtx.Ctx, cs, preemptor); err != nil { - t.Errorf("NominatedNodeName field was not set for pod %v: %v", preemptor.Name, err) - } - } - }) - } - } - } -} diff --git a/deps/github.com/openshift/kubernetes/test/integration/volume/persistent_volumes_test.go b/deps/github.com/openshift/kubernetes/test/integration/volume/persistent_volumes_test.go index eed2c65262..d3a9e6c346 100644 --- a/deps/github.com/openshift/kubernetes/test/integration/volume/persistent_volumes_test.go +++ b/deps/github.com/openshift/kubernetes/test/integration/volume/persistent_volumes_test.go @@ -1468,19 +1468,30 @@ func waitForAnyPersistentVolumePhase(w watch.Interface, phase v1.PersistentVolum } func waitForSomePersistentVolumeClaimPhase(ctx context.Context, testClient clientset.Interface, namespace string, objCount int, watchPVC watch.Interface, phase v1.PersistentVolumeClaimPhase) error { + // The caller doesn't know about new watches, so we have to stop them ourselves. + var newWatchPVC watch.Interface + defer func() { + if newWatchPVC != nil { + newWatchPVC.Stop() + } + }() + return wait.ExponentialBackoffWithContext(ctx, retry.DefaultBackoff, func(ctx context.Context) (bool, error) { for i := 0; i < objCount; i++ { - waitErr := waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound) - if waitErr != nil { - klog.Errorf("Failed to wait for a claim (%d/%d) to be bound: %v", i+1, objCount, waitErr) + err := waitForAnyPersistentVolumeClaimPhase(watchPVC, v1.ClaimBound) + if err != nil { + klog.Errorf("Failed to wait for a claim (%d/%d) to be bound: %v", i+1, objCount, err) klog.Info("Recreating a watch for claims and re-checking the count of bound claims") - newWatchPVC, err := testClient.CoreV1().PersistentVolumeClaims(namespace).Watch(ctx, metav1.ListOptions{}) + newWatchPVC, err = testClient.CoreV1().PersistentVolumeClaims(namespace).Watch(ctx, metav1.ListOptions{}) if err != nil { return false, err } watchPVC.Stop() watchPVC = newWatchPVC - return false, waitErr + // The error from waitForAnyPersistentVolumeClaimPhase is assumed to be harmless + // and/or to be fixed by recreating the watch, so here we continue polling + // via ExponentialBackoffWithContext. + return false, nil } klog.V(1).Infof("%d claims bound", i+1) } diff --git a/deps/github.com/openshift/kubernetes/test/utils/image/manifest.go b/deps/github.com/openshift/kubernetes/test/utils/image/manifest.go index 2498c3c732..242b286f94 100644 --- a/deps/github.com/openshift/kubernetes/test/utils/image/manifest.go +++ b/deps/github.com/openshift/kubernetes/test/utils/image/manifest.go @@ -221,7 +221,7 @@ func initImageConfigs(list RegistryList) (map[ImageID]Config, map[ImageID]Config configs[APIServer] = Config{list.PromoterE2eRegistry, "sample-apiserver", "1.29.2"} configs[AppArmorLoader] = Config{list.PromoterE2eRegistry, "apparmor-loader", "1.4"} configs[BusyBox] = Config{list.PromoterE2eRegistry, "busybox", "1.37.0-1"} - configs[DistrolessIptables] = Config{list.BuildImageRegistry, "distroless-iptables", "v0.7.8"} + configs[DistrolessIptables] = Config{list.BuildImageRegistry, "distroless-iptables", "v0.7.11"} configs[Etcd] = Config{list.GcEtcdRegistry, "etcd", "3.6.4-0"} configs[Httpd] = Config{list.PromoterE2eRegistry, "httpd", "2.4.38-4"} configs[HttpdNew] = Config{list.PromoterE2eRegistry, "httpd", "2.4.39-4"} diff --git a/deps/github.com/openshift/kubernetes/vendor/github.com/MakeNowJust/heredoc/README.md b/deps/github.com/openshift/kubernetes/vendor/github.com/MakeNowJust/heredoc/README.md deleted file mode 100644 index 289ba31d6a..0000000000 --- a/deps/github.com/openshift/kubernetes/vendor/github.com/MakeNowJust/heredoc/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# heredoc - -[![Build Status](https://circleci.com/gh/MakeNowJust/heredoc.svg?style=svg)](https://circleci.com/gh/MakeNowJust/heredoc) [![GoDoc](https://godoc.org/github.com/MakeNowJusti/heredoc?status.svg)](https://godoc.org/github.com/MakeNowJust/heredoc) - -## About - -Package heredoc provides the here-document with keeping indent. - -## Install - -```console -$ go get github.com/MakeNowJust/heredoc -``` - -## Import - -```go -// usual -import "github.com/MakeNowJust/heredoc" -``` - -## Example - -```go -package main - -import ( - "fmt" - "github.com/MakeNowJust/heredoc" -) - -func main() { - fmt.Println(heredoc.Doc(` - Lorem ipsum dolor sit amet, consectetur adipisicing elit, - sed do eiusmod tempor incididunt ut labore et dolore magna - aliqua. Ut enim ad minim veniam, ... - `)) - // Output: - // Lorem ipsum dolor sit amet, consectetur adipisicing elit, - // sed do eiusmod tempor incididunt ut labore et dolore magna - // aliqua. Ut enim ad minim veniam, ... - // -} -``` - -## API Document - - - [heredoc - GoDoc](https://godoc.org/github.com/MakeNowJust/heredoc) - -## License - -This software is released under the MIT License, see LICENSE. diff --git a/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/cache/memory/memory.go b/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/cache/memory/memory.go index a43e1b442e..e30b30fc9e 100644 --- a/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/cache/memory/memory.go +++ b/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/cache/memory/memory.go @@ -29,6 +29,38 @@ import ( // ErrDataNotFound is the error resulting if failed to find a container in memory cache. var ErrDataNotFound = errors.New("unable to find data in memory cache") +// containerCacheMap is a typed wrapper around sync.Map that eliminates the need +// for type assertions at every call site. It stores container name strings +// mapped to *containerCache values. +type containerCacheMap struct { + m sync.Map +} + +// Load retrieves a container cache by name. Returns nil, false if not found. +func (c *containerCacheMap) Load(name string) (*containerCache, bool) { + v, ok := c.m.Load(name) + if !ok { + return nil, false + } + return v.(*containerCache), true +} + +// Store saves a container cache with the given name. +func (c *containerCacheMap) Store(name string, cache *containerCache) { + c.m.Store(name, cache) +} + +// LoadOrStore returns the existing cache if present, otherwise stores and returns the given one. +func (c *containerCacheMap) LoadOrStore(name string, cache *containerCache) (*containerCache, bool) { + v, loaded := c.m.LoadOrStore(name, cache) + return v.(*containerCache), loaded +} + +// Delete removes a container cache by name. +func (c *containerCacheMap) Delete(name string) { + c.m.Delete(name) +} + // TODO(vmarmol): See about refactoring this class, we have an unnecessary redirection of containerCache and InMemoryCache. // containerCache is used to store per-container information type containerCache struct { @@ -67,24 +99,18 @@ func newContainerStore(ref info.ContainerReference, maxAge time.Duration) *conta } type InMemoryCache struct { - lock sync.RWMutex - containerCacheMap map[string]*containerCache + containerCacheMap containerCacheMap maxAge time.Duration backend []storage.StorageDriver } func (c *InMemoryCache) AddStats(cInfo *info.ContainerInfo, stats *info.ContainerStats) error { - var cstore *containerCache - var ok bool - - func() { - c.lock.Lock() - defer c.lock.Unlock() - if cstore, ok = c.containerCacheMap[cInfo.ContainerReference.Name]; !ok { - cstore = newContainerStore(cInfo.ContainerReference, c.maxAge) - c.containerCacheMap[cInfo.ContainerReference.Name] = cstore - } - }() + name := cInfo.ContainerReference.Name + cstore, ok := c.containerCacheMap.Load(name) + if !ok { + newStore := newContainerStore(cInfo.ContainerReference, c.maxAge) + cstore, _ = c.containerCacheMap.LoadOrStore(name, newStore) + } for _, backend := range c.backend { // TODO(monnand): To deal with long delay write operations, we @@ -98,34 +124,20 @@ func (c *InMemoryCache) AddStats(cInfo *info.ContainerInfo, stats *info.Containe } func (c *InMemoryCache) RecentStats(name string, start, end time.Time, maxStats int) ([]*info.ContainerStats, error) { - var cstore *containerCache - var ok bool - err := func() error { - c.lock.RLock() - defer c.lock.RUnlock() - if cstore, ok = c.containerCacheMap[name]; !ok { - return ErrDataNotFound - } - return nil - }() - if err != nil { - return nil, err + cstore, ok := c.containerCacheMap.Load(name) + if !ok { + return nil, ErrDataNotFound } - return cstore.RecentStats(start, end, maxStats) } func (c *InMemoryCache) Close() error { - c.lock.Lock() - c.containerCacheMap = make(map[string]*containerCache, 32) - c.lock.Unlock() + c.containerCacheMap = containerCacheMap{} return nil } func (c *InMemoryCache) RemoveContainer(containerName string) error { - c.lock.Lock() - delete(c.containerCacheMap, containerName) - c.lock.Unlock() + c.containerCacheMap.Delete(containerName) return nil } @@ -133,10 +145,8 @@ func New( maxAge time.Duration, backend []storage.StorageDriver, ) *InMemoryCache { - ret := &InMemoryCache{ - containerCacheMap: make(map[string]*containerCache, 32), - maxAge: maxAge, - backend: backend, + return &InMemoryCache{ + maxAge: maxAge, + backend: backend, } - return ret } diff --git a/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/manager/container.go b/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/manager/container.go index 4efbfda191..58700d116d 100644 --- a/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/manager/container.go +++ b/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/manager/container.go @@ -64,6 +64,18 @@ type containerInfo struct { Spec info.ContainerSpec } +// atomicTime is a lock-free wrapper for storing and retrieving time values. +// It stores time as Unix nanoseconds in an atomic.Int64, enabling concurrent +// reads and writes without mutex contention. +type atomicTime struct { + atomic.Int64 +} + +// Time returns the stored time value as a time.Time. +func (t *atomicTime) Time() time.Time { + return time.Unix(0, t.Load()) +} + type containerData struct { oomEvents uint64 handler container.ContainerHandler @@ -77,8 +89,8 @@ type containerData struct { housekeepingInterval time.Duration maxHousekeepingInterval time.Duration allowDynamicHousekeeping bool - infoLastUpdatedTime time.Time - statsLastUpdatedTime time.Time + infoLastUpdatedTime atomicTime // Unix nano + statsLastUpdatedTime atomicTime // Unix nano lastErrorTime time.Time // used to track time clock clock.Clock @@ -145,9 +157,7 @@ func (cd *containerData) allowErrorLogging() bool { // periodic housekeeping to reset. This should be used sparingly, as calling OnDemandHousekeeping frequently // can have serious performance costs. func (cd *containerData) OnDemandHousekeeping(maxAge time.Duration) { - cd.lock.Lock() - timeSinceStatsLastUpdate := cd.clock.Since(cd.statsLastUpdatedTime) - cd.lock.Unlock() + timeSinceStatsLastUpdate := cd.clock.Since(cd.statsLastUpdatedTime.Time()) if timeSinceStatsLastUpdate > maxAge { housekeepingFinishedChan := make(chan struct{}) cd.onDemandChan <- housekeepingFinishedChan @@ -172,7 +182,7 @@ func (cd *containerData) notifyOnDemand() { func (cd *containerData) GetInfo(shouldUpdateSubcontainers bool) (*containerInfo, error) { // Get spec and subcontainers. - if cd.clock.Since(cd.infoLastUpdatedTime) > 5*time.Second || shouldUpdateSubcontainers { + if cd.clock.Since(cd.infoLastUpdatedTime.Time()) > 5*time.Second || shouldUpdateSubcontainers { err := cd.updateSpec() if err != nil { return nil, err @@ -183,7 +193,7 @@ func (cd *containerData) GetInfo(shouldUpdateSubcontainers bool) (*containerInfo return nil, err } } - cd.infoLastUpdatedTime = cd.clock.Now() + cd.infoLastUpdatedTime.Store(cd.clock.Now().UnixNano()) } cd.lock.Lock() defer cd.lock.Unlock() @@ -594,9 +604,7 @@ func (cd *containerData) housekeepingTick(timer <-chan time.Time, longHousekeepi klog.V(3).Infof("[%s] Housekeeping took %s", cd.info.Name, duration) } cd.notifyOnDemand() - cd.lock.Lock() - defer cd.lock.Unlock() - cd.statsLastUpdatedTime = cd.clock.Now() + cd.statsLastUpdatedTime.Store(cd.clock.Now().UnixNano()) return true } diff --git a/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/manager/manager.go b/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/manager/manager.go index 7dbb01ecfb..ca16405d4a 100644 --- a/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/manager/manager.go +++ b/deps/github.com/openshift/kubernetes/vendor/github.com/google/cadvisor/manager/manager.go @@ -191,7 +191,6 @@ func New(memoryCache *memory.InMemoryCache, sysfs sysfs.SysFs, HousekeepingConfi eventsChannel := make(chan watcher.ContainerEvent, 16) newManager := &manager{ - containers: make(map[namespacedContainerName]*containerData), quitChannels: make([]chan error, 0, 2), memoryCache: memoryCache, fsInfo: fsInfo, @@ -245,9 +244,40 @@ type namespacedContainerName struct { Name string } +// containerMap is a type-safe wrapper around sync.Map for storing containerData +// keyed by namespacedContainerName. +type containerMap struct { + m sync.Map +} + +// Load returns the containerData for the given name, or nil if not found. +func (c *containerMap) Load(name namespacedContainerName) (*containerData, bool) { + v, ok := c.m.Load(name) + if !ok { + return nil, false + } + return v.(*containerData), true +} + +// Store stores the containerData for the given name. +func (c *containerMap) Store(name namespacedContainerName, data *containerData) { + c.m.Store(name, data) +} + +// Delete removes the containerData for the given name. +func (c *containerMap) Delete(name namespacedContainerName) { + c.m.Delete(name) +} + +// Range calls f for each container in the map. If f returns false, iteration stops. +func (c *containerMap) Range(f func(name namespacedContainerName, data *containerData) bool) { + c.m.Range(func(key, value any) bool { + return f(key.(namespacedContainerName), value.(*containerData)) + }) +} + type manager struct { - containers map[namespacedContainerName]*containerData - containersLock sync.RWMutex + containers containerMap memoryCache *memory.InMemoryCache fsInfo fs.FsInfo sysFs sysfs.SysFs @@ -363,10 +393,14 @@ func (m *manager) Stop() error { } func (m *manager) destroyCollectors() { - for _, container := range m.containers { + m.containers.Range(func(_ namespacedContainerName, container *containerData) bool { + if container == nil { + return true + } container.perfCollector.Destroy() container.resctrlCollector.Destroy() - } + return true + }) } func (m *manager) updateMachineInfo(quit chan error) { @@ -425,17 +459,8 @@ func (m *manager) globalHousekeeping(quit chan error) { } func (m *manager) getContainerData(containerName string) (*containerData, error) { - var cont *containerData - var ok bool - func() { - m.containersLock.RLock() - defer m.containersLock.RUnlock() - - // Ensure we have the container. - cont, ok = m.containers[namespacedContainerName{ - Name: containerName, - }] - }() + // Ensure we have the container. + cont, ok := m.containers.Load(namespacedContainerName{Name: containerName}) if !ok { return nil, fmt.Errorf("unknown container %q", containerName) } @@ -563,9 +588,7 @@ func (m *manager) containerDataToContainerInfo(cont *containerData, query *info. } func (m *manager) getContainer(containerName string) (*containerData, error) { - m.containersLock.RLock() - defer m.containersLock.RUnlock() - cont, ok := m.containers[namespacedContainerName{Name: containerName}] + cont, ok := m.containers.Load(namespacedContainerName{Name: containerName}) if !ok { return nil, fmt.Errorf("unknown container %q", containerName) } @@ -573,21 +596,20 @@ func (m *manager) getContainer(containerName string) (*containerData, error) { } func (m *manager) getSubcontainers(containerName string) map[string]*containerData { - m.containersLock.RLock() - defer m.containersLock.RUnlock() - containersMap := make(map[string]*containerData, len(m.containers)) + matchedName := path.Join(containerName, "/") + containersMap := make(map[string]*containerData) // Get all the unique subcontainers of the specified container - matchedName := path.Join(containerName, "/") - for i := range m.containers { - if m.containers[i] == nil { - continue + m.containers.Range(func(_ namespacedContainerName, cont *containerData) bool { + if cont == nil { + return true } - name := m.containers[i].info.Name + name := cont.info.Name if name == containerName || strings.HasPrefix(name, matchedName) { - containersMap[m.containers[i].info.Name] = m.containers[i] + containersMap[name] = cont } - } + return true + }) return containersMap } @@ -602,16 +624,18 @@ func (m *manager) SubcontainersInfo(containerName string, query *info.ContainerI } func (m *manager) getAllNamespacedContainers(ns string) map[string]*containerData { - m.containersLock.RLock() - defer m.containersLock.RUnlock() - containers := make(map[string]*containerData, len(m.containers)) + containers := make(map[string]*containerData) // Get containers in a namespace. - for name, cont := range m.containers { + m.containers.Range(func(name namespacedContainerName, cont *containerData) bool { + if cont == nil { + return true + } if name.Namespace == ns { containers[cont.info.Name] = cont } - } + return true + }) return containers } @@ -621,30 +645,32 @@ func (m *manager) AllDockerContainers(query *info.ContainerInfoRequest) (map[str } func (m *manager) namespacedContainer(containerName string, ns string) (*containerData, error) { - m.containersLock.RLock() - defer m.containersLock.RUnlock() - // Check for the container in the namespace. - cont, ok := m.containers[namespacedContainerName{ - Namespace: ns, - Name: containerName, - }] + if cont, ok := m.containers.Load(namespacedContainerName{Namespace: ns, Name: containerName}); ok { + return cont, nil + } // Look for container by short prefix name if no exact match found. - if !ok { - for contName, c := range m.containers { - if contName.Namespace == ns && strings.HasPrefix(contName.Name, containerName) { - if cont == nil { - cont = c - } else { - return nil, fmt.Errorf("unable to find container in %q namespace. Container %q is not unique", ns, containerName) - } + var cont *containerData + var err error + m.containers.Range(func(name namespacedContainerName, c *containerData) bool { + if name.Namespace == ns && strings.HasPrefix(name.Name, containerName) { + if cont == nil { + cont = c + } else { + err = fmt.Errorf("unable to find container in %q namespace. Container %q is not unique", ns, containerName) + return false // stop iteration } } + return true + }) - if cont == nil { - return nil, fmt.Errorf("unable to find container %q in %q namespace", containerName, ns) - } + if err != nil { + return nil, err + } + + if cont == nil { + return nil, fmt.Errorf("unable to find container %q in %q namespace", containerName, ns) } return cont, nil @@ -837,14 +863,7 @@ func (m *manager) GetVersionInfo() (*info.VersionInfo, error) { } func (m *manager) Exists(containerName string) bool { - m.containersLock.RLock() - defer m.containersLock.RUnlock() - - namespacedName := namespacedContainerName{ - Name: containerName, - } - - _, ok := m.containers[namespacedName] + _, ok := m.containers.Load(namespacedContainerName{Name: containerName}) return ok } @@ -904,19 +923,12 @@ func (m *manager) registerCollectors(collectorConfigs map[string]string, cont *c // Create a container. func (m *manager) createContainer(containerName string, watchSource watcher.ContainerWatchSource) error { - m.containersLock.Lock() - defer m.containersLock.Unlock() - - return m.createContainerLocked(containerName, watchSource) -} - -func (m *manager) createContainerLocked(containerName string, watchSource watcher.ContainerWatchSource) error { namespacedName := namespacedContainerName{ Name: containerName, } // Check that the container didn't already exist. - if _, ok := m.containers[namespacedName]; ok { + if _, ok := m.containers.Load(namespacedName); ok { return nil } @@ -970,12 +982,12 @@ func (m *manager) createContainerLocked(containerName string, watchSource watche } // Add the container name and all its aliases. The aliases must be within the namespace of the factory. - m.containers[namespacedName] = cont + m.containers.Store(namespacedName, cont) for _, alias := range cont.info.Aliases { - m.containers[namespacedContainerName{ + m.containers.Store(namespacedContainerName{ Namespace: cont.info.Namespace, Name: alias, - }] = cont + }, cont) } klog.V(3).Infof("Added container: %q (aliases: %v, namespace: %q)", containerName, cont.info.Aliases, cont.info.Namespace) @@ -1004,17 +1016,10 @@ func (m *manager) createContainerLocked(containerName string, watchSource watche } func (m *manager) destroyContainer(containerName string) error { - m.containersLock.Lock() - defer m.containersLock.Unlock() - - return m.destroyContainerLocked(containerName) -} - -func (m *manager) destroyContainerLocked(containerName string) error { namespacedName := namespacedContainerName{ Name: containerName, } - cont, ok := m.containers[namespacedName] + cont, ok := m.containers.Load(namespacedName) if !ok { // Already destroyed, done. return nil @@ -1027,9 +1032,9 @@ func (m *manager) destroyContainerLocked(containerName string) error { } // Remove the container from our records (and all its aliases). - delete(m.containers, namespacedName) + m.containers.Delete(namespacedName) for _, alias := range cont.info.Aliases { - delete(m.containers, namespacedContainerName{ + m.containers.Delete(namespacedContainerName{ Namespace: cont.info.Namespace, Name: alias, }) @@ -1056,11 +1061,7 @@ func (m *manager) destroyContainerLocked(containerName string) error { // Detect all containers that have been added or deleted from the specified container. func (m *manager) getContainersDiff(containerName string) (added []info.ContainerReference, removed []info.ContainerReference, err error) { // Get all subcontainers recursively. - m.containersLock.RLock() - cont, ok := m.containers[namespacedContainerName{ - Name: containerName, - }] - m.containersLock.RUnlock() + cont, ok := m.containers.Load(namespacedContainerName{Name: containerName}) if !ok { return nil, nil, fmt.Errorf("failed to find container %q while checking for new containers", containerName) } @@ -1071,24 +1072,23 @@ func (m *manager) getContainersDiff(containerName string) (added []info.Containe } allContainers = append(allContainers, info.ContainerReference{Name: containerName}) - m.containersLock.RLock() - defer m.containersLock.RUnlock() - // Determine which were added and which were removed. allContainersSet := make(map[string]*containerData) - for name, d := range m.containers { + m.containers.Range(func(name namespacedContainerName, cont *containerData) bool { + if cont == nil { + return true + } // Only add the canonical name. - if d.info.Name == name.Name { - allContainersSet[name.Name] = d + if cont.info.Name == name.Name { + allContainersSet[name.Name] = cont } - } + return true + }) // Added containers for _, c := range allContainers { delete(allContainersSet, c.Name) - _, ok := m.containers[namespacedContainerName{ - Name: c.Name, - }] + _, ok := m.containers.Load(namespacedContainerName{Name: c.Name}) if !ok { added = append(added, c) } @@ -1319,16 +1319,13 @@ func (m *manager) DebugInfo() map[string][]string { debugInfo := container.DebugInfo() // Get unique containers. - var conts map[*containerData]struct{} - func() { - m.containersLock.RLock() - defer m.containersLock.RUnlock() - - conts = make(map[*containerData]struct{}, len(m.containers)) - for _, c := range m.containers { - conts[c] = struct{}{} + conts := make(map[*containerData]struct{}) + m.containers.Range(func(_ namespacedContainerName, cont *containerData) bool { + if cont != nil { + conts[cont] = struct{}{} } - }() + return true + }) // List containers. lines := make([]string, 0, len(conts)) diff --git a/deps/github.com/openshift/kubernetes/vendor/k8s.io/system-validators/validators/types_unix.go b/deps/github.com/openshift/kubernetes/vendor/k8s.io/system-validators/validators/types_unix.go index 28eb1d38ba..e2fc25fc50 100644 --- a/deps/github.com/openshift/kubernetes/vendor/k8s.io/system-validators/validators/types_unix.go +++ b/deps/github.com/openshift/kubernetes/vendor/k8s.io/system-validators/validators/types_unix.go @@ -42,12 +42,6 @@ var DefaultSysSpec = SysSpec{ {Name: "IPC_NS"}, {Name: "UTS_NS"}, {Name: "CGROUPS"}, - {Name: "CGROUP_BPF"}, // cgroups v2 - {Name: "CGROUP_CPUACCT"}, // cgroups v1 cpuacct - {Name: "CGROUP_DEVICE"}, - {Name: "CGROUP_FREEZER"}, // cgroups v1 freezer - {Name: "CGROUP_PIDS"}, - {Name: "CGROUP_SCHED"}, // cgroups v1 & v2 cpu {Name: "CPUSETS"}, {Name: "MEMCG"}, {Name: "INET"}, @@ -62,7 +56,6 @@ var DefaultSysSpec = SysSpec{ {Name: "AUFS_FS", Description: "Required for aufs."}, {Name: "BLK_DEV_DM", Description: "Required for devicemapper."}, {Name: "CFS_BANDWIDTH", Description: "Required for CPU quota."}, - {Name: "CGROUP_HUGETLB", Description: "Required for hugetlb cgroup."}, {Name: "SECCOMP", Description: "Required for seccomp."}, {Name: "SECCOMP_FILTER", Description: "Required for seccomp mode 2."}, }, diff --git a/deps/github.com/openshift/kubernetes/vendor/modules.txt b/deps/github.com/openshift/kubernetes/vendor/modules.txt index aff9ef6ea9..2159fd7c51 100644 --- a/deps/github.com/openshift/kubernetes/vendor/modules.txt +++ b/deps/github.com/openshift/kubernetes/vendor/modules.txt @@ -228,7 +228,7 @@ github.com/golang/protobuf/ptypes/wrappers # github.com/google/btree v1.1.3 ## explicit; go 1.18 github.com/google/btree -# github.com/google/cadvisor v0.52.1 +# github.com/google/cadvisor v0.52.1 => github.com/openshift/google-cadvisor v0.52.1-openshift-4.21-1 ## explicit; go 1.23.0 github.com/google/cadvisor/cache/memory github.com/google/cadvisor/client/v2 @@ -1449,7 +1449,7 @@ k8s.io/kube-openapi/pkg/validation/validate ## explicit; go 1.24.0 # k8s.io/sample-apiserver v0.0.0 => ./staging/src/k8s.io/sample-apiserver ## explicit; go 1.24.0 -# k8s.io/system-validators v1.10.1 +# k8s.io/system-validators v1.10.2 ## explicit; go 1.16 k8s.io/system-validators/validators # k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 @@ -1582,4 +1582,5 @@ sigs.k8s.io/structured-merge-diff/v6/value ## explicit; go 1.22 sigs.k8s.io/yaml sigs.k8s.io/yaml/kyaml +# github.com/google/cadvisor => github.com/openshift/google-cadvisor v0.52.1-openshift-4.21-1 # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 diff --git a/docs/user/README.md b/docs/user/README.md index bda6071928..cfaef34fe1 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -2,22 +2,22 @@ List of the documents in alphabetical file name order. -- [AI Model Serving on MicroShift](./docs/user/ai_model_serving.md) -- [Auto-recovery From Manual Backups](./docs/user/autorecovery.md) -- [Debugging Tips](./docs/user/debugging_tips.md) -- [Getting Started with MicroShift](./docs/user/getting_started.md) -- [Integrating MicroShift with Greenboot](./docs/user/greenboot.md) -- [AMQ Broker on MicroShift](./docs/user/howto_amq_broker.md) -- [MicroShift Configuration](./docs/user/howto_config.md) -- [Firewall Configuration](./docs/user/howto_firewall.md) -- [Gateway API](./docs/user/howto_gateway_api.md) -- [MicroShift Behind Proxy](./docs/user/howto_http_proxy.md) -- [MicroShift kubeconfig Handling](./docs/user/howto_kubeconfig.md) -- [Load Balancer for User Workloads](./docs/user/howto_load_balancer.md) -- [Mirror MicroShift Container Images](./docs/user/howto_mirror_images.md) -- [Embedding MicroShift Container Images for Offline Deployments](./docs/user/howto_offline_containers.md) -- [How To Configure a Workload with Custom Security Context](./docs/user/howto_pod_security.md) -- [MicroShift Mitigation of System Configuration Changes](./docs/user/howto_sysconf_watch.md) -- [Running MicroShift Fully Offline](./docs/user/howto_test_offline.md) -- [Image Mode for MicroShift Users](./docs/user/image_mode.md) -- [Known Limitations](./docs/user/known_limitations.md) +- [AI Model Serving on MicroShift](./ai_model_serving.md) +- [Auto-recovery From Manual Backups](./autorecovery.md) +- [Debugging Tips](./debugging_tips.md) +- [Getting Started with MicroShift](./getting_started.md) +- [Integrating MicroShift with Greenboot](./greenboot.md) +- [AMQ Broker on MicroShift](./howto_amq_broker.md) +- [MicroShift Configuration](./howto_config.md) +- [Firewall Configuration](./howto_firewall.md) +- [Gateway API](./howto_gateway_api.md) +- [MicroShift Behind Proxy](./howto_http_proxy.md) +- [MicroShift kubeconfig Handling](./howto_kubeconfig.md) +- [Load Balancer for User Workloads](./howto_load_balancer.md) +- [Mirror MicroShift Container Images](./howto_mirror_images.md) +- [Embedding MicroShift Container Images for Offline Deployments](./howto_offline_containers.md) +- [How To Configure a Workload with Custom Security Context](./howto_pod_security.md) +- [MicroShift Mitigation of System Configuration Changes](./howto_sysconf_watch.md) +- [Running MicroShift Fully Offline](./howto_test_offline.md) +- [Image Mode for MicroShift Users](./image_mode.md) +- [Known Limitations](./known_limitations.md) diff --git a/docs/user/howto_config.md b/docs/user/howto_config.md index a858de3c2a..1ae5bf9927 100644 --- a/docs/user/howto_config.md +++ b/docs/user/howto_config.md @@ -14,6 +14,11 @@ apiServer: maxFileSize: 0 maxFiles: 0 profile: "" + featureGates: + customNoUpgrade: + disabled: [] + enabled: [] + featureSet: "" namedCertificates: - certPath: "" keyPath: "" @@ -26,6 +31,9 @@ debugging: logLevel: "" dns: baseDomain: "" + hosts: + file: "" + status: "" etcd: memoryLimitMB: 0 genericDevicePlugin: @@ -155,6 +163,11 @@ apiServer: maxFileSize: 200 maxFiles: 10 profile: Default + featureGates: + customNoUpgrade: + disabled: [] + enabled: [] + featureSet: "" namedCertificates: - certPath: "" keyPath: "" @@ -167,6 +180,9 @@ debugging: logLevel: Normal dns: baseDomain: example.com + hosts: + file: /etc/hosts + status: Disabled etcd: memoryLimitMB: 0 genericDevicePlugin: diff --git a/etcd/cmd/microshift-etcd/run.go b/etcd/cmd/microshift-etcd/run.go index 018b129a76..a573a5c013 100644 --- a/etcd/cmd/microshift-etcd/run.go +++ b/etcd/cmd/microshift-etcd/run.go @@ -19,7 +19,7 @@ import ( "github.com/spf13/cobra" etcd "go.etcd.io/etcd/server/v3/embed" - "go.etcd.io/etcd/server/v3/mvcc/backend" + "go.etcd.io/etcd/server/v3/storage/backend" "k8s.io/klog/v2" ) @@ -100,7 +100,7 @@ func (s *EtcdService) configure(cfg *config.Config) { s.etcdCfg.PeerTLSInfo.KeyFile = cryptomaterial.PeerKeyPath(etcdPeerCertDir) s.etcdCfg.PeerTLSInfo.TrustedCAFile = etcdSignerCertPath - s.etcdCfg.ExperimentalMaxLearners = MaxLearners + s.etcdCfg.MaxLearners = MaxLearners updateConfigFromFile(s.etcdCfg, getConfigFilePath()) } diff --git a/etcd/go.mod b/etcd/go.mod index 975aae0073..6484b3999c 100644 --- a/etcd/go.mod +++ b/etcd/go.mod @@ -11,48 +11,40 @@ replace ( ) require ( - github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7 - github.com/openshift/build-machinery-go v0.0.0-20250602125535-1b6d00b8c37c + github.com/openshift/api v0.0.0-20251117165054-348370f055bf + github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af github.com/spf13/cobra v1.9.1 go.etcd.io/etcd/server/v3 v3.6.4 - k8s.io/apimachinery v1.34.1 - k8s.io/cli-runtime v1.34.1 - k8s.io/component-base v1.34.1 + k8s.io/apimachinery v1.34.2 + k8s.io/cli-runtime v1.34.2 + k8s.io/component-base v1.34.2 k8s.io/klog/v2 v2.130.1 - k8s.io/kubectl v1.34.1 + k8s.io/kubectl v1.34.2 sigs.k8s.io/yaml v1.6.0 ) require ( github.com/blang/semver/v4 v4.0.0 // indirect - github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect - github.com/ghodss/yaml v1.0.0 // indirect - github.com/go-kit/kit v0.9.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.2 // indirect github.com/google/gnostic-models v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect - github.com/mitchellh/mapstructure v1.5.0 // 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-20251015151611-6fc7a74b67c5 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.11.0 // indirect - github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect - github.com/spf13/afero v1.15.0 // indirect - github.com/spf13/cast v1.10.0 // indirect - github.com/spf13/viper v1.21.0 // indirect github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 // indirect - github.com/subosito/gotenv v1.6.0 // indirect github.com/vishvananda/netlink v1.3.1 // indirect github.com/vishvananda/netns v0.0.5 // indirect github.com/x448/float16 v0.8.4 // indirect + 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 @@ -61,9 +53,8 @@ require ( 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/yaml.v2 v2.4.0 // indirect - k8s.io/apiserver v1.34.1 // indirect - k8s.io/kubelet v1.34.1 // indirect + k8s.io/apiserver v1.34.2 // indirect + k8s.io/kubelet v1.34.2 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect ) @@ -89,15 +80,11 @@ require ( github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.5.2 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // 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 - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect - github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jonboulle/clockwork v0.5.0 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -123,13 +110,11 @@ require ( github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 // indirect github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 // indirect github.com/xlab/treeprint v1.2.0 // indirect - go.etcd.io/bbolt v1.4.2 // indirect - go.etcd.io/etcd/api/v3 v3.6.4 - go.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect - go.etcd.io/etcd/client/v2 v2.305.21 // indirect - go.etcd.io/etcd/client/v3 v3.6.4 // indirect - go.etcd.io/etcd/pkg/v3 v3.6.4 // indirect - go.etcd.io/etcd/raft/v3 v3.5.21 // indirect + go.etcd.io/bbolt v1.4.3 // indirect + go.etcd.io/etcd/api/v3 v3.6.5 + go.etcd.io/etcd/client/pkg/v3 v3.6.5 // indirect + go.etcd.io/etcd/client/v3 v3.6.5 // indirect + go.etcd.io/etcd/pkg/v3 v3.6.5 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect go.opentelemetry.io/otel v1.37.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect @@ -146,16 +131,15 @@ require ( golang.org/x/term v0.35.0 // indirect golang.org/x/text v0.29.0 // indirect golang.org/x/time v0.9.0 // indirect - google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/grpc v1.76.0 // indirect google.golang.org/protobuf v1.36.8 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v1.34.1 // indirect - k8s.io/client-go v1.34.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/utils v0.0.0-20250604170112-4c0f3b243397 // indirect + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect sigs.k8s.io/kustomize/api v0.20.1 // indirect sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect @@ -163,12 +147,11 @@ require ( replace ( github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 // from kubernetes - go.etcd.io/etcd/api/v3 => github.com/openshift/etcd/api/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 // from etcd - go.etcd.io/etcd/client/pkg/v3 => github.com/openshift/etcd/client/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 // from etcd - go.etcd.io/etcd/client/v3 => github.com/openshift/etcd/client/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 // from etcd - go.etcd.io/etcd/pkg/v3 => github.com/openshift/etcd/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 // from etcd - go.etcd.io/etcd/raft/v3 => github.com/openshift/etcd/raft/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 // from etcd - go.etcd.io/etcd/server/v3 => github.com/openshift/etcd/server/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 // from etcd + go.etcd.io/etcd/api/v3 => github.com/openshift/etcd/api/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 // from etcd + go.etcd.io/etcd/client/pkg/v3 => github.com/openshift/etcd/client/pkg/v3 v3.0.0-20251111143920-806f690e1f14 // from etcd + go.etcd.io/etcd/client/v3 => github.com/openshift/etcd/client/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 // from etcd + go.etcd.io/etcd/pkg/v3 => github.com/openshift/etcd/pkg/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 // from etcd + go.etcd.io/etcd/server/v3 => github.com/openshift/etcd/server/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 // from etcd ) replace ( diff --git a/etcd/go.sum b/etcd/go.sum index ec3c427635..a20f9d9ed9 100644 --- a/etcd/go.sum +++ b/etcd/go.sum @@ -1,11 +1,7 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 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/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= @@ -16,13 +12,10 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v1.0.2 h1:H9MtNqVoVhvd9nCBwOyDjUEdZCREqbIdCJD93PBm/jA= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= @@ -40,27 +33,16 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= -github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= -github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -76,37 +58,24 @@ github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= -github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI= -github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= +github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo= github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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= @@ -114,12 +83,10 @@ github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5T github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 h1:FbSCl+KggFl+Ocym490i/EyXF4lPgLoUtcSWquBM0Rs= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0/go.mod h1:qOchhhIlmRcqk/O9uCo/puJlyo07YINaIqdZfZG3Jkc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -134,8 +101,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -148,8 +113,6 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= @@ -166,107 +129,70 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= -github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7 h1:Ot2fbEEPmF3WlPQkyEW/bUCV38GMugH/UmZvxpWceNc= -github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY= -github.com/openshift/build-machinery-go v0.0.0-20250602125535-1b6d00b8c37c h1:gJvhduWIrpzoUTwrJjjeul+hGETKkhRhEZosBg/X3Hg= -github.com/openshift/build-machinery-go v0.0.0-20250602125535-1b6d00b8c37c/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= -github.com/openshift/etcd/api/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 h1:ns2o+FgsPXiH2jTRyiMAJ5P/qT742Fkf54KXlBxB5hM= -github.com/openshift/etcd/api/v3 v3.5.1-0.20251001062325-e2b3dfdf0379/go.mod h1:c3aH5wcvXv/9dqIw2Y810LDXJfhSYdHQ0vxmP3CCHVY= -github.com/openshift/etcd/client/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 h1:c8Uhuc86HWnaoZ3OhvwpK6Op7dGiQrVEG15N2hYzYNc= -github.com/openshift/etcd/client/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379/go.mod h1:BgqT/IXPjK9NkeSDjbzwsHySX3yIle2+ndz28nVsjUs= -github.com/openshift/etcd/client/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 h1:efuin88U75UVVwXmKEQj9W+wC+UiT4RBcLqnlFCT1rk= -github.com/openshift/etcd/client/v3 v3.5.1-0.20251001062325-e2b3dfdf0379/go.mod h1:mFYy67IOqmbRf/kRUvsHixzo3iG+1OF2W2+jVIQRAnU= -github.com/openshift/etcd/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 h1:rxEiXhgqrPZ0BCsKsaUqcEK0fRUp5GGQtwxlW/jt/+o= -github.com/openshift/etcd/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379/go.mod h1:wpZx8Egv1g4y+N7JAsqi2zoUiBIUWznLjqJbylDjWgU= -github.com/openshift/etcd/raft/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 h1:qbnk193U7CUW0+PO1PKr7zknqmr1qOHmDj8l70LqZbo= -github.com/openshift/etcd/raft/v3 v3.5.1-0.20251001062325-e2b3dfdf0379/go.mod h1:fmcuY5R2SNkklU4+fKVBQi2biVp5vafMrWUEj4TJ4Cs= -github.com/openshift/etcd/server/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 h1:a/IORN+M82sTtcKAlJm2HSmxE7TmKYIQ7nO2hDkvBxs= -github.com/openshift/etcd/server/v3 v3.5.1-0.20251001062325-e2b3dfdf0379/go.mod h1:G1mOzdwuzKT1VRL7SqRchli/qcFrtLBTAQ4lV20sXXo= -github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 h1:bANtDc8SgetSK4nQehf59x3+H9FqVJCprgjs49/OTg0= -github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5/go.mod h1:OlFFws1AO51uzfc48MsStGE4SFMWlMZD0+f5a/zCtKI= +github.com/openshift/api v0.0.0-20251117165054-348370f055bf h1:8VzLlQFneh4bnHA3SS+Bb9VWdVaR7WugtSeqIngMC3s= +github.com/openshift/api v0.0.0-20251117165054-348370f055bf/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY= +github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af h1:UiYYMi/CCV+kwWrXuXfuUSOY2yNXOpWpNVgHc6aLQlE= +github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= +github.com/openshift/etcd/api/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 h1:3fyOgcjFbMjZgVGYGZvSTH8Zi5LavfXVwwjnAZOfpQA= +github.com/openshift/etcd/api/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14/go.mod h1:ob0/oWA/UQQlT1BmaEkWQzI0sJ1M0Et0mMpaABxguOQ= +github.com/openshift/etcd/client/pkg/v3 v3.0.0-20251111143920-806f690e1f14 h1:dXIOqD1issPq7FFvWUcZ20QHi/tJ0bn0egqTDW0PuCU= +github.com/openshift/etcd/client/pkg/v3 v3.0.0-20251111143920-806f690e1f14/go.mod h1:8Wx3eGRPiy0qOFMZT/hfvdos+DjEaPxdIDiCDUv/FQk= +github.com/openshift/etcd/client/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 h1:Eogcz8Tix+Lbh2poNuOKmVcYcxTT0ymeJLQB5jhJafk= +github.com/openshift/etcd/client/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14/go.mod h1:ZqwG/7TAFZ0BJ0jXRPoJjKQJtbFo/9NIY8uoFFKcCyo= +github.com/openshift/etcd/pkg/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 h1:Ndy/MFW8U36LJsXWfP8AP3shZvpyQqb3h3PXjVFQdeE= +github.com/openshift/etcd/pkg/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14/go.mod h1:uqrXrzmMIJDEy5j00bCqhVLzR5jEJIwDp5wTlLwPGOU= +github.com/openshift/etcd/server/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 h1:SpT3jxkbfO6cx9UH3dcDCmqBkbUuioFhqqYJRLlU1Rc= +github.com/openshift/etcd/server/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14/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/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/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= 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= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -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/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= -github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 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/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= -github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= -github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= -github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= -github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= 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/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= -github.com/spf13/pflag v1.0.7/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/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= -github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= -github.com/squat/generic-device-plugin v0.0.0-20250710162141-0f7fddf166f1 h1:jNjbOvtxFsLW9OkNs20b1hY/8Q8DWccUjYyOOxi1O00= -github.com/squat/generic-device-plugin v0.0.0-20250710162141-0f7fddf166f1/go.mod h1:rFRt0GxGw04yGcbfSqoUENZH0p+1oL6IziAVQ31NAVw= github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 h1:wPJNupO/W9VJkwf/5vVnEReuS3pf5u+V+RGv6TOPrLM= github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31/go.mod h1:9pAOQhVkVgGnpJcHSumKIQXSp8ALx3TeYoGUih9BNwY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= @@ -281,45 +207,34 @@ github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 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/client/v2 v2.305.21 h1:eLiFfexc2mE+pTLz9WwnoEsX5JTTpLCYVivKkmVXIRA= -go.etcd.io/etcd/client/v2 v2.305.21/go.mod h1:OKkn4hlYNf43hpjEM3Ke3aRdUkhSl8xjKjSf8eCq2J8= +go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= +go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= +go.etcd.io/raft/v3 v3.6.0 h1:5NtvbDVYpnfZWcIHgGRk9DyzkBIXOi8j+DDp1IcnUWQ= +go.etcd.io/raft/v3 v3.6.0/go.mod h1:nLvLevg6+xrVtHUmVaTcTz603gQPHfh7kUAwV6YpfGo= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 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/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= -go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 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.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 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= @@ -331,46 +246,26 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U 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/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 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-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 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/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= 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-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -392,10 +287,6 @@ golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= 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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 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= @@ -405,34 +296,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ= -google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b h1:ULiyYQ0FdsJhwwZUwbaXpZF5yUE3h+RA+gxvBu37ucc= google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:oDOGiMSXHL4sDTJvFvIB9nRQCGdLP1o/iVaqQK8zB+M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 h1:pmJpJEvT846VzausCQ5d7KreSROcDqmO388w5YbnltA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= -google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -444,21 +315,15 @@ 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= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 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/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +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/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md b/etcd/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md deleted file mode 100644 index 32966f5981..0000000000 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md +++ /dev/null @@ -1,22 +0,0 @@ -## Migration Guide (v4.0.0) - -Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0), the import path will be: - - "github.com/golang-jwt/jwt/v4" - -The `/v4` version will be backwards compatible with existing `v3.x.y` tags in this repo, as well as -`github.com/dgrijalva/jwt-go`. For most users this should be a drop-in replacement, if you're having -troubles migrating, please open an issue. - -You can replace all occurrences of `github.com/dgrijalva/jwt-go` or `github.com/golang-jwt/jwt` with `github.com/golang-jwt/jwt/v4`, either manually or by using tools such as `sed` or `gofmt`. - -And then you'd typically run: - -``` -go get github.com/golang-jwt/jwt/v4 -go mod tidy -``` - -## Older releases (before v3.2.0) - -The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md. diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/README.md b/etcd/vendor/github.com/golang-jwt/jwt/v4/README.md deleted file mode 100644 index 30f2f2a6f7..0000000000 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/README.md +++ /dev/null @@ -1,138 +0,0 @@ -# jwt-go - -[![build](https://github.com/golang-jwt/jwt/actions/workflows/build.yml/badge.svg)](https://github.com/golang-jwt/jwt/actions/workflows/build.yml) -[![Go Reference](https://pkg.go.dev/badge/github.com/golang-jwt/jwt/v4.svg)](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) - -A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519). - -Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) this project adds Go module support, but maintains backwards compatibility with older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`. -See the [`MIGRATION_GUIDE.md`](./MIGRATION_GUIDE.md) for more information. - -> After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic. - - -**SECURITY NOTICE:** Some older versions of Go have a security issue in the crypto/elliptic. Recommendation is to upgrade to at least 1.15 See issue [dgrijalva/jwt-go#216](https://github.com/dgrijalva/jwt-go/issues/216) for more detail. - -**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided. - -### Supported Go versions - -Our support of Go versions is aligned with Go's [version release policy](https://golang.org/doc/devel/release#policy). -So we will support a major version of Go until there are two newer major releases. -We no longer support building jwt-go with unsupported Go versions, as these contain security vulnerabilities -which will not be fixed. - -## What the heck is a JWT? - -JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens. - -In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](https://datatracker.ietf.org/doc/html/rfc4648) encoded. The last part is the signature, encoded the same way. - -The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. - -The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) for information about reserved keys and the proper way to add your own. - -## What's in the box? - -This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own. - -## Installation Guidelines - -1. To install the jwt package, you first need to have [Go](https://go.dev/doc/install) installed, then you can use the command below to add `jwt-go` as a dependency in your Go program. - -```sh -go get -u github.com/golang-jwt/jwt/v4 -``` - -2. Import it in your code: - -```go -import "github.com/golang-jwt/jwt/v4" -``` - -## Examples - -See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) for examples of usage: - -* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-Parse-Hmac) -* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-New-Hmac) -* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#pkg-examples) - -## Extensions - -This library publishes all the necessary components for adding your own signing methods or key functions. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod` or provide a `jwt.Keyfunc`. - -A common use case would be integrating with different 3rd party signature providers, like key management services from various cloud providers or Hardware Security Modules (HSMs) or to implement additional standards. - -| Extension | Purpose | Repo | -| --------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------ | -| GCP | Integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS) | https://github.com/someone1/gcp-jwt-go | -| AWS | Integrates with AWS Key Management Service, KMS | https://github.com/matelang/jwt-go-aws-kms | -| JWKS | Provides support for JWKS ([RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517)) as a `jwt.Keyfunc` | https://github.com/MicahParks/keyfunc | - -*Disclaimer*: Unless otherwise specified, these integrations are maintained by third parties and should not be considered as a primary offer by any of the mentioned cloud providers - -## Compliance - -This library was last reviewed to comply with [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences: - -* In order to protect against accidental use of [Unsecured JWTs](https://datatracker.ietf.org/doc/html/rfc7519#section-6), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. - -## Project Status & Versioning - -This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). - -This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `main`. Periodically, versions will be tagged from `main`. You can find all the releases on [the project releases page](https://github.com/golang-jwt/jwt/releases). - -**BREAKING CHANGES:*** -A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code. - -## Usage Tips - -### Signing vs Encryption - -A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data: - -* The author of the token was in the possession of the signing secret -* The data has not been modified since it was signed - -It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. The companion project https://github.com/golang-jwt/jwe aims at a (very) experimental implementation of the JWE standard. - -### Choosing a Signing Method - -There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric. - -Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation. - -Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification. - -### Signing Methods and Key Types - -Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones: - -* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation -* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation -* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation -* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation - -### JWT and OAuth - -It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication. - -Without going too far down the rabbit hole, here's a description of the interaction of these technologies: - -* OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth. -* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token. -* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL. - -### Troubleshooting - -This library uses descriptive error messages whenever possible. If you are not getting the expected result, have a look at the errors. The most common place people get stuck is providing the correct type of key to the parser. See the above section on signing methods and key types. - -## More - -Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt/v4). - -The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation. - -[golang-jwt](https://github.com/orgs/golang-jwt) incorporates a modified version of the JWT logo, which is distributed under the terms of the [MIT License](https://github.com/jsonwebtoken/jsonwebtoken.github.io/blob/master/LICENSE.txt). diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/claims.go b/etcd/vendor/github.com/golang-jwt/jwt/v4/claims.go deleted file mode 100644 index 364cec8773..0000000000 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/claims.go +++ /dev/null @@ -1,269 +0,0 @@ -package jwt - -import ( - "crypto/subtle" - "fmt" - "time" -) - -// Claims must just have a Valid method that determines -// if the token is invalid for any supported reason -type Claims interface { - Valid() error -} - -// RegisteredClaims are a structured version of the JWT Claims Set, -// restricted to Registered Claim Names, as referenced at -// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1 -// -// This type can be used on its own, but then additional private and -// public claims embedded in the JWT will not be parsed. The typical usecase -// therefore is to embedded this in a user-defined claim type. -// -// See examples for how to use this with your own claim types. -type RegisteredClaims struct { - // the `iss` (Issuer) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1 - Issuer string `json:"iss,omitempty"` - - // the `sub` (Subject) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2 - Subject string `json:"sub,omitempty"` - - // the `aud` (Audience) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3 - Audience ClaimStrings `json:"aud,omitempty"` - - // the `exp` (Expiration Time) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4 - ExpiresAt *NumericDate `json:"exp,omitempty"` - - // the `nbf` (Not Before) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5 - NotBefore *NumericDate `json:"nbf,omitempty"` - - // the `iat` (Issued At) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6 - IssuedAt *NumericDate `json:"iat,omitempty"` - - // the `jti` (JWT ID) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7 - ID string `json:"jti,omitempty"` -} - -// Valid validates time based claims "exp, iat, nbf". -// There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (c RegisteredClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc() - - // The claims below are optional, by default, so if they are set to the - // default value in Go, let's not fail the verification for them. - if !c.VerifyExpiresAt(now, false) { - delta := now.Sub(c.ExpiresAt.Time) - vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta) - vErr.Errors |= ValidationErrorExpired - } - - if !c.VerifyIssuedAt(now, false) { - vErr.Inner = ErrTokenUsedBeforeIssued - vErr.Errors |= ValidationErrorIssuedAt - } - - if !c.VerifyNotBefore(now, false) { - vErr.Inner = ErrTokenNotValidYet - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} - -// VerifyAudience compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *RegisteredClaims) VerifyAudience(cmp string, req bool) bool { - return verifyAud(c.Audience, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp < exp). -// If req is false, it will return true, if exp is unset. -func (c *RegisteredClaims) VerifyExpiresAt(cmp time.Time, req bool) bool { - if c.ExpiresAt == nil { - return verifyExp(nil, cmp, req) - } - - return verifyExp(&c.ExpiresAt.Time, cmp, req) -} - -// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (c *RegisteredClaims) VerifyIssuedAt(cmp time.Time, req bool) bool { - if c.IssuedAt == nil { - return verifyIat(nil, cmp, req) - } - - return verifyIat(&c.IssuedAt.Time, cmp, req) -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (c *RegisteredClaims) VerifyNotBefore(cmp time.Time, req bool) bool { - if c.NotBefore == nil { - return verifyNbf(nil, cmp, req) - } - - return verifyNbf(&c.NotBefore.Time, cmp, req) -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *RegisteredClaims) VerifyIssuer(cmp string, req bool) bool { - return verifyIss(c.Issuer, cmp, req) -} - -// StandardClaims are a structured version of the JWT Claims Set, as referenced at -// https://datatracker.ietf.org/doc/html/rfc7519#section-4. They do not follow the -// specification exactly, since they were based on an earlier draft of the -// specification and not updated. The main difference is that they only -// support integer-based date fields and singular audiences. This might lead to -// incompatibilities with other JWT implementations. The use of this is discouraged, instead -// the newer RegisteredClaims struct should be used. -// -// Deprecated: Use RegisteredClaims instead for a forward-compatible way to access registered claims in a struct. -type StandardClaims struct { - Audience string `json:"aud,omitempty"` - ExpiresAt int64 `json:"exp,omitempty"` - Id string `json:"jti,omitempty"` - IssuedAt int64 `json:"iat,omitempty"` - Issuer string `json:"iss,omitempty"` - NotBefore int64 `json:"nbf,omitempty"` - Subject string `json:"sub,omitempty"` -} - -// Valid validates time based claims "exp, iat, nbf". There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (c StandardClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc().Unix() - - // The claims below are optional, by default, so if they are set to the - // default value in Go, let's not fail the verification for them. - if !c.VerifyExpiresAt(now, false) { - delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0)) - vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta) - vErr.Errors |= ValidationErrorExpired - } - - if !c.VerifyIssuedAt(now, false) { - vErr.Inner = ErrTokenUsedBeforeIssued - vErr.Errors |= ValidationErrorIssuedAt - } - - if !c.VerifyNotBefore(now, false) { - vErr.Inner = ErrTokenNotValidYet - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} - -// VerifyAudience compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool { - return verifyAud([]string{c.Audience}, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp < exp). -// If req is false, it will return true, if exp is unset. -func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool { - if c.ExpiresAt == 0 { - return verifyExp(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.ExpiresAt, 0) - return verifyExp(&t, time.Unix(cmp, 0), req) -} - -// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool { - if c.IssuedAt == 0 { - return verifyIat(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.IssuedAt, 0) - return verifyIat(&t, time.Unix(cmp, 0), req) -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { - if c.NotBefore == 0 { - return verifyNbf(nil, time.Unix(cmp, 0), req) - } - - t := time.Unix(c.NotBefore, 0) - return verifyNbf(&t, time.Unix(cmp, 0), req) -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool { - return verifyIss(c.Issuer, cmp, req) -} - -// ----- helpers - -func verifyAud(aud []string, cmp string, required bool) bool { - if len(aud) == 0 { - return !required - } - // use a var here to keep constant time compare when looping over a number of claims - result := false - - var stringClaims string - for _, a := range aud { - if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 { - result = true - } - stringClaims = stringClaims + a - } - - // case where "" is sent in one or many aud claims - if len(stringClaims) == 0 { - return !required - } - - return result -} - -func verifyExp(exp *time.Time, now time.Time, required bool) bool { - if exp == nil { - return !required - } - return now.Before(*exp) -} - -func verifyIat(iat *time.Time, now time.Time, required bool) bool { - if iat == nil { - return !required - } - return now.After(*iat) || now.Equal(*iat) -} - -func verifyNbf(nbf *time.Time, now time.Time, required bool) bool { - if nbf == nil { - return !required - } - return now.After(*nbf) || now.Equal(*nbf) -} - -func verifyIss(iss string, cmp string, required bool) bool { - if iss == "" { - return !required - } - return subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 -} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/errors.go b/etcd/vendor/github.com/golang-jwt/jwt/v4/errors.go deleted file mode 100644 index 10ac8835cc..0000000000 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/errors.go +++ /dev/null @@ -1,112 +0,0 @@ -package jwt - -import ( - "errors" -) - -// Error constants -var ( - ErrInvalidKey = errors.New("key is invalid") - ErrInvalidKeyType = errors.New("key is of invalid type") - ErrHashUnavailable = errors.New("the requested hash function is unavailable") - - ErrTokenMalformed = errors.New("token is malformed") - ErrTokenUnverifiable = errors.New("token is unverifiable") - ErrTokenSignatureInvalid = errors.New("token signature is invalid") - - ErrTokenInvalidAudience = errors.New("token has invalid audience") - ErrTokenExpired = errors.New("token is expired") - ErrTokenUsedBeforeIssued = errors.New("token used before issued") - ErrTokenInvalidIssuer = errors.New("token has invalid issuer") - ErrTokenNotValidYet = errors.New("token is not valid yet") - ErrTokenInvalidId = errors.New("token has invalid id") - ErrTokenInvalidClaims = errors.New("token has invalid claims") -) - -// The errors that might occur when parsing and validating a token -const ( - ValidationErrorMalformed uint32 = 1 << iota // Token is malformed - ValidationErrorUnverifiable // Token could not be verified because of signing problems - ValidationErrorSignatureInvalid // Signature validation failed - - // Standard Claim validation errors - ValidationErrorAudience // AUD validation failed - ValidationErrorExpired // EXP validation failed - ValidationErrorIssuedAt // IAT validation failed - ValidationErrorIssuer // ISS validation failed - ValidationErrorNotValidYet // NBF validation failed - ValidationErrorId // JTI validation failed - ValidationErrorClaimsInvalid // Generic claims validation error -) - -// NewValidationError is a helper for constructing a ValidationError with a string error message -func NewValidationError(errorText string, errorFlags uint32) *ValidationError { - return &ValidationError{ - text: errorText, - Errors: errorFlags, - } -} - -// ValidationError represents an error from Parse if token is not valid -type ValidationError struct { - Inner error // stores the error returned by external dependencies, i.e.: KeyFunc - Errors uint32 // bitfield. see ValidationError... constants - text string // errors that do not have a valid error just have text -} - -// Error is the implementation of the err interface. -func (e ValidationError) Error() string { - if e.Inner != nil { - return e.Inner.Error() - } else if e.text != "" { - return e.text - } else { - return "token is invalid" - } -} - -// Unwrap gives errors.Is and errors.As access to the inner error. -func (e *ValidationError) Unwrap() error { - return e.Inner -} - -// No errors -func (e *ValidationError) valid() bool { - return e.Errors == 0 -} - -// Is checks if this ValidationError is of the supplied error. We are first checking for the exact error message -// by comparing the inner error message. If that fails, we compare using the error flags. This way we can use -// custom error messages (mainly for backwards compatability) and still leverage errors.Is using the global error variables. -func (e *ValidationError) Is(err error) bool { - // Check, if our inner error is a direct match - if errors.Is(errors.Unwrap(e), err) { - return true - } - - // Otherwise, we need to match using our error flags - switch err { - case ErrTokenMalformed: - return e.Errors&ValidationErrorMalformed != 0 - case ErrTokenUnverifiable: - return e.Errors&ValidationErrorUnverifiable != 0 - case ErrTokenSignatureInvalid: - return e.Errors&ValidationErrorSignatureInvalid != 0 - case ErrTokenInvalidAudience: - return e.Errors&ValidationErrorAudience != 0 - case ErrTokenExpired: - return e.Errors&ValidationErrorExpired != 0 - case ErrTokenUsedBeforeIssued: - return e.Errors&ValidationErrorIssuedAt != 0 - case ErrTokenInvalidIssuer: - return e.Errors&ValidationErrorIssuer != 0 - case ErrTokenNotValidYet: - return e.Errors&ValidationErrorNotValidYet != 0 - case ErrTokenInvalidId: - return e.Errors&ValidationErrorId != 0 - case ErrTokenInvalidClaims: - return e.Errors&ValidationErrorClaimsInvalid != 0 - } - - return false -} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/map_claims.go b/etcd/vendor/github.com/golang-jwt/jwt/v4/map_claims.go deleted file mode 100644 index 2700d64a0d..0000000000 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/map_claims.go +++ /dev/null @@ -1,151 +0,0 @@ -package jwt - -import ( - "encoding/json" - "errors" - "time" - // "fmt" -) - -// MapClaims is a claims type that uses the map[string]interface{} for JSON decoding. -// This is the default claims type if you don't supply one -type MapClaims map[string]interface{} - -// VerifyAudience Compares the aud claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyAudience(cmp string, req bool) bool { - var aud []string - switch v := m["aud"].(type) { - case string: - aud = append(aud, v) - case []string: - aud = v - case []interface{}: - for _, a := range v { - vs, ok := a.(string) - if !ok { - return false - } - aud = append(aud, vs) - } - } - return verifyAud(aud, cmp, req) -} - -// VerifyExpiresAt compares the exp claim against cmp (cmp <= exp). -// If req is false, it will return true, if exp is unset. -func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool { - cmpTime := time.Unix(cmp, 0) - - v, ok := m["exp"] - if !ok { - return !req - } - - switch exp := v.(type) { - case float64: - if exp == 0 { - return verifyExp(nil, cmpTime, req) - } - - return verifyExp(&newNumericDateFromSeconds(exp).Time, cmpTime, req) - case json.Number: - v, _ := exp.Float64() - - return verifyExp(&newNumericDateFromSeconds(v).Time, cmpTime, req) - } - - return false -} - -// VerifyIssuedAt compares the exp claim against cmp (cmp >= iat). -// If req is false, it will return true, if iat is unset. -func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool { - cmpTime := time.Unix(cmp, 0) - - v, ok := m["iat"] - if !ok { - return !req - } - - switch iat := v.(type) { - case float64: - if iat == 0 { - return verifyIat(nil, cmpTime, req) - } - - return verifyIat(&newNumericDateFromSeconds(iat).Time, cmpTime, req) - case json.Number: - v, _ := iat.Float64() - - return verifyIat(&newNumericDateFromSeconds(v).Time, cmpTime, req) - } - - return false -} - -// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). -// If req is false, it will return true, if nbf is unset. -func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { - cmpTime := time.Unix(cmp, 0) - - v, ok := m["nbf"] - if !ok { - return !req - } - - switch nbf := v.(type) { - case float64: - if nbf == 0 { - return verifyNbf(nil, cmpTime, req) - } - - return verifyNbf(&newNumericDateFromSeconds(nbf).Time, cmpTime, req) - case json.Number: - v, _ := nbf.Float64() - - return verifyNbf(&newNumericDateFromSeconds(v).Time, cmpTime, req) - } - - return false -} - -// VerifyIssuer compares the iss claim against cmp. -// If required is false, this method will return true if the value matches or is unset -func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { - iss, _ := m["iss"].(string) - return verifyIss(iss, cmp, req) -} - -// Valid validates time based claims "exp, iat, nbf". -// There is no accounting for clock skew. -// As well, if any of the above claims are not in the token, it will still -// be considered a valid claim. -func (m MapClaims) Valid() error { - vErr := new(ValidationError) - now := TimeFunc().Unix() - - if !m.VerifyExpiresAt(now, false) { - // TODO(oxisto): this should be replaced with ErrTokenExpired - vErr.Inner = errors.New("Token is expired") - vErr.Errors |= ValidationErrorExpired - } - - if !m.VerifyIssuedAt(now, false) { - // TODO(oxisto): this should be replaced with ErrTokenUsedBeforeIssued - vErr.Inner = errors.New("Token used before issued") - vErr.Errors |= ValidationErrorIssuedAt - } - - if !m.VerifyNotBefore(now, false) { - // TODO(oxisto): this should be replaced with ErrTokenNotValidYet - vErr.Inner = errors.New("Token is not valid yet") - vErr.Errors |= ValidationErrorNotValidYet - } - - if vErr.valid() { - return nil - } - - return vErr -} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/parser.go b/etcd/vendor/github.com/golang-jwt/jwt/v4/parser.go deleted file mode 100644 index 0fc510a0aa..0000000000 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/parser.go +++ /dev/null @@ -1,206 +0,0 @@ -package jwt - -import ( - "bytes" - "encoding/json" - "fmt" - "strings" -) - -const tokenDelimiter = "." - -type Parser struct { - // If populated, only these methods will be considered valid. - // - // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. - ValidMethods []string - - // Use JSON Number format in JSON decoder. - // - // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. - UseJSONNumber bool - - // Skip claims validation during token parsing. - // - // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. - SkipClaimsValidation bool -} - -// NewParser creates a new Parser with the specified options -func NewParser(options ...ParserOption) *Parser { - p := &Parser{} - - // loop through our parsing options and apply them - for _, option := range options { - option(p) - } - - return p -} - -// Parse parses, validates, verifies the signature and returns the parsed token. keyFunc will -// receive the parsed token and should return the key for validating. -func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { - return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) -} - -// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object -// implementing the Claims interface. This provides default values which can be overridden and -// allows a caller to use their own type, rather than the default MapClaims implementation of -// Claims. -// -// Note: If you provide a custom claim implementation that embeds one of the standard claims (such -// as RegisteredClaims), make sure that a) you either embed a non-pointer version of the claims or -// b) if you are using a pointer, allocate the proper memory for it before passing in the overall -// claims, otherwise you might run into a panic. -func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { - token, parts, err := p.ParseUnverified(tokenString, claims) - if err != nil { - return token, err - } - - // Verify signing method is in the required set - if p.ValidMethods != nil { - var signingMethodValid = false - var alg = token.Method.Alg() - for _, m := range p.ValidMethods { - if m == alg { - signingMethodValid = true - break - } - } - if !signingMethodValid { - // signing method is not in the listed set - return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid) - } - } - - // Lookup key - var key interface{} - if keyFunc == nil { - // keyFunc was not provided. short circuiting validation - return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable) - } - if key, err = keyFunc(token); err != nil { - // keyFunc returned an error - if ve, ok := err.(*ValidationError); ok { - return token, ve - } - return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable} - } - - // Perform validation - token.Signature = parts[2] - if err := token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil { - return token, &ValidationError{Inner: err, Errors: ValidationErrorSignatureInvalid} - } - - vErr := &ValidationError{} - - // Validate Claims - if !p.SkipClaimsValidation { - if err := token.Claims.Valid(); err != nil { - // If the Claims Valid returned an error, check if it is a validation error, - // If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set - if e, ok := err.(*ValidationError); !ok { - vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid} - } else { - vErr = e - } - return token, vErr - } - } - - // No errors so far, token is valid. - token.Valid = true - - return token, nil -} - -// ParseUnverified parses the token but doesn't validate the signature. -// -// WARNING: Don't use this method unless you know what you're doing. -// -// It's only ever useful in cases where you know the signature is valid (because it has -// been checked previously in the stack) and you want to extract values from it. -func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) { - var ok bool - parts, ok = splitToken(tokenString) - if !ok { - return nil, nil, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) - } - - token = &Token{Raw: tokenString} - - // parse Header - var headerBytes []byte - if headerBytes, err = DecodeSegment(parts[0]); err != nil { - if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") { - return token, parts, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) - } - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - if err = json.Unmarshal(headerBytes, &token.Header); err != nil { - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - - // parse Claims - var claimBytes []byte - token.Claims = claims - - if claimBytes, err = DecodeSegment(parts[1]); err != nil { - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) - if p.UseJSONNumber { - dec.UseNumber() - } - // JSON Decode. Special case for map type to avoid weird pointer behavior - if c, ok := token.Claims.(MapClaims); ok { - err = dec.Decode(&c) - } else { - err = dec.Decode(&claims) - } - // Handle decode error - if err != nil { - return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} - } - - // Lookup signature method - if method, ok := token.Header["alg"].(string); ok { - if token.Method = GetSigningMethod(method); token.Method == nil { - return token, parts, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) - } - } else { - return token, parts, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) - } - - return token, parts, nil -} - -// splitToken splits a token string into three parts: header, claims, and signature. It will only -// return true if the token contains exactly two delimiters and three parts. In all other cases, it -// will return nil parts and false. -func splitToken(token string) ([]string, bool) { - parts := make([]string, 3) - header, remain, ok := strings.Cut(token, tokenDelimiter) - if !ok { - return nil, false - } - parts[0] = header - claims, remain, ok := strings.Cut(remain, tokenDelimiter) - if !ok { - return nil, false - } - parts[1] = claims - // One more cut to ensure the signature is the last part of the token and there are no more - // delimiters. This avoids an issue where malicious input could contain additional delimiters - // causing unecessary overhead parsing tokens. - signature, _, unexpected := strings.Cut(remain, tokenDelimiter) - if unexpected { - return nil, false - } - parts[2] = signature - - return parts, true -} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/parser_option.go b/etcd/vendor/github.com/golang-jwt/jwt/v4/parser_option.go deleted file mode 100644 index 6ea6f9527d..0000000000 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/parser_option.go +++ /dev/null @@ -1,29 +0,0 @@ -package jwt - -// ParserOption is used to implement functional-style options that modify the behavior of the parser. To add -// new options, just create a function (ideally beginning with With or Without) that returns an anonymous function that -// takes a *Parser type as input and manipulates its configuration accordingly. -type ParserOption func(*Parser) - -// WithValidMethods is an option to supply algorithm methods that the parser will check. Only those methods will be considered valid. -// It is heavily encouraged to use this option in order to prevent attacks such as https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/. -func WithValidMethods(methods []string) ParserOption { - return func(p *Parser) { - p.ValidMethods = methods - } -} - -// WithJSONNumber is an option to configure the underlying JSON parser with UseNumber -func WithJSONNumber() ParserOption { - return func(p *Parser) { - p.UseJSONNumber = true - } -} - -// WithoutClaimsValidation is an option to disable claims validation. This option should only be used if you exactly know -// what you are doing. -func WithoutClaimsValidation() ParserOption { - return func(p *Parser) { - p.SkipClaimsValidation = true - } -} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/token.go b/etcd/vendor/github.com/golang-jwt/jwt/v4/token.go deleted file mode 100644 index 786b275ce0..0000000000 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/token.go +++ /dev/null @@ -1,143 +0,0 @@ -package jwt - -import ( - "encoding/base64" - "encoding/json" - "strings" - "time" -) - -// DecodePaddingAllowed will switch the codec used for decoding JWTs respectively. Note that the JWS RFC7515 -// states that the tokens will utilize a Base64url encoding with no padding. Unfortunately, some implementations -// of JWT are producing non-standard tokens, and thus require support for decoding. Note that this is a global -// variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe. -// To use the non-recommended decoding, set this boolean to `true` prior to using this package. -var DecodePaddingAllowed bool - -// DecodeStrict will switch the codec used for decoding JWTs into strict mode. -// In this mode, the decoder requires that trailing padding bits are zero, as described in RFC 4648 section 3.5. -// Note that this is a global variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe. -// To use strict decoding, set this boolean to `true` prior to using this package. -var DecodeStrict bool - -// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time). -// You can override it to use another time value. This is useful for testing or if your -// server uses a different time zone than your tokens. -var TimeFunc = time.Now - -// Keyfunc will be used by the Parse methods as a callback function to supply -// the key for verification. The function receives the parsed, -// but unverified Token. This allows you to use properties in the -// Header of the token (such as `kid`) to identify which key to use. -type Keyfunc func(*Token) (interface{}, error) - -// Token represents a JWT Token. Different fields will be used depending on whether you're -// creating or parsing/verifying a token. -type Token struct { - Raw string // The raw token. Populated when you Parse a token - Method SigningMethod // The signing method used or to be used - Header map[string]interface{} // The first segment of the token - Claims Claims // The second segment of the token - Signature string // The third segment of the token. Populated when you Parse a token - Valid bool // Is the token valid? Populated when you Parse/Verify a token -} - -// New creates a new Token with the specified signing method and an empty map of claims. -func New(method SigningMethod) *Token { - return NewWithClaims(method, MapClaims{}) -} - -// NewWithClaims creates a new Token with the specified signing method and claims. -func NewWithClaims(method SigningMethod, claims Claims) *Token { - return &Token{ - Header: map[string]interface{}{ - "typ": "JWT", - "alg": method.Alg(), - }, - Claims: claims, - Method: method, - } -} - -// SignedString creates and returns a complete, signed JWT. -// The token is signed using the SigningMethod specified in the token. -func (t *Token) SignedString(key interface{}) (string, error) { - var sig, sstr string - var err error - if sstr, err = t.SigningString(); err != nil { - return "", err - } - if sig, err = t.Method.Sign(sstr, key); err != nil { - return "", err - } - return strings.Join([]string{sstr, sig}, "."), nil -} - -// SigningString generates the signing string. This is the -// most expensive part of the whole deal. Unless you -// need this for something special, just go straight for -// the SignedString. -func (t *Token) SigningString() (string, error) { - var err error - var jsonValue []byte - - if jsonValue, err = json.Marshal(t.Header); err != nil { - return "", err - } - header := EncodeSegment(jsonValue) - - if jsonValue, err = json.Marshal(t.Claims); err != nil { - return "", err - } - claim := EncodeSegment(jsonValue) - - return strings.Join([]string{header, claim}, "."), nil -} - -// Parse parses, validates, verifies the signature and returns the parsed token. -// keyFunc will receive the parsed token and should return the cryptographic key -// for verifying the signature. -// The caller is strongly encouraged to set the WithValidMethods option to -// validate the 'alg' claim in the token matches the expected algorithm. -// For more details about the importance of validating the 'alg' claim, -// see https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/ -func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { - return NewParser(options...).Parse(tokenString, keyFunc) -} - -// ParseWithClaims is a shortcut for NewParser().ParseWithClaims(). -// -// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims), -// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the -// proper memory for it before passing in the overall claims, otherwise you might run into a panic. -func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { - return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc) -} - -// EncodeSegment encodes a JWT specific base64url encoding with padding stripped -// -// Deprecated: In a future release, we will demote this function to a non-exported function, since it -// should only be used internally -func EncodeSegment(seg []byte) string { - return base64.RawURLEncoding.EncodeToString(seg) -} - -// DecodeSegment decodes a JWT specific base64url encoding with padding stripped -// -// Deprecated: In a future release, we will demote this function to a non-exported function, since it -// should only be used internally -func DecodeSegment(seg string) ([]byte, error) { - encoding := base64.RawURLEncoding - - if DecodePaddingAllowed { - if l := len(seg) % 4; l > 0 { - seg += strings.Repeat("=", 4-l) - } - encoding = base64.URLEncoding - } - - if DecodeStrict { - encoding = encoding.Strict() - } - return encoding.DecodeString(seg) -} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/.gitignore b/etcd/vendor/github.com/golang-jwt/jwt/v5/.gitignore similarity index 100% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/.gitignore rename to etcd/vendor/github.com/golang-jwt/jwt/v5/.gitignore diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/LICENSE b/etcd/vendor/github.com/golang-jwt/jwt/v5/LICENSE similarity index 100% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/LICENSE rename to etcd/vendor/github.com/golang-jwt/jwt/v5/LICENSE diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/MIGRATION_GUIDE.md b/etcd/vendor/github.com/golang-jwt/jwt/v5/MIGRATION_GUIDE.md new file mode 100644 index 0000000000..ff9c57e1d8 --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/MIGRATION_GUIDE.md @@ -0,0 +1,195 @@ +# Migration Guide (v5.0.0) + +Version `v5` contains a major rework of core functionalities in the `jwt-go` +library. This includes support for several validation options as well as a +re-design of the `Claims` interface. Lastly, we reworked how errors work under +the hood, which should provide a better overall developer experience. + +Starting from [v5.0.0](https://github.com/golang-jwt/jwt/releases/tag/v5.0.0), +the import path will be: + + "github.com/golang-jwt/jwt/v5" + +For most users, changing the import path *should* suffice. However, since we +intentionally changed and cleaned some of the public API, existing programs +might need to be updated. The following sections describe significant changes +and corresponding updates for existing programs. + +## Parsing and Validation Options + +Under the hood, a new `Validator` struct takes care of validating the claims. A +long awaited feature has been the option to fine-tune the validation of tokens. +This is now possible with several `ParserOption` functions that can be appended +to most `Parse` functions, such as `ParseWithClaims`. The most important options +and changes are: + * Added `WithLeeway` to support specifying the leeway that is allowed when + validating time-based claims, such as `exp` or `nbf`. + * Changed default behavior to not check the `iat` claim. Usage of this claim + is OPTIONAL according to the JWT RFC. The claim itself is also purely + informational according to the RFC, so a strict validation failure is not + recommended. If you want to check for sensible values in these claims, + please use the `WithIssuedAt` parser option. + * Added `WithAudience`, `WithSubject` and `WithIssuer` to support checking for + expected `aud`, `sub` and `iss`. + * Added `WithStrictDecoding` and `WithPaddingAllowed` options to allow + previously global settings to enable base64 strict encoding and the parsing + of base64 strings with padding. The latter is strictly speaking against the + standard, but unfortunately some of the major identity providers issue some + of these incorrect tokens. Both options are disabled by default. + +## Changes to the `Claims` interface + +### Complete Restructuring + +Previously, the claims interface was satisfied with an implementation of a +`Valid() error` function. This had several issues: + * The different claim types (struct claims, map claims, etc.) then contained + similar (but not 100 % identical) code of how this validation was done. This + lead to a lot of (almost) duplicate code and was hard to maintain + * It was not really semantically close to what a "claim" (or a set of claims) + really is; which is a list of defined key/value pairs with a certain + semantic meaning. + +Since all the validation functionality is now extracted into the validator, all +`VerifyXXX` and `Valid` functions have been removed from the `Claims` interface. +Instead, the interface now represents a list of getters to retrieve values with +a specific meaning. This allows us to completely decouple the validation logic +with the underlying storage representation of the claim, which could be a +struct, a map or even something stored in a database. + +```go +type Claims interface { + GetExpirationTime() (*NumericDate, error) + GetIssuedAt() (*NumericDate, error) + GetNotBefore() (*NumericDate, error) + GetIssuer() (string, error) + GetSubject() (string, error) + GetAudience() (ClaimStrings, error) +} +``` + +Users that previously directly called the `Valid` function on their claims, +e.g., to perform validation independently of parsing/verifying a token, can now +use the `jwt.NewValidator` function to create a `Validator` independently of the +`Parser`. + +```go +var v = jwt.NewValidator(jwt.WithLeeway(5*time.Second)) +v.Validate(myClaims) +``` + +### Supported Claim Types and Removal of `StandardClaims` + +The two standard claim types supported by this library, `MapClaims` and +`RegisteredClaims` both implement the necessary functions of this interface. The +old `StandardClaims` struct, which has already been deprecated in `v4` is now +removed. + +Users using custom claims, in most cases, will not experience any changes in the +behavior as long as they embedded `RegisteredClaims`. If they created a new +claim type from scratch, they now need to implemented the proper getter +functions. + +### Migrating Application Specific Logic of the old `Valid` + +Previously, users could override the `Valid` method in a custom claim, for +example to extend the validation with application-specific claims. However, this +was always very dangerous, since once could easily disable the standard +validation and signature checking. + +In order to avoid that, while still supporting the use-case, a new +`ClaimsValidator` interface has been introduced. This interface consists of the +`Validate() error` function. If the validator sees, that a `Claims` struct +implements this interface, the errors returned to the `Validate` function will +be *appended* to the regular standard validation. It is not possible to disable +the standard validation anymore (even only by accident). + +Usage examples can be found in [example_test.go](./example_test.go), to build +claims structs like the following. + +```go +// MyCustomClaims includes all registered claims, plus Foo. +type MyCustomClaims struct { + Foo string `json:"foo"` + jwt.RegisteredClaims +} + +// Validate can be used to execute additional application-specific claims +// validation. +func (m MyCustomClaims) Validate() error { + if m.Foo != "bar" { + return errors.New("must be foobar") + } + + return nil +} +``` + +## Changes to the `Token` and `Parser` struct + +The previously global functions `DecodeSegment` and `EncodeSegment` were moved +to the `Parser` and `Token` struct respectively. This will allow us in the +future to configure the behavior of these two based on options supplied on the +parser or the token (creation). This also removes two previously global +variables and moves them to parser options `WithStrictDecoding` and +`WithPaddingAllowed`. + +In order to do that, we had to adjust the way signing methods work. Previously +they were given a base64 encoded signature in `Verify` and were expected to +return a base64 encoded version of the signature in `Sign`, both as a `string`. +However, this made it necessary to have `DecodeSegment` and `EncodeSegment` +global and was a less than perfect design because we were repeating +encoding/decoding steps for all signing methods. Now, `Sign` and `Verify` +operate on a decoded signature as a `[]byte`, which feels more natural for a +cryptographic operation anyway. Lastly, `Parse` and `SignedString` take care of +the final encoding/decoding part. + +In addition to that, we also changed the `Signature` field on `Token` from a +`string` to `[]byte` and this is also now populated with the decoded form. This +is also more consistent, because the other parts of the JWT, mainly `Header` and +`Claims` were already stored in decoded form in `Token`. Only the signature was +stored in base64 encoded form, which was redundant with the information in the +`Raw` field, which contains the complete token as base64. + +```go +type Token struct { + Raw string // Raw contains the raw token + Method SigningMethod // Method is the signing method used or to be used + Header map[string]interface{} // Header is the first segment of the token in decoded form + Claims Claims // Claims is the second segment of the token in decoded form + Signature []byte // Signature is the third segment of the token in decoded form + Valid bool // Valid specifies if the token is valid +} +``` + +Most (if not all) of these changes should not impact the normal usage of this +library. Only users directly accessing the `Signature` field as well as +developers of custom signing methods should be affected. + +# Migration Guide (v4.0.0) + +Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0), +the import path will be: + + "github.com/golang-jwt/jwt/v4" + +The `/v4` version will be backwards compatible with existing `v3.x.y` tags in +this repo, as well as `github.com/dgrijalva/jwt-go`. For most users this should +be a drop-in replacement, if you're having troubles migrating, please open an +issue. + +You can replace all occurrences of `github.com/dgrijalva/jwt-go` or +`github.com/golang-jwt/jwt` with `github.com/golang-jwt/jwt/v4`, either manually +or by using tools such as `sed` or `gofmt`. + +And then you'd typically run: + +``` +go get github.com/golang-jwt/jwt/v4 +go mod tidy +``` + +# Older releases (before v3.2.0) + +The original migration guide for older releases can be found at +https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md. diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/README.md b/etcd/vendor/github.com/golang-jwt/jwt/v5/README.md new file mode 100644 index 0000000000..0bb636f222 --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/README.md @@ -0,0 +1,167 @@ +# jwt-go + +[![build](https://github.com/golang-jwt/jwt/actions/workflows/build.yml/badge.svg)](https://github.com/golang-jwt/jwt/actions/workflows/build.yml) +[![Go +Reference](https://pkg.go.dev/badge/github.com/golang-jwt/jwt/v5.svg)](https://pkg.go.dev/github.com/golang-jwt/jwt/v5) +[![Coverage Status](https://coveralls.io/repos/github/golang-jwt/jwt/badge.svg?branch=main)](https://coveralls.io/github/golang-jwt/jwt?branch=main) + +A [go](http://www.golang.org) (or 'golang' for search engine friendliness) +implementation of [JSON Web +Tokens](https://datatracker.ietf.org/doc/html/rfc7519). + +Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) +this project adds Go module support, but maintains backward compatibility with +older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`. See the +[`MIGRATION_GUIDE.md`](./MIGRATION_GUIDE.md) for more information. Version +v5.0.0 introduces major improvements to the validation of tokens, but is not +entirely backward compatible. + +> After the original author of the library suggested migrating the maintenance +> of `jwt-go`, a dedicated team of open source maintainers decided to clone the +> existing library into this repository. See +> [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a +> detailed discussion on this topic. + + +**SECURITY NOTICE:** Some older versions of Go have a security issue in the +crypto/elliptic. The recommendation is to upgrade to at least 1.15 See issue +[dgrijalva/jwt-go#216](https://github.com/dgrijalva/jwt-go/issues/216) for more +detail. + +**SECURITY NOTICE:** It's important that you [validate the `alg` presented is +what you +expect](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/). +This library attempts to make it easy to do the right thing by requiring key +types to match the expected alg, but you should take the extra step to verify it in +your usage. See the examples provided. + +### Supported Go versions + +Our support of Go versions is aligned with Go's [version release +policy](https://golang.org/doc/devel/release#policy). So we will support a major +version of Go until there are two newer major releases. We no longer support +building jwt-go with unsupported Go versions, as these contain security +vulnerabilities that will not be fixed. + +## What the heck is a JWT? + +JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web +Tokens. + +In short, it's a signed JSON object that does something useful (for example, +authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is +made of three parts, separated by `.`'s. The first two parts are JSON objects, +that have been [base64url](https://datatracker.ietf.org/doc/html/rfc4648) +encoded. The last part is the signature, encoded the same way. + +The first part is called the header. It contains the necessary information for +verifying the last part, the signature. For example, which encryption method +was used for signing and what key was used. + +The part in the middle is the interesting bit. It's called the Claims and +contains the actual stuff you care about. Refer to [RFC +7519](https://datatracker.ietf.org/doc/html/rfc7519) for information about +reserved keys and the proper way to add your own. + +## What's in the box? + +This library supports the parsing and verification as well as the generation and +signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, +RSA-PSS, and ECDSA, though hooks are present for adding your own. + +## Installation Guidelines + +1. To install the jwt package, you first need to have + [Go](https://go.dev/doc/install) installed, then you can use the command + below to add `jwt-go` as a dependency in your Go program. + +```sh +go get -u github.com/golang-jwt/jwt/v5 +``` + +2. Import it in your code: + +```go +import "github.com/golang-jwt/jwt/v5" +``` + +## Usage + +A detailed usage guide, including how to sign and verify tokens can be found on +our [documentation website](https://golang-jwt.github.io/jwt/usage/create/). + +## Examples + +See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt/v5) +for examples of usage: + +* [Simple example of parsing and validating a + token](https://pkg.go.dev/github.com/golang-jwt/jwt/v5#example-Parse-Hmac) +* [Simple example of building and signing a + token](https://pkg.go.dev/github.com/golang-jwt/jwt/v5#example-New-Hmac) +* [Directory of + Examples](https://pkg.go.dev/github.com/golang-jwt/jwt/v5#pkg-examples) + +## Compliance + +This library was last reviewed to comply with [RFC +7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few +notable differences: + +* In order to protect against accidental use of [Unsecured + JWTs](https://datatracker.ietf.org/doc/html/rfc7519#section-6), tokens using + `alg=none` will only be accepted if the constant + `jwt.UnsafeAllowNoneSignatureType` is provided as the key. + +## Project Status & Versioning + +This library is considered production ready. Feedback and feature requests are +appreciated. The API should be considered stable. There should be very few +backward-incompatible changes outside of major version updates (and only with +good reason). + +This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull +requests will land on `main`. Periodically, versions will be tagged from +`main`. You can find all the releases on [the project releases +page](https://github.com/golang-jwt/jwt/releases). + +**BREAKING CHANGES:** A full list of breaking changes is available in +`VERSION_HISTORY.md`. See [`MIGRATION_GUIDE.md`](./MIGRATION_GUIDE.md) for more information on updating +your code. + +## Extensions + +This library publishes all the necessary components for adding your own signing +methods or key functions. Simply implement the `SigningMethod` interface and +register a factory method using `RegisterSigningMethod` or provide a +`jwt.Keyfunc`. + +A common use case would be integrating with different 3rd party signature +providers, like key management services from various cloud providers or Hardware +Security Modules (HSMs) or to implement additional standards. + +| Extension | Purpose | Repo | +| --------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------ | +| GCP | Integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS) | https://github.com/someone1/gcp-jwt-go | +| AWS | Integrates with AWS Key Management Service, KMS | https://github.com/matelang/jwt-go-aws-kms | +| JWKS | Provides support for JWKS ([RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517)) as a `jwt.Keyfunc` | https://github.com/MicahParks/keyfunc | + +*Disclaimer*: Unless otherwise specified, these integrations are maintained by +third parties and should not be considered as a primary offer by any of the +mentioned cloud providers + +## More + +Go package documentation can be found [on +pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt/v5). Additional +documentation can be found on [our project +page](https://golang-jwt.github.io/jwt/). + +The command line utility included in this project (cmd/jwt) provides a +straightforward example of token creation and parsing as well as a useful tool +for debugging your own integration. You'll also find several implementation +examples in the documentation. + +[golang-jwt](https://github.com/orgs/golang-jwt) incorporates a modified version +of the JWT logo, which is distributed under the terms of the [MIT +License](https://github.com/jsonwebtoken/jsonwebtoken.github.io/blob/master/LICENSE.txt). diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md b/etcd/vendor/github.com/golang-jwt/jwt/v5/SECURITY.md similarity index 59% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md rename to etcd/vendor/github.com/golang-jwt/jwt/v5/SECURITY.md index b08402c342..2740597f17 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/SECURITY.md @@ -2,11 +2,11 @@ ## Supported Versions -As of February 2022 (and until this document is updated), the latest version `v4` is supported. +As of November 2024 (and until this document is updated), the latest version `v5` is supported. In critical cases, we might supply back-ported patches for `v4`. ## Reporting a Vulnerability -If you think you found a vulnerability, and even if you are not sure, please report it to jwt-go-security@googlegroups.com or one of the other [golang-jwt maintainers](https://github.com/orgs/golang-jwt/people). Please try be explicit, describe steps to reproduce the security issue with code example(s). +If you think you found a vulnerability, and even if you are not sure, please report it a [GitHub Security Advisory](https://github.com/golang-jwt/jwt/security/advisories/new). Please try be explicit, describe steps to reproduce the security issue with code example(s). You will receive a response within a timely manner. If the issue is confirmed, we will do our best to release a patch as soon as possible given the complexity of the problem. diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md b/etcd/vendor/github.com/golang-jwt/jwt/v5/VERSION_HISTORY.md similarity index 96% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md rename to etcd/vendor/github.com/golang-jwt/jwt/v5/VERSION_HISTORY.md index afbfc4e408..b5039e49c1 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/VERSION_HISTORY.md @@ -1,17 +1,19 @@ -## `jwt-go` Version History +# `jwt-go` Version History -#### 4.0.0 +The following version history is kept for historic purposes. To retrieve the current changes of each version, please refer to the change-log of the specific release versions on https://github.com/golang-jwt/jwt/releases. + +## 4.0.0 * Introduces support for Go modules. The `v4` version will be backwards compatible with `v3.x.y`. -#### 3.2.2 +## 3.2.2 * Starting from this release, we are adopting the policy to support the most 2 recent versions of Go currently available. By the time of this release, this is Go 1.15 and 1.16 ([#28](https://github.com/golang-jwt/jwt/pull/28)). * Fixed a potential issue that could occur when the verification of `exp`, `iat` or `nbf` was not required and contained invalid contents, i.e. non-numeric/date. Thanks for @thaJeztah for making us aware of that and @giorgos-f3 for originally reporting it to the formtech fork ([#40](https://github.com/golang-jwt/jwt/pull/40)). * Added support for EdDSA / ED25519 ([#36](https://github.com/golang-jwt/jwt/pull/36)). * Optimized allocations ([#33](https://github.com/golang-jwt/jwt/pull/33)). -#### 3.2.1 +## 3.2.1 * **Import Path Change**: See MIGRATION_GUIDE.md for tips on updating your code * Changed the import path from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt` @@ -117,17 +119,17 @@ It is likely the only integration change required here will be to change `func(t * Refactored the RSA implementation to be easier to read * Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` -#### 1.0.2 +## 1.0.2 * Fixed bug in parsing public keys from certificates * Added more tests around the parsing of keys for RS256 * Code refactoring in RS256 implementation. No functional changes -#### 1.0.1 +## 1.0.1 * Fixed panic if RS256 signing method was passed an invalid key -#### 1.0.0 +## 1.0.0 * First versioned release * API stabilized diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/claims.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/claims.go new file mode 100644 index 0000000000..d50ff3dad8 --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/claims.go @@ -0,0 +1,16 @@ +package jwt + +// Claims represent any form of a JWT Claims Set according to +// https://datatracker.ietf.org/doc/html/rfc7519#section-4. In order to have a +// common basis for validation, it is required that an implementation is able to +// supply at least the claim names provided in +// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1 namely `exp`, +// `iat`, `nbf`, `iss`, `sub` and `aud`. +type Claims interface { + GetExpirationTime() (*NumericDate, error) + GetIssuedAt() (*NumericDate, error) + GetNotBefore() (*NumericDate, error) + GetIssuer() (string, error) + GetSubject() (string, error) + GetAudience() (ClaimStrings, error) +} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/doc.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/doc.go similarity index 100% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/doc.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/doc.go diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/ecdsa.go similarity index 88% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/ecdsa.go index eac023fc6c..c929e4a02f 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/ecdsa.go @@ -55,22 +55,14 @@ func (m *SigningMethodECDSA) Alg() string { // Verify implements token verification for the SigningMethod. // For this verify method, key must be an ecdsa.PublicKey struct -func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - +func (m *SigningMethodECDSA) Verify(signingString string, sig []byte, key interface{}) error { // Get the key var ecdsaKey *ecdsa.PublicKey switch k := key.(type) { case *ecdsa.PublicKey: ecdsaKey = k default: - return ErrInvalidKeyType + return newError("ECDSA verify expects *ecdsa.PublicKey", ErrInvalidKeyType) } if len(sig) != 2*m.KeySize { @@ -97,19 +89,19 @@ func (m *SigningMethodECDSA) Verify(signingString, signature string, key interfa // Sign implements token signing for the SigningMethod. // For this signing method, key must be an ecdsa.PrivateKey struct -func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { +func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) ([]byte, error) { // Get the key var ecdsaKey *ecdsa.PrivateKey switch k := key.(type) { case *ecdsa.PrivateKey: ecdsaKey = k default: - return "", ErrInvalidKeyType + return nil, newError("ECDSA sign expects *ecdsa.PrivateKey", ErrInvalidKeyType) } // Create the hasher if !m.Hash.Available() { - return "", ErrHashUnavailable + return nil, ErrHashUnavailable } hasher := m.Hash.New() @@ -120,7 +112,7 @@ func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string curveBits := ecdsaKey.Curve.Params().BitSize if m.CurveBits != curveBits { - return "", ErrInvalidKey + return nil, ErrInvalidKey } keyBytes := curveBits / 8 @@ -135,8 +127,8 @@ func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string r.FillBytes(out[0:keyBytes]) // r is assigned to the first half of output. s.FillBytes(out[keyBytes:]) // s is assigned to the second half of output. - return EncodeSegment(out), nil + return out, nil } else { - return "", err + return nil, err } } diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/ecdsa_utils.go similarity index 100% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/ecdsa_utils.go diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/ed25519.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/ed25519.go similarity index 71% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/ed25519.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/ed25519.go index 07d3aacd63..c2138119e5 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/ed25519.go +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/ed25519.go @@ -1,11 +1,10 @@ package jwt import ( - "errors" - "crypto" "crypto/ed25519" "crypto/rand" + "errors" ) var ( @@ -34,25 +33,18 @@ func (m *SigningMethodEd25519) Alg() string { // Verify implements token verification for the SigningMethod. // For this verify method, key must be an ed25519.PublicKey -func (m *SigningMethodEd25519) Verify(signingString, signature string, key interface{}) error { - var err error +func (m *SigningMethodEd25519) Verify(signingString string, sig []byte, key interface{}) error { var ed25519Key ed25519.PublicKey var ok bool if ed25519Key, ok = key.(ed25519.PublicKey); !ok { - return ErrInvalidKeyType + return newError("Ed25519 verify expects ed25519.PublicKey", ErrInvalidKeyType) } if len(ed25519Key) != ed25519.PublicKeySize { return ErrInvalidKey } - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - // Verify the signature if !ed25519.Verify(ed25519Key, []byte(signingString), sig) { return ErrEd25519Verification @@ -63,23 +55,25 @@ func (m *SigningMethodEd25519) Verify(signingString, signature string, key inter // Sign implements token signing for the SigningMethod. // For this signing method, key must be an ed25519.PrivateKey -func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) { +func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) ([]byte, error) { var ed25519Key crypto.Signer var ok bool if ed25519Key, ok = key.(crypto.Signer); !ok { - return "", ErrInvalidKeyType + return nil, newError("Ed25519 sign expects crypto.Signer", ErrInvalidKeyType) } if _, ok := ed25519Key.Public().(ed25519.PublicKey); !ok { - return "", ErrInvalidKey + return nil, ErrInvalidKey } - // Sign the string and return the encoded result - // ed25519 performs a two-pass hash as part of its algorithm. Therefore, we need to pass a non-prehashed message into the Sign function, as indicated by crypto.Hash(0) + // Sign the string and return the result. ed25519 performs a two-pass hash + // as part of its algorithm. Therefore, we need to pass a non-prehashed + // message into the Sign function, as indicated by crypto.Hash(0) sig, err := ed25519Key.Sign(rand.Reader, []byte(signingString), crypto.Hash(0)) if err != nil { - return "", err + return nil, err } - return EncodeSegment(sig), nil + + return sig, nil } diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/ed25519_utils.go similarity index 100% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/ed25519_utils.go diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/errors.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/errors.go new file mode 100644 index 0000000000..23bb616ddd --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/errors.go @@ -0,0 +1,49 @@ +package jwt + +import ( + "errors" + "strings" +) + +var ( + ErrInvalidKey = errors.New("key is invalid") + ErrInvalidKeyType = errors.New("key is of invalid type") + ErrHashUnavailable = errors.New("the requested hash function is unavailable") + ErrTokenMalformed = errors.New("token is malformed") + ErrTokenUnverifiable = errors.New("token is unverifiable") + ErrTokenSignatureInvalid = errors.New("token signature is invalid") + ErrTokenRequiredClaimMissing = errors.New("token is missing required claim") + ErrTokenInvalidAudience = errors.New("token has invalid audience") + ErrTokenExpired = errors.New("token is expired") + ErrTokenUsedBeforeIssued = errors.New("token used before issued") + ErrTokenInvalidIssuer = errors.New("token has invalid issuer") + ErrTokenInvalidSubject = errors.New("token has invalid subject") + ErrTokenNotValidYet = errors.New("token is not valid yet") + ErrTokenInvalidId = errors.New("token has invalid id") + ErrTokenInvalidClaims = errors.New("token has invalid claims") + ErrInvalidType = errors.New("invalid type for claim") +) + +// joinedError is an error type that works similar to what [errors.Join] +// produces, with the exception that it has a nice error string; mainly its +// error messages are concatenated using a comma, rather than a newline. +type joinedError struct { + errs []error +} + +func (je joinedError) Error() string { + msg := []string{} + for _, err := range je.errs { + msg = append(msg, err.Error()) + } + + return strings.Join(msg, ", ") +} + +// joinErrors joins together multiple errors. Useful for scenarios where +// multiple errors next to each other occur, e.g., in claims validation. +func joinErrors(errs ...error) error { + return &joinedError{ + errs: errs, + } +} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/errors_go1_20.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/errors_go1_20.go new file mode 100644 index 0000000000..a893d355e1 --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/errors_go1_20.go @@ -0,0 +1,47 @@ +//go:build go1.20 +// +build go1.20 + +package jwt + +import ( + "fmt" +) + +// Unwrap implements the multiple error unwrapping for this error type, which is +// possible in Go 1.20. +func (je joinedError) Unwrap() []error { + return je.errs +} + +// newError creates a new error message with a detailed error message. The +// message will be prefixed with the contents of the supplied error type. +// Additionally, more errors, that provide more context can be supplied which +// will be appended to the message. This makes use of Go 1.20's possibility to +// include more than one %w formatting directive in [fmt.Errorf]. +// +// For example, +// +// newError("no keyfunc was provided", ErrTokenUnverifiable) +// +// will produce the error string +// +// "token is unverifiable: no keyfunc was provided" +func newError(message string, err error, more ...error) error { + var format string + var args []any + if message != "" { + format = "%w: %s" + args = []any{err, message} + } else { + format = "%w" + args = []any{err} + } + + for _, e := range more { + format += ": %w" + args = append(args, e) + } + + err = fmt.Errorf(format, args...) + return err +} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/errors_go_other.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/errors_go_other.go new file mode 100644 index 0000000000..2ad542f00c --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/errors_go_other.go @@ -0,0 +1,78 @@ +//go:build !go1.20 +// +build !go1.20 + +package jwt + +import ( + "errors" + "fmt" +) + +// Is implements checking for multiple errors using [errors.Is], since multiple +// error unwrapping is not possible in versions less than Go 1.20. +func (je joinedError) Is(err error) bool { + for _, e := range je.errs { + if errors.Is(e, err) { + return true + } + } + + return false +} + +// wrappedErrors is a workaround for wrapping multiple errors in environments +// where Go 1.20 is not available. It basically uses the already implemented +// functionality of joinedError to handle multiple errors with supplies a +// custom error message that is identical to the one we produce in Go 1.20 using +// multiple %w directives. +type wrappedErrors struct { + msg string + joinedError +} + +// Error returns the stored error string +func (we wrappedErrors) Error() string { + return we.msg +} + +// newError creates a new error message with a detailed error message. The +// message will be prefixed with the contents of the supplied error type. +// Additionally, more errors, that provide more context can be supplied which +// will be appended to the message. Since we cannot use of Go 1.20's possibility +// to include more than one %w formatting directive in [fmt.Errorf], we have to +// emulate that. +// +// For example, +// +// newError("no keyfunc was provided", ErrTokenUnverifiable) +// +// will produce the error string +// +// "token is unverifiable: no keyfunc was provided" +func newError(message string, err error, more ...error) error { + // We cannot wrap multiple errors here with %w, so we have to be a little + // bit creative. Basically, we are using %s instead of %w to produce the + // same error message and then throw the result into a custom error struct. + var format string + var args []any + if message != "" { + format = "%s: %s" + args = []any{err, message} + } else { + format = "%s" + args = []any{err} + } + errs := []error{err} + + for _, e := range more { + format += ": %s" + args = append(args, e) + errs = append(errs, e) + } + + err = &wrappedErrors{ + msg: fmt.Sprintf(format, args...), + joinedError: joinedError{errs: errs}, + } + return err +} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/hmac.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/hmac.go similarity index 57% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/hmac.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/hmac.go index 011f68a274..aca600ce1b 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/hmac.go +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/hmac.go @@ -45,18 +45,21 @@ func (m *SigningMethodHMAC) Alg() string { return m.Name } -// Verify implements token verification for the SigningMethod. Returns nil if the signature is valid. -func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error { +// Verify implements token verification for the SigningMethod. Returns nil if +// the signature is valid. Key must be []byte. +// +// Note it is not advised to provide a []byte which was converted from a 'human +// readable' string using a subset of ASCII characters. To maximize entropy, you +// should ideally be providing a []byte key which was produced from a +// cryptographically random source, e.g. crypto/rand. Additional information +// about this, and why we intentionally are not supporting string as a key can +// be found on our usage guide +// https://golang-jwt.github.io/jwt/usage/signing_methods/#signing-methods-and-key-types. +func (m *SigningMethodHMAC) Verify(signingString string, sig []byte, key interface{}) error { // Verify the key is the right type keyBytes, ok := key.([]byte) if !ok { - return ErrInvalidKeyType - } - - // Decode signature, for comparison - sig, err := DecodeSegment(signature) - if err != nil { - return err + return newError("HMAC verify expects []byte", ErrInvalidKeyType) } // Can we use the specified hashing method? @@ -77,19 +80,25 @@ func (m *SigningMethodHMAC) Verify(signingString, signature string, key interfac return nil } -// Sign implements token signing for the SigningMethod. -// Key must be []byte -func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) { +// Sign implements token signing for the SigningMethod. Key must be []byte. +// +// Note it is not advised to provide a []byte which was converted from a 'human +// readable' string using a subset of ASCII characters. To maximize entropy, you +// should ideally be providing a []byte key which was produced from a +// cryptographically random source, e.g. crypto/rand. Additional information +// about this, and why we intentionally are not supporting string as a key can +// be found on our usage guide https://golang-jwt.github.io/jwt/usage/signing_methods/. +func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) ([]byte, error) { if keyBytes, ok := key.([]byte); ok { if !m.Hash.Available() { - return "", ErrHashUnavailable + return nil, ErrHashUnavailable } hasher := hmac.New(m.Hash.New, keyBytes) hasher.Write([]byte(signingString)) - return EncodeSegment(hasher.Sum(nil)), nil + return hasher.Sum(nil), nil } - return "", ErrInvalidKeyType + return nil, newError("HMAC sign expects []byte", ErrInvalidKeyType) } diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/map_claims.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/map_claims.go new file mode 100644 index 0000000000..b2b51a1f80 --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/map_claims.go @@ -0,0 +1,109 @@ +package jwt + +import ( + "encoding/json" + "fmt" +) + +// MapClaims is a claims type that uses the map[string]interface{} for JSON +// decoding. This is the default claims type if you don't supply one +type MapClaims map[string]interface{} + +// GetExpirationTime implements the Claims interface. +func (m MapClaims) GetExpirationTime() (*NumericDate, error) { + return m.parseNumericDate("exp") +} + +// GetNotBefore implements the Claims interface. +func (m MapClaims) GetNotBefore() (*NumericDate, error) { + return m.parseNumericDate("nbf") +} + +// GetIssuedAt implements the Claims interface. +func (m MapClaims) GetIssuedAt() (*NumericDate, error) { + return m.parseNumericDate("iat") +} + +// GetAudience implements the Claims interface. +func (m MapClaims) GetAudience() (ClaimStrings, error) { + return m.parseClaimsString("aud") +} + +// GetIssuer implements the Claims interface. +func (m MapClaims) GetIssuer() (string, error) { + return m.parseString("iss") +} + +// GetSubject implements the Claims interface. +func (m MapClaims) GetSubject() (string, error) { + return m.parseString("sub") +} + +// parseNumericDate tries to parse a key in the map claims type as a number +// date. This will succeed, if the underlying type is either a [float64] or a +// [json.Number]. Otherwise, nil will be returned. +func (m MapClaims) parseNumericDate(key string) (*NumericDate, error) { + v, ok := m[key] + if !ok { + return nil, nil + } + + switch exp := v.(type) { + case float64: + if exp == 0 { + return nil, nil + } + + return newNumericDateFromSeconds(exp), nil + case json.Number: + v, _ := exp.Float64() + + return newNumericDateFromSeconds(v), nil + } + + return nil, newError(fmt.Sprintf("%s is invalid", key), ErrInvalidType) +} + +// parseClaimsString tries to parse a key in the map claims type as a +// [ClaimsStrings] type, which can either be a string or an array of string. +func (m MapClaims) parseClaimsString(key string) (ClaimStrings, error) { + var cs []string + switch v := m[key].(type) { + case string: + cs = append(cs, v) + case []string: + cs = v + case []interface{}: + for _, a := range v { + vs, ok := a.(string) + if !ok { + return nil, newError(fmt.Sprintf("%s is invalid", key), ErrInvalidType) + } + cs = append(cs, vs) + } + } + + return cs, nil +} + +// parseString tries to parse a key in the map claims type as a [string] type. +// If the key does not exist, an empty string is returned. If the key has the +// wrong type, an error is returned. +func (m MapClaims) parseString(key string) (string, error) { + var ( + ok bool + raw interface{} + iss string + ) + raw, ok = m[key] + if !ok { + return "", nil + } + + iss, ok = raw.(string) + if !ok { + return "", newError(fmt.Sprintf("%s is invalid", key), ErrInvalidType) + } + + return iss, nil +} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/none.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/none.go similarity index 72% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/none.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/none.go index f19835d207..685c2ea306 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/none.go +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/none.go @@ -13,7 +13,7 @@ type unsafeNoneMagicConstant string func init() { SigningMethodNone = &signingMethodNone{} - NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid) + NoneSignatureTypeDisallowedError = newError("'none' signature type is not allowed", ErrTokenUnverifiable) RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod { return SigningMethodNone @@ -25,18 +25,15 @@ func (m *signingMethodNone) Alg() string { } // Only allow 'none' alg type if UnsafeAllowNoneSignatureType is specified as the key -func (m *signingMethodNone) Verify(signingString, signature string, key interface{}) (err error) { +func (m *signingMethodNone) Verify(signingString string, sig []byte, key interface{}) (err error) { // Key must be UnsafeAllowNoneSignatureType to prevent accidentally // accepting 'none' signing method if _, ok := key.(unsafeNoneMagicConstant); !ok { return NoneSignatureTypeDisallowedError } // If signing method is none, signature must be an empty string - if signature != "" { - return NewValidationError( - "'none' signing method with non-empty signature", - ValidationErrorSignatureInvalid, - ) + if len(sig) != 0 { + return newError("'none' signing method with non-empty signature", ErrTokenUnverifiable) } // Accept 'none' signing method. @@ -44,9 +41,10 @@ func (m *signingMethodNone) Verify(signingString, signature string, key interfac } // Only allow 'none' signing if UnsafeAllowNoneSignatureType is specified as the key -func (m *signingMethodNone) Sign(signingString string, key interface{}) (string, error) { +func (m *signingMethodNone) Sign(signingString string, key interface{}) ([]byte, error) { if _, ok := key.(unsafeNoneMagicConstant); ok { - return "", nil + return []byte{}, nil } - return "", NoneSignatureTypeDisallowedError + + return nil, NoneSignatureTypeDisallowedError } diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/parser.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/parser.go new file mode 100644 index 0000000000..054c7eb6ff --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/parser.go @@ -0,0 +1,268 @@ +package jwt + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "fmt" + "strings" +) + +const tokenDelimiter = "." + +type Parser struct { + // If populated, only these methods will be considered valid. + validMethods []string + + // Use JSON Number format in JSON decoder. + useJSONNumber bool + + // Skip claims validation during token parsing. + skipClaimsValidation bool + + validator *Validator + + decodeStrict bool + + decodePaddingAllowed bool +} + +// NewParser creates a new Parser with the specified options +func NewParser(options ...ParserOption) *Parser { + p := &Parser{ + validator: &Validator{}, + } + + // Loop through our parsing options and apply them + for _, option := range options { + option(p) + } + + return p +} + +// Parse parses, validates, verifies the signature and returns the parsed token. +// keyFunc will receive the parsed token and should return the key for validating. +func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { + return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) +} + +// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object implementing the Claims +// interface. This provides default values which can be overridden and allows a caller to use their own type, rather +// than the default MapClaims implementation of Claims. +// +// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims), +// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the +// proper memory for it before passing in the overall claims, otherwise you might run into a panic. +func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { + token, parts, err := p.ParseUnverified(tokenString, claims) + if err != nil { + return token, err + } + + // Verify signing method is in the required set + if p.validMethods != nil { + var signingMethodValid = false + var alg = token.Method.Alg() + for _, m := range p.validMethods { + if m == alg { + signingMethodValid = true + break + } + } + if !signingMethodValid { + // signing method is not in the listed set + return token, newError(fmt.Sprintf("signing method %v is invalid", alg), ErrTokenSignatureInvalid) + } + } + + // Decode signature + token.Signature, err = p.DecodeSegment(parts[2]) + if err != nil { + return token, newError("could not base64 decode signature", ErrTokenMalformed, err) + } + text := strings.Join(parts[0:2], ".") + + // Lookup key(s) + if keyFunc == nil { + // keyFunc was not provided. short circuiting validation + return token, newError("no keyfunc was provided", ErrTokenUnverifiable) + } + + got, err := keyFunc(token) + if err != nil { + return token, newError("error while executing keyfunc", ErrTokenUnverifiable, err) + } + + switch have := got.(type) { + case VerificationKeySet: + if len(have.Keys) == 0 { + return token, newError("keyfunc returned empty verification key set", ErrTokenUnverifiable) + } + // Iterate through keys and verify signature, skipping the rest when a match is found. + // Return the last error if no match is found. + for _, key := range have.Keys { + if err = token.Method.Verify(text, token.Signature, key); err == nil { + break + } + } + default: + err = token.Method.Verify(text, token.Signature, have) + } + if err != nil { + return token, newError("", ErrTokenSignatureInvalid, err) + } + + // Validate Claims + if !p.skipClaimsValidation { + // Make sure we have at least a default validator + if p.validator == nil { + p.validator = NewValidator() + } + + if err := p.validator.Validate(claims); err != nil { + return token, newError("", ErrTokenInvalidClaims, err) + } + } + + // No errors so far, token is valid. + token.Valid = true + + return token, nil +} + +// ParseUnverified parses the token but doesn't validate the signature. +// +// WARNING: Don't use this method unless you know what you're doing. +// +// It's only ever useful in cases where you know the signature is valid (since it has already +// been or will be checked elsewhere in the stack) and you want to extract values from it. +func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) { + var ok bool + parts, ok = splitToken(tokenString) + if !ok { + return nil, nil, newError("token contains an invalid number of segments", ErrTokenMalformed) + } + + token = &Token{Raw: tokenString} + + // parse Header + var headerBytes []byte + if headerBytes, err = p.DecodeSegment(parts[0]); err != nil { + return token, parts, newError("could not base64 decode header", ErrTokenMalformed, err) + } + if err = json.Unmarshal(headerBytes, &token.Header); err != nil { + return token, parts, newError("could not JSON decode header", ErrTokenMalformed, err) + } + + // parse Claims + token.Claims = claims + + claimBytes, err := p.DecodeSegment(parts[1]) + if err != nil { + return token, parts, newError("could not base64 decode claim", ErrTokenMalformed, err) + } + + // If `useJSONNumber` is enabled then we must use *json.Decoder to decode + // the claims. However, this comes with a performance penalty so only use + // it if we must and, otherwise, simple use json.Unmarshal. + if !p.useJSONNumber { + // JSON Unmarshal. Special case for map type to avoid weird pointer behavior. + if c, ok := token.Claims.(MapClaims); ok { + err = json.Unmarshal(claimBytes, &c) + } else { + err = json.Unmarshal(claimBytes, &claims) + } + } else { + dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) + dec.UseNumber() + // JSON Decode. Special case for map type to avoid weird pointer behavior. + if c, ok := token.Claims.(MapClaims); ok { + err = dec.Decode(&c) + } else { + err = dec.Decode(&claims) + } + } + if err != nil { + return token, parts, newError("could not JSON decode claim", ErrTokenMalformed, err) + } + + // Lookup signature method + if method, ok := token.Header["alg"].(string); ok { + if token.Method = GetSigningMethod(method); token.Method == nil { + return token, parts, newError("signing method (alg) is unavailable", ErrTokenUnverifiable) + } + } else { + return token, parts, newError("signing method (alg) is unspecified", ErrTokenUnverifiable) + } + + return token, parts, nil +} + +// splitToken splits a token string into three parts: header, claims, and signature. It will only +// return true if the token contains exactly two delimiters and three parts. In all other cases, it +// will return nil parts and false. +func splitToken(token string) ([]string, bool) { + parts := make([]string, 3) + header, remain, ok := strings.Cut(token, tokenDelimiter) + if !ok { + return nil, false + } + parts[0] = header + claims, remain, ok := strings.Cut(remain, tokenDelimiter) + if !ok { + return nil, false + } + parts[1] = claims + // One more cut to ensure the signature is the last part of the token and there are no more + // delimiters. This avoids an issue where malicious input could contain additional delimiters + // causing unecessary overhead parsing tokens. + signature, _, unexpected := strings.Cut(remain, tokenDelimiter) + if unexpected { + return nil, false + } + parts[2] = signature + + return parts, true +} + +// DecodeSegment decodes a JWT specific base64url encoding. This function will +// take into account whether the [Parser] is configured with additional options, +// such as [WithStrictDecoding] or [WithPaddingAllowed]. +func (p *Parser) DecodeSegment(seg string) ([]byte, error) { + encoding := base64.RawURLEncoding + + if p.decodePaddingAllowed { + if l := len(seg) % 4; l > 0 { + seg += strings.Repeat("=", 4-l) + } + encoding = base64.URLEncoding + } + + if p.decodeStrict { + encoding = encoding.Strict() + } + return encoding.DecodeString(seg) +} + +// Parse parses, validates, verifies the signature and returns the parsed token. +// keyFunc will receive the parsed token and should return the cryptographic key +// for verifying the signature. The caller is strongly encouraged to set the +// WithValidMethods option to validate the 'alg' claim in the token matches the +// expected algorithm. For more details about the importance of validating the +// 'alg' claim, see +// https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/ +func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { + return NewParser(options...).Parse(tokenString, keyFunc) +} + +// ParseWithClaims is a shortcut for NewParser().ParseWithClaims(). +// +// Note: If you provide a custom claim implementation that embeds one of the +// standard claims (such as RegisteredClaims), make sure that a) you either +// embed a non-pointer version of the claims or b) if you are using a pointer, +// allocate the proper memory for it before passing in the overall claims, +// otherwise you might run into a panic. +func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { + return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc) +} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/parser_option.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/parser_option.go new file mode 100644 index 0000000000..88a780fbd4 --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/parser_option.go @@ -0,0 +1,128 @@ +package jwt + +import "time" + +// ParserOption is used to implement functional-style options that modify the +// behavior of the parser. To add new options, just create a function (ideally +// beginning with With or Without) that returns an anonymous function that takes +// a *Parser type as input and manipulates its configuration accordingly. +type ParserOption func(*Parser) + +// WithValidMethods is an option to supply algorithm methods that the parser +// will check. Only those methods will be considered valid. It is heavily +// encouraged to use this option in order to prevent attacks such as +// https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/. +func WithValidMethods(methods []string) ParserOption { + return func(p *Parser) { + p.validMethods = methods + } +} + +// WithJSONNumber is an option to configure the underlying JSON parser with +// UseNumber. +func WithJSONNumber() ParserOption { + return func(p *Parser) { + p.useJSONNumber = true + } +} + +// WithoutClaimsValidation is an option to disable claims validation. This +// option should only be used if you exactly know what you are doing. +func WithoutClaimsValidation() ParserOption { + return func(p *Parser) { + p.skipClaimsValidation = true + } +} + +// WithLeeway returns the ParserOption for specifying the leeway window. +func WithLeeway(leeway time.Duration) ParserOption { + return func(p *Parser) { + p.validator.leeway = leeway + } +} + +// WithTimeFunc returns the ParserOption for specifying the time func. The +// primary use-case for this is testing. If you are looking for a way to account +// for clock-skew, WithLeeway should be used instead. +func WithTimeFunc(f func() time.Time) ParserOption { + return func(p *Parser) { + p.validator.timeFunc = f + } +} + +// WithIssuedAt returns the ParserOption to enable verification +// of issued-at. +func WithIssuedAt() ParserOption { + return func(p *Parser) { + p.validator.verifyIat = true + } +} + +// WithExpirationRequired returns the ParserOption to make exp claim required. +// By default exp claim is optional. +func WithExpirationRequired() ParserOption { + return func(p *Parser) { + p.validator.requireExp = true + } +} + +// WithAudience configures the validator to require the specified audience in +// the `aud` claim. Validation will fail if the audience is not listed in the +// token or the `aud` claim is missing. +// +// NOTE: While the `aud` claim is OPTIONAL in a JWT, the handling of it is +// application-specific. Since this validation API is helping developers in +// writing secure application, we decided to REQUIRE the existence of the claim, +// if an audience is expected. +func WithAudience(aud string) ParserOption { + return func(p *Parser) { + p.validator.expectedAud = aud + } +} + +// WithIssuer configures the validator to require the specified issuer in the +// `iss` claim. Validation will fail if a different issuer is specified in the +// token or the `iss` claim is missing. +// +// NOTE: While the `iss` claim is OPTIONAL in a JWT, the handling of it is +// application-specific. Since this validation API is helping developers in +// writing secure application, we decided to REQUIRE the existence of the claim, +// if an issuer is expected. +func WithIssuer(iss string) ParserOption { + return func(p *Parser) { + p.validator.expectedIss = iss + } +} + +// WithSubject configures the validator to require the specified subject in the +// `sub` claim. Validation will fail if a different subject is specified in the +// token or the `sub` claim is missing. +// +// NOTE: While the `sub` claim is OPTIONAL in a JWT, the handling of it is +// application-specific. Since this validation API is helping developers in +// writing secure application, we decided to REQUIRE the existence of the claim, +// if a subject is expected. +func WithSubject(sub string) ParserOption { + return func(p *Parser) { + p.validator.expectedSub = sub + } +} + +// WithPaddingAllowed will enable the codec used for decoding JWTs to allow +// padding. Note that the JWS RFC7515 states that the tokens will utilize a +// Base64url encoding with no padding. Unfortunately, some implementations of +// JWT are producing non-standard tokens, and thus require support for decoding. +func WithPaddingAllowed() ParserOption { + return func(p *Parser) { + p.decodePaddingAllowed = true + } +} + +// WithStrictDecoding will switch the codec used for decoding JWTs into strict +// mode. In this mode, the decoder requires that trailing padding bits are zero, +// as described in RFC 4648 section 3.5. +func WithStrictDecoding() ParserOption { + return func(p *Parser) { + p.decodeStrict = true + } +} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/registered_claims.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/registered_claims.go new file mode 100644 index 0000000000..77951a531d --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/registered_claims.go @@ -0,0 +1,63 @@ +package jwt + +// RegisteredClaims are a structured version of the JWT Claims Set, +// restricted to Registered Claim Names, as referenced at +// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1 +// +// This type can be used on its own, but then additional private and +// public claims embedded in the JWT will not be parsed. The typical use-case +// therefore is to embedded this in a user-defined claim type. +// +// See examples for how to use this with your own claim types. +type RegisteredClaims struct { + // the `iss` (Issuer) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1 + Issuer string `json:"iss,omitempty"` + + // the `sub` (Subject) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2 + Subject string `json:"sub,omitempty"` + + // the `aud` (Audience) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3 + Audience ClaimStrings `json:"aud,omitempty"` + + // the `exp` (Expiration Time) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4 + ExpiresAt *NumericDate `json:"exp,omitempty"` + + // the `nbf` (Not Before) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5 + NotBefore *NumericDate `json:"nbf,omitempty"` + + // the `iat` (Issued At) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6 + IssuedAt *NumericDate `json:"iat,omitempty"` + + // the `jti` (JWT ID) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7 + ID string `json:"jti,omitempty"` +} + +// GetExpirationTime implements the Claims interface. +func (c RegisteredClaims) GetExpirationTime() (*NumericDate, error) { + return c.ExpiresAt, nil +} + +// GetNotBefore implements the Claims interface. +func (c RegisteredClaims) GetNotBefore() (*NumericDate, error) { + return c.NotBefore, nil +} + +// GetIssuedAt implements the Claims interface. +func (c RegisteredClaims) GetIssuedAt() (*NumericDate, error) { + return c.IssuedAt, nil +} + +// GetAudience implements the Claims interface. +func (c RegisteredClaims) GetAudience() (ClaimStrings, error) { + return c.Audience, nil +} + +// GetIssuer implements the Claims interface. +func (c RegisteredClaims) GetIssuer() (string, error) { + return c.Issuer, nil +} + +// GetSubject implements the Claims interface. +func (c RegisteredClaims) GetSubject() (string, error) { + return c.Subject, nil +} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/rsa.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/rsa.go similarity index 84% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/rsa.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/rsa.go index b910b19c0b..83cbee6ae2 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/rsa.go +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/rsa.go @@ -46,20 +46,12 @@ func (m *SigningMethodRSA) Alg() string { // Verify implements token verification for the SigningMethod // For this signing method, must be an *rsa.PublicKey structure. -func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - +func (m *SigningMethodRSA) Verify(signingString string, sig []byte, key interface{}) error { var rsaKey *rsa.PublicKey var ok bool if rsaKey, ok = key.(*rsa.PublicKey); !ok { - return ErrInvalidKeyType + return newError("RSA verify expects *rsa.PublicKey", ErrInvalidKeyType) } // Create hasher @@ -75,18 +67,18 @@ func (m *SigningMethodRSA) Verify(signingString, signature string, key interface // Sign implements token signing for the SigningMethod // For this signing method, must be an *rsa.PrivateKey structure. -func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) { +func (m *SigningMethodRSA) Sign(signingString string, key interface{}) ([]byte, error) { var rsaKey *rsa.PrivateKey var ok bool // Validate type of key if rsaKey, ok = key.(*rsa.PrivateKey); !ok { - return "", ErrInvalidKey + return nil, newError("RSA sign expects *rsa.PrivateKey", ErrInvalidKeyType) } // Create the hasher if !m.Hash.Available() { - return "", ErrHashUnavailable + return nil, ErrHashUnavailable } hasher := m.Hash.New() @@ -94,8 +86,8 @@ func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, // Sign the string and return the encoded bytes if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil { - return EncodeSegment(sigBytes), nil + return sigBytes, nil } else { - return "", err + return nil, err } } diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/rsa_pss.go similarity index 88% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/rsa_pss.go index 4fd6f9e610..28c386ec43 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/rsa_pss.go @@ -82,21 +82,13 @@ func init() { // Verify implements token verification for the SigningMethod. // For this verify method, key must be an rsa.PublicKey struct -func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { - var err error - - // Decode the signature - var sig []byte - if sig, err = DecodeSegment(signature); err != nil { - return err - } - +func (m *SigningMethodRSAPSS) Verify(signingString string, sig []byte, key interface{}) error { var rsaKey *rsa.PublicKey switch k := key.(type) { case *rsa.PublicKey: rsaKey = k default: - return ErrInvalidKey + return newError("RSA-PSS verify expects *rsa.PublicKey", ErrInvalidKeyType) } // Create hasher @@ -116,19 +108,19 @@ func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interf // Sign implements token signing for the SigningMethod. // For this signing method, key must be an rsa.PrivateKey struct -func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { +func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) ([]byte, error) { var rsaKey *rsa.PrivateKey switch k := key.(type) { case *rsa.PrivateKey: rsaKey = k default: - return "", ErrInvalidKeyType + return nil, newError("RSA-PSS sign expects *rsa.PrivateKey", ErrInvalidKeyType) } // Create the hasher if !m.Hash.Available() { - return "", ErrHashUnavailable + return nil, ErrHashUnavailable } hasher := m.Hash.New() @@ -136,8 +128,8 @@ func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (strin // Sign the string and return the encoded bytes if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { - return EncodeSegment(sigBytes), nil + return sigBytes, nil } else { - return "", err + return nil, err } } diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/rsa_utils.go similarity index 93% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/rsa_utils.go index 1966c450bf..b3aeebbe11 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/rsa_utils.go @@ -75,7 +75,7 @@ func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.Pr return pkey, nil } -// ParseRSAPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key +// ParseRSAPublicKeyFromPEM parses a certificate or a PEM encoded PKCS1 or PKIX public key func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { var err error @@ -91,7 +91,9 @@ func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { if cert, err := x509.ParseCertificate(block.Bytes); err == nil { parsedKey = cert.PublicKey } else { - return nil, err + if parsedKey, err = x509.ParsePKCS1PublicKey(block.Bytes); err != nil { + return nil, err + } } } diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/signing_method.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/signing_method.go similarity index 71% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/signing_method.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/signing_method.go index 241ae9c60d..0d73631c1b 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/signing_method.go +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/signing_method.go @@ -7,11 +7,14 @@ import ( var signingMethods = map[string]func() SigningMethod{} var signingMethodLock = new(sync.RWMutex) -// SigningMethod can be used add new methods for signing or verifying tokens. +// SigningMethod can be used add new methods for signing or verifying tokens. It +// takes a decoded signature as an input in the Verify function and produces a +// signature in Sign. The signature is then usually base64 encoded as part of a +// JWT. type SigningMethod interface { - Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid - Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error - Alg() string // returns the alg identifier for this method (example: 'HS256') + Verify(signingString string, sig []byte, key interface{}) error // Returns nil if signature is valid + Sign(signingString string, key interface{}) ([]byte, error) // Returns signature or error + Alg() string // returns the alg identifier for this method (example: 'HS256') } // RegisterSigningMethod registers the "alg" name and a factory function for signing method. diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf b/etcd/vendor/github.com/golang-jwt/jwt/v5/staticcheck.conf similarity index 100% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf rename to etcd/vendor/github.com/golang-jwt/jwt/v5/staticcheck.conf diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/token.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/token.go new file mode 100644 index 0000000000..9c7f4ab010 --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/token.go @@ -0,0 +1,100 @@ +package jwt + +import ( + "crypto" + "encoding/base64" + "encoding/json" +) + +// Keyfunc will be used by the Parse methods as a callback function to supply +// the key for verification. The function receives the parsed, but unverified +// Token. This allows you to use properties in the Header of the token (such as +// `kid`) to identify which key to use. +// +// The returned interface{} may be a single key or a VerificationKeySet containing +// multiple keys. +type Keyfunc func(*Token) (interface{}, error) + +// VerificationKey represents a public or secret key for verifying a token's signature. +type VerificationKey interface { + crypto.PublicKey | []uint8 +} + +// VerificationKeySet is a set of public or secret keys. It is used by the parser to verify a token. +type VerificationKeySet struct { + Keys []VerificationKey +} + +// Token represents a JWT Token. Different fields will be used depending on +// whether you're creating or parsing/verifying a token. +type Token struct { + Raw string // Raw contains the raw token. Populated when you [Parse] a token + Method SigningMethod // Method is the signing method used or to be used + Header map[string]interface{} // Header is the first segment of the token in decoded form + Claims Claims // Claims is the second segment of the token in decoded form + Signature []byte // Signature is the third segment of the token in decoded form. Populated when you Parse a token + Valid bool // Valid specifies if the token is valid. Populated when you Parse/Verify a token +} + +// New creates a new [Token] with the specified signing method and an empty map +// of claims. Additional options can be specified, but are currently unused. +func New(method SigningMethod, opts ...TokenOption) *Token { + return NewWithClaims(method, MapClaims{}, opts...) +} + +// NewWithClaims creates a new [Token] with the specified signing method and +// claims. Additional options can be specified, but are currently unused. +func NewWithClaims(method SigningMethod, claims Claims, opts ...TokenOption) *Token { + return &Token{ + Header: map[string]interface{}{ + "typ": "JWT", + "alg": method.Alg(), + }, + Claims: claims, + Method: method, + } +} + +// SignedString creates and returns a complete, signed JWT. The token is signed +// using the SigningMethod specified in the token. Please refer to +// https://golang-jwt.github.io/jwt/usage/signing_methods/#signing-methods-and-key-types +// for an overview of the different signing methods and their respective key +// types. +func (t *Token) SignedString(key interface{}) (string, error) { + sstr, err := t.SigningString() + if err != nil { + return "", err + } + + sig, err := t.Method.Sign(sstr, key) + if err != nil { + return "", err + } + + return sstr + "." + t.EncodeSegment(sig), nil +} + +// SigningString generates the signing string. This is the most expensive part +// of the whole deal. Unless you need this for something special, just go +// straight for the SignedString. +func (t *Token) SigningString() (string, error) { + h, err := json.Marshal(t.Header) + if err != nil { + return "", err + } + + c, err := json.Marshal(t.Claims) + if err != nil { + return "", err + } + + return t.EncodeSegment(h) + "." + t.EncodeSegment(c), nil +} + +// EncodeSegment encodes a JWT specific base64url encoding with padding +// stripped. In the future, this function might take into account a +// [TokenOption]. Therefore, this function exists as a method of [Token], rather +// than a global function. +func (*Token) EncodeSegment(seg []byte) string { + return base64.RawURLEncoding.EncodeToString(seg) +} diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/token_option.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/token_option.go new file mode 100644 index 0000000000..b4ae3badf8 --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/token_option.go @@ -0,0 +1,5 @@ +package jwt + +// TokenOption is a reserved type, which provides some forward compatibility, +// if we ever want to introduce token creation-related options. +type TokenOption func(*Token) diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v4/types.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/types.go similarity index 73% rename from etcd/vendor/github.com/golang-jwt/jwt/v4/types.go rename to etcd/vendor/github.com/golang-jwt/jwt/v5/types.go index ac8e140eb1..b2655a9e6d 100644 --- a/etcd/vendor/github.com/golang-jwt/jwt/v4/types.go +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/types.go @@ -4,27 +4,27 @@ import ( "encoding/json" "fmt" "math" - "reflect" "strconv" "time" ) -// TimePrecision sets the precision of times and dates within this library. -// This has an influence on the precision of times when comparing expiry or -// other related time fields. Furthermore, it is also the precision of times -// when serializing. +// TimePrecision sets the precision of times and dates within this library. This +// has an influence on the precision of times when comparing expiry or other +// related time fields. Furthermore, it is also the precision of times when +// serializing. // // For backwards compatibility the default precision is set to seconds, so that // no fractional timestamps are generated. var TimePrecision = time.Second -// MarshalSingleStringAsArray modifies the behaviour of the ClaimStrings type, especially -// its MarshalJSON function. +// MarshalSingleStringAsArray modifies the behavior of the ClaimStrings type, +// especially its MarshalJSON function. // // If it is set to true (the default), it will always serialize the type as an -// array of strings, even if it just contains one element, defaulting to the behaviour -// of the underlying []string. If it is set to false, it will serialize to a single -// string, if it contains one element. Otherwise, it will serialize to an array of strings. +// array of strings, even if it just contains one element, defaulting to the +// behavior of the underlying []string. If it is set to false, it will serialize +// to a single string, if it contains one element. Otherwise, it will serialize +// to an array of strings. var MarshalSingleStringAsArray = true // NumericDate represents a JSON numeric date value, as referenced at @@ -58,9 +58,10 @@ func (date NumericDate) MarshalJSON() (b []byte, err error) { // For very large timestamps, UnixNano would overflow an int64, but this // function requires nanosecond level precision, so we have to use the // following technique to get round the issue: + // // 1. Take the normal unix timestamp to form the whole number part of the // output, - // 2. Take the result of the Nanosecond function, which retuns the offset + // 2. Take the result of the Nanosecond function, which returns the offset // within the second of the particular unix time instance, to form the // decimal part of the output // 3. Concatenate them to produce the final result @@ -72,9 +73,10 @@ func (date NumericDate) MarshalJSON() (b []byte, err error) { return output, nil } -// UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a -// NumericDate from a JSON representation, i.e. a json.Number. This number represents an UNIX epoch -// with either integer or non-integer seconds. +// UnmarshalJSON is an implementation of the json.RawMessage interface and +// deserializes a [NumericDate] from a JSON representation, i.e. a +// [json.Number]. This number represents an UNIX epoch with either integer or +// non-integer seconds. func (date *NumericDate) UnmarshalJSON(b []byte) (err error) { var ( number json.Number @@ -95,8 +97,9 @@ func (date *NumericDate) UnmarshalJSON(b []byte) (err error) { return nil } -// ClaimStrings is basically just a slice of strings, but it can be either serialized from a string array or just a string. -// This type is necessary, since the "aud" claim can either be a single string or an array. +// ClaimStrings is basically just a slice of strings, but it can be either +// serialized from a string array or just a string. This type is necessary, +// since the "aud" claim can either be a single string or an array. type ClaimStrings []string func (s *ClaimStrings) UnmarshalJSON(data []byte) (err error) { @@ -117,14 +120,14 @@ func (s *ClaimStrings) UnmarshalJSON(data []byte) (err error) { for _, vv := range v { vs, ok := vv.(string) if !ok { - return &json.UnsupportedTypeError{Type: reflect.TypeOf(vv)} + return ErrInvalidType } aud = append(aud, vs) } case nil: return nil default: - return &json.UnsupportedTypeError{Type: reflect.TypeOf(v)} + return ErrInvalidType } *s = aud @@ -133,10 +136,11 @@ func (s *ClaimStrings) UnmarshalJSON(data []byte) (err error) { } func (s ClaimStrings) MarshalJSON() (b []byte, err error) { - // This handles a special case in the JWT RFC. If the string array, e.g. used by the "aud" field, - // only contains one element, it MAY be serialized as a single string. This may or may not be - // desired based on the ecosystem of other JWT library used, so we make it configurable by the - // variable MarshalSingleStringAsArray. + // This handles a special case in the JWT RFC. If the string array, e.g. + // used by the "aud" field, only contains one element, it MAY be serialized + // as a single string. This may or may not be desired based on the ecosystem + // of other JWT library used, so we make it configurable by the variable + // MarshalSingleStringAsArray. if len(s) == 1 && !MarshalSingleStringAsArray { return json.Marshal(s[0]) } diff --git a/etcd/vendor/github.com/golang-jwt/jwt/v5/validator.go b/etcd/vendor/github.com/golang-jwt/jwt/v5/validator.go new file mode 100644 index 0000000000..008ecd8712 --- /dev/null +++ b/etcd/vendor/github.com/golang-jwt/jwt/v5/validator.go @@ -0,0 +1,316 @@ +package jwt + +import ( + "crypto/subtle" + "fmt" + "time" +) + +// ClaimsValidator is an interface that can be implemented by custom claims who +// wish to execute any additional claims validation based on +// application-specific logic. The Validate function is then executed in +// addition to the regular claims validation and any error returned is appended +// to the final validation result. +// +// type MyCustomClaims struct { +// Foo string `json:"foo"` +// jwt.RegisteredClaims +// } +// +// func (m MyCustomClaims) Validate() error { +// if m.Foo != "bar" { +// return errors.New("must be foobar") +// } +// return nil +// } +type ClaimsValidator interface { + Claims + Validate() error +} + +// Validator is the core of the new Validation API. It is automatically used by +// a [Parser] during parsing and can be modified with various parser options. +// +// The [NewValidator] function should be used to create an instance of this +// struct. +type Validator struct { + // leeway is an optional leeway that can be provided to account for clock skew. + leeway time.Duration + + // timeFunc is used to supply the current time that is needed for + // validation. If unspecified, this defaults to time.Now. + timeFunc func() time.Time + + // requireExp specifies whether the exp claim is required + requireExp bool + + // verifyIat specifies whether the iat (Issued At) claim will be verified. + // According to https://www.rfc-editor.org/rfc/rfc7519#section-4.1.6 this + // only specifies the age of the token, but no validation check is + // necessary. However, if wanted, it can be checked if the iat is + // unrealistic, i.e., in the future. + verifyIat bool + + // expectedAud contains the audience this token expects. Supplying an empty + // string will disable aud checking. + expectedAud string + + // expectedIss contains the issuer this token expects. Supplying an empty + // string will disable iss checking. + expectedIss string + + // expectedSub contains the subject this token expects. Supplying an empty + // string will disable sub checking. + expectedSub string +} + +// NewValidator can be used to create a stand-alone validator with the supplied +// options. This validator can then be used to validate already parsed claims. +// +// Note: Under normal circumstances, explicitly creating a validator is not +// needed and can potentially be dangerous; instead functions of the [Parser] +// class should be used. +// +// The [Validator] is only checking the *validity* of the claims, such as its +// expiration time, but it does NOT perform *signature verification* of the +// token. +func NewValidator(opts ...ParserOption) *Validator { + p := NewParser(opts...) + return p.validator +} + +// Validate validates the given claims. It will also perform any custom +// validation if claims implements the [ClaimsValidator] interface. +// +// Note: It will NOT perform any *signature verification* on the token that +// contains the claims and expects that the [Claim] was already successfully +// verified. +func (v *Validator) Validate(claims Claims) error { + var ( + now time.Time + errs []error = make([]error, 0, 6) + err error + ) + + // Check, if we have a time func + if v.timeFunc != nil { + now = v.timeFunc() + } else { + now = time.Now() + } + + // We always need to check the expiration time, but usage of the claim + // itself is OPTIONAL by default. requireExp overrides this behavior + // and makes the exp claim mandatory. + if err = v.verifyExpiresAt(claims, now, v.requireExp); err != nil { + errs = append(errs, err) + } + + // We always need to check not-before, but usage of the claim itself is + // OPTIONAL. + if err = v.verifyNotBefore(claims, now, false); err != nil { + errs = append(errs, err) + } + + // Check issued-at if the option is enabled + if v.verifyIat { + if err = v.verifyIssuedAt(claims, now, false); err != nil { + errs = append(errs, err) + } + } + + // If we have an expected audience, we also require the audience claim + if v.expectedAud != "" { + if err = v.verifyAudience(claims, v.expectedAud, true); err != nil { + errs = append(errs, err) + } + } + + // If we have an expected issuer, we also require the issuer claim + if v.expectedIss != "" { + if err = v.verifyIssuer(claims, v.expectedIss, true); err != nil { + errs = append(errs, err) + } + } + + // If we have an expected subject, we also require the subject claim + if v.expectedSub != "" { + if err = v.verifySubject(claims, v.expectedSub, true); err != nil { + errs = append(errs, err) + } + } + + // Finally, we want to give the claim itself some possibility to do some + // additional custom validation based on a custom Validate function. + cvt, ok := claims.(ClaimsValidator) + if ok { + if err := cvt.Validate(); err != nil { + errs = append(errs, err) + } + } + + if len(errs) == 0 { + return nil + } + + return joinErrors(errs...) +} + +// verifyExpiresAt compares the exp claim in claims against cmp. This function +// will succeed if cmp < exp. Additional leeway is taken into account. +// +// If exp is not set, it will succeed if the claim is not required, +// otherwise ErrTokenRequiredClaimMissing will be returned. +// +// Additionally, if any error occurs while retrieving the claim, e.g., when its +// the wrong type, an ErrTokenUnverifiable error will be returned. +func (v *Validator) verifyExpiresAt(claims Claims, cmp time.Time, required bool) error { + exp, err := claims.GetExpirationTime() + if err != nil { + return err + } + + if exp == nil { + return errorIfRequired(required, "exp") + } + + return errorIfFalse(cmp.Before((exp.Time).Add(+v.leeway)), ErrTokenExpired) +} + +// verifyIssuedAt compares the iat claim in claims against cmp. This function +// will succeed if cmp >= iat. Additional leeway is taken into account. +// +// If iat is not set, it will succeed if the claim is not required, +// otherwise ErrTokenRequiredClaimMissing will be returned. +// +// Additionally, if any error occurs while retrieving the claim, e.g., when its +// the wrong type, an ErrTokenUnverifiable error will be returned. +func (v *Validator) verifyIssuedAt(claims Claims, cmp time.Time, required bool) error { + iat, err := claims.GetIssuedAt() + if err != nil { + return err + } + + if iat == nil { + return errorIfRequired(required, "iat") + } + + return errorIfFalse(!cmp.Before(iat.Add(-v.leeway)), ErrTokenUsedBeforeIssued) +} + +// verifyNotBefore compares the nbf claim in claims against cmp. This function +// will return true if cmp >= nbf. Additional leeway is taken into account. +// +// If nbf is not set, it will succeed if the claim is not required, +// otherwise ErrTokenRequiredClaimMissing will be returned. +// +// Additionally, if any error occurs while retrieving the claim, e.g., when its +// the wrong type, an ErrTokenUnverifiable error will be returned. +func (v *Validator) verifyNotBefore(claims Claims, cmp time.Time, required bool) error { + nbf, err := claims.GetNotBefore() + if err != nil { + return err + } + + if nbf == nil { + return errorIfRequired(required, "nbf") + } + + return errorIfFalse(!cmp.Before(nbf.Add(-v.leeway)), ErrTokenNotValidYet) +} + +// verifyAudience compares the aud claim against cmp. +// +// If aud is not set or an empty list, it will succeed if the claim is not required, +// otherwise ErrTokenRequiredClaimMissing will be returned. +// +// Additionally, if any error occurs while retrieving the claim, e.g., when its +// the wrong type, an ErrTokenUnverifiable error will be returned. +func (v *Validator) verifyAudience(claims Claims, cmp string, required bool) error { + aud, err := claims.GetAudience() + if err != nil { + return err + } + + if len(aud) == 0 { + return errorIfRequired(required, "aud") + } + + // use a var here to keep constant time compare when looping over a number of claims + result := false + + var stringClaims string + for _, a := range aud { + if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 { + result = true + } + stringClaims = stringClaims + a + } + + // case where "" is sent in one or many aud claims + if stringClaims == "" { + return errorIfRequired(required, "aud") + } + + return errorIfFalse(result, ErrTokenInvalidAudience) +} + +// verifyIssuer compares the iss claim in claims against cmp. +// +// If iss is not set, it will succeed if the claim is not required, +// otherwise ErrTokenRequiredClaimMissing will be returned. +// +// Additionally, if any error occurs while retrieving the claim, e.g., when its +// the wrong type, an ErrTokenUnverifiable error will be returned. +func (v *Validator) verifyIssuer(claims Claims, cmp string, required bool) error { + iss, err := claims.GetIssuer() + if err != nil { + return err + } + + if iss == "" { + return errorIfRequired(required, "iss") + } + + return errorIfFalse(iss == cmp, ErrTokenInvalidIssuer) +} + +// verifySubject compares the sub claim against cmp. +// +// If sub is not set, it will succeed if the claim is not required, +// otherwise ErrTokenRequiredClaimMissing will be returned. +// +// Additionally, if any error occurs while retrieving the claim, e.g., when its +// the wrong type, an ErrTokenUnverifiable error will be returned. +func (v *Validator) verifySubject(claims Claims, cmp string, required bool) error { + sub, err := claims.GetSubject() + if err != nil { + return err + } + + if sub == "" { + return errorIfRequired(required, "sub") + } + + return errorIfFalse(sub == cmp, ErrTokenInvalidSubject) +} + +// errorIfFalse returns the error specified in err, if the value is true. +// Otherwise, nil is returned. +func errorIfFalse(value bool, err error) error { + if value { + return nil + } else { + return err + } +} + +// errorIfRequired returns an ErrTokenRequiredClaimMissing error if required is +// true. Otherwise, nil is returned. +func errorIfRequired(required bool, claim string) error { + if required { + return newError(fmt.Sprintf("%s claim is required", claim), ErrTokenRequiredClaimMissing) + } else { + return nil + } +} diff --git a/etcd/vendor/github.com/golang/protobuf/descriptor/descriptor.go b/etcd/vendor/github.com/golang/protobuf/descriptor/descriptor.go deleted file mode 100644 index ffde8a6508..0000000000 --- a/etcd/vendor/github.com/golang/protobuf/descriptor/descriptor.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2016 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 descriptor provides functions for obtaining the protocol buffer -// descriptors of generated Go types. -// -// Deprecated: See the "google.golang.org/protobuf/reflect/protoreflect" package -// for how to obtain an EnumDescriptor or MessageDescriptor in order to -// programatically interact with the protobuf type system. -package descriptor - -import ( - "bytes" - "compress/gzip" - "io/ioutil" - "sync" - - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/reflect/protodesc" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/runtime/protoimpl" - - descriptorpb "github.com/golang/protobuf/protoc-gen-go/descriptor" -) - -// Message is proto.Message with a method to return its descriptor. -// -// Deprecated: The Descriptor method may not be generated by future -// versions of protoc-gen-go, meaning that this interface may not -// be implemented by many concrete message types. -type Message interface { - proto.Message - Descriptor() ([]byte, []int) -} - -// ForMessage returns the file descriptor proto containing -// the message and the message descriptor proto for the message itself. -// The returned proto messages must not be mutated. -// -// Deprecated: Not all concrete message types satisfy the Message interface. -// Use MessageDescriptorProto instead. If possible, the calling code should -// be rewritten to use protobuf reflection instead. -// See package "google.golang.org/protobuf/reflect/protoreflect" for details. -func ForMessage(m Message) (*descriptorpb.FileDescriptorProto, *descriptorpb.DescriptorProto) { - return MessageDescriptorProto(m) -} - -type rawDesc struct { - fileDesc []byte - indexes []int -} - -var rawDescCache sync.Map // map[protoreflect.Descriptor]*rawDesc - -func deriveRawDescriptor(d protoreflect.Descriptor) ([]byte, []int) { - // Fast-path: check whether raw descriptors are already cached. - origDesc := d - if v, ok := rawDescCache.Load(origDesc); ok { - return v.(*rawDesc).fileDesc, v.(*rawDesc).indexes - } - - // Slow-path: derive the raw descriptor from the v2 descriptor. - - // Start with the leaf (a given enum or message declaration) and - // ascend upwards until we hit the parent file descriptor. - var idxs []int - for { - idxs = append(idxs, d.Index()) - d = d.Parent() - if d == nil { - // TODO: We could construct a FileDescriptor stub for standalone - // descriptors to satisfy the API. - return nil, nil - } - if _, ok := d.(protoreflect.FileDescriptor); ok { - break - } - } - - // Obtain the raw file descriptor. - fd := d.(protoreflect.FileDescriptor) - b, _ := proto.Marshal(protodesc.ToFileDescriptorProto(fd)) - file := protoimpl.X.CompressGZIP(b) - - // Reverse the indexes, since we populated it in reverse. - for i, j := 0, len(idxs)-1; i < j; i, j = i+1, j-1 { - idxs[i], idxs[j] = idxs[j], idxs[i] - } - - if v, ok := rawDescCache.LoadOrStore(origDesc, &rawDesc{file, idxs}); ok { - return v.(*rawDesc).fileDesc, v.(*rawDesc).indexes - } - return file, idxs -} - -// EnumRawDescriptor returns the GZIP'd raw file descriptor representing -// the enum and the index path to reach the enum declaration. -// The returned slices must not be mutated. -func EnumRawDescriptor(e proto.GeneratedEnum) ([]byte, []int) { - if ev, ok := e.(interface{ EnumDescriptor() ([]byte, []int) }); ok { - return ev.EnumDescriptor() - } - ed := protoimpl.X.EnumTypeOf(e) - return deriveRawDescriptor(ed.Descriptor()) -} - -// MessageRawDescriptor returns the GZIP'd raw file descriptor representing -// the message and the index path to reach the message declaration. -// The returned slices must not be mutated. -func MessageRawDescriptor(m proto.GeneratedMessage) ([]byte, []int) { - if mv, ok := m.(interface{ Descriptor() ([]byte, []int) }); ok { - return mv.Descriptor() - } - md := protoimpl.X.MessageTypeOf(m) - return deriveRawDescriptor(md.Descriptor()) -} - -var fileDescCache sync.Map // map[*byte]*descriptorpb.FileDescriptorProto - -func deriveFileDescriptor(rawDesc []byte) *descriptorpb.FileDescriptorProto { - // Fast-path: check whether descriptor protos are already cached. - if v, ok := fileDescCache.Load(&rawDesc[0]); ok { - return v.(*descriptorpb.FileDescriptorProto) - } - - // Slow-path: derive the descriptor proto from the GZIP'd message. - zr, err := gzip.NewReader(bytes.NewReader(rawDesc)) - if err != nil { - panic(err) - } - b, err := ioutil.ReadAll(zr) - if err != nil { - panic(err) - } - fd := new(descriptorpb.FileDescriptorProto) - if err := proto.Unmarshal(b, fd); err != nil { - panic(err) - } - if v, ok := fileDescCache.LoadOrStore(&rawDesc[0], fd); ok { - return v.(*descriptorpb.FileDescriptorProto) - } - return fd -} - -// EnumDescriptorProto returns the file descriptor proto representing -// the enum and the enum descriptor proto for the enum itself. -// The returned proto messages must not be mutated. -func EnumDescriptorProto(e proto.GeneratedEnum) (*descriptorpb.FileDescriptorProto, *descriptorpb.EnumDescriptorProto) { - rawDesc, idxs := EnumRawDescriptor(e) - if rawDesc == nil || idxs == nil { - return nil, nil - } - fd := deriveFileDescriptor(rawDesc) - if len(idxs) == 1 { - return fd, fd.EnumType[idxs[0]] - } - md := fd.MessageType[idxs[0]] - for _, i := range idxs[1 : len(idxs)-1] { - md = md.NestedType[i] - } - ed := md.EnumType[idxs[len(idxs)-1]] - return fd, ed -} - -// MessageDescriptorProto returns the file descriptor proto representing -// the message and the message descriptor proto for the message itself. -// The returned proto messages must not be mutated. -func MessageDescriptorProto(m proto.GeneratedMessage) (*descriptorpb.FileDescriptorProto, *descriptorpb.DescriptorProto) { - rawDesc, idxs := MessageRawDescriptor(m) - if rawDesc == nil || idxs == nil { - return nil, nil - } - fd := deriveFileDescriptor(rawDesc) - md := fd.MessageType[idxs[0]] - for _, i := range idxs[1:] { - md = md.NestedType[i] - } - return fd, md -} diff --git a/etcd/vendor/github.com/golang/protobuf/jsonpb/decode.go b/etcd/vendor/github.com/golang/protobuf/jsonpb/decode.go deleted file mode 100644 index c6f66f1039..0000000000 --- a/etcd/vendor/github.com/golang/protobuf/jsonpb/decode.go +++ /dev/null @@ -1,531 +0,0 @@ -// Copyright 2015 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 jsonpb - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "math" - "reflect" - "strconv" - "strings" - "time" - - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/encoding/protojson" - protoV2 "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" -) - -const wrapJSONUnmarshalV2 = false - -// UnmarshalNext unmarshals the next JSON object from d into m. -func UnmarshalNext(d *json.Decoder, m proto.Message) error { - return new(Unmarshaler).UnmarshalNext(d, m) -} - -// Unmarshal unmarshals a JSON object from r into m. -func Unmarshal(r io.Reader, m proto.Message) error { - return new(Unmarshaler).Unmarshal(r, m) -} - -// UnmarshalString unmarshals a JSON object from s into m. -func UnmarshalString(s string, m proto.Message) error { - return new(Unmarshaler).Unmarshal(strings.NewReader(s), m) -} - -// Unmarshaler is a configurable object for converting from a JSON -// representation to a protocol buffer object. -type Unmarshaler struct { - // AllowUnknownFields specifies whether to allow messages to contain - // unknown JSON fields, as opposed to failing to unmarshal. - AllowUnknownFields bool - - // AnyResolver is used to resolve the google.protobuf.Any well-known type. - // If unset, the global registry is used by default. - AnyResolver AnyResolver -} - -// JSONPBUnmarshaler is implemented by protobuf messages that customize the way -// they are unmarshaled from JSON. Messages that implement this should also -// implement JSONPBMarshaler so that the custom format can be produced. -// -// The JSON unmarshaling must follow the JSON to proto specification: -// -// https://developers.google.com/protocol-buffers/docs/proto3#json -// -// Deprecated: Custom types should implement protobuf reflection instead. -type JSONPBUnmarshaler interface { - UnmarshalJSONPB(*Unmarshaler, []byte) error -} - -// Unmarshal unmarshals a JSON object from r into m. -func (u *Unmarshaler) Unmarshal(r io.Reader, m proto.Message) error { - return u.UnmarshalNext(json.NewDecoder(r), m) -} - -// UnmarshalNext unmarshals the next JSON object from d into m. -func (u *Unmarshaler) UnmarshalNext(d *json.Decoder, m proto.Message) error { - if m == nil { - return errors.New("invalid nil message") - } - - // Parse the next JSON object from the stream. - raw := json.RawMessage{} - if err := d.Decode(&raw); err != nil { - return err - } - - // Check for custom unmarshalers first since they may not properly - // implement protobuf reflection that the logic below relies on. - if jsu, ok := m.(JSONPBUnmarshaler); ok { - return jsu.UnmarshalJSONPB(u, raw) - } - - mr := proto.MessageReflect(m) - - // NOTE: For historical reasons, a top-level null is treated as a noop. - // This is incorrect, but kept for compatibility. - if string(raw) == "null" && mr.Descriptor().FullName() != "google.protobuf.Value" { - return nil - } - - if wrapJSONUnmarshalV2 { - // NOTE: If input message is non-empty, we need to preserve merge semantics - // of the old jsonpb implementation. These semantics are not supported by - // the protobuf JSON specification. - isEmpty := true - mr.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool { - isEmpty = false // at least one iteration implies non-empty - return false - }) - if !isEmpty { - // Perform unmarshaling into a newly allocated, empty message. - mr = mr.New() - - // Use a defer to copy all unmarshaled fields into the original message. - dst := proto.MessageReflect(m) - defer mr.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { - dst.Set(fd, v) - return true - }) - } - - // Unmarshal using the v2 JSON unmarshaler. - opts := protojson.UnmarshalOptions{ - DiscardUnknown: u.AllowUnknownFields, - } - if u.AnyResolver != nil { - opts.Resolver = anyResolver{u.AnyResolver} - } - return opts.Unmarshal(raw, mr.Interface()) - } else { - if err := u.unmarshalMessage(mr, raw); err != nil { - return err - } - return protoV2.CheckInitialized(mr.Interface()) - } -} - -func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error { - md := m.Descriptor() - fds := md.Fields() - - if jsu, ok := proto.MessageV1(m.Interface()).(JSONPBUnmarshaler); ok { - return jsu.UnmarshalJSONPB(u, in) - } - - if string(in) == "null" && md.FullName() != "google.protobuf.Value" { - return nil - } - - switch wellKnownType(md.FullName()) { - case "Any": - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return err - } - - rawTypeURL, ok := jsonObject["@type"] - if !ok { - return errors.New("Any JSON doesn't have '@type'") - } - typeURL, err := unquoteString(string(rawTypeURL)) - if err != nil { - return fmt.Errorf("can't unmarshal Any's '@type': %q", rawTypeURL) - } - m.Set(fds.ByNumber(1), protoreflect.ValueOfString(typeURL)) - - var m2 protoreflect.Message - if u.AnyResolver != nil { - mi, err := u.AnyResolver.Resolve(typeURL) - if err != nil { - return err - } - m2 = proto.MessageReflect(mi) - } else { - mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) - if err != nil { - if err == protoregistry.NotFound { - return fmt.Errorf("could not resolve Any message type: %v", typeURL) - } - return err - } - m2 = mt.New() - } - - if wellKnownType(m2.Descriptor().FullName()) != "" { - rawValue, ok := jsonObject["value"] - if !ok { - return errors.New("Any JSON doesn't have 'value'") - } - if err := u.unmarshalMessage(m2, rawValue); err != nil { - return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) - } - } else { - delete(jsonObject, "@type") - rawJSON, err := json.Marshal(jsonObject) - if err != nil { - return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", err) - } - if err = u.unmarshalMessage(m2, rawJSON); err != nil { - return fmt.Errorf("can't unmarshal Any nested proto %v: %v", typeURL, err) - } - } - - rawWire, err := protoV2.Marshal(m2.Interface()) - if err != nil { - return fmt.Errorf("can't marshal proto %v into Any.Value: %v", typeURL, err) - } - m.Set(fds.ByNumber(2), protoreflect.ValueOfBytes(rawWire)) - return nil - case "BoolValue", "BytesValue", "StringValue", - "Int32Value", "UInt32Value", "FloatValue", - "Int64Value", "UInt64Value", "DoubleValue": - fd := fds.ByNumber(1) - v, err := u.unmarshalValue(m.NewField(fd), in, fd) - if err != nil { - return err - } - m.Set(fd, v) - return nil - case "Duration": - v, err := unquoteString(string(in)) - if err != nil { - return err - } - d, err := time.ParseDuration(v) - if err != nil { - return fmt.Errorf("bad Duration: %v", err) - } - - sec := d.Nanoseconds() / 1e9 - nsec := d.Nanoseconds() % 1e9 - m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) - m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) - return nil - case "Timestamp": - v, err := unquoteString(string(in)) - if err != nil { - return err - } - t, err := time.Parse(time.RFC3339Nano, v) - if err != nil { - return fmt.Errorf("bad Timestamp: %v", err) - } - - sec := t.Unix() - nsec := t.Nanosecond() - m.Set(fds.ByNumber(1), protoreflect.ValueOfInt64(int64(sec))) - m.Set(fds.ByNumber(2), protoreflect.ValueOfInt32(int32(nsec))) - return nil - case "Value": - switch { - case string(in) == "null": - m.Set(fds.ByNumber(1), protoreflect.ValueOfEnum(0)) - case string(in) == "true": - m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(true)) - case string(in) == "false": - m.Set(fds.ByNumber(4), protoreflect.ValueOfBool(false)) - case hasPrefixAndSuffix('"', in, '"'): - s, err := unquoteString(string(in)) - if err != nil { - return fmt.Errorf("unrecognized type for Value %q", in) - } - m.Set(fds.ByNumber(3), protoreflect.ValueOfString(s)) - case hasPrefixAndSuffix('[', in, ']'): - v := m.Mutable(fds.ByNumber(6)) - return u.unmarshalMessage(v.Message(), in) - case hasPrefixAndSuffix('{', in, '}'): - v := m.Mutable(fds.ByNumber(5)) - return u.unmarshalMessage(v.Message(), in) - default: - f, err := strconv.ParseFloat(string(in), 0) - if err != nil { - return fmt.Errorf("unrecognized type for Value %q", in) - } - m.Set(fds.ByNumber(2), protoreflect.ValueOfFloat64(f)) - } - return nil - case "ListValue": - var jsonArray []json.RawMessage - if err := json.Unmarshal(in, &jsonArray); err != nil { - return fmt.Errorf("bad ListValue: %v", err) - } - - lv := m.Mutable(fds.ByNumber(1)).List() - for _, raw := range jsonArray { - ve := lv.NewElement() - if err := u.unmarshalMessage(ve.Message(), raw); err != nil { - return err - } - lv.Append(ve) - } - return nil - case "Struct": - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return fmt.Errorf("bad StructValue: %v", err) - } - - mv := m.Mutable(fds.ByNumber(1)).Map() - for key, raw := range jsonObject { - kv := protoreflect.ValueOf(key).MapKey() - vv := mv.NewValue() - if err := u.unmarshalMessage(vv.Message(), raw); err != nil { - return fmt.Errorf("bad value in StructValue for key %q: %v", key, err) - } - mv.Set(kv, vv) - } - return nil - } - - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return err - } - - // Handle known fields. - for i := 0; i < fds.Len(); i++ { - fd := fds.Get(i) - if fd.IsWeak() && fd.Message().IsPlaceholder() { - continue // weak reference is not linked in - } - - // Search for any raw JSON value associated with this field. - var raw json.RawMessage - name := string(fd.Name()) - if fd.Kind() == protoreflect.GroupKind { - name = string(fd.Message().Name()) - } - if v, ok := jsonObject[name]; ok { - delete(jsonObject, name) - raw = v - } - name = string(fd.JSONName()) - if v, ok := jsonObject[name]; ok { - delete(jsonObject, name) - raw = v - } - - field := m.NewField(fd) - // Unmarshal the field value. - if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { - continue - } - v, err := u.unmarshalValue(field, raw, fd) - if err != nil { - return err - } - m.Set(fd, v) - } - - // Handle extension fields. - for name, raw := range jsonObject { - if !strings.HasPrefix(name, "[") || !strings.HasSuffix(name, "]") { - continue - } - - // Resolve the extension field by name. - xname := protoreflect.FullName(name[len("[") : len(name)-len("]")]) - xt, _ := protoregistry.GlobalTypes.FindExtensionByName(xname) - if xt == nil && isMessageSet(md) { - xt, _ = protoregistry.GlobalTypes.FindExtensionByName(xname.Append("message_set_extension")) - } - if xt == nil { - continue - } - delete(jsonObject, name) - fd := xt.TypeDescriptor() - if fd.ContainingMessage().FullName() != m.Descriptor().FullName() { - return fmt.Errorf("extension field %q does not extend message %q", xname, m.Descriptor().FullName()) - } - - field := m.NewField(fd) - // Unmarshal the field value. - if raw == nil || (string(raw) == "null" && !isSingularWellKnownValue(fd) && !isSingularJSONPBUnmarshaler(field, fd)) { - continue - } - v, err := u.unmarshalValue(field, raw, fd) - if err != nil { - return err - } - m.Set(fd, v) - } - - if !u.AllowUnknownFields && len(jsonObject) > 0 { - for name := range jsonObject { - return fmt.Errorf("unknown field %q in %v", name, md.FullName()) - } - } - return nil -} - -func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool { - if fd.Cardinality() == protoreflect.Repeated { - return false - } - if md := fd.Message(); md != nil { - return md.FullName() == "google.protobuf.Value" - } - if ed := fd.Enum(); ed != nil { - return ed.FullName() == "google.protobuf.NullValue" - } - return false -} - -func isSingularJSONPBUnmarshaler(v protoreflect.Value, fd protoreflect.FieldDescriptor) bool { - if fd.Message() != nil && fd.Cardinality() != protoreflect.Repeated { - _, ok := proto.MessageV1(v.Interface()).(JSONPBUnmarshaler) - return ok - } - return false -} - -func (u *Unmarshaler) unmarshalValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { - switch { - case fd.IsList(): - var jsonArray []json.RawMessage - if err := json.Unmarshal(in, &jsonArray); err != nil { - return v, err - } - lv := v.List() - for _, raw := range jsonArray { - ve, err := u.unmarshalSingularValue(lv.NewElement(), raw, fd) - if err != nil { - return v, err - } - lv.Append(ve) - } - return v, nil - case fd.IsMap(): - var jsonObject map[string]json.RawMessage - if err := json.Unmarshal(in, &jsonObject); err != nil { - return v, err - } - kfd := fd.MapKey() - vfd := fd.MapValue() - mv := v.Map() - for key, raw := range jsonObject { - var kv protoreflect.MapKey - if kfd.Kind() == protoreflect.StringKind { - kv = protoreflect.ValueOf(key).MapKey() - } else { - v, err := u.unmarshalSingularValue(kfd.Default(), []byte(key), kfd) - if err != nil { - return v, err - } - kv = v.MapKey() - } - - vv, err := u.unmarshalSingularValue(mv.NewValue(), raw, vfd) - if err != nil { - return v, err - } - mv.Set(kv, vv) - } - return v, nil - default: - return u.unmarshalSingularValue(v, in, fd) - } -} - -var nonFinite = map[string]float64{ - `"NaN"`: math.NaN(), - `"Infinity"`: math.Inf(+1), - `"-Infinity"`: math.Inf(-1), -} - -func (u *Unmarshaler) unmarshalSingularValue(v protoreflect.Value, in []byte, fd protoreflect.FieldDescriptor) (protoreflect.Value, error) { - switch fd.Kind() { - case protoreflect.BoolKind: - return unmarshalValue(in, new(bool)) - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: - return unmarshalValue(trimQuote(in), new(int32)) - case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - return unmarshalValue(trimQuote(in), new(int64)) - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: - return unmarshalValue(trimQuote(in), new(uint32)) - case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - return unmarshalValue(trimQuote(in), new(uint64)) - case protoreflect.FloatKind: - if f, ok := nonFinite[string(in)]; ok { - return protoreflect.ValueOfFloat32(float32(f)), nil - } - return unmarshalValue(trimQuote(in), new(float32)) - case protoreflect.DoubleKind: - if f, ok := nonFinite[string(in)]; ok { - return protoreflect.ValueOfFloat64(float64(f)), nil - } - return unmarshalValue(trimQuote(in), new(float64)) - case protoreflect.StringKind: - return unmarshalValue(in, new(string)) - case protoreflect.BytesKind: - return unmarshalValue(in, new([]byte)) - case protoreflect.EnumKind: - if hasPrefixAndSuffix('"', in, '"') { - vd := fd.Enum().Values().ByName(protoreflect.Name(trimQuote(in))) - if vd == nil { - return v, fmt.Errorf("unknown value %q for enum %s", in, fd.Enum().FullName()) - } - return protoreflect.ValueOfEnum(vd.Number()), nil - } - return unmarshalValue(in, new(protoreflect.EnumNumber)) - case protoreflect.MessageKind, protoreflect.GroupKind: - err := u.unmarshalMessage(v.Message(), in) - return v, err - default: - panic(fmt.Sprintf("invalid kind %v", fd.Kind())) - } -} - -func unmarshalValue(in []byte, v interface{}) (protoreflect.Value, error) { - err := json.Unmarshal(in, v) - return protoreflect.ValueOf(reflect.ValueOf(v).Elem().Interface()), err -} - -func unquoteString(in string) (out string, err error) { - err = json.Unmarshal([]byte(in), &out) - return out, err -} - -func hasPrefixAndSuffix(prefix byte, in []byte, suffix byte) bool { - if len(in) >= 2 && in[0] == prefix && in[len(in)-1] == suffix { - return true - } - return false -} - -// trimQuote is like unquoteString but simply strips surrounding quotes. -// This is incorrect, but is behavior done by the legacy implementation. -func trimQuote(in []byte) []byte { - if len(in) >= 2 && in[0] == '"' && in[len(in)-1] == '"' { - in = in[1 : len(in)-1] - } - return in -} diff --git a/etcd/vendor/github.com/golang/protobuf/jsonpb/encode.go b/etcd/vendor/github.com/golang/protobuf/jsonpb/encode.go deleted file mode 100644 index e9438a93f3..0000000000 --- a/etcd/vendor/github.com/golang/protobuf/jsonpb/encode.go +++ /dev/null @@ -1,560 +0,0 @@ -// Copyright 2015 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 jsonpb - -import ( - "encoding/json" - "errors" - "fmt" - "io" - "math" - "reflect" - "sort" - "strconv" - "strings" - "time" - - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/encoding/protojson" - protoV2 "google.golang.org/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" -) - -const wrapJSONMarshalV2 = false - -// Marshaler is a configurable object for marshaling protocol buffer messages -// to the specified JSON representation. -type Marshaler struct { - // OrigName specifies whether to use the original protobuf name for fields. - OrigName bool - - // EnumsAsInts specifies whether to render enum values as integers, - // as opposed to string values. - EnumsAsInts bool - - // EmitDefaults specifies whether to render fields with zero values. - EmitDefaults bool - - // Indent controls whether the output is compact or not. - // If empty, the output is compact JSON. Otherwise, every JSON object - // entry and JSON array value will be on its own line. - // Each line will be preceded by repeated copies of Indent, where the - // number of copies is the current indentation depth. - Indent string - - // AnyResolver is used to resolve the google.protobuf.Any well-known type. - // If unset, the global registry is used by default. - AnyResolver AnyResolver -} - -// JSONPBMarshaler is implemented by protobuf messages that customize the -// way they are marshaled to JSON. Messages that implement this should also -// implement JSONPBUnmarshaler so that the custom format can be parsed. -// -// The JSON marshaling must follow the proto to JSON specification: -// -// https://developers.google.com/protocol-buffers/docs/proto3#json -// -// Deprecated: Custom types should implement protobuf reflection instead. -type JSONPBMarshaler interface { - MarshalJSONPB(*Marshaler) ([]byte, error) -} - -// Marshal serializes a protobuf message as JSON into w. -func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error { - b, err := jm.marshal(m) - if len(b) > 0 { - if _, err := w.Write(b); err != nil { - return err - } - } - return err -} - -// MarshalToString serializes a protobuf message as JSON in string form. -func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) { - b, err := jm.marshal(m) - if err != nil { - return "", err - } - return string(b), nil -} - -func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) { - v := reflect.ValueOf(m) - if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) { - return nil, errors.New("Marshal called with nil") - } - - // Check for custom marshalers first since they may not properly - // implement protobuf reflection that the logic below relies on. - if jsm, ok := m.(JSONPBMarshaler); ok { - return jsm.MarshalJSONPB(jm) - } - - if wrapJSONMarshalV2 { - opts := protojson.MarshalOptions{ - UseProtoNames: jm.OrigName, - UseEnumNumbers: jm.EnumsAsInts, - EmitUnpopulated: jm.EmitDefaults, - Indent: jm.Indent, - } - if jm.AnyResolver != nil { - opts.Resolver = anyResolver{jm.AnyResolver} - } - return opts.Marshal(proto.MessageReflect(m).Interface()) - } else { - // Check for unpopulated required fields first. - m2 := proto.MessageReflect(m) - if err := protoV2.CheckInitialized(m2.Interface()); err != nil { - return nil, err - } - - w := jsonWriter{Marshaler: jm} - err := w.marshalMessage(m2, "", "") - return w.buf, err - } -} - -type jsonWriter struct { - *Marshaler - buf []byte -} - -func (w *jsonWriter) write(s string) { - w.buf = append(w.buf, s...) -} - -func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error { - if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok { - b, err := jsm.MarshalJSONPB(w.Marshaler) - if err != nil { - return err - } - if typeURL != "" { - // we are marshaling this object to an Any type - var js map[string]*json.RawMessage - if err = json.Unmarshal(b, &js); err != nil { - return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err) - } - turl, err := json.Marshal(typeURL) - if err != nil { - return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err) - } - js["@type"] = (*json.RawMessage)(&turl) - if b, err = json.Marshal(js); err != nil { - return err - } - } - w.write(string(b)) - return nil - } - - md := m.Descriptor() - fds := md.Fields() - - // Handle well-known types. - const secondInNanos = int64(time.Second / time.Nanosecond) - switch wellKnownType(md.FullName()) { - case "Any": - return w.marshalAny(m, indent) - case "BoolValue", "BytesValue", "StringValue", - "Int32Value", "UInt32Value", "FloatValue", - "Int64Value", "UInt64Value", "DoubleValue": - fd := fds.ByNumber(1) - return w.marshalValue(fd, m.Get(fd), indent) - case "Duration": - const maxSecondsInDuration = 315576000000 - // "Generated output always contains 0, 3, 6, or 9 fractional digits, - // depending on required precision." - s := m.Get(fds.ByNumber(1)).Int() - ns := m.Get(fds.ByNumber(2)).Int() - if s < -maxSecondsInDuration || s > maxSecondsInDuration { - return fmt.Errorf("seconds out of range %v", s) - } - if ns <= -secondInNanos || ns >= secondInNanos { - return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos) - } - if (s > 0 && ns < 0) || (s < 0 && ns > 0) { - return errors.New("signs of seconds and nanos do not match") - } - var sign string - if s < 0 || ns < 0 { - sign, s, ns = "-", -1*s, -1*ns - } - x := fmt.Sprintf("%s%d.%09d", sign, s, ns) - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, ".000") - w.write(fmt.Sprintf(`"%vs"`, x)) - return nil - case "Timestamp": - // "RFC 3339, where generated output will always be Z-normalized - // and uses 0, 3, 6 or 9 fractional digits." - s := m.Get(fds.ByNumber(1)).Int() - ns := m.Get(fds.ByNumber(2)).Int() - if ns < 0 || ns >= secondInNanos { - return fmt.Errorf("ns out of range [0, %v)", secondInNanos) - } - t := time.Unix(s, ns).UTC() - // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). - x := t.Format("2006-01-02T15:04:05.000000000") - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, "000") - x = strings.TrimSuffix(x, ".000") - w.write(fmt.Sprintf(`"%vZ"`, x)) - return nil - case "Value": - // JSON value; which is a null, number, string, bool, object, or array. - od := md.Oneofs().Get(0) - fd := m.WhichOneof(od) - if fd == nil { - return errors.New("nil Value") - } - return w.marshalValue(fd, m.Get(fd), indent) - case "Struct", "ListValue": - // JSON object or array. - fd := fds.ByNumber(1) - return w.marshalValue(fd, m.Get(fd), indent) - } - - w.write("{") - if w.Indent != "" { - w.write("\n") - } - - firstField := true - if typeURL != "" { - if err := w.marshalTypeURL(indent, typeURL); err != nil { - return err - } - firstField = false - } - - for i := 0; i < fds.Len(); { - fd := fds.Get(i) - if od := fd.ContainingOneof(); od != nil { - fd = m.WhichOneof(od) - i += od.Fields().Len() - if fd == nil { - continue - } - } else { - i++ - } - - v := m.Get(fd) - - if !m.Has(fd) { - if !w.EmitDefaults || fd.ContainingOneof() != nil { - continue - } - if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) { - v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars - } - } - - if !firstField { - w.writeComma() - } - if err := w.marshalField(fd, v, indent); err != nil { - return err - } - firstField = false - } - - // Handle proto2 extensions. - if md.ExtensionRanges().Len() > 0 { - // Collect a sorted list of all extension descriptor and values. - type ext struct { - desc protoreflect.FieldDescriptor - val protoreflect.Value - } - var exts []ext - m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { - if fd.IsExtension() { - exts = append(exts, ext{fd, v}) - } - return true - }) - sort.Slice(exts, func(i, j int) bool { - return exts[i].desc.Number() < exts[j].desc.Number() - }) - - for _, ext := range exts { - if !firstField { - w.writeComma() - } - if err := w.marshalField(ext.desc, ext.val, indent); err != nil { - return err - } - firstField = false - } - } - - if w.Indent != "" { - w.write("\n") - w.write(indent) - } - w.write("}") - return nil -} - -func (w *jsonWriter) writeComma() { - if w.Indent != "" { - w.write(",\n") - } else { - w.write(",") - } -} - -func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error { - // "If the Any contains a value that has a special JSON mapping, - // it will be converted as follows: {"@type": xxx, "value": yyy}. - // Otherwise, the value will be converted into a JSON object, - // and the "@type" field will be inserted to indicate the actual data type." - md := m.Descriptor() - typeURL := m.Get(md.Fields().ByNumber(1)).String() - rawVal := m.Get(md.Fields().ByNumber(2)).Bytes() - - var m2 protoreflect.Message - if w.AnyResolver != nil { - mi, err := w.AnyResolver.Resolve(typeURL) - if err != nil { - return err - } - m2 = proto.MessageReflect(mi) - } else { - mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL) - if err != nil { - return err - } - m2 = mt.New() - } - - if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil { - return err - } - - if wellKnownType(m2.Descriptor().FullName()) == "" { - return w.marshalMessage(m2, indent, typeURL) - } - - w.write("{") - if w.Indent != "" { - w.write("\n") - } - if err := w.marshalTypeURL(indent, typeURL); err != nil { - return err - } - w.writeComma() - if w.Indent != "" { - w.write(indent) - w.write(w.Indent) - w.write(`"value": `) - } else { - w.write(`"value":`) - } - if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil { - return err - } - if w.Indent != "" { - w.write("\n") - w.write(indent) - } - w.write("}") - return nil -} - -func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error { - if w.Indent != "" { - w.write(indent) - w.write(w.Indent) - } - w.write(`"@type":`) - if w.Indent != "" { - w.write(" ") - } - b, err := json.Marshal(typeURL) - if err != nil { - return err - } - w.write(string(b)) - return nil -} - -// marshalField writes field description and value to the Writer. -func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { - if w.Indent != "" { - w.write(indent) - w.write(w.Indent) - } - w.write(`"`) - switch { - case fd.IsExtension(): - // For message set, use the fname of the message as the extension name. - name := string(fd.FullName()) - if isMessageSet(fd.ContainingMessage()) { - name = strings.TrimSuffix(name, ".message_set_extension") - } - - w.write("[" + name + "]") - case w.OrigName: - name := string(fd.Name()) - if fd.Kind() == protoreflect.GroupKind { - name = string(fd.Message().Name()) - } - w.write(name) - default: - w.write(string(fd.JSONName())) - } - w.write(`":`) - if w.Indent != "" { - w.write(" ") - } - return w.marshalValue(fd, v, indent) -} - -func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { - switch { - case fd.IsList(): - w.write("[") - comma := "" - lv := v.List() - for i := 0; i < lv.Len(); i++ { - w.write(comma) - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - w.write(w.Indent) - } - if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil { - return err - } - comma = "," - } - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - } - w.write("]") - return nil - case fd.IsMap(): - kfd := fd.MapKey() - vfd := fd.MapValue() - mv := v.Map() - - // Collect a sorted list of all map keys and values. - type entry struct{ key, val protoreflect.Value } - var entries []entry - mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { - entries = append(entries, entry{k.Value(), v}) - return true - }) - sort.Slice(entries, func(i, j int) bool { - switch kfd.Kind() { - case protoreflect.BoolKind: - return !entries[i].key.Bool() && entries[j].key.Bool() - case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: - return entries[i].key.Int() < entries[j].key.Int() - case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind: - return entries[i].key.Uint() < entries[j].key.Uint() - case protoreflect.StringKind: - return entries[i].key.String() < entries[j].key.String() - default: - panic("invalid kind") - } - }) - - w.write(`{`) - comma := "" - for _, entry := range entries { - w.write(comma) - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - w.write(w.Indent) - } - - s := fmt.Sprint(entry.key.Interface()) - b, err := json.Marshal(s) - if err != nil { - return err - } - w.write(string(b)) - - w.write(`:`) - if w.Indent != "" { - w.write(` `) - } - - if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil { - return err - } - comma = "," - } - if w.Indent != "" { - w.write("\n") - w.write(indent) - w.write(w.Indent) - } - w.write(`}`) - return nil - default: - return w.marshalSingularValue(fd, v, indent) - } -} - -func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error { - switch { - case !v.IsValid(): - w.write("null") - return nil - case fd.Message() != nil: - return w.marshalMessage(v.Message(), indent+w.Indent, "") - case fd.Enum() != nil: - if fd.Enum().FullName() == "google.protobuf.NullValue" { - w.write("null") - return nil - } - - vd := fd.Enum().Values().ByNumber(v.Enum()) - if vd == nil || w.EnumsAsInts { - w.write(strconv.Itoa(int(v.Enum()))) - } else { - w.write(`"` + string(vd.Name()) + `"`) - } - return nil - default: - switch v.Interface().(type) { - case float32, float64: - switch { - case math.IsInf(v.Float(), +1): - w.write(`"Infinity"`) - return nil - case math.IsInf(v.Float(), -1): - w.write(`"-Infinity"`) - return nil - case math.IsNaN(v.Float()): - w.write(`"NaN"`) - return nil - } - case int64, uint64: - w.write(fmt.Sprintf(`"%d"`, v.Interface())) - return nil - } - - b, err := json.Marshal(v.Interface()) - if err != nil { - return err - } - w.write(string(b)) - return nil - } -} diff --git a/etcd/vendor/github.com/golang/protobuf/jsonpb/json.go b/etcd/vendor/github.com/golang/protobuf/jsonpb/json.go deleted file mode 100644 index 480e2448de..0000000000 --- a/etcd/vendor/github.com/golang/protobuf/jsonpb/json.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2015 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 jsonpb provides functionality to marshal and unmarshal between a -// protocol buffer message and JSON. It follows the specification at -// https://developers.google.com/protocol-buffers/docs/proto3#json. -// -// Do not rely on the default behavior of the standard encoding/json package -// when called on generated message types as it does not operate correctly. -// -// Deprecated: Use the "google.golang.org/protobuf/encoding/protojson" -// package instead. -package jsonpb - -import ( - "github.com/golang/protobuf/proto" - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/reflect/protoregistry" - "google.golang.org/protobuf/runtime/protoimpl" -) - -// AnyResolver takes a type URL, present in an Any message, -// and resolves it into an instance of the associated message. -type AnyResolver interface { - Resolve(typeURL string) (proto.Message, error) -} - -type anyResolver struct{ AnyResolver } - -func (r anyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) { - return r.FindMessageByURL(string(message)) -} - -func (r anyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) { - m, err := r.Resolve(url) - if err != nil { - return nil, err - } - return protoimpl.X.MessageTypeOf(m), nil -} - -func (r anyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) { - return protoregistry.GlobalTypes.FindExtensionByName(field) -} - -func (r anyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) { - return protoregistry.GlobalTypes.FindExtensionByNumber(message, field) -} - -func wellKnownType(s protoreflect.FullName) string { - if s.Parent() == "google.protobuf" { - switch s.Name() { - case "Empty", "Any", - "BoolValue", "BytesValue", "StringValue", - "Int32Value", "UInt32Value", "FloatValue", - "Int64Value", "UInt64Value", "DoubleValue", - "Duration", "Timestamp", - "NullValue", "Struct", "Value", "ListValue": - return string(s.Name()) - } - } - return "" -} - -func isMessageSet(md protoreflect.MessageDescriptor) bool { - ms, ok := md.(interface{ IsMessageSet() bool }) - return ok && ms.IsMessageSet() -} diff --git a/etcd/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go b/etcd/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go deleted file mode 100644 index a5a138613a..0000000000 --- a/etcd/vendor/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.pb.go +++ /dev/null @@ -1,324 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor.proto - -package descriptor - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - descriptorpb "google.golang.org/protobuf/types/descriptorpb" - reflect "reflect" -) - -// Symbols defined in public import of google/protobuf/descriptor.proto. - -type Edition = descriptorpb.Edition - -const Edition_EDITION_UNKNOWN = descriptorpb.Edition_EDITION_UNKNOWN -const Edition_EDITION_PROTO2 = descriptorpb.Edition_EDITION_PROTO2 -const Edition_EDITION_PROTO3 = descriptorpb.Edition_EDITION_PROTO3 -const Edition_EDITION_2023 = descriptorpb.Edition_EDITION_2023 -const Edition_EDITION_2024 = descriptorpb.Edition_EDITION_2024 -const Edition_EDITION_1_TEST_ONLY = descriptorpb.Edition_EDITION_1_TEST_ONLY -const Edition_EDITION_2_TEST_ONLY = descriptorpb.Edition_EDITION_2_TEST_ONLY -const Edition_EDITION_99997_TEST_ONLY = descriptorpb.Edition_EDITION_99997_TEST_ONLY -const Edition_EDITION_99998_TEST_ONLY = descriptorpb.Edition_EDITION_99998_TEST_ONLY -const Edition_EDITION_99999_TEST_ONLY = descriptorpb.Edition_EDITION_99999_TEST_ONLY -const Edition_EDITION_MAX = descriptorpb.Edition_EDITION_MAX - -var Edition_name = descriptorpb.Edition_name -var Edition_value = descriptorpb.Edition_value - -type ExtensionRangeOptions_VerificationState = descriptorpb.ExtensionRangeOptions_VerificationState - -const ExtensionRangeOptions_DECLARATION = descriptorpb.ExtensionRangeOptions_DECLARATION -const ExtensionRangeOptions_UNVERIFIED = descriptorpb.ExtensionRangeOptions_UNVERIFIED - -var ExtensionRangeOptions_VerificationState_name = descriptorpb.ExtensionRangeOptions_VerificationState_name -var ExtensionRangeOptions_VerificationState_value = descriptorpb.ExtensionRangeOptions_VerificationState_value - -type FieldDescriptorProto_Type = descriptorpb.FieldDescriptorProto_Type - -const FieldDescriptorProto_TYPE_DOUBLE = descriptorpb.FieldDescriptorProto_TYPE_DOUBLE -const FieldDescriptorProto_TYPE_FLOAT = descriptorpb.FieldDescriptorProto_TYPE_FLOAT -const FieldDescriptorProto_TYPE_INT64 = descriptorpb.FieldDescriptorProto_TYPE_INT64 -const FieldDescriptorProto_TYPE_UINT64 = descriptorpb.FieldDescriptorProto_TYPE_UINT64 -const FieldDescriptorProto_TYPE_INT32 = descriptorpb.FieldDescriptorProto_TYPE_INT32 -const FieldDescriptorProto_TYPE_FIXED64 = descriptorpb.FieldDescriptorProto_TYPE_FIXED64 -const FieldDescriptorProto_TYPE_FIXED32 = descriptorpb.FieldDescriptorProto_TYPE_FIXED32 -const FieldDescriptorProto_TYPE_BOOL = descriptorpb.FieldDescriptorProto_TYPE_BOOL -const FieldDescriptorProto_TYPE_STRING = descriptorpb.FieldDescriptorProto_TYPE_STRING -const FieldDescriptorProto_TYPE_GROUP = descriptorpb.FieldDescriptorProto_TYPE_GROUP -const FieldDescriptorProto_TYPE_MESSAGE = descriptorpb.FieldDescriptorProto_TYPE_MESSAGE -const FieldDescriptorProto_TYPE_BYTES = descriptorpb.FieldDescriptorProto_TYPE_BYTES -const FieldDescriptorProto_TYPE_UINT32 = descriptorpb.FieldDescriptorProto_TYPE_UINT32 -const FieldDescriptorProto_TYPE_ENUM = descriptorpb.FieldDescriptorProto_TYPE_ENUM -const FieldDescriptorProto_TYPE_SFIXED32 = descriptorpb.FieldDescriptorProto_TYPE_SFIXED32 -const FieldDescriptorProto_TYPE_SFIXED64 = descriptorpb.FieldDescriptorProto_TYPE_SFIXED64 -const FieldDescriptorProto_TYPE_SINT32 = descriptorpb.FieldDescriptorProto_TYPE_SINT32 -const FieldDescriptorProto_TYPE_SINT64 = descriptorpb.FieldDescriptorProto_TYPE_SINT64 - -var FieldDescriptorProto_Type_name = descriptorpb.FieldDescriptorProto_Type_name -var FieldDescriptorProto_Type_value = descriptorpb.FieldDescriptorProto_Type_value - -type FieldDescriptorProto_Label = descriptorpb.FieldDescriptorProto_Label - -const FieldDescriptorProto_LABEL_OPTIONAL = descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL -const FieldDescriptorProto_LABEL_REPEATED = descriptorpb.FieldDescriptorProto_LABEL_REPEATED -const FieldDescriptorProto_LABEL_REQUIRED = descriptorpb.FieldDescriptorProto_LABEL_REQUIRED - -var FieldDescriptorProto_Label_name = descriptorpb.FieldDescriptorProto_Label_name -var FieldDescriptorProto_Label_value = descriptorpb.FieldDescriptorProto_Label_value - -type FileOptions_OptimizeMode = descriptorpb.FileOptions_OptimizeMode - -const FileOptions_SPEED = descriptorpb.FileOptions_SPEED -const FileOptions_CODE_SIZE = descriptorpb.FileOptions_CODE_SIZE -const FileOptions_LITE_RUNTIME = descriptorpb.FileOptions_LITE_RUNTIME - -var FileOptions_OptimizeMode_name = descriptorpb.FileOptions_OptimizeMode_name -var FileOptions_OptimizeMode_value = descriptorpb.FileOptions_OptimizeMode_value - -type FieldOptions_CType = descriptorpb.FieldOptions_CType - -const FieldOptions_STRING = descriptorpb.FieldOptions_STRING -const FieldOptions_CORD = descriptorpb.FieldOptions_CORD -const FieldOptions_STRING_PIECE = descriptorpb.FieldOptions_STRING_PIECE - -var FieldOptions_CType_name = descriptorpb.FieldOptions_CType_name -var FieldOptions_CType_value = descriptorpb.FieldOptions_CType_value - -type FieldOptions_JSType = descriptorpb.FieldOptions_JSType - -const FieldOptions_JS_NORMAL = descriptorpb.FieldOptions_JS_NORMAL -const FieldOptions_JS_STRING = descriptorpb.FieldOptions_JS_STRING -const FieldOptions_JS_NUMBER = descriptorpb.FieldOptions_JS_NUMBER - -var FieldOptions_JSType_name = descriptorpb.FieldOptions_JSType_name -var FieldOptions_JSType_value = descriptorpb.FieldOptions_JSType_value - -type FieldOptions_OptionRetention = descriptorpb.FieldOptions_OptionRetention - -const FieldOptions_RETENTION_UNKNOWN = descriptorpb.FieldOptions_RETENTION_UNKNOWN -const FieldOptions_RETENTION_RUNTIME = descriptorpb.FieldOptions_RETENTION_RUNTIME -const FieldOptions_RETENTION_SOURCE = descriptorpb.FieldOptions_RETENTION_SOURCE - -var FieldOptions_OptionRetention_name = descriptorpb.FieldOptions_OptionRetention_name -var FieldOptions_OptionRetention_value = descriptorpb.FieldOptions_OptionRetention_value - -type FieldOptions_OptionTargetType = descriptorpb.FieldOptions_OptionTargetType - -const FieldOptions_TARGET_TYPE_UNKNOWN = descriptorpb.FieldOptions_TARGET_TYPE_UNKNOWN -const FieldOptions_TARGET_TYPE_FILE = descriptorpb.FieldOptions_TARGET_TYPE_FILE -const FieldOptions_TARGET_TYPE_EXTENSION_RANGE = descriptorpb.FieldOptions_TARGET_TYPE_EXTENSION_RANGE -const FieldOptions_TARGET_TYPE_MESSAGE = descriptorpb.FieldOptions_TARGET_TYPE_MESSAGE -const FieldOptions_TARGET_TYPE_FIELD = descriptorpb.FieldOptions_TARGET_TYPE_FIELD -const FieldOptions_TARGET_TYPE_ONEOF = descriptorpb.FieldOptions_TARGET_TYPE_ONEOF -const FieldOptions_TARGET_TYPE_ENUM = descriptorpb.FieldOptions_TARGET_TYPE_ENUM -const FieldOptions_TARGET_TYPE_ENUM_ENTRY = descriptorpb.FieldOptions_TARGET_TYPE_ENUM_ENTRY -const FieldOptions_TARGET_TYPE_SERVICE = descriptorpb.FieldOptions_TARGET_TYPE_SERVICE -const FieldOptions_TARGET_TYPE_METHOD = descriptorpb.FieldOptions_TARGET_TYPE_METHOD - -var FieldOptions_OptionTargetType_name = descriptorpb.FieldOptions_OptionTargetType_name -var FieldOptions_OptionTargetType_value = descriptorpb.FieldOptions_OptionTargetType_value - -type MethodOptions_IdempotencyLevel = descriptorpb.MethodOptions_IdempotencyLevel - -const MethodOptions_IDEMPOTENCY_UNKNOWN = descriptorpb.MethodOptions_IDEMPOTENCY_UNKNOWN -const MethodOptions_NO_SIDE_EFFECTS = descriptorpb.MethodOptions_NO_SIDE_EFFECTS -const MethodOptions_IDEMPOTENT = descriptorpb.MethodOptions_IDEMPOTENT - -var MethodOptions_IdempotencyLevel_name = descriptorpb.MethodOptions_IdempotencyLevel_name -var MethodOptions_IdempotencyLevel_value = descriptorpb.MethodOptions_IdempotencyLevel_value - -type FeatureSet_FieldPresence = descriptorpb.FeatureSet_FieldPresence - -const FeatureSet_FIELD_PRESENCE_UNKNOWN = descriptorpb.FeatureSet_FIELD_PRESENCE_UNKNOWN -const FeatureSet_EXPLICIT = descriptorpb.FeatureSet_EXPLICIT -const FeatureSet_IMPLICIT = descriptorpb.FeatureSet_IMPLICIT -const FeatureSet_LEGACY_REQUIRED = descriptorpb.FeatureSet_LEGACY_REQUIRED - -var FeatureSet_FieldPresence_name = descriptorpb.FeatureSet_FieldPresence_name -var FeatureSet_FieldPresence_value = descriptorpb.FeatureSet_FieldPresence_value - -type FeatureSet_EnumType = descriptorpb.FeatureSet_EnumType - -const FeatureSet_ENUM_TYPE_UNKNOWN = descriptorpb.FeatureSet_ENUM_TYPE_UNKNOWN -const FeatureSet_OPEN = descriptorpb.FeatureSet_OPEN -const FeatureSet_CLOSED = descriptorpb.FeatureSet_CLOSED - -var FeatureSet_EnumType_name = descriptorpb.FeatureSet_EnumType_name -var FeatureSet_EnumType_value = descriptorpb.FeatureSet_EnumType_value - -type FeatureSet_RepeatedFieldEncoding = descriptorpb.FeatureSet_RepeatedFieldEncoding - -const FeatureSet_REPEATED_FIELD_ENCODING_UNKNOWN = descriptorpb.FeatureSet_REPEATED_FIELD_ENCODING_UNKNOWN -const FeatureSet_PACKED = descriptorpb.FeatureSet_PACKED -const FeatureSet_EXPANDED = descriptorpb.FeatureSet_EXPANDED - -var FeatureSet_RepeatedFieldEncoding_name = descriptorpb.FeatureSet_RepeatedFieldEncoding_name -var FeatureSet_RepeatedFieldEncoding_value = descriptorpb.FeatureSet_RepeatedFieldEncoding_value - -type FeatureSet_Utf8Validation = descriptorpb.FeatureSet_Utf8Validation - -const FeatureSet_UTF8_VALIDATION_UNKNOWN = descriptorpb.FeatureSet_UTF8_VALIDATION_UNKNOWN -const FeatureSet_VERIFY = descriptorpb.FeatureSet_VERIFY -const FeatureSet_NONE = descriptorpb.FeatureSet_NONE - -var FeatureSet_Utf8Validation_name = descriptorpb.FeatureSet_Utf8Validation_name -var FeatureSet_Utf8Validation_value = descriptorpb.FeatureSet_Utf8Validation_value - -type FeatureSet_MessageEncoding = descriptorpb.FeatureSet_MessageEncoding - -const FeatureSet_MESSAGE_ENCODING_UNKNOWN = descriptorpb.FeatureSet_MESSAGE_ENCODING_UNKNOWN -const FeatureSet_LENGTH_PREFIXED = descriptorpb.FeatureSet_LENGTH_PREFIXED -const FeatureSet_DELIMITED = descriptorpb.FeatureSet_DELIMITED - -var FeatureSet_MessageEncoding_name = descriptorpb.FeatureSet_MessageEncoding_name -var FeatureSet_MessageEncoding_value = descriptorpb.FeatureSet_MessageEncoding_value - -type FeatureSet_JsonFormat = descriptorpb.FeatureSet_JsonFormat - -const FeatureSet_JSON_FORMAT_UNKNOWN = descriptorpb.FeatureSet_JSON_FORMAT_UNKNOWN -const FeatureSet_ALLOW = descriptorpb.FeatureSet_ALLOW -const FeatureSet_LEGACY_BEST_EFFORT = descriptorpb.FeatureSet_LEGACY_BEST_EFFORT - -var FeatureSet_JsonFormat_name = descriptorpb.FeatureSet_JsonFormat_name -var FeatureSet_JsonFormat_value = descriptorpb.FeatureSet_JsonFormat_value - -type GeneratedCodeInfo_Annotation_Semantic = descriptorpb.GeneratedCodeInfo_Annotation_Semantic - -const GeneratedCodeInfo_Annotation_NONE = descriptorpb.GeneratedCodeInfo_Annotation_NONE -const GeneratedCodeInfo_Annotation_SET = descriptorpb.GeneratedCodeInfo_Annotation_SET -const GeneratedCodeInfo_Annotation_ALIAS = descriptorpb.GeneratedCodeInfo_Annotation_ALIAS - -var GeneratedCodeInfo_Annotation_Semantic_name = descriptorpb.GeneratedCodeInfo_Annotation_Semantic_name -var GeneratedCodeInfo_Annotation_Semantic_value = descriptorpb.GeneratedCodeInfo_Annotation_Semantic_value - -type FileDescriptorSet = descriptorpb.FileDescriptorSet -type FileDescriptorProto = descriptorpb.FileDescriptorProto -type DescriptorProto = descriptorpb.DescriptorProto -type ExtensionRangeOptions = descriptorpb.ExtensionRangeOptions - -const Default_ExtensionRangeOptions_Verification = descriptorpb.Default_ExtensionRangeOptions_Verification - -type FieldDescriptorProto = descriptorpb.FieldDescriptorProto -type OneofDescriptorProto = descriptorpb.OneofDescriptorProto -type EnumDescriptorProto = descriptorpb.EnumDescriptorProto -type EnumValueDescriptorProto = descriptorpb.EnumValueDescriptorProto -type ServiceDescriptorProto = descriptorpb.ServiceDescriptorProto -type MethodDescriptorProto = descriptorpb.MethodDescriptorProto - -const Default_MethodDescriptorProto_ClientStreaming = descriptorpb.Default_MethodDescriptorProto_ClientStreaming -const Default_MethodDescriptorProto_ServerStreaming = descriptorpb.Default_MethodDescriptorProto_ServerStreaming - -type FileOptions = descriptorpb.FileOptions - -const Default_FileOptions_JavaMultipleFiles = descriptorpb.Default_FileOptions_JavaMultipleFiles -const Default_FileOptions_JavaStringCheckUtf8 = descriptorpb.Default_FileOptions_JavaStringCheckUtf8 -const Default_FileOptions_OptimizeFor = descriptorpb.Default_FileOptions_OptimizeFor -const Default_FileOptions_CcGenericServices = descriptorpb.Default_FileOptions_CcGenericServices -const Default_FileOptions_JavaGenericServices = descriptorpb.Default_FileOptions_JavaGenericServices -const Default_FileOptions_PyGenericServices = descriptorpb.Default_FileOptions_PyGenericServices -const Default_FileOptions_Deprecated = descriptorpb.Default_FileOptions_Deprecated -const Default_FileOptions_CcEnableArenas = descriptorpb.Default_FileOptions_CcEnableArenas - -type MessageOptions = descriptorpb.MessageOptions - -const Default_MessageOptions_MessageSetWireFormat = descriptorpb.Default_MessageOptions_MessageSetWireFormat -const Default_MessageOptions_NoStandardDescriptorAccessor = descriptorpb.Default_MessageOptions_NoStandardDescriptorAccessor -const Default_MessageOptions_Deprecated = descriptorpb.Default_MessageOptions_Deprecated - -type FieldOptions = descriptorpb.FieldOptions - -const Default_FieldOptions_Ctype = descriptorpb.Default_FieldOptions_Ctype -const Default_FieldOptions_Jstype = descriptorpb.Default_FieldOptions_Jstype -const Default_FieldOptions_Lazy = descriptorpb.Default_FieldOptions_Lazy -const Default_FieldOptions_UnverifiedLazy = descriptorpb.Default_FieldOptions_UnverifiedLazy -const Default_FieldOptions_Deprecated = descriptorpb.Default_FieldOptions_Deprecated -const Default_FieldOptions_Weak = descriptorpb.Default_FieldOptions_Weak -const Default_FieldOptions_DebugRedact = descriptorpb.Default_FieldOptions_DebugRedact - -type OneofOptions = descriptorpb.OneofOptions -type EnumOptions = descriptorpb.EnumOptions - -const Default_EnumOptions_Deprecated = descriptorpb.Default_EnumOptions_Deprecated - -type EnumValueOptions = descriptorpb.EnumValueOptions - -const Default_EnumValueOptions_Deprecated = descriptorpb.Default_EnumValueOptions_Deprecated -const Default_EnumValueOptions_DebugRedact = descriptorpb.Default_EnumValueOptions_DebugRedact - -type ServiceOptions = descriptorpb.ServiceOptions - -const Default_ServiceOptions_Deprecated = descriptorpb.Default_ServiceOptions_Deprecated - -type MethodOptions = descriptorpb.MethodOptions - -const Default_MethodOptions_Deprecated = descriptorpb.Default_MethodOptions_Deprecated -const Default_MethodOptions_IdempotencyLevel = descriptorpb.Default_MethodOptions_IdempotencyLevel - -type UninterpretedOption = descriptorpb.UninterpretedOption -type FeatureSet = descriptorpb.FeatureSet -type FeatureSetDefaults = descriptorpb.FeatureSetDefaults -type SourceCodeInfo = descriptorpb.SourceCodeInfo -type GeneratedCodeInfo = descriptorpb.GeneratedCodeInfo -type DescriptorProto_ExtensionRange = descriptorpb.DescriptorProto_ExtensionRange -type DescriptorProto_ReservedRange = descriptorpb.DescriptorProto_ReservedRange -type ExtensionRangeOptions_Declaration = descriptorpb.ExtensionRangeOptions_Declaration -type EnumDescriptorProto_EnumReservedRange = descriptorpb.EnumDescriptorProto_EnumReservedRange -type FieldOptions_EditionDefault = descriptorpb.FieldOptions_EditionDefault -type UninterpretedOption_NamePart = descriptorpb.UninterpretedOption_NamePart -type FeatureSetDefaults_FeatureSetEditionDefault = descriptorpb.FeatureSetDefaults_FeatureSetEditionDefault -type SourceCodeInfo_Location = descriptorpb.SourceCodeInfo_Location -type GeneratedCodeInfo_Annotation = descriptorpb.GeneratedCodeInfo_Annotation - -var File_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto protoreflect.FileDescriptor - -var file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_rawDesc = []byte{ - 0x0a, 0x44, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, - 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x40, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, - 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x3b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x32, -} - -var file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_goTypes = []interface{}{} -var file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_init() } -func file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_init() { - if File_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_rawDesc, - NumEnums: 0, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_goTypes, - DependencyIndexes: file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_depIdxs, - }.Build() - File_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto = out.File - file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_rawDesc = nil - file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_goTypes = nil - file_github_com_golang_protobuf_protoc_gen_go_descriptor_descriptor_proto_depIdxs = nil -} diff --git a/etcd/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go b/etcd/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go deleted file mode 100644 index 0ef27d33de..0000000000 --- a/etcd/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go +++ /dev/null @@ -1,62 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/golang/protobuf/ptypes/any/any.proto - -package any - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - anypb "google.golang.org/protobuf/types/known/anypb" - reflect "reflect" -) - -// Symbols defined in public import of google/protobuf/any.proto. - -type Any = anypb.Any - -var File_github_com_golang_protobuf_ptypes_any_any_proto protoreflect.FileDescriptor - -var file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc = []byte{ - 0x0a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, - 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x61, 0x6e, 0x79, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x2b, 0x5a, 0x29, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, - 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2f, 0x61, 0x6e, 0x79, 0x3b, 0x61, 0x6e, 0x79, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, -} - -var file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes = []interface{}{} -var file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_github_com_golang_protobuf_ptypes_any_any_proto_init() } -func file_github_com_golang_protobuf_ptypes_any_any_proto_init() { - if File_github_com_golang_protobuf_ptypes_any_any_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc, - NumEnums: 0, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes, - DependencyIndexes: file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs, - }.Build() - File_github_com_golang_protobuf_ptypes_any_any_proto = out.File - file_github_com_golang_protobuf_ptypes_any_any_proto_rawDesc = nil - file_github_com_golang_protobuf_ptypes_any_any_proto_goTypes = nil - file_github_com_golang_protobuf_ptypes_any_any_proto_depIdxs = nil -} diff --git a/etcd/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go b/etcd/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go deleted file mode 100644 index d0079ee3ef..0000000000 --- a/etcd/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go +++ /dev/null @@ -1,63 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/golang/protobuf/ptypes/duration/duration.proto - -package duration - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - reflect "reflect" -) - -// Symbols defined in public import of google/protobuf/duration.proto. - -type Duration = durationpb.Duration - -var File_github_com_golang_protobuf_ptypes_duration_duration_proto protoreflect.FileDescriptor - -var file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc = []byte{ - 0x0a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, - 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x64, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x35, 0x5a, 0x33, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes = []interface{}{} -var file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_github_com_golang_protobuf_ptypes_duration_duration_proto_init() } -func file_github_com_golang_protobuf_ptypes_duration_duration_proto_init() { - if File_github_com_golang_protobuf_ptypes_duration_duration_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc, - NumEnums: 0, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes, - DependencyIndexes: file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs, - }.Build() - File_github_com_golang_protobuf_ptypes_duration_duration_proto = out.File - file_github_com_golang_protobuf_ptypes_duration_duration_proto_rawDesc = nil - file_github_com_golang_protobuf_ptypes_duration_duration_proto_goTypes = nil - file_github_com_golang_protobuf_ptypes_duration_duration_proto_depIdxs = nil -} diff --git a/etcd/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go b/etcd/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go deleted file mode 100644 index a76f807600..0000000000 --- a/etcd/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go +++ /dev/null @@ -1,64 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/golang/protobuf/ptypes/timestamp/timestamp.proto - -package timestamp - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" -) - -// Symbols defined in public import of google/protobuf/timestamp.proto. - -type Timestamp = timestamppb.Timestamp - -var File_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto protoreflect.FileDescriptor - -var file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_rawDesc = []byte{ - 0x0a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, - 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2f, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x37, - 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, - 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x3b, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_goTypes = []interface{}{} -var file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_init() } -func file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_init() { - if File_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_rawDesc, - NumEnums: 0, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_goTypes, - DependencyIndexes: file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_depIdxs, - }.Build() - File_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto = out.File - file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_rawDesc = nil - file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_goTypes = nil - file_github_com_golang_protobuf_ptypes_timestamp_timestamp_proto_depIdxs = nil -} diff --git a/etcd/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go b/etcd/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go deleted file mode 100644 index cc40f27ad3..0000000000 --- a/etcd/vendor/github.com/golang/protobuf/ptypes/wrappers/wrappers.pb.go +++ /dev/null @@ -1,71 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: github.com/golang/protobuf/ptypes/wrappers/wrappers.proto - -package wrappers - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" - reflect "reflect" -) - -// Symbols defined in public import of google/protobuf/wrappers.proto. - -type DoubleValue = wrapperspb.DoubleValue -type FloatValue = wrapperspb.FloatValue -type Int64Value = wrapperspb.Int64Value -type UInt64Value = wrapperspb.UInt64Value -type Int32Value = wrapperspb.Int32Value -type UInt32Value = wrapperspb.UInt32Value -type BoolValue = wrapperspb.BoolValue -type StringValue = wrapperspb.StringValue -type BytesValue = wrapperspb.BytesValue - -var File_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto protoreflect.FileDescriptor - -var file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_rawDesc = []byte{ - 0x0a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, - 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2f, 0x77, 0x72, 0x61, - 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, - 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x42, 0x35, 0x5a, 0x33, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x3b, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, - 0x72, 0x73, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_goTypes = []interface{}{} -var file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_init() } -func file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_init() { - if File_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_rawDesc, - NumEnums: 0, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_goTypes, - DependencyIndexes: file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_depIdxs, - }.Build() - File_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto = out.File - file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_rawDesc = nil - file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_goTypes = nil - file_github_com_golang_protobuf_ptypes_wrappers_wrappers_proto_depIdxs = nil -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/.gitignore b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/.gitignore deleted file mode 100644 index 826caa3902..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/.gitignore +++ /dev/null @@ -1,204 +0,0 @@ -# Created by .ignore support plugin (hsz.mobi) -### Go template -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof -### Windows template -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk -### Kate template -# Swap Files # -.*.kate-swp -.swp.* -### SublimeText template -# cache files for sublime text -*.tmlanguage.cache -*.tmPreferences.cache -*.stTheme.cache - -# workspace files are user-specific -*.sublime-workspace - -# project files should be checked into the repository, unless a significant -# proportion of contributors will probably not be using SublimeText -# *.sublime-project - -# sftp configuration file -sftp-config.json -### Linux template -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* -### JetBrains template -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff: -.idea -.idea/tasks.xml -.idea/dictionaries -.idea/vcs.xml -.idea/jsLibraryMappings.xml - -# Sensitive or high-churn files: -.idea/dataSources.ids -.idea/dataSources.xml -.idea/dataSources.local.xml -.idea/sqlDataSources.xml -.idea/dynamic.xml -.idea/uiDesigner.xml - -# Gradle: -.idea/gradle.xml -.idea/libraries - -# Mongo Explorer plugin: -.idea/mongoSettings.xml - -## File-based project format: -*.iws - -## Plugin-specific files: - -# IntelliJ -/out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties -### Xcode template -# Xcode -# -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## Build generated -build/ -DerivedData/ - -## Various settings -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata/ - -## Other -*.moved-aside -*.xccheckout -*.xcscmblueprint -### Eclipse template - -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.settings/ -.loadpath -.recommenders - -# Eclipse Core -.project - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# PyDev specific (Python IDE for Eclipse) -*.pydevproject - -# CDT-specific (C/C++ Development Tooling) -.cproject - -# JDT-specific (Eclipse Java Development Tools) -.classpath - -# Java annotation processor (APT) -.factorypath - -# PDT-specific (PHP Development Tools) -.buildpath - -# sbteclipse plugin -.target - -# Tern plugin -.tern-project - -# TeXlipse plugin -.texlipse - -# STS (Spring Tool Suite) -.springBeans - -# Code Recommenders -.recommenders/ - - -coverage.txt - -#vendor -vendor/ - -.envrc \ No newline at end of file diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/.travis.yml b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/.travis.yml deleted file mode 100644 index fc198d8827..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -sudo: false -language: go -go: - - 1.13.x - - 1.14.x - - 1.15.x - -env: - global: - - GO111MODULE=on - -script: - - make test - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/CHANGELOG.md b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/CHANGELOG.md deleted file mode 100644 index 6eeb7e2dc3..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/CHANGELOG.md +++ /dev/null @@ -1,51 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - -Types of changes: -- `Added` for new features. -- `Changed` for changes in existing functionality. -- `Deprecated` for soon-to-be removed features. -- `Removed` for now removed features. -- `Fixed` for any bug fixes. -- `Security` in case of vulnerabilities. - -## [Unreleased] - -### Added - -- [#223](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/223) Add go-kit logging middleware - [adrien-f](https://github.com/adrien-f) - -## [v1.1.0] - 2019-09-12 -### Added -- [#226](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/226) Support for go modules. -- [#221](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/221) logging/zap add support for gRPC LoggerV2 - [kush-patel-hs](https://github.com/kush-patel-hs) -- [#181](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/181) Rate Limit support - [ceshihao](https://github.com/ceshihao) -- [#161](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/161) Retry on server stream call - [lonnblad](https://github.com/lonnblad) -- [#152](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/152) Exponential backoff functions - [polyfloyd](https://github.com/polyfloyd) -- [#147](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/147) Jaeger support for ctxtags extraction - [vporoshok](https://github.com/vporoshok) -- [#184](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/184) ctxTags identifies if the call was sampled - -### Deprecated -- [#201](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/201) `golang.org/x/net/context` - [houz42](https://github.com/houz42) -- [#183](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/183) Documentation Generation in favour of . - -### Fixed -- [172](https://github.com/grpc-ecosystem/go-grpc-middleware/pull/172) Passing ctx into retry and recover - [johanbrandhorst](https://github.com/johanbrandhorst) -- Numerious documentation fixes. - -## v1.0.0 - 2018-05-08 -### Added -- grpc_auth -- grpc_ctxtags -- grpc_zap -- grpc_logrus -- grpc_opentracing -- grpc_retry -- grpc_validator -- grpc_recovery - -[Unreleased]: https://github.com/grpc-ecosystem/go-grpc-middleware/compare/v1.1.0...HEAD -[v1.1.0]: https://github.com/grpc-ecosystem/go-grpc-middleware/compare/v1.0.0...v1.1.0 diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/CONTRIBUTING.md b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/CONTRIBUTING.md deleted file mode 100644 index dd52ab8938..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/CONTRIBUTING.md +++ /dev/null @@ -1,20 +0,0 @@ -# Contributing - -We would love to have people submit pull requests and help make `grpc-ecosystem/go-grpc-middleware` even better 👍. - -Fork, then clone the repo: - -```bash -git clone git@github.com:your-username/go-grpc-middleware.git -``` - -Before checking in please run the following: - -```bash -make all -``` - -This will `vet`, `fmt`, regenerate documentation and run all tests. - - -Push to your fork and open a pull request. \ No newline at end of file diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md deleted file mode 100644 index 814e155176..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/README.md +++ /dev/null @@ -1,86 +0,0 @@ -# Go gRPC Middleware - -[![Travis Build](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware.svg?branch=master)](https://travis-ci.org/grpc-ecosystem/go-grpc-middleware) -[![Go Report Card](https://goreportcard.com/badge/github.com/grpc-ecosystem/go-grpc-middleware)](https://goreportcard.com/report/github.com/grpc-ecosystem/go-grpc-middleware) -[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/grpc-ecosystem/go-grpc-middleware) -[![SourceGraph](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/-/badge.svg)](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-middleware/?badge) -[![codecov](https://codecov.io/gh/grpc-ecosystem/go-grpc-middleware/branch/master/graph/badge.svg)](https://codecov.io/gh/grpc-ecosystem/go-grpc-middleware) -[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) -[![quality: production](https://img.shields.io/badge/quality-production-orange.svg)](#status) -[![Slack](https://img.shields.io/badge/slack-%23grpc--middleware-brightgreen)](https://slack.com/share/IRUQCFC23/9Tm7hxRFVKKNoajQfMOcUiIk/enQtODc4ODI4NTIyMDcxLWM5NDA0ZTE4Njg5YjRjYWZkMTI5MzQwNDY3YzBjMzE1YzdjOGM5ZjI1NDNiM2JmNzI2YjM5ODE5OTRiNTEyOWE) - -[gRPC Go](https://github.com/grpc/grpc-go) Middleware: interceptors, helpers, utilities. - -## Middleware - -[gRPC Go](https://github.com/grpc/grpc-go) recently acquired support for -Interceptors, i.e. [middleware](https://medium.com/@matryer/writing-middleware-in-golang-and-how-go-makes-it-so-much-fun-4375c1246e81#.gv7tdlghs) -that is executed either on the gRPC Server before the request is passed onto the user's application logic, or on the gRPC client around the user call. It is a perfect way to implement -common patterns: auth, logging, message, validation, retries or monitoring. - -These are generic building blocks that make it easy to build multiple microservices easily. -The purpose of this repository is to act as a go-to point for such reusable functionality. It contains -some of them itself, but also will link to useful external repos. - -`grpc_middleware` itself provides support for chaining interceptors, here's an example: - -```go -import "github.com/grpc-ecosystem/go-grpc-middleware" - -myServer := grpc.NewServer( - grpc.StreamInterceptor(grpc_middleware.ChainStreamServer( - grpc_recovery.StreamServerInterceptor(), - grpc_ctxtags.StreamServerInterceptor(), - grpc_opentracing.StreamServerInterceptor(), - grpc_prometheus.StreamServerInterceptor, - grpc_zap.StreamServerInterceptor(zapLogger), - grpc_auth.StreamServerInterceptor(myAuthFunction), - )), - grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer( - grpc_recovery.UnaryServerInterceptor(), - grpc_ctxtags.UnaryServerInterceptor(), - grpc_opentracing.UnaryServerInterceptor(), - grpc_prometheus.UnaryServerInterceptor, - grpc_zap.UnaryServerInterceptor(zapLogger), - grpc_auth.UnaryServerInterceptor(myAuthFunction), - )), -) -``` - -## Interceptors - -*Please send a PR to add new interceptors or middleware to this list* - -#### Auth - * [`grpc_auth`](auth) - a customizable (via `AuthFunc`) piece of auth middleware - -#### Logging - * [`grpc_ctxtags`](tags/) - a library that adds a `Tag` map to context, with data populated from request body - * [`grpc_zap`](logging/zap/) - integration of [zap](https://github.com/uber-go/zap) logging library into gRPC handlers. - * [`grpc_logrus`](logging/logrus/) - integration of [logrus](https://github.com/sirupsen/logrus) logging library into gRPC handlers. - * [`grpc_kit`](logging/kit/) - integration of [go-kit](https://github.com/go-kit/kit/tree/master/log) logging library into gRPC handlers. - * [`grpc_grpc_logsettable`](logging/settable/) - a wrapper around `grpclog.LoggerV2` that allows to replace loggers in runtime (thread-safe). - -#### Monitoring - * [`grpc_prometheus`⚡](https://github.com/grpc-ecosystem/go-grpc-prometheus) - Prometheus client-side and server-side monitoring middleware - * [`otgrpc`⚡](https://github.com/grpc-ecosystem/grpc-opentracing/tree/master/go/otgrpc) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors - * [`grpc_opentracing`](tracing/opentracing) - [OpenTracing](http://opentracing.io/) client-side and server-side interceptors with support for streaming and handler-returned tags - -#### Client - * [`grpc_retry`](retry/) - a generic gRPC response code retry mechanism, client-side middleware - -#### Server - * [`grpc_validator`](validator/) - codegen inbound message validation from `.proto` options - * [`grpc_recovery`](recovery/) - turn panics into gRPC errors - * [`ratelimit`](ratelimit/) - grpc rate limiting by your own limiter - - -## Status - -This code has been running in *production* since May 2016 as the basis of the gRPC micro services stack at [Improbable](https://improbable.io). - -Additional tooling will be added, and contributions are welcome. - -## License - -`go-grpc-middleware` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details. diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go deleted file mode 100644 index ea3738b896..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/chain.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2016 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -// gRPC Server Interceptor chaining middleware. - -package grpc_middleware - -import ( - "context" - - "google.golang.org/grpc" -) - -// ChainUnaryServer creates a single interceptor out of a chain of many interceptors. -// -// Execution is done in left-to-right order, including passing of context. -// For example ChainUnaryServer(one, two, three) will execute one before two before three, and three -// will see context changes of one and two. -func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor { - n := len(interceptors) - - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - chainer := func(currentInter grpc.UnaryServerInterceptor, currentHandler grpc.UnaryHandler) grpc.UnaryHandler { - return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) { - return currentInter(currentCtx, currentReq, info, currentHandler) - } - } - - chainedHandler := handler - for i := n - 1; i >= 0; i-- { - chainedHandler = chainer(interceptors[i], chainedHandler) - } - - return chainedHandler(ctx, req) - } -} - -// ChainStreamServer creates a single interceptor out of a chain of many interceptors. -// -// Execution is done in left-to-right order, including passing of context. -// For example ChainUnaryServer(one, two, three) will execute one before two before three. -// If you want to pass context between interceptors, use WrapServerStream. -func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor { - n := len(interceptors) - - return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { - chainer := func(currentInter grpc.StreamServerInterceptor, currentHandler grpc.StreamHandler) grpc.StreamHandler { - return func(currentSrv interface{}, currentStream grpc.ServerStream) error { - return currentInter(currentSrv, currentStream, info, currentHandler) - } - } - - chainedHandler := handler - for i := n - 1; i >= 0; i-- { - chainedHandler = chainer(interceptors[i], chainedHandler) - } - - return chainedHandler(srv, ss) - } -} - -// ChainUnaryClient creates a single interceptor out of a chain of many interceptors. -// -// Execution is done in left-to-right order, including passing of context. -// For example ChainUnaryClient(one, two, three) will execute one before two before three. -func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor { - n := len(interceptors) - - return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { - chainer := func(currentInter grpc.UnaryClientInterceptor, currentInvoker grpc.UnaryInvoker) grpc.UnaryInvoker { - return func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error { - return currentInter(currentCtx, currentMethod, currentReq, currentRepl, currentConn, currentInvoker, currentOpts...) - } - } - - chainedInvoker := invoker - for i := n - 1; i >= 0; i-- { - chainedInvoker = chainer(interceptors[i], chainedInvoker) - } - - return chainedInvoker(ctx, method, req, reply, cc, opts...) - } -} - -// ChainStreamClient creates a single interceptor out of a chain of many interceptors. -// -// Execution is done in left-to-right order, including passing of context. -// For example ChainStreamClient(one, two, three) will execute one before two before three. -func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor { - n := len(interceptors) - - return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { - chainer := func(currentInter grpc.StreamClientInterceptor, currentStreamer grpc.Streamer) grpc.Streamer { - return func(currentCtx context.Context, currentDesc *grpc.StreamDesc, currentConn *grpc.ClientConn, currentMethod string, currentOpts ...grpc.CallOption) (grpc.ClientStream, error) { - return currentInter(currentCtx, currentDesc, currentConn, currentMethod, currentStreamer, currentOpts...) - } - } - - chainedStreamer := streamer - for i := n - 1; i >= 0; i-- { - chainedStreamer = chainer(interceptors[i], chainedStreamer) - } - - return chainedStreamer(ctx, desc, cc, method, opts...) - } -} - -// Chain creates a single interceptor out of a chain of many interceptors. -// -// WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors. -// Basically syntactic sugar. -func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption { - return grpc.UnaryInterceptor(ChainUnaryServer(interceptors...)) -} - -// WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors. -// Basically syntactic sugar. -func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption { - return grpc.StreamInterceptor(ChainStreamServer(interceptors...)) -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go deleted file mode 100644 index 718e10046a..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/doc.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2016 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -/* -`grpc_middleware` is a collection of gRPC middleware packages: interceptors, helpers and tools. - -Middleware - -gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang world. However, the -upstream gRPC codebase is relatively bare bones. - -This package, and most of its child packages provides commonly needed middleware for gRPC: -client-side interceptors for retires, server-side interceptors for input validation and auth, -functions for chaining said interceptors, metadata convenience methods and more. - -Chaining - -By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on -the server side. `grpc_middleware` provides convenient chaining methods - -Simple way of turning a multiple interceptors into a single interceptor. Here's an example for -server chaining: - - myServer := grpc.NewServer( - grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)), - grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary)), - ) - -These interceptors will be executed from left to right: logging, monitoring and auth. - -Here's an example for client side chaining: - - clientConn, err = grpc.Dial( - address, - grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)), - grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)), - ) - client = pb_testproto.NewTestServiceClient(clientConn) - resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"}) - -These interceptors will be executed from left to right: monitoring and then retry logic. - -The retry interceptor will call every interceptor that follows it whenever when a retry happens. - -Writing Your Own - -Implementing your own interceptor is pretty trivial: there are interfaces for that. But the interesting -bit exposing common data to handlers (and other middleware), similarly to HTTP Middleware design. -For example, you may want to pass the identity of the caller from the auth interceptor all the way -to the handling function. - -For example, a client side interceptor example for auth looks like: - - func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - newCtx := context.WithValue(ctx, "user_id", "john@example.com") - return handler(newCtx, req) - } - -Unfortunately, it's not as easy for streaming RPCs. These have the `context.Context` embedded within -the `grpc.ServerStream` object. To pass values through context, a wrapper (`WrappedServerStream`) is -needed. For example: - - func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { - newStream := grpc_middleware.WrapServerStream(stream) - newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com") - return handler(srv, newStream) - } -*/ -package grpc_middleware diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/makefile b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/makefile deleted file mode 100644 index b18d2d2bb1..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/makefile +++ /dev/null @@ -1,17 +0,0 @@ -SHELL=/bin/bash - -GOFILES_NOVENDOR = $(shell go list ./... | grep -v /vendor/) - -all: vet fmt test - -fmt: - go fmt $(GOFILES_NOVENDOR) - -vet: - # do not check lostcancel, they are intentional. - go vet -lostcancel=false $(GOFILES_NOVENDOR) - -test: vet - ./scripts/test_all.sh - -.PHONY: all test diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/LICENSE b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/LICENSE similarity index 100% rename from etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/LICENSE rename to etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/LICENSE diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_metrics.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_metrics.go new file mode 100644 index 0000000000..5c8ba20765 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_metrics.go @@ -0,0 +1,117 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +package prometheus + +import ( + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" + "github.com/prometheus/client_golang/prometheus" + "google.golang.org/grpc" +) + +// ClientMetrics represents a collection of metrics to be registered on a +// Prometheus metrics registry for a gRPC client. +type ClientMetrics struct { + clientStartedCounter *prometheus.CounterVec + clientHandledCounter *prometheus.CounterVec + clientStreamMsgReceived *prometheus.CounterVec + clientStreamMsgSent *prometheus.CounterVec + + // clientHandledHistogram can be nil + clientHandledHistogram *prometheus.HistogramVec + // clientStreamRecvHistogram can be nil + clientStreamRecvHistogram *prometheus.HistogramVec + // clientStreamSendHistogram can be nil + clientStreamSendHistogram *prometheus.HistogramVec +} + +// NewClientMetrics returns a new ClientMetrics object. +// NOTE: Remember to register ClientMetrics object using prometheus registry +// e.g. prometheus.MustRegister(myClientMetrics). +func NewClientMetrics(opts ...ClientMetricsOption) *ClientMetrics { + var config clientMetricsConfig + config.apply(opts) + return &ClientMetrics{ + clientStartedCounter: prometheus.NewCounterVec( + config.counterOpts.apply(prometheus.CounterOpts{ + Name: "grpc_client_started_total", + Help: "Total number of RPCs started on the client.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + + clientHandledCounter: prometheus.NewCounterVec( + config.counterOpts.apply(prometheus.CounterOpts{ + Name: "grpc_client_handled_total", + Help: "Total number of RPCs completed by the client, regardless of success or failure.", + }), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}), + + clientStreamMsgReceived: prometheus.NewCounterVec( + config.counterOpts.apply(prometheus.CounterOpts{ + Name: "grpc_client_msg_received_total", + Help: "Total number of RPC stream messages received by the client.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + + clientStreamMsgSent: prometheus.NewCounterVec( + config.counterOpts.apply(prometheus.CounterOpts{ + Name: "grpc_client_msg_sent_total", + Help: "Total number of gRPC stream messages sent by the client.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + + clientHandledHistogram: config.clientHandledHistogram, + clientStreamRecvHistogram: config.clientStreamRecvHistogram, + clientStreamSendHistogram: config.clientStreamSendHistogram, + } +} + +// Describe sends the super-set of all possible descriptors of metrics +// collected by this Collector to the provided channel and returns once +// the last descriptor has been sent. +func (m *ClientMetrics) Describe(ch chan<- *prometheus.Desc) { + m.clientStartedCounter.Describe(ch) + m.clientHandledCounter.Describe(ch) + m.clientStreamMsgReceived.Describe(ch) + m.clientStreamMsgSent.Describe(ch) + if m.clientHandledHistogram != nil { + m.clientHandledHistogram.Describe(ch) + } + if m.clientStreamRecvHistogram != nil { + m.clientStreamRecvHistogram.Describe(ch) + } + if m.clientStreamSendHistogram != nil { + m.clientStreamSendHistogram.Describe(ch) + } +} + +// Collect is called by the Prometheus registry when collecting +// metrics. The implementation sends each collected metric via the +// provided channel and returns once the last metric has been sent. +func (m *ClientMetrics) Collect(ch chan<- prometheus.Metric) { + m.clientStartedCounter.Collect(ch) + m.clientHandledCounter.Collect(ch) + m.clientStreamMsgReceived.Collect(ch) + m.clientStreamMsgSent.Collect(ch) + if m.clientHandledHistogram != nil { + m.clientHandledHistogram.Collect(ch) + } + if m.clientStreamRecvHistogram != nil { + m.clientStreamRecvHistogram.Collect(ch) + } + if m.clientStreamSendHistogram != nil { + m.clientStreamSendHistogram.Collect(ch) + } +} + +// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs. +func (m *ClientMetrics) UnaryClientInterceptor(opts ...Option) grpc.UnaryClientInterceptor { + return interceptors.UnaryClientInterceptor(&reportable{ + opts: opts, + clientMetrics: m, + }) +} + +// StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs. +func (m *ClientMetrics) StreamClientInterceptor(opts ...Option) grpc.StreamClientInterceptor { + return interceptors.StreamClientInterceptor(&reportable{ + opts: opts, + clientMetrics: m, + }) +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_options.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_options.go new file mode 100644 index 0000000000..c2671679c6 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/client_options.go @@ -0,0 +1,77 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +package prometheus + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +type clientMetricsConfig struct { + counterOpts counterOptions + // clientHandledHistogram can be nil. + clientHandledHistogram *prometheus.HistogramVec + // clientStreamRecvHistogram can be nil. + clientStreamRecvHistogram *prometheus.HistogramVec + // clientStreamSendHistogram can be nil. + clientStreamSendHistogram *prometheus.HistogramVec +} + +type ClientMetricsOption func(*clientMetricsConfig) + +func (c *clientMetricsConfig) apply(opts []ClientMetricsOption) { + for _, o := range opts { + o(c) + } +} + +func WithClientCounterOptions(opts ...CounterOption) ClientMetricsOption { + return func(o *clientMetricsConfig) { + o.counterOpts = opts + } +} + +// WithClientHandlingTimeHistogram turns on recording of handling time of RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func WithClientHandlingTimeHistogram(opts ...HistogramOption) ClientMetricsOption { + return func(o *clientMetricsConfig) { + o.clientHandledHistogram = prometheus.NewHistogramVec( + histogramOptions(opts).apply(prometheus.HistogramOpts{ + Name: "grpc_client_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC until it is finished by the application.", + Buckets: prometheus.DefBuckets, + }), + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } +} + +// WithClientStreamRecvHistogram turns on recording of single message receive time of streaming RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func WithClientStreamRecvHistogram(opts ...HistogramOption) ClientMetricsOption { + return func(o *clientMetricsConfig) { + o.clientStreamRecvHistogram = prometheus.NewHistogramVec( + histogramOptions(opts).apply(prometheus.HistogramOpts{ + Name: "grpc_client_msg_recv_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC single message receive.", + Buckets: prometheus.DefBuckets, + }), + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } +} + +// WithClientStreamSendHistogram turns on recording of single message send time of streaming RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func WithClientStreamSendHistogram(opts ...HistogramOption) ClientMetricsOption { + return func(o *clientMetricsConfig) { + o.clientStreamSendHistogram = prometheus.NewHistogramVec( + histogramOptions(opts).apply(prometheus.HistogramOpts{ + Name: "grpc_client_msg_send_handling_seconds", + Help: "Histogram of response latency (seconds) of the gRPC single message send.", + Buckets: prometheus.DefBuckets, + }), + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/constants.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/constants.go new file mode 100644 index 0000000000..5c36923f7e --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/constants.go @@ -0,0 +1,23 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +package prometheus + +type grpcType string + +// grpcType describes all types of grpc connection. +const ( + Unary grpcType = "unary" + ClientStream grpcType = "client_stream" + ServerStream grpcType = "server_stream" + BidiStream grpcType = "bidi_stream" +) + +// Kind describes whether interceptor is a client or server type. +type Kind string + +// Enum for Client and Server Kind. +const ( + KindClient Kind = "client" + KindServer Kind = "server" +) diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/doc.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/doc.go new file mode 100644 index 0000000000..b62f17efb7 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/doc.go @@ -0,0 +1,8 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +/* +Package prometheus provides a standalone interceptor for metrics. It's next iteration of deprecated https://github.com/grpc-ecosystem/go-grpc-prometheus. +See https://github.com/grpc-ecosystem/go-grpc-middleware/tree/main/examples for example. +*/ +package prometheus diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/options.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/options.go new file mode 100644 index 0000000000..bdd171e295 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/options.go @@ -0,0 +1,129 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +package prometheus + +import ( + "github.com/prometheus/client_golang/prometheus" + "google.golang.org/grpc" + "google.golang.org/grpc/status" +) + +// FromError returns a grpc status. If the error code is neither a valid grpc status nor a context error, codes.Unknown +// will be set. +func FromError(err error) *status.Status { + s, ok := status.FromError(err) + // Mirror what the grpc server itself does, i.e. also convert context errors to status + if !ok { + s = status.FromContextError(err) + } + return s +} + +// A CounterOption lets you add options to Counter metrics using With* funcs. +type CounterOption func(*prometheus.CounterOpts) + +type counterOptions []CounterOption + +func (co counterOptions) apply(o prometheus.CounterOpts) prometheus.CounterOpts { + for _, f := range co { + f(&o) + } + return o +} + +// WithConstLabels allows you to add ConstLabels to Counter metrics. +func WithConstLabels(labels prometheus.Labels) CounterOption { + return func(o *prometheus.CounterOpts) { + o.ConstLabels = labels + } +} + +// WithSubsystem allows you to add a Subsystem to Counter metrics. +func WithSubsystem(subsystem string) CounterOption { + return func(o *prometheus.CounterOpts) { + o.Subsystem = subsystem + } +} + +// A HistogramOption lets you add options to Histogram metrics using With* +// funcs. +type HistogramOption func(*prometheus.HistogramOpts) + +type histogramOptions []HistogramOption + +func (ho histogramOptions) apply(o prometheus.HistogramOpts) prometheus.HistogramOpts { + for _, f := range ho { + f(&o) + } + return o +} + +// WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on. +func WithHistogramBuckets(buckets []float64) HistogramOption { + return func(o *prometheus.HistogramOpts) { o.Buckets = buckets } +} + +// WithHistogramOpts allows you to specify HistogramOpts but makes sure the correct name and label is used. +// This function is helpful when specifying more than just the buckets, like using NativeHistograms. +func WithHistogramOpts(opts *prometheus.HistogramOpts) HistogramOption { + // TODO: This isn't ideal either if new fields are added to prometheus.HistogramOpts. + // Maybe we can change the interface to accept abitrary HistogramOpts and + // only make sure to overwrite the necessary fields (name, labels). + return func(o *prometheus.HistogramOpts) { + o.Buckets = opts.Buckets + o.NativeHistogramBucketFactor = opts.NativeHistogramBucketFactor + o.NativeHistogramZeroThreshold = opts.NativeHistogramZeroThreshold + o.NativeHistogramMaxBucketNumber = opts.NativeHistogramMaxBucketNumber + o.NativeHistogramMinResetDuration = opts.NativeHistogramMinResetDuration + o.NativeHistogramMaxZeroThreshold = opts.NativeHistogramMaxZeroThreshold + } +} + +// WithHistogramConstLabels allows you to add custom ConstLabels to +// histograms metrics. +func WithHistogramConstLabels(labels prometheus.Labels) HistogramOption { + return func(o *prometheus.HistogramOpts) { + o.ConstLabels = labels + } +} + +// WithHistogramSubsystem allows you to add a Subsystem to histograms metrics. +func WithHistogramSubsystem(subsystem string) HistogramOption { + return func(o *prometheus.HistogramOpts) { + o.Subsystem = subsystem + } +} + +func typeFromMethodInfo(mInfo *grpc.MethodInfo) grpcType { + if !mInfo.IsClientStream && !mInfo.IsServerStream { + return Unary + } + if mInfo.IsClientStream && !mInfo.IsServerStream { + return ClientStream + } + if !mInfo.IsClientStream && mInfo.IsServerStream { + return ServerStream + } + return BidiStream +} + +// An Option lets you add options to prometheus interceptors using With* funcs. +type Option func(*config) + +type config struct { + exemplarFn exemplarFromCtxFn +} + +func (c *config) apply(opts []Option) { + for _, o := range opts { + o(c) + } +} + +// WithExemplarFromContext sets function that will be used to deduce exemplar for all counter and histogram metrics. +func WithExemplarFromContext(exemplarFn exemplarFromCtxFn) Option { + return func(o *config) { + o.exemplarFn = exemplarFn + } +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/reporter.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/reporter.go new file mode 100644 index 0000000000..96c49ad93a --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/reporter.go @@ -0,0 +1,113 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +package prometheus + +import ( + "context" + "time" + + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" + "github.com/prometheus/client_golang/prometheus" +) + +type reporter struct { + clientMetrics *ClientMetrics + serverMetrics *ServerMetrics + typ interceptors.GRPCType + service, method string + kind Kind + exemplar prometheus.Labels +} + +func (r *reporter) PostCall(err error, rpcDuration time.Duration) { + // get status code from error + status := FromError(err) + code := status.Code() + + // perform handling of metrics from code + switch r.kind { + case KindServer: + r.incrementWithExemplar(r.serverMetrics.serverHandledCounter, string(r.typ), r.service, r.method, code.String()) + if r.serverMetrics.serverHandledHistogram != nil { + r.observeWithExemplar(r.serverMetrics.serverHandledHistogram, rpcDuration.Seconds(), string(r.typ), r.service, r.method) + } + + case KindClient: + r.incrementWithExemplar(r.clientMetrics.clientHandledCounter, string(r.typ), r.service, r.method, code.String()) + if r.clientMetrics.clientHandledHistogram != nil { + r.observeWithExemplar(r.clientMetrics.clientHandledHistogram, rpcDuration.Seconds(), string(r.typ), r.service, r.method) + } + } +} + +func (r *reporter) PostMsgSend(_ any, _ error, sendDuration time.Duration) { + switch r.kind { + case KindServer: + r.incrementWithExemplar(r.serverMetrics.serverStreamMsgSent, string(r.typ), r.service, r.method) + case KindClient: + r.incrementWithExemplar(r.clientMetrics.clientStreamMsgSent, string(r.typ), r.service, r.method) + if r.clientMetrics.clientStreamSendHistogram != nil { + r.observeWithExemplar(r.clientMetrics.clientStreamSendHistogram, sendDuration.Seconds(), string(r.typ), r.service, r.method) + } + } +} + +func (r *reporter) PostMsgReceive(_ any, _ error, recvDuration time.Duration) { + switch r.kind { + case KindServer: + r.incrementWithExemplar(r.serverMetrics.serverStreamMsgReceived, string(r.typ), r.service, r.method) + case KindClient: + r.incrementWithExemplar(r.clientMetrics.clientStreamMsgReceived, string(r.typ), r.service, r.method) + if r.clientMetrics.clientStreamRecvHistogram != nil { + r.observeWithExemplar(r.clientMetrics.clientStreamRecvHistogram, recvDuration.Seconds(), string(r.typ), r.service, r.method) + } + } +} + +type reportable struct { + clientMetrics *ClientMetrics + serverMetrics *ServerMetrics + + opts []Option +} + +func (rep *reportable) ServerReporter(ctx context.Context, meta interceptors.CallMeta) (interceptors.Reporter, context.Context) { + return rep.reporter(ctx, rep.serverMetrics, nil, meta, KindServer) +} + +func (rep *reportable) ClientReporter(ctx context.Context, meta interceptors.CallMeta) (interceptors.Reporter, context.Context) { + return rep.reporter(ctx, nil, rep.clientMetrics, meta, KindClient) +} + +func (rep *reportable) reporter(ctx context.Context, sm *ServerMetrics, cm *ClientMetrics, meta interceptors.CallMeta, kind Kind) (interceptors.Reporter, context.Context) { + var c config + c.apply(rep.opts) + r := &reporter{ + clientMetrics: cm, + serverMetrics: sm, + typ: meta.Typ, + service: meta.Service, + method: meta.Method, + kind: kind, + } + if c.exemplarFn != nil { + r.exemplar = c.exemplarFn(ctx) + } + + switch kind { + case KindClient: + r.incrementWithExemplar(r.clientMetrics.clientStartedCounter, string(r.typ), r.service, r.method) + case KindServer: + r.incrementWithExemplar(r.serverMetrics.serverStartedCounter, string(r.typ), r.service, r.method) + } + return r, ctx +} + +func (r *reporter) incrementWithExemplar(c *prometheus.CounterVec, lvals ...string) { + c.WithLabelValues(lvals...).(prometheus.ExemplarAdder).AddWithExemplar(1, r.exemplar) +} + +func (r *reporter) observeWithExemplar(h *prometheus.HistogramVec, value float64, lvals ...string) { + h.WithLabelValues(lvals...).(prometheus.ExemplarObserver).ObserveWithExemplar(value, r.exemplar) +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_metrics.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_metrics.go new file mode 100644 index 0000000000..def21e5bf1 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_metrics.go @@ -0,0 +1,124 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +package prometheus + +import ( + "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" + "github.com/prometheus/client_golang/prometheus" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +// ServerMetrics represents a collection of metrics to be registered on a +// Prometheus metrics registry for a gRPC server. +type ServerMetrics struct { + serverStartedCounter *prometheus.CounterVec + serverHandledCounter *prometheus.CounterVec + serverStreamMsgReceived *prometheus.CounterVec + serverStreamMsgSent *prometheus.CounterVec + // serverHandledHistogram can be nil. + serverHandledHistogram *prometheus.HistogramVec +} + +// NewServerMetrics returns a new ServerMetrics object that has server interceptor methods. +// NOTE: Remember to register ServerMetrics object by using prometheus registry +// e.g. prometheus.MustRegister(myServerMetrics). +func NewServerMetrics(opts ...ServerMetricsOption) *ServerMetrics { + var config serverMetricsConfig + config.apply(opts) + return &ServerMetrics{ + serverStartedCounter: prometheus.NewCounterVec( + config.counterOpts.apply(prometheus.CounterOpts{ + Name: "grpc_server_started_total", + Help: "Total number of RPCs started on the server.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + serverHandledCounter: prometheus.NewCounterVec( + config.counterOpts.apply(prometheus.CounterOpts{ + Name: "grpc_server_handled_total", + Help: "Total number of RPCs completed on the server, regardless of success or failure.", + }), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}), + serverStreamMsgReceived: prometheus.NewCounterVec( + config.counterOpts.apply(prometheus.CounterOpts{ + Name: "grpc_server_msg_received_total", + Help: "Total number of RPC stream messages received on the server.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + serverStreamMsgSent: prometheus.NewCounterVec( + config.counterOpts.apply(prometheus.CounterOpts{ + Name: "grpc_server_msg_sent_total", + Help: "Total number of gRPC stream messages sent by the server.", + }), []string{"grpc_type", "grpc_service", "grpc_method"}), + serverHandledHistogram: config.serverHandledHistogram, + } +} + +// Describe sends the super-set of all possible descriptors of metrics +// collected by this Collector to the provided channel and returns once +// the last descriptor has been sent. +func (m *ServerMetrics) Describe(ch chan<- *prometheus.Desc) { + m.serverStartedCounter.Describe(ch) + m.serverHandledCounter.Describe(ch) + m.serverStreamMsgReceived.Describe(ch) + m.serverStreamMsgSent.Describe(ch) + if m.serverHandledHistogram != nil { + m.serverHandledHistogram.Describe(ch) + } +} + +// Collect is called by the Prometheus registry when collecting +// metrics. The implementation sends each collected metric via the +// provided channel and returns once the last metric has been sent. +func (m *ServerMetrics) Collect(ch chan<- prometheus.Metric) { + m.serverStartedCounter.Collect(ch) + m.serverHandledCounter.Collect(ch) + m.serverStreamMsgReceived.Collect(ch) + m.serverStreamMsgSent.Collect(ch) + if m.serverHandledHistogram != nil { + m.serverHandledHistogram.Collect(ch) + } +} + +// InitializeMetrics initializes all metrics, with their appropriate null +// value, for all gRPC methods registered on a gRPC server. This is useful, to +// ensure that all metrics exist when collecting and querying. +// NOTE: This might add significant cardinality and might not be needed in future version of Prometheus (created timestamp). +func (m *ServerMetrics) InitializeMetrics(server reflection.ServiceInfoProvider) { + serviceInfo := server.GetServiceInfo() + for serviceName, info := range serviceInfo { + for _, mInfo := range info.Methods { + m.preRegisterMethod(serviceName, &mInfo) + } + } +} + +// preRegisterMethod is invoked on Register of a Server, allowing all gRPC services labels to be pre-populated. +func (m *ServerMetrics) preRegisterMethod(serviceName string, mInfo *grpc.MethodInfo) { + methodName := mInfo.Name + methodType := string(typeFromMethodInfo(mInfo)) + // These are just references (no increments), as just referencing will create the labels but not set values. + _, _ = m.serverStartedCounter.GetMetricWithLabelValues(methodType, serviceName, methodName) + _, _ = m.serverStreamMsgReceived.GetMetricWithLabelValues(methodType, serviceName, methodName) + _, _ = m.serverStreamMsgSent.GetMetricWithLabelValues(methodType, serviceName, methodName) + if m.serverHandledHistogram != nil { + _, _ = m.serverHandledHistogram.GetMetricWithLabelValues(methodType, serviceName, methodName) + } + for _, code := range interceptors.AllCodes { + _, _ = m.serverHandledCounter.GetMetricWithLabelValues(methodType, serviceName, methodName, code.String()) + } +} + +// UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs. +func (m *ServerMetrics) UnaryServerInterceptor(opts ...Option) grpc.UnaryServerInterceptor { + return interceptors.UnaryServerInterceptor(&reportable{ + opts: opts, + serverMetrics: m, + }) +} + +// StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs. +func (m *ServerMetrics) StreamServerInterceptor(opts ...Option) grpc.StreamServerInterceptor { + return interceptors.StreamServerInterceptor(&reportable{ + opts: opts, + serverMetrics: m, + }) +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_options.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_options.go new file mode 100644 index 0000000000..39d422042c --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus/server_options.go @@ -0,0 +1,48 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +package prometheus + +import ( + "context" + + "github.com/prometheus/client_golang/prometheus" +) + +type exemplarFromCtxFn func(ctx context.Context) prometheus.Labels + +type serverMetricsConfig struct { + counterOpts counterOptions + // serverHandledHistogram can be nil. + serverHandledHistogram *prometheus.HistogramVec +} + +type ServerMetricsOption func(*serverMetricsConfig) + +func (c *serverMetricsConfig) apply(opts []ServerMetricsOption) { + for _, o := range opts { + o(c) + } +} + +// WithServerCounterOptions sets counter options. +func WithServerCounterOptions(opts ...CounterOption) ServerMetricsOption { + return func(o *serverMetricsConfig) { + o.counterOpts = opts + } +} + +// WithServerHandlingTimeHistogram turns on recording of handling time of RPCs. +// Histogram metrics can be very expensive for Prometheus to retain and query. +func WithServerHandlingTimeHistogram(opts ...HistogramOption) ServerMetricsOption { + return func(o *serverMetricsConfig) { + o.serverHandledHistogram = prometheus.NewHistogramVec( + histogramOptions(opts).apply(prometheus.HistogramOpts{ + Name: "grpc_server_handling_seconds", + Help: "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.", + Buckets: prometheus.DefBuckets, + }), + []string{"grpc_type", "grpc_service", "grpc_method"}, + ) + } +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/slack.png b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/slack.png deleted file mode 100644 index cc8f9a68a9368ca56dab09e6902ae41ecb8356b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5088 zcmZ|Tc{Ei2`vCAe3x;e-vX2jlNl|9+lk+JWL6qTqDN!GHjk+C(5ghC|Q z89rp+TE@P8@A&Wc$M1E{ooDX7=b1U@eeXQaGxw31i7o>jCmjF)4ElOn=3p!VH&$k9 z@Kt}PY#$78cXeZR0C@NG+>s*{xXd;33>H00c<_z^VfPD82-M zOW4=V*OkE&)J}%FT3`h2YqrFIfflQ09RNm~vkfcI7zMte3Dh^%rkR6tA+FNiG=De_ z04%BcTIx4LCpPTDZn9dAoZbov8v4dCE&J634Y7Qp&X3^i)B1M(ADWDkSV*iN7kd)> zqd4~Y*H}BDdBJ$Wu0|IuL+0RbEjvkFo(wIsbO_aTEJU62)m;xvI%)0jP3x;w2nU<) z@2u*WC30Bt>TuK+>2UK948xvI_!&&wc(kmn$)(p4^0&uYvw!h_KvchE7vw+xNJ63p z3Va*cnVhjFDE_dqa(r-66Cwh$yDuYa9*+6AtDq3Cwa`yfL=H^(#{~0H2xDMeh>qp- z^0}j7#;SeYqT9-`^VAd*dw##F3SPruUt0PBV_h~NfP4F@M5ydvA!>`oqlOxml8Y8r zzfJG|=l*wk%qpd)pteM8&76R;qWwW9TCpcwP@;TaNh#IBX&G4&UHg$vw7J6|@A&?( zsfCrJb_kZ;Db(IIm_invBB-A-P@PNa5ztNMR`CDXx!apYBH{6GbYWa_$-D%2rihp| ziumC^e*@} z5o=w0)5UGOMz$zNTcdDaT%=!s;j^5_|Ht17GT%whqFOCH|R>^DXD zMAt}!?X}qW_^PT`uTGwxI&3RM$cnB1cIFcXO+WPqH??+8`FYhm@jsCz)QXkD-GBF8Qf68r3Zu%CeRqd`Zn=g=d52GkeC(9`Y}Fe(j(-f zIIZf6-pfd_l$3qrk^7gQy|S@j;}~za9XDL8R95EYEh-vYQPI=WXN2p%kf^|&j_&P6 zs)~ui`m@W+6oct&8ffAfV2nJElL&#djZrO?l{L?@_rQ9^QRmL|>*P?_w5tocu)x63 z*$E_QGTTYa&PjQtX+h1>DmTz`cKK#kSm_*o&!q}?e8m02-kDkU;FAs*spv?EP2xh? z8yP_HzSR|dpMmJ@aw0K})!{!4WbUnUoT(Zi1a+<6{YWx1SL@@Fk^-dM^6=o~KPI%( z+~6B&H-LeG)7VG+SsJ;E%XjyYFVTVXHO#B;RyQ&## z@L;7Qc6O3T9k8(m-`{i6?zlq3#Ke`0w}Q48deMR8w10au>Nc*5R%OW{)g;8;Ru>yV zHc3%`ej-l+AtPqGViPJxq=fkKswl4DzQ$wd$zC@yW~v5aR%&DW!a(+hi2)t0bqkwS z4RKmUf#Y+3Rpm6kax2t7c!wMq$lZ9GI&QpTbXUy;yd#Iti1`&2Q@}2sL0_jh?;y!e zPpvrsaqi)ecI$h26^1xR0Ylv5L)`m{%`{36i~jlfIoLtqWoK{)6ya#0RIm`@k(CzZ z!(P@Jt~FtQ7r$o7!J5vX?J0Qq*b+OP{AS?echqR%5)#~uv-8rCjnyc#J2N8|H(>N! zI}_f@ypq8c#Y^{TiKc2QVJTVX^aSU-|Awj@a;Qv<$VxI_5iKuo@q>NyQc=lz1w8uH z72gdr$&LOsyL_GRvg_QZuUX;?>+4Wh>|_HMr-31)exkDw&&Dp>H<{H9`}2qO@m4Er zr1HWe@Z!LsjJj9g&CNzdJ3FKe&I;9Ozl~SsVT<$*zG_~q`a2b$2pZ_m?Pe&u-psIvNqrE7IY+BJO(JCuY8Qd0kALDo~MNUruFUps0kp?Xp@ZQ>(NTrg)<2ilGn-s%qyqC*?ACXe<52jCC{+^x<` zudRfOGkjvmR+(W$qRFl}Vz1`ZPs#!6<4FNwIfMI>Dr}mg%z>bzfI6MQy+4x!Tb!qW zY3Wcv|2>1#c{AuCgZ7}fQsdBmkLny-jej`7zIwDyt9Sl)sIt9jg4Fi()+IKI+KoGH z(Z>hdYbuXg<;V-dmoCK;hc1jY`b{;eL;y52DQN}}-lqi^46Z`#(a$~(;^buiU9hnT zU3g??hg)6k@2{1bO+=NIeIFX%dD2xSQOCiDprN@3EQ`ljFmZ8Z_Whx1pOVW|RPt0% z%w5DT2LU%w%<>9;P3itR0@{#(#m1KIZrHg?t$*mU^}ox9zsK)@y&NxF|4OJJc4df1 zC^at5WK=1i7S2MO%M=)BcGL0_ddp*Q-Z%v}_<2m%6msvG0R$(gT~M5)MDSBbDP)MP zOt&IqFqos02t$R^9}W)E|1fs<_hYC76;t(#-$?WHo**>%Br`qC8lbq*)B@>@?%*0I@&nN;MQ%13cLLdrt8;La^(5zc-hS1AWflLodNPhs z$(YuJZm?fFIhpkLWr7!LsB{=@^|E2N!kXB!MNM60H$Id@np?5nSVd7s(hayoo()&Y zXg`XpHDCw3-4gtc<1M8gKTx4D=VL~|p?PQ3A#*x4jnV*FUn&GF_GL;(^jtLzx^sp& zK=HKFUCKm>q9rGp)E0Aka(p;WpZ?`FM-qV8wy}tu! z9i6+IwXSHl#g!rNQRrxuN+|X}C^ItVmqVz0P0-qS-P*`Drn*3*P(%bOWP}Z3perz4 zo1Pjwu&$e$c6JIsDE(kpC?W>$N)8HUMC9$piyg~E;InKoV%Q~<8$(~S(7FkOC4)eB z@{6>{L-AiblXqfN{P=B8erZ~dKNpA_Enb2bX%ZU3b<`GHTUyYPPH>-rPmj>r+J=UX z|6teB4T6ppCH>zTEpC}^5sY7Za4^XP(LJ!MvYKj$G8K4Lym4{I4Jm4zK^X70n`th* zNos7LxXkL`#K?$=(tDUXG_=_6un;~pzi3=on+N>*{rrp0Q|gZ$Goj91^k^|&xn#j{ z|J5IIGxQ7_`eU7)be+TH#JNs;`*KT|t1CDJQUUrClNaD-HV1ot>X4eycMZF%!{GG_ z_&Z!)@u9M^osSJhr)_KNEP!V2NN8w)IlXIB(}xBu!r@|8MDo~aXt+hofi0svEGUG6 zCgqIS%e@%d^}XNo-A|G3OmWRjR{9jQErB!dJ%@^nv&K63o9rYqdLa>KEUL;W5~mN1 zj451cQx%TJTSB%-goxN43Ilvh5h0F-iB~z4+3LN=V1afbj!Et4R|k_C9FG|X2XZ!i z?&fl@sgaHl+f$@z3h_QIFR!{faVdAEEjOL|!{6lG8Svh{e*MPKLhpJ2p}yK8peZSd zD4hFREjNcT^3NCYN_R3uktaLzHo@jbz$SOzphvxFPR$=5AHh;HAWJq|@x^O;%#?h< zqTCFi%$w0W4>53!XwiT~k_VdtL@lAXV&QCcMWq0F%s7u%y}cTH6!ogEgk||f1kSgW zmhRwiW_-X$^<=LvbC(2@;e1|F_#i5Jy7_|e+PwY~H49>Y@_;)dZJ!%hmqbM6 zFn|oF`;zx)ctf?^y_K!{%LLV^g46P;RAJ>D4am`o=_Qn#3y_&PRK%kQ|GYrX*T0=@ z;2PGrTLCtRK~n!x10K3X2w5L%*@Aj{*13cA{>zu>Xk<)Zj+don`S8L5TKj>`ZL81t z8x|v^=xveNRS{OOni)T{tO8iIFK`8@#GI5@3kgA8T{#(y^Z3teLmoWv-v_4^t@}5d zL$B8O*gDLH%s@Dk21_hp{$V##?HJ|d^$L@dk2z>K2fQp})cdmJd`Ta|j*HE*O^SzB z#x941NOBbE34$Xk+L=ON_H5++DDiICtKOy(ZwDRR&3uw(Z6lreFU;-V0rJdrY@g$W zRBNeY=>)@yxJi(8#LH-Qm1gI>)2<&AHa1?801GWaw`jO$LFfXSnM}Tju)8gu@twfP zoNsXsjyCM=NZ@2ZBa?u^!BnBnE~qbIVUw4K;pk-d+BHAF^k^@iYgw`V{mqK0w0SG= zS?pfqJwS^eiIfPLHB4_`eRFehX>A*4#KvjR=5=!MlEnQ4IXPHq+whseVvzZIEPd>n*c0HEB^=b!T)9QYs_=a=?8XoCa14=Hoi@)!d!C3hU}x zNiI;A+Gos$QPiTNS-ek9czB-jawL&S(&Fj^5-F^7v;|A{0`nQ^>2pqTv6T()`~rVs zfozjPsVqoRQCZJ-Un6d*4R4v<&B1xyn8;6V z_@5+XbLzAR)tTtNkV~=sx!;hur~c>cV>Wyz?6{lDo6_rS*%QgIK@+5n!#;|{wB)KyB4U|;DLJPP1C@@FzM@~ctV z`mHaSe&=SWiri9zfq#_FkUp?_PmRjf*3^_S zLE;YeaZZM+`O42Pr<>#nI#GKOILrA)zKm3Cy!7h;|7BwR5gE*}62^niPug*NjKT`} z3JP|)qN41kp6 zRe5nq8F4AOo02k$G75^43gE7yq@<=ga_s*k`1rbbx`qA!2~ym}E?|NrQ|-94SX#jjnJm)CTa(>D^oW*K(PRrb$m?jo2A=xdv3 JRcScf`yb{=X{rDK diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/COPYRIGHT b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/COPYRIGHT new file mode 100644 index 0000000000..3b13627cdb --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/COPYRIGHT @@ -0,0 +1,2 @@ +Copyright (c) The go-grpc-middleware Authors. +Licensed under the Apache License 2.0. diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/LICENSE b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/LICENSE similarity index 100% rename from etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/LICENSE rename to etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/LICENSE diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/callmeta.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/callmeta.go new file mode 100644 index 0000000000..16a18288d9 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/callmeta.go @@ -0,0 +1,66 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +package interceptors + +import ( + "fmt" + "strings" + + "google.golang.org/grpc" +) + +func splitFullMethodName(fullMethod string) (string, string) { + fullMethod = strings.TrimPrefix(fullMethod, "/") // remove leading slash + if i := strings.Index(fullMethod, "/"); i >= 0 { + return fullMethod[:i], fullMethod[i+1:] + } + return "unknown", "unknown" +} + +type CallMeta struct { + ReqOrNil any + Typ GRPCType + Service string + Method string + IsClient bool +} + +func NewClientCallMeta(fullMethod string, streamDesc *grpc.StreamDesc, reqOrNil any) CallMeta { + c := CallMeta{IsClient: true, ReqOrNil: reqOrNil, Typ: Unary} + if streamDesc != nil { + c.Typ = clientStreamType(streamDesc) + } + c.Service, c.Method = splitFullMethodName(fullMethod) + return c +} + +func NewServerCallMeta(fullMethod string, streamInfo *grpc.StreamServerInfo, reqOrNil any) CallMeta { + c := CallMeta{IsClient: false, ReqOrNil: reqOrNil, Typ: Unary} + if streamInfo != nil { + c.Typ = serverStreamType(streamInfo) + } + c.Service, c.Method = splitFullMethodName(fullMethod) + return c +} +func (c CallMeta) FullMethod() string { + return fmt.Sprintf("/%s/%s", c.Service, c.Method) +} + +func clientStreamType(desc *grpc.StreamDesc) GRPCType { + if desc.ClientStreams && !desc.ServerStreams { + return ClientStream + } else if !desc.ClientStreams && desc.ServerStreams { + return ServerStream + } + return BidiStream +} + +func serverStreamType(info *grpc.StreamServerInfo) GRPCType { + if info.IsClientStream && !info.IsServerStream { + return ClientStream + } else if !info.IsClientStream && info.IsServerStream { + return ServerStream + } + return BidiStream +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/client.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/client.go new file mode 100644 index 0000000000..2b059015c8 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/client.go @@ -0,0 +1,79 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +// Go gRPC Middleware monitoring interceptors for client-side gRPC. + +package interceptors + +import ( + "context" + "io" + "time" + + "google.golang.org/grpc" +) + +// UnaryClientInterceptor is a gRPC client-side interceptor that provides reporting for Unary RPCs. +func UnaryClientInterceptor(reportable ClientReportable) grpc.UnaryClientInterceptor { + return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + r := newReport(NewClientCallMeta(method, nil, req)) + reporter, newCtx := reportable.ClientReporter(ctx, r.callMeta) + + reporter.PostMsgSend(req, nil, time.Since(r.startTime)) + err := invoker(newCtx, method, req, reply, cc, opts...) + reporter.PostMsgReceive(reply, err, time.Since(r.startTime)) + reporter.PostCall(err, time.Since(r.startTime)) + return err + } +} + +// StreamClientInterceptor is a gRPC client-side interceptor that provides reporting for Stream RPCs. +func StreamClientInterceptor(reportable ClientReportable) grpc.StreamClientInterceptor { + return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { + r := newReport(NewClientCallMeta(method, desc, nil)) + reporter, newCtx := reportable.ClientReporter(ctx, r.callMeta) + + clientStream, err := streamer(newCtx, desc, cc, method, opts...) + if err != nil { + reporter.PostCall(err, time.Since(r.startTime)) + return nil, err + } + return &monitoredClientStream{ClientStream: clientStream, startTime: r.startTime, hasServerStream: desc.ServerStreams, reporter: reporter}, nil + } +} + +// monitoredClientStream wraps grpc.ClientStream allowing each Sent/Recv of message to report. +type monitoredClientStream struct { + grpc.ClientStream + + startTime time.Time + hasServerStream bool + reporter Reporter +} + +func (s *monitoredClientStream) SendMsg(m any) error { + start := time.Now() + err := s.ClientStream.SendMsg(m) + s.reporter.PostMsgSend(m, err, time.Since(start)) + return err +} + +func (s *monitoredClientStream) RecvMsg(m any) error { + start := time.Now() + err := s.ClientStream.RecvMsg(m) + s.reporter.PostMsgReceive(m, err, time.Since(start)) + + if s.hasServerStream { + if err == nil { + return nil + } + var postErr error + if err != io.EOF { + postErr = err + } + s.reporter.PostCall(postErr, time.Since(s.startTime)) + } else { + s.reporter.PostCall(err, time.Since(s.startTime)) + } + return err +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/doc.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/doc.go new file mode 100644 index 0000000000..2608b9a4f8 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/doc.go @@ -0,0 +1,12 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +// +/* +interceptor is an internal package used by higher level middlewares. It allows injecting custom code in various +places of the gRPC lifecycle. + +This particular package is intended for use by other middleware, metric, logging or otherwise. +This allows code to be shared between different implementations. +*/ +package interceptors diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/reporter.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/reporter.go new file mode 100644 index 0000000000..c93a3af79d --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/reporter.go @@ -0,0 +1,75 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +package interceptors + +import ( + "context" + "time" + + "google.golang.org/grpc/codes" +) + +type GRPCType string + +const ( + Unary GRPCType = "unary" + ClientStream GRPCType = "client_stream" + ServerStream GRPCType = "server_stream" + BidiStream GRPCType = "bidi_stream" +) + +var ( + AllCodes = []codes.Code{ + codes.OK, codes.Canceled, codes.Unknown, codes.InvalidArgument, codes.DeadlineExceeded, codes.NotFound, + codes.AlreadyExists, codes.PermissionDenied, codes.Unauthenticated, codes.ResourceExhausted, + codes.FailedPrecondition, codes.Aborted, codes.OutOfRange, codes.Unimplemented, codes.Internal, + codes.Unavailable, codes.DataLoss, + } +) + +type ClientReportable interface { + ClientReporter(context.Context, CallMeta) (Reporter, context.Context) +} + +type ServerReportable interface { + ServerReporter(context.Context, CallMeta) (Reporter, context.Context) +} + +// CommonReportableFunc helper allows an easy way to implement reporter with common client and server logic. +type CommonReportableFunc func(ctx context.Context, c CallMeta) (Reporter, context.Context) + +func (f CommonReportableFunc) ClientReporter(ctx context.Context, c CallMeta) (Reporter, context.Context) { + return f(ctx, c) +} + +func (f CommonReportableFunc) ServerReporter(ctx context.Context, c CallMeta) (Reporter, context.Context) { + return f(ctx, c) +} + +type Reporter interface { + PostCall(err error, rpcDuration time.Duration) + PostMsgSend(reqProto any, err error, sendDuration time.Duration) + PostMsgReceive(replyProto any, err error, recvDuration time.Duration) +} + +var _ Reporter = NoopReporter{} + +type NoopReporter struct{} + +func (NoopReporter) PostCall(error, time.Duration) {} +func (NoopReporter) PostMsgSend(any, error, time.Duration) {} +func (NoopReporter) PostMsgReceive(any, error, time.Duration) {} + +type report struct { + callMeta CallMeta + startTime time.Time +} + +func newReport(callMeta CallMeta) report { + r := report{ + startTime: time.Now(), + callMeta: callMeta, + } + return r +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/server.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/server.go new file mode 100644 index 0000000000..0484109069 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/server.go @@ -0,0 +1,65 @@ +// Copyright (c) The go-grpc-middleware Authors. +// Licensed under the Apache License 2.0. + +// Go gRPC Middleware monitoring interceptors for server-side gRPC. + +package interceptors + +import ( + "context" + "time" + + "google.golang.org/grpc" +) + +// UnaryServerInterceptor is a gRPC server-side interceptor that provides reporting for Unary RPCs. +func UnaryServerInterceptor(reportable ServerReportable) grpc.UnaryServerInterceptor { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { + r := newReport(NewServerCallMeta(info.FullMethod, nil, req)) + reporter, newCtx := reportable.ServerReporter(ctx, r.callMeta) + + reporter.PostMsgReceive(req, nil, time.Since(r.startTime)) + resp, err := handler(newCtx, req) + reporter.PostMsgSend(resp, err, time.Since(r.startTime)) + + reporter.PostCall(err, time.Since(r.startTime)) + return resp, err + } +} + +// StreamServerInterceptor is a gRPC server-side interceptor that provides reporting for Streaming RPCs. +func StreamServerInterceptor(reportable ServerReportable) grpc.StreamServerInterceptor { + return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + r := newReport(NewServerCallMeta(info.FullMethod, info, nil)) + reporter, newCtx := reportable.ServerReporter(ss.Context(), r.callMeta) + err := handler(srv, &monitoredServerStream{ServerStream: ss, newCtx: newCtx, reporter: reporter}) + reporter.PostCall(err, time.Since(r.startTime)) + return err + } +} + +// monitoredStream wraps grpc.ServerStream allowing each Sent/Recv of message to report. +type monitoredServerStream struct { + grpc.ServerStream + + newCtx context.Context + reporter Reporter +} + +func (s *monitoredServerStream) Context() context.Context { + return s.newCtx +} + +func (s *monitoredServerStream) SendMsg(m any) error { + start := time.Now() + err := s.ServerStream.SendMsg(m) + s.reporter.PostMsgSend(m, err, time.Since(start)) + return err +} + +func (s *monitoredServerStream) RecvMsg(m any) error { + start := time.Now() + err := s.ServerStream.RecvMsg(m) + s.reporter.PostMsgReceive(m, err, time.Since(start)) + return err +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go deleted file mode 100644 index 05ccfb3f24..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-middleware/wrappers.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2016 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -package grpc_middleware - -import ( - "context" - - "google.golang.org/grpc" -) - -// WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context. -type WrappedServerStream struct { - grpc.ServerStream - // WrappedContext is the wrapper's own Context. You can assign it. - WrappedContext context.Context -} - -// Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context() -func (w *WrappedServerStream) Context() context.Context { - return w.WrappedContext -} - -// WrapServerStream returns a ServerStream that has the ability to overwrite context. -func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream { - if existing, ok := stream.(*WrappedServerStream); ok { - return existing - } - return &WrappedServerStream{ServerStream: stream, WrappedContext: stream.Context()} -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/.gitignore b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/.gitignore deleted file mode 100644 index 2233cff9d1..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/.gitignore +++ /dev/null @@ -1,201 +0,0 @@ -#vendor -vendor/ - -# Created by .ignore support plugin (hsz.mobi) -coverage.txt -### Go template -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof -### Windows template -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk -### Kate template -# Swap Files # -.*.kate-swp -.swp.* -### SublimeText template -# cache files for sublime text -*.tmlanguage.cache -*.tmPreferences.cache -*.stTheme.cache - -# workspace files are user-specific -*.sublime-workspace - -# project files should be checked into the repository, unless a significant -# proportion of contributors will probably not be using SublimeText -# *.sublime-project - -# sftp configuration file -sftp-config.json -### Linux template -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* -### JetBrains template -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff: -.idea -.idea/tasks.xml -.idea/dictionaries -.idea/vcs.xml -.idea/jsLibraryMappings.xml - -# Sensitive or high-churn files: -.idea/dataSources.ids -.idea/dataSources.xml -.idea/dataSources.local.xml -.idea/sqlDataSources.xml -.idea/dynamic.xml -.idea/uiDesigner.xml - -# Gradle: -.idea/gradle.xml -.idea/libraries - -# Mongo Explorer plugin: -.idea/mongoSettings.xml - -## File-based project format: -*.iws - -## Plugin-specific files: - -# IntelliJ -/out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties -### Xcode template -# Xcode -# -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## Build generated -build/ -DerivedData/ - -## Various settings -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata/ - -## Other -*.moved-aside -*.xccheckout -*.xcscmblueprint -### Eclipse template - -.metadata -bin/ -tmp/ -*.tmp -*.bak -*.swp -*~.nib -local.properties -.settings/ -.loadpath -.recommenders - -# Eclipse Core -.project - -# External tool builders -.externalToolBuilders/ - -# Locally stored "Eclipse launch configurations" -*.launch - -# PyDev specific (Python IDE for Eclipse) -*.pydevproject - -# CDT-specific (C/C++ Development Tooling) -.cproject - -# JDT-specific (Eclipse Java Development Tools) -.classpath - -# Java annotation processor (APT) -.factorypath - -# PDT-specific (PHP Development Tools) -.buildpath - -# sbteclipse plugin -.target - -# Tern plugin -.tern-project - -# TeXlipse plugin -.texlipse - -# STS (Spring Tool Suite) -.springBeans - -# Code Recommenders -.recommenders/ - diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/.travis.yml b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/.travis.yml deleted file mode 100644 index 2a845b96ae..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -sudo: false -language: go -# * github.com/grpc/grpc-go still supports go1.6 -# - When we drop support for go1.6 we can remove golang.org/x/net/context -# below as it is part of the Go std library since go1.7 -# * github.com/prometheus/client_golang already requires at least go1.7 since -# September 2017 -go: - - 1.6.x - - 1.7.x - - 1.8.x - - 1.9.x - - 1.10.x - - master - -install: - - go get github.com/prometheus/client_golang/prometheus - - go get google.golang.org/grpc - - go get golang.org/x/net/context - - go get github.com/stretchr/testify -script: - - make test - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/CHANGELOG.md b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/CHANGELOG.md deleted file mode 100644 index 19a8059e1b..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/CHANGELOG.md +++ /dev/null @@ -1,24 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - -## [Unreleased] - -## [1.2.0](https://github.com/grpc-ecosystem/go-grpc-prometheus/releases/tag/v1.2.0) - 2018-06-04 - -### Added - -* Provide metrics object as `prometheus.Collector`, for conventional metric registration. -* Support non-default/global Prometheus registry. -* Allow configuring counters with `prometheus.CounterOpts`. - -### Changed - -* Remove usage of deprecated `grpc.Code()`. -* Remove usage of deprecated `grpc.Errorf` and replace with `status.Errorf`. - ---- - -This changelog was started with version `v1.2.0`, for earlier versions refer to the respective [GitHub releases](https://github.com/grpc-ecosystem/go-grpc-prometheus/releases). diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md deleted file mode 100644 index 499c583553..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/README.md +++ /dev/null @@ -1,247 +0,0 @@ -# Go gRPC Interceptors for Prometheus monitoring - -[![Travis Build](https://travis-ci.org/grpc-ecosystem/go-grpc-prometheus.svg)](https://travis-ci.org/grpc-ecosystem/go-grpc-prometheus) -[![Go Report Card](https://goreportcard.com/badge/github.com/grpc-ecosystem/go-grpc-prometheus)](http://goreportcard.com/report/grpc-ecosystem/go-grpc-prometheus) -[![GoDoc](http://img.shields.io/badge/GoDoc-Reference-blue.svg)](https://godoc.org/github.com/grpc-ecosystem/go-grpc-prometheus) -[![SourceGraph](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-prometheus/-/badge.svg)](https://sourcegraph.com/github.com/grpc-ecosystem/go-grpc-prometheus/?badge) -[![codecov](https://codecov.io/gh/grpc-ecosystem/go-grpc-prometheus/branch/master/graph/badge.svg)](https://codecov.io/gh/grpc-ecosystem/go-grpc-prometheus) -[![Apache 2.0 License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) - -[Prometheus](https://prometheus.io/) monitoring for your [gRPC Go](https://github.com/grpc/grpc-go) servers and clients. - -A sister implementation for [gRPC Java](https://github.com/grpc/grpc-java) (same metrics, same semantics) is in [grpc-ecosystem/java-grpc-prometheus](https://github.com/grpc-ecosystem/java-grpc-prometheus). - -## Interceptors - -[gRPC Go](https://github.com/grpc/grpc-go) recently acquired support for Interceptors, i.e. middleware that is executed -by a gRPC Server before the request is passed onto the user's application logic. It is a perfect way to implement -common patterns: auth, logging and... monitoring. - -To use Interceptors in chains, please see [`go-grpc-middleware`](https://github.com/mwitkow/go-grpc-middleware). - -## Usage - -There are two types of interceptors: client-side and server-side. This package provides monitoring Interceptors for both. - -### Server-side - -```go -import "github.com/grpc-ecosystem/go-grpc-prometheus" -... - // Initialize your gRPC server's interceptor. - myServer := grpc.NewServer( - grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor), - grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor), - ) - // Register your gRPC service implementations. - myservice.RegisterMyServiceServer(s.server, &myServiceImpl{}) - // After all your registrations, make sure all of the Prometheus metrics are initialized. - grpc_prometheus.Register(myServer) - // Register Prometheus metrics handler. - http.Handle("/metrics", promhttp.Handler()) -... -``` - -### Client-side - -```go -import "github.com/grpc-ecosystem/go-grpc-prometheus" -... - clientConn, err = grpc.Dial( - address, - grpc.WithUnaryInterceptor(grpc_prometheus.UnaryClientInterceptor), - grpc.WithStreamInterceptor(grpc_prometheus.StreamClientInterceptor) - ) - client = pb_testproto.NewTestServiceClient(clientConn) - resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"}) -... -``` - -# Metrics - -## Labels - -All server-side metrics start with `grpc_server` as Prometheus subsystem name. All client-side metrics start with `grpc_client`. Both of them have mirror-concepts. Similarly all methods -contain the same rich labels: - - * `grpc_service` - the [gRPC service](http://www.grpc.io/docs/#defining-a-service) name, which is the combination of protobuf `package` and - the `grpc_service` section name. E.g. for `package = mwitkow.testproto` and - `service TestService` the label will be `grpc_service="mwitkow.testproto.TestService"` - * `grpc_method` - the name of the method called on the gRPC service. E.g. - `grpc_method="Ping"` - * `grpc_type` - the gRPC [type of request](http://www.grpc.io/docs/guides/concepts.html#rpc-life-cycle). - Differentiating between the two is important especially for latency measurements. - - - `unary` is single request, single response RPC - - `client_stream` is a multi-request, single response RPC - - `server_stream` is a single request, multi-response RPC - - `bidi_stream` is a multi-request, multi-response RPC - - -Additionally for completed RPCs, the following labels are used: - - * `grpc_code` - the human-readable [gRPC status code](https://github.com/grpc/grpc-go/blob/master/codes/codes.go). - The list of all statuses is to long, but here are some common ones: - - - `OK` - means the RPC was successful - - `IllegalArgument` - RPC contained bad values - - `Internal` - server-side error not disclosed to the clients - -## Counters - -The counters and their up to date documentation is in [server_reporter.go](server_reporter.go) and [client_reporter.go](client_reporter.go) -the respective Prometheus handler (usually `/metrics`). - -For the purpose of this documentation we will only discuss `grpc_server` metrics. The `grpc_client` ones contain mirror concepts. - -For simplicity, let's assume we're tracking a single server-side RPC call of [`mwitkow.testproto.TestService`](examples/testproto/test.proto), -calling the method `PingList`. The call succeeds and returns 20 messages in the stream. - -First, immediately after the server receives the call it will increment the -`grpc_server_started_total` and start the handling time clock (if histograms are enabled). - -```jsoniq -grpc_server_started_total{grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 1 -``` - -Then the user logic gets invoked. It receives one message from the client containing the request -(it's a `server_stream`): - -```jsoniq -grpc_server_msg_received_total{grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 1 -``` - -The user logic may return an error, or send multiple messages back to the client. In this case, on -each of the 20 messages sent back, a counter will be incremented: - -```jsoniq -grpc_server_msg_sent_total{grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 20 -``` - -After the call completes, its status (`OK` or other [gRPC status code](https://github.com/grpc/grpc-go/blob/master/codes/codes.go)) -and the relevant call labels increment the `grpc_server_handled_total` counter. - -```jsoniq -grpc_server_handled_total{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 1 -``` - -## Histograms - -[Prometheus histograms](https://prometheus.io/docs/concepts/metric_types/#histogram) are a great way -to measure latency distributions of your RPCs. However, since it is bad practice to have metrics -of [high cardinality](https://prometheus.io/docs/practices/instrumentation/#do-not-overuse-labels) -the latency monitoring metrics are disabled by default. To enable them please call the following -in your server initialization code: - -```jsoniq -grpc_prometheus.EnableHandlingTimeHistogram() -``` - -After the call completes, its handling time will be recorded in a [Prometheus histogram](https://prometheus.io/docs/concepts/metric_types/#histogram) -variable `grpc_server_handling_seconds`. The histogram variable contains three sub-metrics: - - * `grpc_server_handling_seconds_count` - the count of all completed RPCs by status and method - * `grpc_server_handling_seconds_sum` - cumulative time of RPCs by status and method, useful for - calculating average handling times - * `grpc_server_handling_seconds_bucket` - contains the counts of RPCs by status and method in respective - handling-time buckets. These buckets can be used by Prometheus to estimate SLAs (see [here](https://prometheus.io/docs/practices/histograms/)) - -The counter values will look as follows: - -```jsoniq -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="0.005"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="0.01"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="0.025"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="0.05"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="0.1"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="0.25"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="0.5"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="1"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="2.5"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="5"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="10"} 1 -grpc_server_handling_seconds_bucket{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream",le="+Inf"} 1 -grpc_server_handling_seconds_sum{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 0.0003866430000000001 -grpc_server_handling_seconds_count{grpc_code="OK",grpc_method="PingList",grpc_service="mwitkow.testproto.TestService",grpc_type="server_stream"} 1 -``` - - -## Useful query examples - -Prometheus philosophy is to provide raw metrics to the monitoring system, and -let the aggregations be handled there. The verbosity of above metrics make it possible to have that -flexibility. Here's a couple of useful monitoring queries: - - -### request inbound rate -```jsoniq -sum(rate(grpc_server_started_total{job="foo"}[1m])) by (grpc_service) -``` -For `job="foo"` (common label to differentiate between Prometheus monitoring targets), calculate the -rate of requests per second (1 minute window) for each gRPC `grpc_service` that the job has. Please note -how the `grpc_method` is being omitted here: all methods of a given gRPC service will be summed together. - -### unary request error rate -```jsoniq -sum(rate(grpc_server_handled_total{job="foo",grpc_type="unary",grpc_code!="OK"}[1m])) by (grpc_service) -``` -For `job="foo"`, calculate the per-`grpc_service` rate of `unary` (1:1) RPCs that failed, i.e. the -ones that didn't finish with `OK` code. - -### unary request error percentage -```jsoniq -sum(rate(grpc_server_handled_total{job="foo",grpc_type="unary",grpc_code!="OK"}[1m])) by (grpc_service) - / -sum(rate(grpc_server_started_total{job="foo",grpc_type="unary"}[1m])) by (grpc_service) - * 100.0 -``` -For `job="foo"`, calculate the percentage of failed requests by service. It's easy to notice that -this is a combination of the two above examples. This is an example of a query you would like to -[alert on](https://prometheus.io/docs/alerting/rules/) in your system for SLA violations, e.g. -"no more than 1% requests should fail". - -### average response stream size -```jsoniq -sum(rate(grpc_server_msg_sent_total{job="foo",grpc_type="server_stream"}[10m])) by (grpc_service) - / -sum(rate(grpc_server_started_total{job="foo",grpc_type="server_stream"}[10m])) by (grpc_service) -``` -For `job="foo"` what is the `grpc_service`-wide `10m` average of messages returned for all ` -server_stream` RPCs. This allows you to track the stream sizes returned by your system, e.g. allows -you to track when clients started to send "wide" queries that ret -Note the divisor is the number of started RPCs, in order to account for in-flight requests. - -### 99%-tile latency of unary requests -```jsoniq -histogram_quantile(0.99, - sum(rate(grpc_server_handling_seconds_bucket{job="foo",grpc_type="unary"}[5m])) by (grpc_service,le) -) -``` -For `job="foo"`, returns an 99%-tile [quantile estimation](https://prometheus.io/docs/practices/histograms/#quantiles) -of the handling time of RPCs per service. Please note the `5m` rate, this means that the quantile -estimation will take samples in a rolling `5m` window. When combined with other quantiles -(e.g. 50%, 90%), this query gives you tremendous insight into the responsiveness of your system -(e.g. impact of caching). - -### percentage of slow unary queries (>250ms) -```jsoniq -100.0 - ( -sum(rate(grpc_server_handling_seconds_bucket{job="foo",grpc_type="unary",le="0.25"}[5m])) by (grpc_service) - / -sum(rate(grpc_server_handling_seconds_count{job="foo",grpc_type="unary"}[5m])) by (grpc_service) -) * 100.0 -``` -For `job="foo"` calculate the by-`grpc_service` fraction of slow requests that took longer than `0.25` -seconds. This query is relatively complex, since the Prometheus aggregations use `le` (less or equal) -buckets, meaning that counting "fast" requests fractions is easier. However, simple maths helps. -This is an example of a query you would like to alert on in your system for SLA violations, -e.g. "less than 1% of requests are slower than 250ms". - - -## Status - -This code has been used since August 2015 as the basis for monitoring of *production* gRPC micro services at [Improbable](https://improbable.io). - -## License - -`go-grpc-prometheus` is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details. diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go deleted file mode 100644 index 751a4c72d7..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2016 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -// gRPC Prometheus monitoring interceptors for client-side gRPC. - -package grpc_prometheus - -import ( - prom "github.com/prometheus/client_golang/prometheus" -) - -var ( - // DefaultClientMetrics is the default instance of ClientMetrics. It is - // intended to be used in conjunction the default Prometheus metrics - // registry. - DefaultClientMetrics = NewClientMetrics() - - // UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs. - UnaryClientInterceptor = DefaultClientMetrics.UnaryClientInterceptor() - - // StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs. - StreamClientInterceptor = DefaultClientMetrics.StreamClientInterceptor() -) - -func init() { - prom.MustRegister(DefaultClientMetrics.clientStartedCounter) - prom.MustRegister(DefaultClientMetrics.clientHandledCounter) - prom.MustRegister(DefaultClientMetrics.clientStreamMsgReceived) - prom.MustRegister(DefaultClientMetrics.clientStreamMsgSent) -} - -// EnableClientHandlingTimeHistogram turns on recording of handling time of -// RPCs. Histogram metrics can be very expensive for Prometheus to retain and -// query. This function acts on the DefaultClientMetrics variable and the -// default Prometheus metrics registry. -func EnableClientHandlingTimeHistogram(opts ...HistogramOption) { - DefaultClientMetrics.EnableClientHandlingTimeHistogram(opts...) - prom.Register(DefaultClientMetrics.clientHandledHistogram) -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_metrics.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_metrics.go deleted file mode 100644 index 9b476f9832..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_metrics.go +++ /dev/null @@ -1,170 +0,0 @@ -package grpc_prometheus - -import ( - "io" - - prom "github.com/prometheus/client_golang/prometheus" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// ClientMetrics represents a collection of metrics to be registered on a -// Prometheus metrics registry for a gRPC client. -type ClientMetrics struct { - clientStartedCounter *prom.CounterVec - clientHandledCounter *prom.CounterVec - clientStreamMsgReceived *prom.CounterVec - clientStreamMsgSent *prom.CounterVec - clientHandledHistogramEnabled bool - clientHandledHistogramOpts prom.HistogramOpts - clientHandledHistogram *prom.HistogramVec -} - -// NewClientMetrics returns a ClientMetrics object. Use a new instance of -// ClientMetrics when not using the default Prometheus metrics registry, for -// example when wanting to control which metrics are added to a registry as -// opposed to automatically adding metrics via init functions. -func NewClientMetrics(counterOpts ...CounterOption) *ClientMetrics { - opts := counterOptions(counterOpts) - return &ClientMetrics{ - clientStartedCounter: prom.NewCounterVec( - opts.apply(prom.CounterOpts{ - Name: "grpc_client_started_total", - Help: "Total number of RPCs started on the client.", - }), []string{"grpc_type", "grpc_service", "grpc_method"}), - - clientHandledCounter: prom.NewCounterVec( - opts.apply(prom.CounterOpts{ - Name: "grpc_client_handled_total", - Help: "Total number of RPCs completed by the client, regardless of success or failure.", - }), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}), - - clientStreamMsgReceived: prom.NewCounterVec( - opts.apply(prom.CounterOpts{ - Name: "grpc_client_msg_received_total", - Help: "Total number of RPC stream messages received by the client.", - }), []string{"grpc_type", "grpc_service", "grpc_method"}), - - clientStreamMsgSent: prom.NewCounterVec( - opts.apply(prom.CounterOpts{ - Name: "grpc_client_msg_sent_total", - Help: "Total number of gRPC stream messages sent by the client.", - }), []string{"grpc_type", "grpc_service", "grpc_method"}), - - clientHandledHistogramEnabled: false, - clientHandledHistogramOpts: prom.HistogramOpts{ - Name: "grpc_client_handling_seconds", - Help: "Histogram of response latency (seconds) of the gRPC until it is finished by the application.", - Buckets: prom.DefBuckets, - }, - clientHandledHistogram: nil, - } -} - -// Describe sends the super-set of all possible descriptors of metrics -// collected by this Collector to the provided channel and returns once -// the last descriptor has been sent. -func (m *ClientMetrics) Describe(ch chan<- *prom.Desc) { - m.clientStartedCounter.Describe(ch) - m.clientHandledCounter.Describe(ch) - m.clientStreamMsgReceived.Describe(ch) - m.clientStreamMsgSent.Describe(ch) - if m.clientHandledHistogramEnabled { - m.clientHandledHistogram.Describe(ch) - } -} - -// Collect is called by the Prometheus registry when collecting -// metrics. The implementation sends each collected metric via the -// provided channel and returns once the last metric has been sent. -func (m *ClientMetrics) Collect(ch chan<- prom.Metric) { - m.clientStartedCounter.Collect(ch) - m.clientHandledCounter.Collect(ch) - m.clientStreamMsgReceived.Collect(ch) - m.clientStreamMsgSent.Collect(ch) - if m.clientHandledHistogramEnabled { - m.clientHandledHistogram.Collect(ch) - } -} - -// EnableClientHandlingTimeHistogram turns on recording of handling time of RPCs. -// Histogram metrics can be very expensive for Prometheus to retain and query. -func (m *ClientMetrics) EnableClientHandlingTimeHistogram(opts ...HistogramOption) { - for _, o := range opts { - o(&m.clientHandledHistogramOpts) - } - if !m.clientHandledHistogramEnabled { - m.clientHandledHistogram = prom.NewHistogramVec( - m.clientHandledHistogramOpts, - []string{"grpc_type", "grpc_service", "grpc_method"}, - ) - } - m.clientHandledHistogramEnabled = true -} - -// UnaryClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Unary RPCs. -func (m *ClientMetrics) UnaryClientInterceptor() func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { - return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { - monitor := newClientReporter(m, Unary, method) - monitor.SentMessage() - err := invoker(ctx, method, req, reply, cc, opts...) - if err != nil { - monitor.ReceivedMessage() - } - st, _ := status.FromError(err) - monitor.Handled(st.Code()) - return err - } -} - -// StreamClientInterceptor is a gRPC client-side interceptor that provides Prometheus monitoring for Streaming RPCs. -func (m *ClientMetrics) StreamClientInterceptor() func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { - return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { - monitor := newClientReporter(m, clientStreamType(desc), method) - clientStream, err := streamer(ctx, desc, cc, method, opts...) - if err != nil { - st, _ := status.FromError(err) - monitor.Handled(st.Code()) - return nil, err - } - return &monitoredClientStream{clientStream, monitor}, nil - } -} - -func clientStreamType(desc *grpc.StreamDesc) grpcType { - if desc.ClientStreams && !desc.ServerStreams { - return ClientStream - } else if !desc.ClientStreams && desc.ServerStreams { - return ServerStream - } - return BidiStream -} - -// monitoredClientStream wraps grpc.ClientStream allowing each Sent/Recv of message to increment counters. -type monitoredClientStream struct { - grpc.ClientStream - monitor *clientReporter -} - -func (s *monitoredClientStream) SendMsg(m interface{}) error { - err := s.ClientStream.SendMsg(m) - if err == nil { - s.monitor.SentMessage() - } - return err -} - -func (s *monitoredClientStream) RecvMsg(m interface{}) error { - err := s.ClientStream.RecvMsg(m) - if err == nil { - s.monitor.ReceivedMessage() - } else if err == io.EOF { - s.monitor.Handled(codes.OK) - } else { - st, _ := status.FromError(err) - s.monitor.Handled(st.Code()) - } - return err -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go deleted file mode 100644 index cbf1532299..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/client_reporter.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -package grpc_prometheus - -import ( - "time" - - "google.golang.org/grpc/codes" -) - -type clientReporter struct { - metrics *ClientMetrics - rpcType grpcType - serviceName string - methodName string - startTime time.Time -} - -func newClientReporter(m *ClientMetrics, rpcType grpcType, fullMethod string) *clientReporter { - r := &clientReporter{ - metrics: m, - rpcType: rpcType, - } - if r.metrics.clientHandledHistogramEnabled { - r.startTime = time.Now() - } - r.serviceName, r.methodName = splitMethodName(fullMethod) - r.metrics.clientStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc() - return r -} - -func (r *clientReporter) ReceivedMessage() { - r.metrics.clientStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc() -} - -func (r *clientReporter) SentMessage() { - r.metrics.clientStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc() -} - -func (r *clientReporter) Handled(code codes.Code) { - r.metrics.clientHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc() - if r.metrics.clientHandledHistogramEnabled { - r.metrics.clientHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds()) - } -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/makefile b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/makefile deleted file mode 100644 index 74c0842230..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/makefile +++ /dev/null @@ -1,16 +0,0 @@ -SHELL="/bin/bash" - -GOFILES_NOVENDOR = $(shell go list ./... | grep -v /vendor/) - -all: vet fmt test - -fmt: - go fmt $(GOFILES_NOVENDOR) - -vet: - go vet $(GOFILES_NOVENDOR) - -test: vet - ./scripts/test_all.sh - -.PHONY: all vet test diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/metric_options.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/metric_options.go deleted file mode 100644 index 9d51aec981..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/metric_options.go +++ /dev/null @@ -1,41 +0,0 @@ -package grpc_prometheus - -import ( - prom "github.com/prometheus/client_golang/prometheus" -) - -// A CounterOption lets you add options to Counter metrics using With* funcs. -type CounterOption func(*prom.CounterOpts) - -type counterOptions []CounterOption - -func (co counterOptions) apply(o prom.CounterOpts) prom.CounterOpts { - for _, f := range co { - f(&o) - } - return o -} - -// WithConstLabels allows you to add ConstLabels to Counter metrics. -func WithConstLabels(labels prom.Labels) CounterOption { - return func(o *prom.CounterOpts) { - o.ConstLabels = labels - } -} - -// A HistogramOption lets you add options to Histogram metrics using With* -// funcs. -type HistogramOption func(*prom.HistogramOpts) - -// WithHistogramBuckets allows you to specify custom bucket ranges for histograms if EnableHandlingTimeHistogram is on. -func WithHistogramBuckets(buckets []float64) HistogramOption { - return func(o *prom.HistogramOpts) { o.Buckets = buckets } -} - -// WithHistogramConstLabels allows you to add custom ConstLabels to -// histograms metrics. -func WithHistogramConstLabels(labels prom.Labels) HistogramOption { - return func(o *prom.HistogramOpts) { - o.ConstLabels = labels - } -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go deleted file mode 100644 index 322f99046f..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2016 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -// gRPC Prometheus monitoring interceptors for server-side gRPC. - -package grpc_prometheus - -import ( - prom "github.com/prometheus/client_golang/prometheus" - "google.golang.org/grpc" -) - -var ( - // DefaultServerMetrics is the default instance of ServerMetrics. It is - // intended to be used in conjunction the default Prometheus metrics - // registry. - DefaultServerMetrics = NewServerMetrics() - - // UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs. - UnaryServerInterceptor = DefaultServerMetrics.UnaryServerInterceptor() - - // StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs. - StreamServerInterceptor = DefaultServerMetrics.StreamServerInterceptor() -) - -func init() { - prom.MustRegister(DefaultServerMetrics.serverStartedCounter) - prom.MustRegister(DefaultServerMetrics.serverHandledCounter) - prom.MustRegister(DefaultServerMetrics.serverStreamMsgReceived) - prom.MustRegister(DefaultServerMetrics.serverStreamMsgSent) -} - -// Register takes a gRPC server and pre-initializes all counters to 0. This -// allows for easier monitoring in Prometheus (no missing metrics), and should -// be called *after* all services have been registered with the server. This -// function acts on the DefaultServerMetrics variable. -func Register(server *grpc.Server) { - DefaultServerMetrics.InitializeMetrics(server) -} - -// EnableHandlingTimeHistogram turns on recording of handling time -// of RPCs. Histogram metrics can be very expensive for Prometheus -// to retain and query. This function acts on the DefaultServerMetrics -// variable and the default Prometheus metrics registry. -func EnableHandlingTimeHistogram(opts ...HistogramOption) { - DefaultServerMetrics.EnableHandlingTimeHistogram(opts...) - prom.Register(DefaultServerMetrics.serverHandledHistogram) -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_metrics.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_metrics.go deleted file mode 100644 index 5b1467e7aa..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_metrics.go +++ /dev/null @@ -1,185 +0,0 @@ -package grpc_prometheus - -import ( - prom "github.com/prometheus/client_golang/prometheus" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/status" -) - -// ServerMetrics represents a collection of metrics to be registered on a -// Prometheus metrics registry for a gRPC server. -type ServerMetrics struct { - serverStartedCounter *prom.CounterVec - serverHandledCounter *prom.CounterVec - serverStreamMsgReceived *prom.CounterVec - serverStreamMsgSent *prom.CounterVec - serverHandledHistogramEnabled bool - serverHandledHistogramOpts prom.HistogramOpts - serverHandledHistogram *prom.HistogramVec -} - -// NewServerMetrics returns a ServerMetrics object. Use a new instance of -// ServerMetrics when not using the default Prometheus metrics registry, for -// example when wanting to control which metrics are added to a registry as -// opposed to automatically adding metrics via init functions. -func NewServerMetrics(counterOpts ...CounterOption) *ServerMetrics { - opts := counterOptions(counterOpts) - return &ServerMetrics{ - serverStartedCounter: prom.NewCounterVec( - opts.apply(prom.CounterOpts{ - Name: "grpc_server_started_total", - Help: "Total number of RPCs started on the server.", - }), []string{"grpc_type", "grpc_service", "grpc_method"}), - serverHandledCounter: prom.NewCounterVec( - opts.apply(prom.CounterOpts{ - Name: "grpc_server_handled_total", - Help: "Total number of RPCs completed on the server, regardless of success or failure.", - }), []string{"grpc_type", "grpc_service", "grpc_method", "grpc_code"}), - serverStreamMsgReceived: prom.NewCounterVec( - opts.apply(prom.CounterOpts{ - Name: "grpc_server_msg_received_total", - Help: "Total number of RPC stream messages received on the server.", - }), []string{"grpc_type", "grpc_service", "grpc_method"}), - serverStreamMsgSent: prom.NewCounterVec( - opts.apply(prom.CounterOpts{ - Name: "grpc_server_msg_sent_total", - Help: "Total number of gRPC stream messages sent by the server.", - }), []string{"grpc_type", "grpc_service", "grpc_method"}), - serverHandledHistogramEnabled: false, - serverHandledHistogramOpts: prom.HistogramOpts{ - Name: "grpc_server_handling_seconds", - Help: "Histogram of response latency (seconds) of gRPC that had been application-level handled by the server.", - Buckets: prom.DefBuckets, - }, - serverHandledHistogram: nil, - } -} - -// EnableHandlingTimeHistogram enables histograms being registered when -// registering the ServerMetrics on a Prometheus registry. Histograms can be -// expensive on Prometheus servers. It takes options to configure histogram -// options such as the defined buckets. -func (m *ServerMetrics) EnableHandlingTimeHistogram(opts ...HistogramOption) { - for _, o := range opts { - o(&m.serverHandledHistogramOpts) - } - if !m.serverHandledHistogramEnabled { - m.serverHandledHistogram = prom.NewHistogramVec( - m.serverHandledHistogramOpts, - []string{"grpc_type", "grpc_service", "grpc_method"}, - ) - } - m.serverHandledHistogramEnabled = true -} - -// Describe sends the super-set of all possible descriptors of metrics -// collected by this Collector to the provided channel and returns once -// the last descriptor has been sent. -func (m *ServerMetrics) Describe(ch chan<- *prom.Desc) { - m.serverStartedCounter.Describe(ch) - m.serverHandledCounter.Describe(ch) - m.serverStreamMsgReceived.Describe(ch) - m.serverStreamMsgSent.Describe(ch) - if m.serverHandledHistogramEnabled { - m.serverHandledHistogram.Describe(ch) - } -} - -// Collect is called by the Prometheus registry when collecting -// metrics. The implementation sends each collected metric via the -// provided channel and returns once the last metric has been sent. -func (m *ServerMetrics) Collect(ch chan<- prom.Metric) { - m.serverStartedCounter.Collect(ch) - m.serverHandledCounter.Collect(ch) - m.serverStreamMsgReceived.Collect(ch) - m.serverStreamMsgSent.Collect(ch) - if m.serverHandledHistogramEnabled { - m.serverHandledHistogram.Collect(ch) - } -} - -// UnaryServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Unary RPCs. -func (m *ServerMetrics) UnaryServerInterceptor() func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - monitor := newServerReporter(m, Unary, info.FullMethod) - monitor.ReceivedMessage() - resp, err := handler(ctx, req) - st, _ := status.FromError(err) - monitor.Handled(st.Code()) - if err == nil { - monitor.SentMessage() - } - return resp, err - } -} - -// StreamServerInterceptor is a gRPC server-side interceptor that provides Prometheus monitoring for Streaming RPCs. -func (m *ServerMetrics) StreamServerInterceptor() func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { - return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { - monitor := newServerReporter(m, streamRPCType(info), info.FullMethod) - err := handler(srv, &monitoredServerStream{ss, monitor}) - st, _ := status.FromError(err) - monitor.Handled(st.Code()) - return err - } -} - -// InitializeMetrics initializes all metrics, with their appropriate null -// value, for all gRPC methods registered on a gRPC server. This is useful, to -// ensure that all metrics exist when collecting and querying. -func (m *ServerMetrics) InitializeMetrics(server *grpc.Server) { - serviceInfo := server.GetServiceInfo() - for serviceName, info := range serviceInfo { - for _, mInfo := range info.Methods { - preRegisterMethod(m, serviceName, &mInfo) - } - } -} - -func streamRPCType(info *grpc.StreamServerInfo) grpcType { - if info.IsClientStream && !info.IsServerStream { - return ClientStream - } else if !info.IsClientStream && info.IsServerStream { - return ServerStream - } - return BidiStream -} - -// monitoredStream wraps grpc.ServerStream allowing each Sent/Recv of message to increment counters. -type monitoredServerStream struct { - grpc.ServerStream - monitor *serverReporter -} - -func (s *monitoredServerStream) SendMsg(m interface{}) error { - err := s.ServerStream.SendMsg(m) - if err == nil { - s.monitor.SentMessage() - } - return err -} - -func (s *monitoredServerStream) RecvMsg(m interface{}) error { - err := s.ServerStream.RecvMsg(m) - if err == nil { - s.monitor.ReceivedMessage() - } - return err -} - -// preRegisterMethod is invoked on Register of a Server, allowing all gRPC services labels to be pre-populated. -func preRegisterMethod(metrics *ServerMetrics, serviceName string, mInfo *grpc.MethodInfo) { - methodName := mInfo.Name - methodType := string(typeFromMethodInfo(mInfo)) - // These are just references (no increments), as just referencing will create the labels but not set values. - metrics.serverStartedCounter.GetMetricWithLabelValues(methodType, serviceName, methodName) - metrics.serverStreamMsgReceived.GetMetricWithLabelValues(methodType, serviceName, methodName) - metrics.serverStreamMsgSent.GetMetricWithLabelValues(methodType, serviceName, methodName) - if metrics.serverHandledHistogramEnabled { - metrics.serverHandledHistogram.GetMetricWithLabelValues(methodType, serviceName, methodName) - } - for _, code := range allCodes { - metrics.serverHandledCounter.GetMetricWithLabelValues(methodType, serviceName, methodName, code.String()) - } -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go deleted file mode 100644 index aa9db5401a..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/server_reporter.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -package grpc_prometheus - -import ( - "time" - - "google.golang.org/grpc/codes" -) - -type serverReporter struct { - metrics *ServerMetrics - rpcType grpcType - serviceName string - methodName string - startTime time.Time -} - -func newServerReporter(m *ServerMetrics, rpcType grpcType, fullMethod string) *serverReporter { - r := &serverReporter{ - metrics: m, - rpcType: rpcType, - } - if r.metrics.serverHandledHistogramEnabled { - r.startTime = time.Now() - } - r.serviceName, r.methodName = splitMethodName(fullMethod) - r.metrics.serverStartedCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc() - return r -} - -func (r *serverReporter) ReceivedMessage() { - r.metrics.serverStreamMsgReceived.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc() -} - -func (r *serverReporter) SentMessage() { - r.metrics.serverStreamMsgSent.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Inc() -} - -func (r *serverReporter) Handled(code codes.Code) { - r.metrics.serverHandledCounter.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName, code.String()).Inc() - if r.metrics.serverHandledHistogramEnabled { - r.metrics.serverHandledHistogram.WithLabelValues(string(r.rpcType), r.serviceName, r.methodName).Observe(time.Since(r.startTime).Seconds()) - } -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go b/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go deleted file mode 100644 index 7987de35f4..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/go-grpc-prometheus/util.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2016 Michal Witkowski. All Rights Reserved. -// See LICENSE for licensing terms. - -package grpc_prometheus - -import ( - "strings" - - "google.golang.org/grpc" - "google.golang.org/grpc/codes" -) - -type grpcType string - -const ( - Unary grpcType = "unary" - ClientStream grpcType = "client_stream" - ServerStream grpcType = "server_stream" - BidiStream grpcType = "bidi_stream" -) - -var ( - allCodes = []codes.Code{ - codes.OK, codes.Canceled, codes.Unknown, codes.InvalidArgument, codes.DeadlineExceeded, codes.NotFound, - codes.AlreadyExists, codes.PermissionDenied, codes.Unauthenticated, codes.ResourceExhausted, - codes.FailedPrecondition, codes.Aborted, codes.OutOfRange, codes.Unimplemented, codes.Internal, - codes.Unavailable, codes.DataLoss, - } -) - -func splitMethodName(fullMethodName string) (string, string) { - fullMethodName = strings.TrimPrefix(fullMethodName, "/") // remove leading slash - if i := strings.Index(fullMethodName, "/"); i >= 0 { - return fullMethodName[:i], fullMethodName[i+1:] - } - return "unknown", "unknown" -} - -func typeFromMethodInfo(mInfo *grpc.MethodInfo) grpcType { - if !mInfo.IsClientStream && !mInfo.IsServerStream { - return Unary - } - if mInfo.IsClientStream && !mInfo.IsServerStream { - return ClientStream - } - if !mInfo.IsClientStream && mInfo.IsServerStream { - return ServerStream - } - return BidiStream -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt deleted file mode 100644 index 364516251b..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/LICENSE.txt +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2015, Gengo, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name of Gengo, Inc. nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/BUILD.bazel b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/BUILD.bazel deleted file mode 100644 index 5242751fb2..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -load("@rules_proto//proto:defs.bzl", "proto_library") -load("@io_bazel_rules_go//go:def.bzl", "go_library") -load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") - -package(default_visibility = ["//visibility:public"]) - -proto_library( - name = "internal_proto", - srcs = ["errors.proto"], - deps = ["@com_google_protobuf//:any_proto"], -) - -go_proto_library( - name = "internal_go_proto", - importpath = "github.com/grpc-ecosystem/grpc-gateway/internal", - proto = ":internal_proto", -) - -go_library( - name = "go_default_library", - embed = [":internal_go_proto"], - importpath = "github.com/grpc-ecosystem/grpc-gateway/internal", -) diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.pb.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.pb.go deleted file mode 100644 index 61101d7177..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.pb.go +++ /dev/null @@ -1,189 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: internal/errors.proto - -package internal - -import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - any "github.com/golang/protobuf/ptypes/any" - math "math" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -// Error is the generic error returned from unary RPCs. -type Error struct { - Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` - // This is to make the error more compatible with users that expect errors to be Status objects: - // https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto - // It should be the exact same message as the Error field. - Code int32 `protobuf:"varint,2,opt,name=code,proto3" json:"code,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` - Details []*any.Any `protobuf:"bytes,4,rep,name=details,proto3" json:"details,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *Error) Reset() { *m = Error{} } -func (m *Error) String() string { return proto.CompactTextString(m) } -func (*Error) ProtoMessage() {} -func (*Error) Descriptor() ([]byte, []int) { - return fileDescriptor_9b093362ca6d1e03, []int{0} -} - -func (m *Error) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Error.Unmarshal(m, b) -} -func (m *Error) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Error.Marshal(b, m, deterministic) -} -func (m *Error) XXX_Merge(src proto.Message) { - xxx_messageInfo_Error.Merge(m, src) -} -func (m *Error) XXX_Size() int { - return xxx_messageInfo_Error.Size(m) -} -func (m *Error) XXX_DiscardUnknown() { - xxx_messageInfo_Error.DiscardUnknown(m) -} - -var xxx_messageInfo_Error proto.InternalMessageInfo - -func (m *Error) GetError() string { - if m != nil { - return m.Error - } - return "" -} - -func (m *Error) GetCode() int32 { - if m != nil { - return m.Code - } - return 0 -} - -func (m *Error) GetMessage() string { - if m != nil { - return m.Message - } - return "" -} - -func (m *Error) GetDetails() []*any.Any { - if m != nil { - return m.Details - } - return nil -} - -// StreamError is a response type which is returned when -// streaming rpc returns an error. -type StreamError struct { - GrpcCode int32 `protobuf:"varint,1,opt,name=grpc_code,json=grpcCode,proto3" json:"grpc_code,omitempty"` - HttpCode int32 `protobuf:"varint,2,opt,name=http_code,json=httpCode,proto3" json:"http_code,omitempty"` - Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` - HttpStatus string `protobuf:"bytes,4,opt,name=http_status,json=httpStatus,proto3" json:"http_status,omitempty"` - Details []*any.Any `protobuf:"bytes,5,rep,name=details,proto3" json:"details,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *StreamError) Reset() { *m = StreamError{} } -func (m *StreamError) String() string { return proto.CompactTextString(m) } -func (*StreamError) ProtoMessage() {} -func (*StreamError) Descriptor() ([]byte, []int) { - return fileDescriptor_9b093362ca6d1e03, []int{1} -} - -func (m *StreamError) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_StreamError.Unmarshal(m, b) -} -func (m *StreamError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_StreamError.Marshal(b, m, deterministic) -} -func (m *StreamError) XXX_Merge(src proto.Message) { - xxx_messageInfo_StreamError.Merge(m, src) -} -func (m *StreamError) XXX_Size() int { - return xxx_messageInfo_StreamError.Size(m) -} -func (m *StreamError) XXX_DiscardUnknown() { - xxx_messageInfo_StreamError.DiscardUnknown(m) -} - -var xxx_messageInfo_StreamError proto.InternalMessageInfo - -func (m *StreamError) GetGrpcCode() int32 { - if m != nil { - return m.GrpcCode - } - return 0 -} - -func (m *StreamError) GetHttpCode() int32 { - if m != nil { - return m.HttpCode - } - return 0 -} - -func (m *StreamError) GetMessage() string { - if m != nil { - return m.Message - } - return "" -} - -func (m *StreamError) GetHttpStatus() string { - if m != nil { - return m.HttpStatus - } - return "" -} - -func (m *StreamError) GetDetails() []*any.Any { - if m != nil { - return m.Details - } - return nil -} - -func init() { - proto.RegisterType((*Error)(nil), "grpc.gateway.runtime.Error") - proto.RegisterType((*StreamError)(nil), "grpc.gateway.runtime.StreamError") -} - -func init() { proto.RegisterFile("internal/errors.proto", fileDescriptor_9b093362ca6d1e03) } - -var fileDescriptor_9b093362ca6d1e03 = []byte{ - // 252 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x90, 0xc1, 0x4a, 0xc4, 0x30, - 0x10, 0x86, 0x89, 0xbb, 0x75, 0xdb, 0xe9, 0x2d, 0x54, 0x88, 0xee, 0xc1, 0xb2, 0xa7, 0x9e, 0x52, - 0xd0, 0x27, 0xd0, 0xc5, 0x17, 0xe8, 0xde, 0xbc, 0x2c, 0xd9, 0xdd, 0x31, 0x16, 0xda, 0xa4, 0x24, - 0x53, 0xa4, 0xf8, 0x56, 0x3e, 0xa1, 0x24, 0xa5, 0xb0, 0x27, 0xf1, 0xd6, 0xf9, 0xfb, 0xcf, 0x7c, - 0x1f, 0x81, 0xbb, 0xd6, 0x10, 0x3a, 0xa3, 0xba, 0x1a, 0x9d, 0xb3, 0xce, 0xcb, 0xc1, 0x59, 0xb2, - 0xbc, 0xd0, 0x6e, 0x38, 0x4b, 0xad, 0x08, 0xbf, 0xd4, 0x24, 0xdd, 0x68, 0xa8, 0xed, 0xf1, 0xe1, - 0x5e, 0x5b, 0xab, 0x3b, 0xac, 0x63, 0xe7, 0x34, 0x7e, 0xd4, 0xca, 0x4c, 0xf3, 0xc2, 0xee, 0x1b, - 0x92, 0xb7, 0x70, 0x80, 0x17, 0x90, 0xc4, 0x4b, 0x82, 0x95, 0xac, 0xca, 0x9a, 0x79, 0xe0, 0x1c, - 0xd6, 0x67, 0x7b, 0x41, 0x71, 0x53, 0xb2, 0x2a, 0x69, 0xe2, 0x37, 0x17, 0xb0, 0xe9, 0xd1, 0x7b, - 0xa5, 0x51, 0xac, 0x62, 0x77, 0x19, 0xb9, 0x84, 0xcd, 0x05, 0x49, 0xb5, 0x9d, 0x17, 0xeb, 0x72, - 0x55, 0xe5, 0x4f, 0x85, 0x9c, 0xc9, 0x72, 0x21, 0xcb, 0x17, 0x33, 0x35, 0x4b, 0x69, 0xf7, 0xc3, - 0x20, 0x3f, 0x90, 0x43, 0xd5, 0xcf, 0x0e, 0x5b, 0xc8, 0x82, 0xff, 0x31, 0x22, 0x59, 0x44, 0xa6, - 0x21, 0xd8, 0x07, 0xec, 0x16, 0xb2, 0x4f, 0xa2, 0xe1, 0x78, 0xe5, 0x93, 0x86, 0x60, 0xff, 0xb7, - 0xd3, 0x23, 0xe4, 0x71, 0xcd, 0x93, 0xa2, 0x31, 0x78, 0x85, 0xbf, 0x10, 0xa2, 0x43, 0x4c, 0xae, - 0xa5, 0x93, 0x7f, 0x48, 0xbf, 0xc2, 0x7b, 0xba, 0xbc, 0xfd, 0xe9, 0x36, 0x56, 0x9e, 0x7f, 0x03, - 0x00, 0x00, 0xff, 0xff, 0xde, 0x72, 0x6b, 0x83, 0x8e, 0x01, 0x00, 0x00, -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.proto b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.proto deleted file mode 100644 index 4fb212c6b6..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/internal/errors.proto +++ /dev/null @@ -1,26 +0,0 @@ -syntax = "proto3"; -package grpc.gateway.runtime; -option go_package = "internal"; - -import "google/protobuf/any.proto"; - -// Error is the generic error returned from unary RPCs. -message Error { - string error = 1; - // This is to make the error more compatible with users that expect errors to be Status objects: - // https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto - // It should be the exact same message as the Error field. - int32 code = 2; - string message = 3; - repeated google.protobuf.Any details = 4; -} - -// StreamError is a response type which is returned when -// streaming rpc returns an error. -message StreamError { - int32 grpc_code = 1; - int32 http_code = 2; - string message = 3; - string http_status = 4; - repeated google.protobuf.Any details = 5; -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel deleted file mode 100644 index 58b72b9cf7..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel +++ /dev/null @@ -1,85 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -package(default_visibility = ["//visibility:public"]) - -go_library( - name = "go_default_library", - srcs = [ - "context.go", - "convert.go", - "doc.go", - "errors.go", - "fieldmask.go", - "handler.go", - "marshal_httpbodyproto.go", - "marshal_json.go", - "marshal_jsonpb.go", - "marshal_proto.go", - "marshaler.go", - "marshaler_registry.go", - "mux.go", - "pattern.go", - "proto2_convert.go", - "proto_errors.go", - "query.go", - ], - importpath = "github.com/grpc-ecosystem/grpc-gateway/runtime", - deps = [ - "//internal:go_default_library", - "//utilities:go_default_library", - "@com_github_golang_protobuf//descriptor:go_default_library_gen", - "@com_github_golang_protobuf//jsonpb:go_default_library_gen", - "@com_github_golang_protobuf//proto:go_default_library", - "@go_googleapis//google/api:httpbody_go_proto", - "@io_bazel_rules_go//proto/wkt:any_go_proto", - "@io_bazel_rules_go//proto/wkt:descriptor_go_proto", - "@io_bazel_rules_go//proto/wkt:duration_go_proto", - "@io_bazel_rules_go//proto/wkt:field_mask_go_proto", - "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", - "@io_bazel_rules_go//proto/wkt:wrappers_go_proto", - "@org_golang_google_grpc//codes:go_default_library", - "@org_golang_google_grpc//grpclog:go_default_library", - "@org_golang_google_grpc//metadata:go_default_library", - "@org_golang_google_grpc//status:go_default_library", - ], -) - -go_test( - name = "go_default_test", - size = "small", - srcs = [ - "context_test.go", - "convert_test.go", - "errors_test.go", - "fieldmask_test.go", - "handler_test.go", - "marshal_httpbodyproto_test.go", - "marshal_json_test.go", - "marshal_jsonpb_test.go", - "marshal_proto_test.go", - "marshaler_registry_test.go", - "mux_test.go", - "pattern_test.go", - "query_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//internal:go_default_library", - "//runtime/internal/examplepb:go_default_library", - "//utilities:go_default_library", - "@com_github_golang_protobuf//jsonpb:go_default_library_gen", - "@com_github_golang_protobuf//proto:go_default_library", - "@com_github_golang_protobuf//ptypes:go_default_library_gen", - "@go_googleapis//google/api:httpbody_go_proto", - "@go_googleapis//google/rpc:errdetails_go_proto", - "@io_bazel_rules_go//proto/wkt:duration_go_proto", - "@io_bazel_rules_go//proto/wkt:empty_go_proto", - "@io_bazel_rules_go//proto/wkt:field_mask_go_proto", - "@io_bazel_rules_go//proto/wkt:struct_go_proto", - "@io_bazel_rules_go//proto/wkt:timestamp_go_proto", - "@io_bazel_rules_go//proto/wkt:wrappers_go_proto", - "@org_golang_google_grpc//codes:go_default_library", - "@org_golang_google_grpc//metadata:go_default_library", - "@org_golang_google_grpc//status:go_default_library", - ], -) diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go deleted file mode 100644 index d8cbd4cc96..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go +++ /dev/null @@ -1,291 +0,0 @@ -package runtime - -import ( - "context" - "encoding/base64" - "fmt" - "net" - "net/http" - "net/textproto" - "strconv" - "strings" - "sync" - "time" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" -) - -// MetadataHeaderPrefix is the http prefix that represents custom metadata -// parameters to or from a gRPC call. -const MetadataHeaderPrefix = "Grpc-Metadata-" - -// MetadataPrefix is prepended to permanent HTTP header keys (as specified -// by the IANA) when added to the gRPC context. -const MetadataPrefix = "grpcgateway-" - -// MetadataTrailerPrefix is prepended to gRPC metadata as it is converted to -// HTTP headers in a response handled by grpc-gateway -const MetadataTrailerPrefix = "Grpc-Trailer-" - -const metadataGrpcTimeout = "Grpc-Timeout" -const metadataHeaderBinarySuffix = "-Bin" - -const xForwardedFor = "X-Forwarded-For" -const xForwardedHost = "X-Forwarded-Host" - -var ( - // DefaultContextTimeout is used for gRPC call context.WithTimeout whenever a Grpc-Timeout inbound - // header isn't present. If the value is 0 the sent `context` will not have a timeout. - DefaultContextTimeout = 0 * time.Second -) - -func decodeBinHeader(v string) ([]byte, error) { - if len(v)%4 == 0 { - // Input was padded, or padding was not necessary. - return base64.StdEncoding.DecodeString(v) - } - return base64.RawStdEncoding.DecodeString(v) -} - -/* -AnnotateContext adds context information such as metadata from the request. - -At a minimum, the RemoteAddr is included in the fashion of "X-Forwarded-For", -except that the forwarded destination is not another HTTP service but rather -a gRPC service. -*/ -func AnnotateContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, error) { - ctx, md, err := annotateContext(ctx, mux, req) - if err != nil { - return nil, err - } - if md == nil { - return ctx, nil - } - - return metadata.NewOutgoingContext(ctx, md), nil -} - -// AnnotateIncomingContext adds context information such as metadata from the request. -// Attach metadata as incoming context. -func AnnotateIncomingContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, error) { - ctx, md, err := annotateContext(ctx, mux, req) - if err != nil { - return nil, err - } - if md == nil { - return ctx, nil - } - - return metadata.NewIncomingContext(ctx, md), nil -} - -func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, metadata.MD, error) { - var pairs []string - timeout := DefaultContextTimeout - if tm := req.Header.Get(metadataGrpcTimeout); tm != "" { - var err error - timeout, err = timeoutDecode(tm) - if err != nil { - return nil, nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm) - } - } - - for key, vals := range req.Header { - key = textproto.CanonicalMIMEHeaderKey(key) - for _, val := range vals { - // For backwards-compatibility, pass through 'authorization' header with no prefix. - if key == "Authorization" { - pairs = append(pairs, "authorization", val) - } - if h, ok := mux.incomingHeaderMatcher(key); ok { - // Handles "-bin" metadata in grpc, since grpc will do another base64 - // encode before sending to server, we need to decode it first. - if strings.HasSuffix(key, metadataHeaderBinarySuffix) { - b, err := decodeBinHeader(val) - if err != nil { - return nil, nil, status.Errorf(codes.InvalidArgument, "invalid binary header %s: %s", key, err) - } - - val = string(b) - } - pairs = append(pairs, h, val) - } - } - } - if host := req.Header.Get(xForwardedHost); host != "" { - pairs = append(pairs, strings.ToLower(xForwardedHost), host) - } else if req.Host != "" { - pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host) - } - - if addr := req.RemoteAddr; addr != "" { - if remoteIP, _, err := net.SplitHostPort(addr); err == nil { - if fwd := req.Header.Get(xForwardedFor); fwd == "" { - pairs = append(pairs, strings.ToLower(xForwardedFor), remoteIP) - } else { - pairs = append(pairs, strings.ToLower(xForwardedFor), fmt.Sprintf("%s, %s", fwd, remoteIP)) - } - } - } - - if timeout != 0 { - ctx, _ = context.WithTimeout(ctx, timeout) - } - if len(pairs) == 0 { - return ctx, nil, nil - } - md := metadata.Pairs(pairs...) - for _, mda := range mux.metadataAnnotators { - md = metadata.Join(md, mda(ctx, req)) - } - return ctx, md, nil -} - -// ServerMetadata consists of metadata sent from gRPC server. -type ServerMetadata struct { - HeaderMD metadata.MD - TrailerMD metadata.MD -} - -type serverMetadataKey struct{} - -// NewServerMetadataContext creates a new context with ServerMetadata -func NewServerMetadataContext(ctx context.Context, md ServerMetadata) context.Context { - return context.WithValue(ctx, serverMetadataKey{}, md) -} - -// ServerMetadataFromContext returns the ServerMetadata in ctx -func ServerMetadataFromContext(ctx context.Context) (md ServerMetadata, ok bool) { - md, ok = ctx.Value(serverMetadataKey{}).(ServerMetadata) - return -} - -// ServerTransportStream implements grpc.ServerTransportStream. -// It should only be used by the generated files to support grpc.SendHeader -// outside of gRPC server use. -type ServerTransportStream struct { - mu sync.Mutex - header metadata.MD - trailer metadata.MD -} - -// Method returns the method for the stream. -func (s *ServerTransportStream) Method() string { - return "" -} - -// Header returns the header metadata of the stream. -func (s *ServerTransportStream) Header() metadata.MD { - s.mu.Lock() - defer s.mu.Unlock() - return s.header.Copy() -} - -// SetHeader sets the header metadata. -func (s *ServerTransportStream) SetHeader(md metadata.MD) error { - if md.Len() == 0 { - return nil - } - - s.mu.Lock() - s.header = metadata.Join(s.header, md) - s.mu.Unlock() - return nil -} - -// SendHeader sets the header metadata. -func (s *ServerTransportStream) SendHeader(md metadata.MD) error { - return s.SetHeader(md) -} - -// Trailer returns the cached trailer metadata. -func (s *ServerTransportStream) Trailer() metadata.MD { - s.mu.Lock() - defer s.mu.Unlock() - return s.trailer.Copy() -} - -// SetTrailer sets the trailer metadata. -func (s *ServerTransportStream) SetTrailer(md metadata.MD) error { - if md.Len() == 0 { - return nil - } - - s.mu.Lock() - s.trailer = metadata.Join(s.trailer, md) - s.mu.Unlock() - return nil -} - -func timeoutDecode(s string) (time.Duration, error) { - size := len(s) - if size < 2 { - return 0, fmt.Errorf("timeout string is too short: %q", s) - } - d, ok := timeoutUnitToDuration(s[size-1]) - if !ok { - return 0, fmt.Errorf("timeout unit is not recognized: %q", s) - } - t, err := strconv.ParseInt(s[:size-1], 10, 64) - if err != nil { - return 0, err - } - return d * time.Duration(t), nil -} - -func timeoutUnitToDuration(u uint8) (d time.Duration, ok bool) { - switch u { - case 'H': - return time.Hour, true - case 'M': - return time.Minute, true - case 'S': - return time.Second, true - case 'm': - return time.Millisecond, true - case 'u': - return time.Microsecond, true - case 'n': - return time.Nanosecond, true - default: - } - return -} - -// isPermanentHTTPHeader checks whether hdr belongs to the list of -// permanent request headers maintained by IANA. -// http://www.iana.org/assignments/message-headers/message-headers.xml -func isPermanentHTTPHeader(hdr string) bool { - switch hdr { - case - "Accept", - "Accept-Charset", - "Accept-Language", - "Accept-Ranges", - "Authorization", - "Cache-Control", - "Content-Type", - "Cookie", - "Date", - "Expect", - "From", - "Host", - "If-Match", - "If-Modified-Since", - "If-None-Match", - "If-Schedule-Tag-Match", - "If-Unmodified-Since", - "Max-Forwards", - "Origin", - "Pragma", - "Referer", - "User-Agent", - "Via", - "Warning": - return true - } - return false -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go deleted file mode 100644 index 2c279344dc..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go +++ /dev/null @@ -1,318 +0,0 @@ -package runtime - -import ( - "encoding/base64" - "fmt" - "strconv" - "strings" - - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/ptypes/duration" - "github.com/golang/protobuf/ptypes/timestamp" - "github.com/golang/protobuf/ptypes/wrappers" -) - -// String just returns the given string. -// It is just for compatibility to other types. -func String(val string) (string, error) { - return val, nil -} - -// StringSlice converts 'val' where individual strings are separated by -// 'sep' into a string slice. -func StringSlice(val, sep string) ([]string, error) { - return strings.Split(val, sep), nil -} - -// Bool converts the given string representation of a boolean value into bool. -func Bool(val string) (bool, error) { - return strconv.ParseBool(val) -} - -// BoolSlice converts 'val' where individual booleans are separated by -// 'sep' into a bool slice. -func BoolSlice(val, sep string) ([]bool, error) { - s := strings.Split(val, sep) - values := make([]bool, len(s)) - for i, v := range s { - value, err := Bool(v) - if err != nil { - return values, err - } - values[i] = value - } - return values, nil -} - -// Float64 converts the given string representation into representation of a floating point number into float64. -func Float64(val string) (float64, error) { - return strconv.ParseFloat(val, 64) -} - -// Float64Slice converts 'val' where individual floating point numbers are separated by -// 'sep' into a float64 slice. -func Float64Slice(val, sep string) ([]float64, error) { - s := strings.Split(val, sep) - values := make([]float64, len(s)) - for i, v := range s { - value, err := Float64(v) - if err != nil { - return values, err - } - values[i] = value - } - return values, nil -} - -// Float32 converts the given string representation of a floating point number into float32. -func Float32(val string) (float32, error) { - f, err := strconv.ParseFloat(val, 32) - if err != nil { - return 0, err - } - return float32(f), nil -} - -// Float32Slice converts 'val' where individual floating point numbers are separated by -// 'sep' into a float32 slice. -func Float32Slice(val, sep string) ([]float32, error) { - s := strings.Split(val, sep) - values := make([]float32, len(s)) - for i, v := range s { - value, err := Float32(v) - if err != nil { - return values, err - } - values[i] = value - } - return values, nil -} - -// Int64 converts the given string representation of an integer into int64. -func Int64(val string) (int64, error) { - return strconv.ParseInt(val, 0, 64) -} - -// Int64Slice converts 'val' where individual integers are separated by -// 'sep' into a int64 slice. -func Int64Slice(val, sep string) ([]int64, error) { - s := strings.Split(val, sep) - values := make([]int64, len(s)) - for i, v := range s { - value, err := Int64(v) - if err != nil { - return values, err - } - values[i] = value - } - return values, nil -} - -// Int32 converts the given string representation of an integer into int32. -func Int32(val string) (int32, error) { - i, err := strconv.ParseInt(val, 0, 32) - if err != nil { - return 0, err - } - return int32(i), nil -} - -// Int32Slice converts 'val' where individual integers are separated by -// 'sep' into a int32 slice. -func Int32Slice(val, sep string) ([]int32, error) { - s := strings.Split(val, sep) - values := make([]int32, len(s)) - for i, v := range s { - value, err := Int32(v) - if err != nil { - return values, err - } - values[i] = value - } - return values, nil -} - -// Uint64 converts the given string representation of an integer into uint64. -func Uint64(val string) (uint64, error) { - return strconv.ParseUint(val, 0, 64) -} - -// Uint64Slice converts 'val' where individual integers are separated by -// 'sep' into a uint64 slice. -func Uint64Slice(val, sep string) ([]uint64, error) { - s := strings.Split(val, sep) - values := make([]uint64, len(s)) - for i, v := range s { - value, err := Uint64(v) - if err != nil { - return values, err - } - values[i] = value - } - return values, nil -} - -// Uint32 converts the given string representation of an integer into uint32. -func Uint32(val string) (uint32, error) { - i, err := strconv.ParseUint(val, 0, 32) - if err != nil { - return 0, err - } - return uint32(i), nil -} - -// Uint32Slice converts 'val' where individual integers are separated by -// 'sep' into a uint32 slice. -func Uint32Slice(val, sep string) ([]uint32, error) { - s := strings.Split(val, sep) - values := make([]uint32, len(s)) - for i, v := range s { - value, err := Uint32(v) - if err != nil { - return values, err - } - values[i] = value - } - return values, nil -} - -// Bytes converts the given string representation of a byte sequence into a slice of bytes -// A bytes sequence is encoded in URL-safe base64 without padding -func Bytes(val string) ([]byte, error) { - b, err := base64.StdEncoding.DecodeString(val) - if err != nil { - b, err = base64.URLEncoding.DecodeString(val) - if err != nil { - return nil, err - } - } - return b, nil -} - -// BytesSlice converts 'val' where individual bytes sequences, encoded in URL-safe -// base64 without padding, are separated by 'sep' into a slice of bytes slices slice. -func BytesSlice(val, sep string) ([][]byte, error) { - s := strings.Split(val, sep) - values := make([][]byte, len(s)) - for i, v := range s { - value, err := Bytes(v) - if err != nil { - return values, err - } - values[i] = value - } - return values, nil -} - -// Timestamp converts the given RFC3339 formatted string into a timestamp.Timestamp. -func Timestamp(val string) (*timestamp.Timestamp, error) { - var r timestamp.Timestamp - err := jsonpb.UnmarshalString(val, &r) - if err != nil { - return nil, err - } - return &r, nil -} - -// Duration converts the given string into a timestamp.Duration. -func Duration(val string) (*duration.Duration, error) { - var r duration.Duration - err := jsonpb.UnmarshalString(val, &r) - if err != nil { - return nil, err - } - return &r, nil -} - -// Enum converts the given string into an int32 that should be type casted into the -// correct enum proto type. -func Enum(val string, enumValMap map[string]int32) (int32, error) { - e, ok := enumValMap[val] - if ok { - return e, nil - } - - i, err := Int32(val) - if err != nil { - return 0, fmt.Errorf("%s is not valid", val) - } - for _, v := range enumValMap { - if v == i { - return i, nil - } - } - return 0, fmt.Errorf("%s is not valid", val) -} - -// EnumSlice converts 'val' where individual enums are separated by 'sep' -// into a int32 slice. Each individual int32 should be type casted into the -// correct enum proto type. -func EnumSlice(val, sep string, enumValMap map[string]int32) ([]int32, error) { - s := strings.Split(val, sep) - values := make([]int32, len(s)) - for i, v := range s { - value, err := Enum(v, enumValMap) - if err != nil { - return values, err - } - values[i] = value - } - return values, nil -} - -/* - Support fot google.protobuf.wrappers on top of primitive types -*/ - -// StringValue well-known type support as wrapper around string type -func StringValue(val string) (*wrappers.StringValue, error) { - return &wrappers.StringValue{Value: val}, nil -} - -// FloatValue well-known type support as wrapper around float32 type -func FloatValue(val string) (*wrappers.FloatValue, error) { - parsedVal, err := Float32(val) - return &wrappers.FloatValue{Value: parsedVal}, err -} - -// DoubleValue well-known type support as wrapper around float64 type -func DoubleValue(val string) (*wrappers.DoubleValue, error) { - parsedVal, err := Float64(val) - return &wrappers.DoubleValue{Value: parsedVal}, err -} - -// BoolValue well-known type support as wrapper around bool type -func BoolValue(val string) (*wrappers.BoolValue, error) { - parsedVal, err := Bool(val) - return &wrappers.BoolValue{Value: parsedVal}, err -} - -// Int32Value well-known type support as wrapper around int32 type -func Int32Value(val string) (*wrappers.Int32Value, error) { - parsedVal, err := Int32(val) - return &wrappers.Int32Value{Value: parsedVal}, err -} - -// UInt32Value well-known type support as wrapper around uint32 type -func UInt32Value(val string) (*wrappers.UInt32Value, error) { - parsedVal, err := Uint32(val) - return &wrappers.UInt32Value{Value: parsedVal}, err -} - -// Int64Value well-known type support as wrapper around int64 type -func Int64Value(val string) (*wrappers.Int64Value, error) { - parsedVal, err := Int64(val) - return &wrappers.Int64Value{Value: parsedVal}, err -} - -// UInt64Value well-known type support as wrapper around uint64 type -func UInt64Value(val string) (*wrappers.UInt64Value, error) { - parsedVal, err := Uint64(val) - return &wrappers.UInt64Value{Value: parsedVal}, err -} - -// BytesValue well-known type support as wrapper around bytes[] type -func BytesValue(val string) (*wrappers.BytesValue, error) { - parsedVal, err := Bytes(val) - return &wrappers.BytesValue{Value: parsedVal}, err -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/doc.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/doc.go deleted file mode 100644 index b6e5ddf7a9..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -/* -Package runtime contains runtime helper functions used by -servers which protoc-gen-grpc-gateway generates. -*/ -package runtime diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go deleted file mode 100644 index b2ce743bdd..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go +++ /dev/null @@ -1,186 +0,0 @@ -package runtime - -import ( - "context" - "io" - "net/http" - "strings" - - "github.com/grpc-ecosystem/grpc-gateway/internal" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/status" -) - -// HTTPStatusFromCode converts a gRPC error code into the corresponding HTTP response status. -// See: https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto -func HTTPStatusFromCode(code codes.Code) int { - switch code { - case codes.OK: - return http.StatusOK - case codes.Canceled: - return http.StatusRequestTimeout - case codes.Unknown: - return http.StatusInternalServerError - case codes.InvalidArgument: - return http.StatusBadRequest - case codes.DeadlineExceeded: - return http.StatusGatewayTimeout - case codes.NotFound: - return http.StatusNotFound - case codes.AlreadyExists: - return http.StatusConflict - case codes.PermissionDenied: - return http.StatusForbidden - case codes.Unauthenticated: - return http.StatusUnauthorized - case codes.ResourceExhausted: - return http.StatusTooManyRequests - case codes.FailedPrecondition: - // Note, this deliberately doesn't translate to the similarly named '412 Precondition Failed' HTTP response status. - return http.StatusBadRequest - case codes.Aborted: - return http.StatusConflict - case codes.OutOfRange: - return http.StatusBadRequest - case codes.Unimplemented: - return http.StatusNotImplemented - case codes.Internal: - return http.StatusInternalServerError - case codes.Unavailable: - return http.StatusServiceUnavailable - case codes.DataLoss: - return http.StatusInternalServerError - } - - grpclog.Infof("Unknown gRPC error code: %v", code) - return http.StatusInternalServerError -} - -var ( - // HTTPError replies to the request with an error. - // - // HTTPError is called: - // - From generated per-endpoint gateway handler code, when calling the backend results in an error. - // - From gateway runtime code, when forwarding the response message results in an error. - // - // The default value for HTTPError calls the custom error handler configured on the ServeMux via the - // WithProtoErrorHandler serve option if that option was used, calling GlobalHTTPErrorHandler otherwise. - // - // To customize the error handling of a particular ServeMux instance, use the WithProtoErrorHandler - // serve option. - // - // To customize the error format for all ServeMux instances not using the WithProtoErrorHandler serve - // option, set GlobalHTTPErrorHandler to a custom function. - // - // Setting this variable directly to customize error format is deprecated. - HTTPError = MuxOrGlobalHTTPError - - // GlobalHTTPErrorHandler is the HTTPError handler for all ServeMux instances not using the - // WithProtoErrorHandler serve option. - // - // You can set a custom function to this variable to customize error format. - GlobalHTTPErrorHandler = DefaultHTTPError - - // OtherErrorHandler handles gateway errors from parsing and routing client requests for all - // ServeMux instances not using the WithProtoErrorHandler serve option. - // - // It returns the following error codes: StatusMethodNotAllowed StatusNotFound StatusBadRequest - // - // To customize parsing and routing error handling of a particular ServeMux instance, use the - // WithProtoErrorHandler serve option. - // - // To customize parsing and routing error handling of all ServeMux instances not using the - // WithProtoErrorHandler serve option, set a custom function to this variable. - OtherErrorHandler = DefaultOtherErrorHandler -) - -// MuxOrGlobalHTTPError uses the mux-configured error handler, falling back to GlobalErrorHandler. -func MuxOrGlobalHTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, err error) { - if mux.protoErrorHandler != nil { - mux.protoErrorHandler(ctx, mux, marshaler, w, r, err) - } else { - GlobalHTTPErrorHandler(ctx, mux, marshaler, w, r, err) - } -} - -// DefaultHTTPError is the default implementation of HTTPError. -// If "err" is an error from gRPC system, the function replies with the status code mapped by HTTPStatusFromCode. -// If otherwise, it replies with http.StatusInternalServerError. -// -// The response body returned by this function is a JSON object, -// which contains a member whose key is "error" and whose value is err.Error(). -func DefaultHTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, err error) { - const fallback = `{"error": "failed to marshal error message"}` - - s, ok := status.FromError(err) - if !ok { - s = status.New(codes.Unknown, err.Error()) - } - - w.Header().Del("Trailer") - w.Header().Del("Transfer-Encoding") - - contentType := marshaler.ContentType() - // Check marshaler on run time in order to keep backwards compatibility - // An interface param needs to be added to the ContentType() function on - // the Marshal interface to be able to remove this check - if typeMarshaler, ok := marshaler.(contentTypeMarshaler); ok { - pb := s.Proto() - contentType = typeMarshaler.ContentTypeFromMessage(pb) - } - w.Header().Set("Content-Type", contentType) - - body := &internal.Error{ - Error: s.Message(), - Message: s.Message(), - Code: int32(s.Code()), - Details: s.Proto().GetDetails(), - } - - buf, merr := marshaler.Marshal(body) - if merr != nil { - grpclog.Infof("Failed to marshal error message %q: %v", body, merr) - w.WriteHeader(http.StatusInternalServerError) - if _, err := io.WriteString(w, fallback); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - return - } - - md, ok := ServerMetadataFromContext(ctx) - if !ok { - grpclog.Infof("Failed to extract ServerMetadata from context") - } - - handleForwardResponseServerMetadata(w, mux, md) - - // RFC 7230 https://tools.ietf.org/html/rfc7230#section-4.1.2 - // Unless the request includes a TE header field indicating "trailers" - // is acceptable, as described in Section 4.3, a server SHOULD NOT - // generate trailer fields that it believes are necessary for the user - // agent to receive. - var wantsTrailers bool - - if te := r.Header.Get("TE"); strings.Contains(strings.ToLower(te), "trailers") { - wantsTrailers = true - handleForwardResponseTrailerHeader(w, md) - w.Header().Set("Transfer-Encoding", "chunked") - } - - st := HTTPStatusFromCode(s.Code()) - w.WriteHeader(st) - if _, err := w.Write(buf); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - - if wantsTrailers { - handleForwardResponseTrailer(w, md) - } -} - -// DefaultOtherErrorHandler is the default implementation of OtherErrorHandler. -// It simply writes a string representation of the given error into "w". -func DefaultOtherErrorHandler(w http.ResponseWriter, _ *http.Request, msg string, code int) { - http.Error(w, msg, code) -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go deleted file mode 100644 index aef645e40b..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go +++ /dev/null @@ -1,89 +0,0 @@ -package runtime - -import ( - "encoding/json" - "io" - "strings" - - descriptor2 "github.com/golang/protobuf/descriptor" - "github.com/golang/protobuf/protoc-gen-go/descriptor" - "google.golang.org/genproto/protobuf/field_mask" -) - -func translateName(name string, md *descriptor.DescriptorProto) (string, *descriptor.DescriptorProto) { - // TODO - should really gate this with a test that the marshaller has used json names - if md != nil { - for _, f := range md.Field { - if f.JsonName != nil && f.Name != nil && *f.JsonName == name { - var subType *descriptor.DescriptorProto - - // If the field has a TypeName then we retrieve the nested type for translating the embedded message names. - if f.TypeName != nil { - typeSplit := strings.Split(*f.TypeName, ".") - typeName := typeSplit[len(typeSplit)-1] - for _, t := range md.NestedType { - if typeName == *t.Name { - subType = t - } - } - } - return *f.Name, subType - } - } - } - return name, nil -} - -// FieldMaskFromRequestBody creates a FieldMask printing all complete paths from the JSON body. -func FieldMaskFromRequestBody(r io.Reader, md *descriptor.DescriptorProto) (*field_mask.FieldMask, error) { - fm := &field_mask.FieldMask{} - var root interface{} - if err := json.NewDecoder(r).Decode(&root); err != nil { - if err == io.EOF { - return fm, nil - } - return nil, err - } - - queue := []fieldMaskPathItem{{node: root, md: md}} - for len(queue) > 0 { - // dequeue an item - item := queue[0] - queue = queue[1:] - - if m, ok := item.node.(map[string]interface{}); ok { - // if the item is an object, then enqueue all of its children - for k, v := range m { - protoName, subMd := translateName(k, item.md) - if subMsg, ok := v.(descriptor2.Message); ok { - _, subMd = descriptor2.ForMessage(subMsg) - } - - var path string - if item.path == "" { - path = protoName - } else { - path = item.path + "." + protoName - } - queue = append(queue, fieldMaskPathItem{path: path, node: v, md: subMd}) - } - } else if len(item.path) > 0 { - // otherwise, it's a leaf node so print its path - fm.Paths = append(fm.Paths, item.path) - } - } - - return fm, nil -} - -// fieldMaskPathItem stores a in-progress deconstruction of a path for a fieldmask -type fieldMaskPathItem struct { - // the list of prior fields leading up to node connected by dots - path string - - // a generic decoded json object the current item to inspect for further path extraction - node interface{} - - // descriptor for parent message - md *descriptor.DescriptorProto -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go deleted file mode 100644 index e6e8f286e1..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go +++ /dev/null @@ -1,212 +0,0 @@ -package runtime - -import ( - "context" - "errors" - "fmt" - "io" - "net/http" - "net/textproto" - - "github.com/golang/protobuf/proto" - "github.com/grpc-ecosystem/grpc-gateway/internal" - "google.golang.org/grpc/grpclog" -) - -var errEmptyResponse = errors.New("empty response") - -// ForwardResponseStream forwards the stream from gRPC server to REST client. -func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, recv func() (proto.Message, error), opts ...func(context.Context, http.ResponseWriter, proto.Message) error) { - f, ok := w.(http.Flusher) - if !ok { - grpclog.Infof("Flush not supported in %T", w) - http.Error(w, "unexpected type of web server", http.StatusInternalServerError) - return - } - - md, ok := ServerMetadataFromContext(ctx) - if !ok { - grpclog.Infof("Failed to extract ServerMetadata from context") - http.Error(w, "unexpected error", http.StatusInternalServerError) - return - } - handleForwardResponseServerMetadata(w, mux, md) - - w.Header().Set("Transfer-Encoding", "chunked") - w.Header().Set("Content-Type", marshaler.ContentType()) - if err := handleForwardResponseOptions(ctx, w, nil, opts); err != nil { - HTTPError(ctx, mux, marshaler, w, req, err) - return - } - - var delimiter []byte - if d, ok := marshaler.(Delimited); ok { - delimiter = d.Delimiter() - } else { - delimiter = []byte("\n") - } - - var wroteHeader bool - for { - resp, err := recv() - if err == io.EOF { - return - } - if err != nil { - handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) - return - } - if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil { - handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) - return - } - - var buf []byte - switch { - case resp == nil: - buf, err = marshaler.Marshal(errorChunk(streamError(ctx, mux.streamErrorHandler, errEmptyResponse))) - default: - result := map[string]interface{}{"result": resp} - if rb, ok := resp.(responseBody); ok { - result["result"] = rb.XXX_ResponseBody() - } - - buf, err = marshaler.Marshal(result) - } - - if err != nil { - grpclog.Infof("Failed to marshal response chunk: %v", err) - handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err) - return - } - if _, err = w.Write(buf); err != nil { - grpclog.Infof("Failed to send response chunk: %v", err) - return - } - wroteHeader = true - if _, err = w.Write(delimiter); err != nil { - grpclog.Infof("Failed to send delimiter chunk: %v", err) - return - } - f.Flush() - } -} - -func handleForwardResponseServerMetadata(w http.ResponseWriter, mux *ServeMux, md ServerMetadata) { - for k, vs := range md.HeaderMD { - if h, ok := mux.outgoingHeaderMatcher(k); ok { - for _, v := range vs { - w.Header().Add(h, v) - } - } - } -} - -func handleForwardResponseTrailerHeader(w http.ResponseWriter, md ServerMetadata) { - for k := range md.TrailerMD { - tKey := textproto.CanonicalMIMEHeaderKey(fmt.Sprintf("%s%s", MetadataTrailerPrefix, k)) - w.Header().Add("Trailer", tKey) - } -} - -func handleForwardResponseTrailer(w http.ResponseWriter, md ServerMetadata) { - for k, vs := range md.TrailerMD { - tKey := fmt.Sprintf("%s%s", MetadataTrailerPrefix, k) - for _, v := range vs { - w.Header().Add(tKey, v) - } - } -} - -// responseBody interface contains method for getting field for marshaling to the response body -// this method is generated for response struct from the value of `response_body` in the `google.api.HttpRule` -type responseBody interface { - XXX_ResponseBody() interface{} -} - -// ForwardResponseMessage forwards the message "resp" from gRPC server to REST client. -func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error) { - md, ok := ServerMetadataFromContext(ctx) - if !ok { - grpclog.Infof("Failed to extract ServerMetadata from context") - } - - handleForwardResponseServerMetadata(w, mux, md) - handleForwardResponseTrailerHeader(w, md) - - contentType := marshaler.ContentType() - // Check marshaler on run time in order to keep backwards compatibility - // An interface param needs to be added to the ContentType() function on - // the Marshal interface to be able to remove this check - if typeMarshaler, ok := marshaler.(contentTypeMarshaler); ok { - contentType = typeMarshaler.ContentTypeFromMessage(resp) - } - w.Header().Set("Content-Type", contentType) - - if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil { - HTTPError(ctx, mux, marshaler, w, req, err) - return - } - var buf []byte - var err error - if rb, ok := resp.(responseBody); ok { - buf, err = marshaler.Marshal(rb.XXX_ResponseBody()) - } else { - buf, err = marshaler.Marshal(resp) - } - if err != nil { - grpclog.Infof("Marshal error: %v", err) - HTTPError(ctx, mux, marshaler, w, req, err) - return - } - - if _, err = w.Write(buf); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - - handleForwardResponseTrailer(w, md) -} - -func handleForwardResponseOptions(ctx context.Context, w http.ResponseWriter, resp proto.Message, opts []func(context.Context, http.ResponseWriter, proto.Message) error) error { - if len(opts) == 0 { - return nil - } - for _, opt := range opts { - if err := opt(ctx, w, resp); err != nil { - grpclog.Infof("Error handling ForwardResponseOptions: %v", err) - return err - } - } - return nil -} - -func handleForwardResponseStreamError(ctx context.Context, wroteHeader bool, marshaler Marshaler, w http.ResponseWriter, req *http.Request, mux *ServeMux, err error) { - serr := streamError(ctx, mux.streamErrorHandler, err) - if !wroteHeader { - w.WriteHeader(int(serr.HttpCode)) - } - buf, merr := marshaler.Marshal(errorChunk(serr)) - if merr != nil { - grpclog.Infof("Failed to marshal an error: %v", merr) - return - } - if _, werr := w.Write(buf); werr != nil { - grpclog.Infof("Failed to notify error to client: %v", werr) - return - } -} - -// streamError returns the payload for the final message in a response stream -// that represents the given err. -func streamError(ctx context.Context, errHandler StreamErrorHandlerFunc, err error) *StreamError { - serr := errHandler(ctx, err) - if serr != nil { - return serr - } - // TODO: log about misbehaving stream error handler? - return DefaultHTTPStreamErrorHandler(ctx, err) -} - -func errorChunk(err *StreamError) map[string]proto.Message { - return map[string]proto.Message{"error": (*internal.StreamError)(err)} -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go deleted file mode 100644 index 525b0338c7..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go +++ /dev/null @@ -1,43 +0,0 @@ -package runtime - -import ( - "google.golang.org/genproto/googleapis/api/httpbody" -) - -// SetHTTPBodyMarshaler overwrite the default marshaler with the HTTPBodyMarshaler -func SetHTTPBodyMarshaler(serveMux *ServeMux) { - serveMux.marshalers.mimeMap[MIMEWildcard] = &HTTPBodyMarshaler{ - Marshaler: &JSONPb{OrigName: true}, - } -} - -// HTTPBodyMarshaler is a Marshaler which supports marshaling of a -// google.api.HttpBody message as the full response body if it is -// the actual message used as the response. If not, then this will -// simply fallback to the Marshaler specified as its default Marshaler. -type HTTPBodyMarshaler struct { - Marshaler -} - -// ContentType implementation to keep backwards compatibility with marshal interface -func (h *HTTPBodyMarshaler) ContentType() string { - return h.ContentTypeFromMessage(nil) -} - -// ContentTypeFromMessage in case v is a google.api.HttpBody message it returns -// its specified content type otherwise fall back to the default Marshaler. -func (h *HTTPBodyMarshaler) ContentTypeFromMessage(v interface{}) string { - if httpBody, ok := v.(*httpbody.HttpBody); ok { - return httpBody.GetContentType() - } - return h.Marshaler.ContentType() -} - -// Marshal marshals "v" by returning the body bytes if v is a -// google.api.HttpBody message, otherwise it falls back to the default Marshaler. -func (h *HTTPBodyMarshaler) Marshal(v interface{}) ([]byte, error) { - if httpBody, ok := v.(*httpbody.HttpBody); ok { - return httpBody.Data, nil - } - return h.Marshaler.Marshal(v) -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_json.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_json.go deleted file mode 100644 index f9d3a585a4..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_json.go +++ /dev/null @@ -1,45 +0,0 @@ -package runtime - -import ( - "encoding/json" - "io" -) - -// JSONBuiltin is a Marshaler which marshals/unmarshals into/from JSON -// with the standard "encoding/json" package of Golang. -// Although it is generally faster for simple proto messages than JSONPb, -// it does not support advanced features of protobuf, e.g. map, oneof, .... -// -// The NewEncoder and NewDecoder types return *json.Encoder and -// *json.Decoder respectively. -type JSONBuiltin struct{} - -// ContentType always Returns "application/json". -func (*JSONBuiltin) ContentType() string { - return "application/json" -} - -// Marshal marshals "v" into JSON -func (j *JSONBuiltin) Marshal(v interface{}) ([]byte, error) { - return json.Marshal(v) -} - -// Unmarshal unmarshals JSON data into "v". -func (j *JSONBuiltin) Unmarshal(data []byte, v interface{}) error { - return json.Unmarshal(data, v) -} - -// NewDecoder returns a Decoder which reads JSON stream from "r". -func (j *JSONBuiltin) NewDecoder(r io.Reader) Decoder { - return json.NewDecoder(r) -} - -// NewEncoder returns an Encoder which writes JSON stream into "w". -func (j *JSONBuiltin) NewEncoder(w io.Writer) Encoder { - return json.NewEncoder(w) -} - -// Delimiter for newline encoded JSON streams. -func (j *JSONBuiltin) Delimiter() []byte { - return []byte("\n") -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_jsonpb.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_jsonpb.go deleted file mode 100644 index f0de351b21..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_jsonpb.go +++ /dev/null @@ -1,262 +0,0 @@ -package runtime - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "reflect" - - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/proto" -) - -// JSONPb is a Marshaler which marshals/unmarshals into/from JSON -// with the "github.com/golang/protobuf/jsonpb". -// It supports fully functionality of protobuf unlike JSONBuiltin. -// -// The NewDecoder method returns a DecoderWrapper, so the underlying -// *json.Decoder methods can be used. -type JSONPb jsonpb.Marshaler - -// ContentType always returns "application/json". -func (*JSONPb) ContentType() string { - return "application/json" -} - -// Marshal marshals "v" into JSON. -func (j *JSONPb) Marshal(v interface{}) ([]byte, error) { - if _, ok := v.(proto.Message); !ok { - return j.marshalNonProtoField(v) - } - - var buf bytes.Buffer - if err := j.marshalTo(&buf, v); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error { - p, ok := v.(proto.Message) - if !ok { - buf, err := j.marshalNonProtoField(v) - if err != nil { - return err - } - _, err = w.Write(buf) - return err - } - return (*jsonpb.Marshaler)(j).Marshal(w, p) -} - -var ( - // protoMessageType is stored to prevent constant lookup of the same type at runtime. - protoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem() -) - -// marshalNonProto marshals a non-message field of a protobuf message. -// This function does not correctly marshals arbitrary data structure into JSON, -// but it is only capable of marshaling non-message field values of protobuf, -// i.e. primitive types, enums; pointers to primitives or enums; maps from -// integer/string types to primitives/enums/pointers to messages. -func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) { - if v == nil { - return []byte("null"), nil - } - rv := reflect.ValueOf(v) - for rv.Kind() == reflect.Ptr { - if rv.IsNil() { - return []byte("null"), nil - } - rv = rv.Elem() - } - - if rv.Kind() == reflect.Slice { - if rv.IsNil() { - if j.EmitDefaults { - return []byte("[]"), nil - } - return []byte("null"), nil - } - - if rv.Type().Elem().Implements(protoMessageType) { - var buf bytes.Buffer - err := buf.WriteByte('[') - if err != nil { - return nil, err - } - for i := 0; i < rv.Len(); i++ { - if i != 0 { - err = buf.WriteByte(',') - if err != nil { - return nil, err - } - } - if err = (*jsonpb.Marshaler)(j).Marshal(&buf, rv.Index(i).Interface().(proto.Message)); err != nil { - return nil, err - } - } - err = buf.WriteByte(']') - if err != nil { - return nil, err - } - - return buf.Bytes(), nil - } - } - - if rv.Kind() == reflect.Map { - m := make(map[string]*json.RawMessage) - for _, k := range rv.MapKeys() { - buf, err := j.Marshal(rv.MapIndex(k).Interface()) - if err != nil { - return nil, err - } - m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf) - } - if j.Indent != "" { - return json.MarshalIndent(m, "", j.Indent) - } - return json.Marshal(m) - } - if enum, ok := rv.Interface().(protoEnum); ok && !j.EnumsAsInts { - return json.Marshal(enum.String()) - } - return json.Marshal(rv.Interface()) -} - -// Unmarshal unmarshals JSON "data" into "v" -func (j *JSONPb) Unmarshal(data []byte, v interface{}) error { - return unmarshalJSONPb(data, v) -} - -// NewDecoder returns a Decoder which reads JSON stream from "r". -func (j *JSONPb) NewDecoder(r io.Reader) Decoder { - d := json.NewDecoder(r) - return DecoderWrapper{Decoder: d} -} - -// DecoderWrapper is a wrapper around a *json.Decoder that adds -// support for protos to the Decode method. -type DecoderWrapper struct { - *json.Decoder -} - -// Decode wraps the embedded decoder's Decode method to support -// protos using a jsonpb.Unmarshaler. -func (d DecoderWrapper) Decode(v interface{}) error { - return decodeJSONPb(d.Decoder, v) -} - -// NewEncoder returns an Encoder which writes JSON stream into "w". -func (j *JSONPb) NewEncoder(w io.Writer) Encoder { - return EncoderFunc(func(v interface{}) error { - if err := j.marshalTo(w, v); err != nil { - return err - } - // mimic json.Encoder by adding a newline (makes output - // easier to read when it contains multiple encoded items) - _, err := w.Write(j.Delimiter()) - return err - }) -} - -func unmarshalJSONPb(data []byte, v interface{}) error { - d := json.NewDecoder(bytes.NewReader(data)) - return decodeJSONPb(d, v) -} - -func decodeJSONPb(d *json.Decoder, v interface{}) error { - p, ok := v.(proto.Message) - if !ok { - return decodeNonProtoField(d, v) - } - unmarshaler := &jsonpb.Unmarshaler{AllowUnknownFields: allowUnknownFields} - return unmarshaler.UnmarshalNext(d, p) -} - -func decodeNonProtoField(d *json.Decoder, v interface{}) error { - rv := reflect.ValueOf(v) - if rv.Kind() != reflect.Ptr { - return fmt.Errorf("%T is not a pointer", v) - } - for rv.Kind() == reflect.Ptr { - if rv.IsNil() { - rv.Set(reflect.New(rv.Type().Elem())) - } - if rv.Type().ConvertibleTo(typeProtoMessage) { - unmarshaler := &jsonpb.Unmarshaler{AllowUnknownFields: allowUnknownFields} - return unmarshaler.UnmarshalNext(d, rv.Interface().(proto.Message)) - } - rv = rv.Elem() - } - if rv.Kind() == reflect.Map { - if rv.IsNil() { - rv.Set(reflect.MakeMap(rv.Type())) - } - conv, ok := convFromType[rv.Type().Key().Kind()] - if !ok { - return fmt.Errorf("unsupported type of map field key: %v", rv.Type().Key()) - } - - m := make(map[string]*json.RawMessage) - if err := d.Decode(&m); err != nil { - return err - } - for k, v := range m { - result := conv.Call([]reflect.Value{reflect.ValueOf(k)}) - if err := result[1].Interface(); err != nil { - return err.(error) - } - bk := result[0] - bv := reflect.New(rv.Type().Elem()) - if err := unmarshalJSONPb([]byte(*v), bv.Interface()); err != nil { - return err - } - rv.SetMapIndex(bk, bv.Elem()) - } - return nil - } - if _, ok := rv.Interface().(protoEnum); ok { - var repr interface{} - if err := d.Decode(&repr); err != nil { - return err - } - switch repr.(type) { - case string: - // TODO(yugui) Should use proto.StructProperties? - return fmt.Errorf("unmarshaling of symbolic enum %q not supported: %T", repr, rv.Interface()) - case float64: - rv.Set(reflect.ValueOf(int32(repr.(float64))).Convert(rv.Type())) - return nil - default: - return fmt.Errorf("cannot assign %#v into Go type %T", repr, rv.Interface()) - } - } - return d.Decode(v) -} - -type protoEnum interface { - fmt.Stringer - EnumDescriptor() ([]byte, []int) -} - -var typeProtoMessage = reflect.TypeOf((*proto.Message)(nil)).Elem() - -// Delimiter for newline encoded JSON streams. -func (j *JSONPb) Delimiter() []byte { - return []byte("\n") -} - -// allowUnknownFields helps not to return an error when the destination -// is a struct and the input contains object keys which do not match any -// non-ignored, exported fields in the destination. -var allowUnknownFields = true - -// DisallowUnknownFields enables option in decoder (unmarshaller) to -// return an error when it finds an unknown field. This function must be -// called before using the JSON marshaller. -func DisallowUnknownFields() { - allowUnknownFields = false -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_proto.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_proto.go deleted file mode 100644 index f65d1a2676..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_proto.go +++ /dev/null @@ -1,62 +0,0 @@ -package runtime - -import ( - "io" - - "errors" - "github.com/golang/protobuf/proto" - "io/ioutil" -) - -// ProtoMarshaller is a Marshaller which marshals/unmarshals into/from serialize proto bytes -type ProtoMarshaller struct{} - -// ContentType always returns "application/octet-stream". -func (*ProtoMarshaller) ContentType() string { - return "application/octet-stream" -} - -// Marshal marshals "value" into Proto -func (*ProtoMarshaller) Marshal(value interface{}) ([]byte, error) { - message, ok := value.(proto.Message) - if !ok { - return nil, errors.New("unable to marshal non proto field") - } - return proto.Marshal(message) -} - -// Unmarshal unmarshals proto "data" into "value" -func (*ProtoMarshaller) Unmarshal(data []byte, value interface{}) error { - message, ok := value.(proto.Message) - if !ok { - return errors.New("unable to unmarshal non proto field") - } - return proto.Unmarshal(data, message) -} - -// NewDecoder returns a Decoder which reads proto stream from "reader". -func (marshaller *ProtoMarshaller) NewDecoder(reader io.Reader) Decoder { - return DecoderFunc(func(value interface{}) error { - buffer, err := ioutil.ReadAll(reader) - if err != nil { - return err - } - return marshaller.Unmarshal(buffer, value) - }) -} - -// NewEncoder returns an Encoder which writes proto stream into "writer". -func (marshaller *ProtoMarshaller) NewEncoder(writer io.Writer) Encoder { - return EncoderFunc(func(value interface{}) error { - buffer, err := marshaller.Marshal(value) - if err != nil { - return err - } - _, err = writer.Write(buffer) - if err != nil { - return err - } - - return nil - }) -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go deleted file mode 100644 index 4615329421..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go +++ /dev/null @@ -1,55 +0,0 @@ -package runtime - -import ( - "io" -) - -// Marshaler defines a conversion between byte sequence and gRPC payloads / fields. -type Marshaler interface { - // Marshal marshals "v" into byte sequence. - Marshal(v interface{}) ([]byte, error) - // Unmarshal unmarshals "data" into "v". - // "v" must be a pointer value. - Unmarshal(data []byte, v interface{}) error - // NewDecoder returns a Decoder which reads byte sequence from "r". - NewDecoder(r io.Reader) Decoder - // NewEncoder returns an Encoder which writes bytes sequence into "w". - NewEncoder(w io.Writer) Encoder - // ContentType returns the Content-Type which this marshaler is responsible for. - ContentType() string -} - -// Marshalers that implement contentTypeMarshaler will have their ContentTypeFromMessage method called -// to set the Content-Type header on the response -type contentTypeMarshaler interface { - // ContentTypeFromMessage returns the Content-Type this marshaler produces from the provided message - ContentTypeFromMessage(v interface{}) string -} - -// Decoder decodes a byte sequence -type Decoder interface { - Decode(v interface{}) error -} - -// Encoder encodes gRPC payloads / fields into byte sequence. -type Encoder interface { - Encode(v interface{}) error -} - -// DecoderFunc adapts an decoder function into Decoder. -type DecoderFunc func(v interface{}) error - -// Decode delegates invocations to the underlying function itself. -func (f DecoderFunc) Decode(v interface{}) error { return f(v) } - -// EncoderFunc adapts an encoder function into Encoder -type EncoderFunc func(v interface{}) error - -// Encode delegates invocations to the underlying function itself. -func (f EncoderFunc) Encode(v interface{}) error { return f(v) } - -// Delimited defines the streaming delimiter. -type Delimited interface { - // Delimiter returns the record separator for the stream. - Delimiter() []byte -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go deleted file mode 100644 index 8dd5c24db4..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go +++ /dev/null @@ -1,99 +0,0 @@ -package runtime - -import ( - "errors" - "mime" - "net/http" - - "google.golang.org/grpc/grpclog" -) - -// MIMEWildcard is the fallback MIME type used for requests which do not match -// a registered MIME type. -const MIMEWildcard = "*" - -var ( - acceptHeader = http.CanonicalHeaderKey("Accept") - contentTypeHeader = http.CanonicalHeaderKey("Content-Type") - - defaultMarshaler = &JSONPb{OrigName: true} -) - -// MarshalerForRequest returns the inbound/outbound marshalers for this request. -// It checks the registry on the ServeMux for the MIME type set by the Content-Type header. -// If it isn't set (or the request Content-Type is empty), checks for "*". -// If there are multiple Content-Type headers set, choose the first one that it can -// exactly match in the registry. -// Otherwise, it follows the above logic for "*"/InboundMarshaler/OutboundMarshaler. -func MarshalerForRequest(mux *ServeMux, r *http.Request) (inbound Marshaler, outbound Marshaler) { - for _, acceptVal := range r.Header[acceptHeader] { - if m, ok := mux.marshalers.mimeMap[acceptVal]; ok { - outbound = m - break - } - } - - for _, contentTypeVal := range r.Header[contentTypeHeader] { - contentType, _, err := mime.ParseMediaType(contentTypeVal) - if err != nil { - grpclog.Infof("Failed to parse Content-Type %s: %v", contentTypeVal, err) - continue - } - if m, ok := mux.marshalers.mimeMap[contentType]; ok { - inbound = m - break - } - } - - if inbound == nil { - inbound = mux.marshalers.mimeMap[MIMEWildcard] - } - if outbound == nil { - outbound = inbound - } - - return inbound, outbound -} - -// marshalerRegistry is a mapping from MIME types to Marshalers. -type marshalerRegistry struct { - mimeMap map[string]Marshaler -} - -// add adds a marshaler for a case-sensitive MIME type string ("*" to match any -// MIME type). -func (m marshalerRegistry) add(mime string, marshaler Marshaler) error { - if len(mime) == 0 { - return errors.New("empty MIME type") - } - - m.mimeMap[mime] = marshaler - - return nil -} - -// makeMarshalerMIMERegistry returns a new registry of marshalers. -// It allows for a mapping of case-sensitive Content-Type MIME type string to runtime.Marshaler interfaces. -// -// For example, you could allow the client to specify the use of the runtime.JSONPb marshaler -// with a "application/jsonpb" Content-Type and the use of the runtime.JSONBuiltin marshaler -// with a "application/json" Content-Type. -// "*" can be used to match any Content-Type. -// This can be attached to a ServerMux with the marshaler option. -func makeMarshalerMIMERegistry() marshalerRegistry { - return marshalerRegistry{ - mimeMap: map[string]Marshaler{ - MIMEWildcard: defaultMarshaler, - }, - } -} - -// WithMarshalerOption returns a ServeMuxOption which associates inbound and outbound -// Marshalers to a MIME type in mux. -func WithMarshalerOption(mime string, marshaler Marshaler) ServeMuxOption { - return func(mux *ServeMux) { - if err := mux.marshalers.add(mime, marshaler); err != nil { - panic(err) - } - } -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go deleted file mode 100644 index 523a9cb43c..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go +++ /dev/null @@ -1,300 +0,0 @@ -package runtime - -import ( - "context" - "fmt" - "net/http" - "net/textproto" - "strings" - - "github.com/golang/protobuf/proto" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/metadata" - "google.golang.org/grpc/status" -) - -// A HandlerFunc handles a specific pair of path pattern and HTTP method. -type HandlerFunc func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) - -// ErrUnknownURI is the error supplied to a custom ProtoErrorHandlerFunc when -// a request is received with a URI path that does not match any registered -// service method. -// -// Since gRPC servers return an "Unimplemented" code for requests with an -// unrecognized URI path, this error also has a gRPC "Unimplemented" code. -var ErrUnknownURI = status.Error(codes.Unimplemented, http.StatusText(http.StatusNotImplemented)) - -// ServeMux is a request multiplexer for grpc-gateway. -// It matches http requests to patterns and invokes the corresponding handler. -type ServeMux struct { - // handlers maps HTTP method to a list of handlers. - handlers map[string][]handler - forwardResponseOptions []func(context.Context, http.ResponseWriter, proto.Message) error - marshalers marshalerRegistry - incomingHeaderMatcher HeaderMatcherFunc - outgoingHeaderMatcher HeaderMatcherFunc - metadataAnnotators []func(context.Context, *http.Request) metadata.MD - streamErrorHandler StreamErrorHandlerFunc - protoErrorHandler ProtoErrorHandlerFunc - disablePathLengthFallback bool - lastMatchWins bool -} - -// ServeMuxOption is an option that can be given to a ServeMux on construction. -type ServeMuxOption func(*ServeMux) - -// WithForwardResponseOption returns a ServeMuxOption representing the forwardResponseOption. -// -// forwardResponseOption is an option that will be called on the relevant context.Context, -// http.ResponseWriter, and proto.Message before every forwarded response. -// -// The message may be nil in the case where just a header is being sent. -func WithForwardResponseOption(forwardResponseOption func(context.Context, http.ResponseWriter, proto.Message) error) ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.forwardResponseOptions = append(serveMux.forwardResponseOptions, forwardResponseOption) - } -} - -// SetQueryParameterParser sets the query parameter parser, used to populate message from query parameters. -// Configuring this will mean the generated swagger output is no longer correct, and it should be -// done with careful consideration. -func SetQueryParameterParser(queryParameterParser QueryParameterParser) ServeMuxOption { - return func(serveMux *ServeMux) { - currentQueryParser = queryParameterParser - } -} - -// HeaderMatcherFunc checks whether a header key should be forwarded to/from gRPC context. -type HeaderMatcherFunc func(string) (string, bool) - -// DefaultHeaderMatcher is used to pass http request headers to/from gRPC context. This adds permanent HTTP header -// keys (as specified by the IANA) to gRPC context with grpcgateway- prefix. HTTP headers that start with -// 'Grpc-Metadata-' are mapped to gRPC metadata after removing prefix 'Grpc-Metadata-'. -func DefaultHeaderMatcher(key string) (string, bool) { - key = textproto.CanonicalMIMEHeaderKey(key) - if isPermanentHTTPHeader(key) { - return MetadataPrefix + key, true - } else if strings.HasPrefix(key, MetadataHeaderPrefix) { - return key[len(MetadataHeaderPrefix):], true - } - return "", false -} - -// WithIncomingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for incoming request to gateway. -// -// This matcher will be called with each header in http.Request. If matcher returns true, that header will be -// passed to gRPC context. To transform the header before passing to gRPC context, matcher should return modified header. -func WithIncomingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption { - return func(mux *ServeMux) { - mux.incomingHeaderMatcher = fn - } -} - -// WithOutgoingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for outgoing response from gateway. -// -// This matcher will be called with each header in response header metadata. If matcher returns true, that header will be -// passed to http response returned from gateway. To transform the header before passing to response, -// matcher should return modified header. -func WithOutgoingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption { - return func(mux *ServeMux) { - mux.outgoingHeaderMatcher = fn - } -} - -// WithMetadata returns a ServeMuxOption for passing metadata to a gRPC context. -// -// This can be used by services that need to read from http.Request and modify gRPC context. A common use case -// is reading token from cookie and adding it in gRPC context. -func WithMetadata(annotator func(context.Context, *http.Request) metadata.MD) ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.metadataAnnotators = append(serveMux.metadataAnnotators, annotator) - } -} - -// WithProtoErrorHandler returns a ServeMuxOption for configuring a custom error handler. -// -// This can be used to handle an error as general proto message defined by gRPC. -// When this option is used, the mux uses the configured error handler instead of HTTPError and -// OtherErrorHandler. -func WithProtoErrorHandler(fn ProtoErrorHandlerFunc) ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.protoErrorHandler = fn - } -} - -// WithDisablePathLengthFallback returns a ServeMuxOption for disable path length fallback. -func WithDisablePathLengthFallback() ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.disablePathLengthFallback = true - } -} - -// WithStreamErrorHandler returns a ServeMuxOption that will use the given custom stream -// error handler, which allows for customizing the error trailer for server-streaming -// calls. -// -// For stream errors that occur before any response has been written, the mux's -// ProtoErrorHandler will be invoked. However, once data has been written, the errors must -// be handled differently: they must be included in the response body. The response body's -// final message will include the error details returned by the stream error handler. -func WithStreamErrorHandler(fn StreamErrorHandlerFunc) ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.streamErrorHandler = fn - } -} - -// WithLastMatchWins returns a ServeMuxOption that will enable "last -// match wins" behavior, where if multiple path patterns match a -// request path, the last one defined in the .proto file will be used. -func WithLastMatchWins() ServeMuxOption { - return func(serveMux *ServeMux) { - serveMux.lastMatchWins = true - } -} - -// NewServeMux returns a new ServeMux whose internal mapping is empty. -func NewServeMux(opts ...ServeMuxOption) *ServeMux { - serveMux := &ServeMux{ - handlers: make(map[string][]handler), - forwardResponseOptions: make([]func(context.Context, http.ResponseWriter, proto.Message) error, 0), - marshalers: makeMarshalerMIMERegistry(), - streamErrorHandler: DefaultHTTPStreamErrorHandler, - } - - for _, opt := range opts { - opt(serveMux) - } - - if serveMux.incomingHeaderMatcher == nil { - serveMux.incomingHeaderMatcher = DefaultHeaderMatcher - } - - if serveMux.outgoingHeaderMatcher == nil { - serveMux.outgoingHeaderMatcher = func(key string) (string, bool) { - return fmt.Sprintf("%s%s", MetadataHeaderPrefix, key), true - } - } - - return serveMux -} - -// Handle associates "h" to the pair of HTTP method and path pattern. -func (s *ServeMux) Handle(meth string, pat Pattern, h HandlerFunc) { - if s.lastMatchWins { - s.handlers[meth] = append([]handler{handler{pat: pat, h: h}}, s.handlers[meth]...) - } else { - s.handlers[meth] = append(s.handlers[meth], handler{pat: pat, h: h}) - } -} - -// ServeHTTP dispatches the request to the first handler whose pattern matches to r.Method and r.Path. -func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - - path := r.URL.Path - if !strings.HasPrefix(path, "/") { - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - sterr := status.Error(codes.InvalidArgument, http.StatusText(http.StatusBadRequest)) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr) - } else { - OtherErrorHandler(w, r, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) - } - return - } - - components := strings.Split(path[1:], "/") - l := len(components) - var verb string - if idx := strings.LastIndex(components[l-1], ":"); idx == 0 { - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, ErrUnknownURI) - } else { - OtherErrorHandler(w, r, http.StatusText(http.StatusNotFound), http.StatusNotFound) - } - return - } else if idx > 0 { - c := components[l-1] - components[l-1], verb = c[:idx], c[idx+1:] - } - - if override := r.Header.Get("X-HTTP-Method-Override"); override != "" && s.isPathLengthFallback(r) { - r.Method = strings.ToUpper(override) - if err := r.ParseForm(); err != nil { - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - sterr := status.Error(codes.InvalidArgument, err.Error()) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr) - } else { - OtherErrorHandler(w, r, err.Error(), http.StatusBadRequest) - } - return - } - } - for _, h := range s.handlers[r.Method] { - pathParams, err := h.pat.Match(components, verb) - if err != nil { - continue - } - h.h(w, r, pathParams) - return - } - - // lookup other methods to handle fallback from GET to POST and - // to determine if it is MethodNotAllowed or NotFound. - for m, handlers := range s.handlers { - if m == r.Method { - continue - } - for _, h := range handlers { - pathParams, err := h.pat.Match(components, verb) - if err != nil { - continue - } - // X-HTTP-Method-Override is optional. Always allow fallback to POST. - if s.isPathLengthFallback(r) { - if err := r.ParseForm(); err != nil { - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - sterr := status.Error(codes.InvalidArgument, err.Error()) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr) - } else { - OtherErrorHandler(w, r, err.Error(), http.StatusBadRequest) - } - return - } - h.h(w, r, pathParams) - return - } - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, ErrUnknownURI) - } else { - OtherErrorHandler(w, r, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) - } - return - } - } - - if s.protoErrorHandler != nil { - _, outboundMarshaler := MarshalerForRequest(s, r) - s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, ErrUnknownURI) - } else { - OtherErrorHandler(w, r, http.StatusText(http.StatusNotFound), http.StatusNotFound) - } -} - -// GetForwardResponseOptions returns the ForwardResponseOptions associated with this ServeMux. -func (s *ServeMux) GetForwardResponseOptions() []func(context.Context, http.ResponseWriter, proto.Message) error { - return s.forwardResponseOptions -} - -func (s *ServeMux) isPathLengthFallback(r *http.Request) bool { - return !s.disablePathLengthFallback && r.Method == "POST" && r.Header.Get("Content-Type") == "application/x-www-form-urlencoded" -} - -type handler struct { - pat Pattern - h HandlerFunc -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go deleted file mode 100644 index 09053695da..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go +++ /dev/null @@ -1,262 +0,0 @@ -package runtime - -import ( - "errors" - "fmt" - "strings" - - "github.com/grpc-ecosystem/grpc-gateway/utilities" - "google.golang.org/grpc/grpclog" -) - -var ( - // ErrNotMatch indicates that the given HTTP request path does not match to the pattern. - ErrNotMatch = errors.New("not match to the path pattern") - // ErrInvalidPattern indicates that the given definition of Pattern is not valid. - ErrInvalidPattern = errors.New("invalid pattern") -) - -type op struct { - code utilities.OpCode - operand int -} - -// Pattern is a template pattern of http request paths defined in github.com/googleapis/googleapis/google/api/http.proto. -type Pattern struct { - // ops is a list of operations - ops []op - // pool is a constant pool indexed by the operands or vars. - pool []string - // vars is a list of variables names to be bound by this pattern - vars []string - // stacksize is the max depth of the stack - stacksize int - // tailLen is the length of the fixed-size segments after a deep wildcard - tailLen int - // verb is the VERB part of the path pattern. It is empty if the pattern does not have VERB part. - verb string - // assumeColonVerb indicates whether a path suffix after a final - // colon may only be interpreted as a verb. - assumeColonVerb bool -} - -type patternOptions struct { - assumeColonVerb bool -} - -// PatternOpt is an option for creating Patterns. -type PatternOpt func(*patternOptions) - -// NewPattern returns a new Pattern from the given definition values. -// "ops" is a sequence of op codes. "pool" is a constant pool. -// "verb" is the verb part of the pattern. It is empty if the pattern does not have the part. -// "version" must be 1 for now. -// It returns an error if the given definition is invalid. -func NewPattern(version int, ops []int, pool []string, verb string, opts ...PatternOpt) (Pattern, error) { - options := patternOptions{ - assumeColonVerb: true, - } - for _, o := range opts { - o(&options) - } - - if version != 1 { - grpclog.Infof("unsupported version: %d", version) - return Pattern{}, ErrInvalidPattern - } - - l := len(ops) - if l%2 != 0 { - grpclog.Infof("odd number of ops codes: %d", l) - return Pattern{}, ErrInvalidPattern - } - - var ( - typedOps []op - stack, maxstack int - tailLen int - pushMSeen bool - vars []string - ) - for i := 0; i < l; i += 2 { - op := op{code: utilities.OpCode(ops[i]), operand: ops[i+1]} - switch op.code { - case utilities.OpNop: - continue - case utilities.OpPush: - if pushMSeen { - tailLen++ - } - stack++ - case utilities.OpPushM: - if pushMSeen { - grpclog.Infof("pushM appears twice") - return Pattern{}, ErrInvalidPattern - } - pushMSeen = true - stack++ - case utilities.OpLitPush: - if op.operand < 0 || len(pool) <= op.operand { - grpclog.Infof("negative literal index: %d", op.operand) - return Pattern{}, ErrInvalidPattern - } - if pushMSeen { - tailLen++ - } - stack++ - case utilities.OpConcatN: - if op.operand <= 0 { - grpclog.Infof("negative concat size: %d", op.operand) - return Pattern{}, ErrInvalidPattern - } - stack -= op.operand - if stack < 0 { - grpclog.Print("stack underflow") - return Pattern{}, ErrInvalidPattern - } - stack++ - case utilities.OpCapture: - if op.operand < 0 || len(pool) <= op.operand { - grpclog.Infof("variable name index out of bound: %d", op.operand) - return Pattern{}, ErrInvalidPattern - } - v := pool[op.operand] - op.operand = len(vars) - vars = append(vars, v) - stack-- - if stack < 0 { - grpclog.Infof("stack underflow") - return Pattern{}, ErrInvalidPattern - } - default: - grpclog.Infof("invalid opcode: %d", op.code) - return Pattern{}, ErrInvalidPattern - } - - if maxstack < stack { - maxstack = stack - } - typedOps = append(typedOps, op) - } - return Pattern{ - ops: typedOps, - pool: pool, - vars: vars, - stacksize: maxstack, - tailLen: tailLen, - verb: verb, - assumeColonVerb: options.assumeColonVerb, - }, nil -} - -// MustPattern is a helper function which makes it easier to call NewPattern in variable initialization. -func MustPattern(p Pattern, err error) Pattern { - if err != nil { - grpclog.Fatalf("Pattern initialization failed: %v", err) - } - return p -} - -// Match examines components if it matches to the Pattern. -// If it matches, the function returns a mapping from field paths to their captured values. -// If otherwise, the function returns an error. -func (p Pattern) Match(components []string, verb string) (map[string]string, error) { - if p.verb != verb { - if p.assumeColonVerb || p.verb != "" { - return nil, ErrNotMatch - } - if len(components) == 0 { - components = []string{":" + verb} - } else { - components = append([]string{}, components...) - components[len(components)-1] += ":" + verb - } - verb = "" - } - - var pos int - stack := make([]string, 0, p.stacksize) - captured := make([]string, len(p.vars)) - l := len(components) - for _, op := range p.ops { - switch op.code { - case utilities.OpNop: - continue - case utilities.OpPush, utilities.OpLitPush: - if pos >= l { - return nil, ErrNotMatch - } - c := components[pos] - if op.code == utilities.OpLitPush { - if lit := p.pool[op.operand]; c != lit { - return nil, ErrNotMatch - } - } - stack = append(stack, c) - pos++ - case utilities.OpPushM: - end := len(components) - if end < pos+p.tailLen { - return nil, ErrNotMatch - } - end -= p.tailLen - stack = append(stack, strings.Join(components[pos:end], "/")) - pos = end - case utilities.OpConcatN: - n := op.operand - l := len(stack) - n - stack = append(stack[:l], strings.Join(stack[l:], "/")) - case utilities.OpCapture: - n := len(stack) - 1 - captured[op.operand] = stack[n] - stack = stack[:n] - } - } - if pos < l { - return nil, ErrNotMatch - } - bindings := make(map[string]string) - for i, val := range captured { - bindings[p.vars[i]] = val - } - return bindings, nil -} - -// Verb returns the verb part of the Pattern. -func (p Pattern) Verb() string { return p.verb } - -func (p Pattern) String() string { - var stack []string - for _, op := range p.ops { - switch op.code { - case utilities.OpNop: - continue - case utilities.OpPush: - stack = append(stack, "*") - case utilities.OpLitPush: - stack = append(stack, p.pool[op.operand]) - case utilities.OpPushM: - stack = append(stack, "**") - case utilities.OpConcatN: - n := op.operand - l := len(stack) - n - stack = append(stack[:l], strings.Join(stack[l:], "/")) - case utilities.OpCapture: - n := len(stack) - 1 - stack[n] = fmt.Sprintf("{%s=%s}", p.vars[op.operand], stack[n]) - } - } - segs := strings.Join(stack, "/") - if p.verb != "" { - return fmt.Sprintf("/%s:%s", segs, p.verb) - } - return "/" + segs -} - -// AssumeColonVerbOpt indicates whether a path suffix after a final -// colon may only be interpreted as a verb. -func AssumeColonVerbOpt(val bool) PatternOpt { - return PatternOpt(func(o *patternOptions) { - o.assumeColonVerb = val - }) -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto2_convert.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto2_convert.go deleted file mode 100644 index a3151e2a55..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto2_convert.go +++ /dev/null @@ -1,80 +0,0 @@ -package runtime - -import ( - "github.com/golang/protobuf/proto" -) - -// StringP returns a pointer to a string whose pointee is same as the given string value. -func StringP(val string) (*string, error) { - return proto.String(val), nil -} - -// BoolP parses the given string representation of a boolean value, -// and returns a pointer to a bool whose value is same as the parsed value. -func BoolP(val string) (*bool, error) { - b, err := Bool(val) - if err != nil { - return nil, err - } - return proto.Bool(b), nil -} - -// Float64P parses the given string representation of a floating point number, -// and returns a pointer to a float64 whose value is same as the parsed number. -func Float64P(val string) (*float64, error) { - f, err := Float64(val) - if err != nil { - return nil, err - } - return proto.Float64(f), nil -} - -// Float32P parses the given string representation of a floating point number, -// and returns a pointer to a float32 whose value is same as the parsed number. -func Float32P(val string) (*float32, error) { - f, err := Float32(val) - if err != nil { - return nil, err - } - return proto.Float32(f), nil -} - -// Int64P parses the given string representation of an integer -// and returns a pointer to a int64 whose value is same as the parsed integer. -func Int64P(val string) (*int64, error) { - i, err := Int64(val) - if err != nil { - return nil, err - } - return proto.Int64(i), nil -} - -// Int32P parses the given string representation of an integer -// and returns a pointer to a int32 whose value is same as the parsed integer. -func Int32P(val string) (*int32, error) { - i, err := Int32(val) - if err != nil { - return nil, err - } - return proto.Int32(i), err -} - -// Uint64P parses the given string representation of an integer -// and returns a pointer to a uint64 whose value is same as the parsed integer. -func Uint64P(val string) (*uint64, error) { - i, err := Uint64(val) - if err != nil { - return nil, err - } - return proto.Uint64(i), err -} - -// Uint32P parses the given string representation of an integer -// and returns a pointer to a uint32 whose value is same as the parsed integer. -func Uint32P(val string) (*uint32, error) { - i, err := Uint32(val) - if err != nil { - return nil, err - } - return proto.Uint32(i), err -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go deleted file mode 100644 index 3fd30da22a..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go +++ /dev/null @@ -1,106 +0,0 @@ -package runtime - -import ( - "context" - "io" - "net/http" - - "github.com/golang/protobuf/ptypes/any" - "github.com/grpc-ecosystem/grpc-gateway/internal" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/grpclog" - "google.golang.org/grpc/status" -) - -// StreamErrorHandlerFunc accepts an error as a gRPC error generated via status package and translates it into a -// a proto struct used to represent error at the end of a stream. -type StreamErrorHandlerFunc func(context.Context, error) *StreamError - -// StreamError is the payload for the final message in a server stream in the event that the server returns an -// error after a response message has already been sent. -type StreamError internal.StreamError - -// ProtoErrorHandlerFunc handles the error as a gRPC error generated via status package and replies to the request. -type ProtoErrorHandlerFunc func(context.Context, *ServeMux, Marshaler, http.ResponseWriter, *http.Request, error) - -var _ ProtoErrorHandlerFunc = DefaultHTTPProtoErrorHandler - -// DefaultHTTPProtoErrorHandler is an implementation of HTTPError. -// If "err" is an error from gRPC system, the function replies with the status code mapped by HTTPStatusFromCode. -// If otherwise, it replies with http.StatusInternalServerError. -// -// The response body returned by this function is a Status message marshaled by a Marshaler. -// -// Do not set this function to HTTPError variable directly, use WithProtoErrorHandler option instead. -func DefaultHTTPProtoErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, _ *http.Request, err error) { - // return Internal when Marshal failed - const fallback = `{"code": 13, "message": "failed to marshal error message"}` - - s, ok := status.FromError(err) - if !ok { - s = status.New(codes.Unknown, err.Error()) - } - - w.Header().Del("Trailer") - - contentType := marshaler.ContentType() - // Check marshaler on run time in order to keep backwards compatibility - // An interface param needs to be added to the ContentType() function on - // the Marshal interface to be able to remove this check - if typeMarshaler, ok := marshaler.(contentTypeMarshaler); ok { - pb := s.Proto() - contentType = typeMarshaler.ContentTypeFromMessage(pb) - } - w.Header().Set("Content-Type", contentType) - - buf, merr := marshaler.Marshal(s.Proto()) - if merr != nil { - grpclog.Infof("Failed to marshal error message %q: %v", s.Proto(), merr) - w.WriteHeader(http.StatusInternalServerError) - if _, err := io.WriteString(w, fallback); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - return - } - - md, ok := ServerMetadataFromContext(ctx) - if !ok { - grpclog.Infof("Failed to extract ServerMetadata from context") - } - - handleForwardResponseServerMetadata(w, mux, md) - handleForwardResponseTrailerHeader(w, md) - st := HTTPStatusFromCode(s.Code()) - w.WriteHeader(st) - if _, err := w.Write(buf); err != nil { - grpclog.Infof("Failed to write response: %v", err) - } - - handleForwardResponseTrailer(w, md) -} - -// DefaultHTTPStreamErrorHandler converts the given err into a *StreamError via -// default logic. -// -// It extracts the gRPC status from err if possible. The fields of the status are -// used to populate the returned StreamError, and the HTTP status code is derived -// from the gRPC code via HTTPStatusFromCode. If the given err does not contain a -// gRPC status, an "Unknown" gRPC code is used and "Internal Server Error" HTTP code. -func DefaultHTTPStreamErrorHandler(_ context.Context, err error) *StreamError { - grpcCode := codes.Unknown - grpcMessage := err.Error() - var grpcDetails []*any.Any - if s, ok := status.FromError(err); ok { - grpcCode = s.Code() - grpcMessage = s.Message() - grpcDetails = s.Proto().GetDetails() - } - httpCode := HTTPStatusFromCode(grpcCode) - return &StreamError{ - GrpcCode: int32(grpcCode), - HttpCode: int32(httpCode), - Message: grpcMessage, - HttpStatus: http.StatusText(httpCode), - Details: grpcDetails, - } -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go deleted file mode 100644 index ba66842c33..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go +++ /dev/null @@ -1,406 +0,0 @@ -package runtime - -import ( - "encoding/base64" - "fmt" - "net/url" - "reflect" - "regexp" - "strconv" - "strings" - "time" - - "github.com/golang/protobuf/proto" - "github.com/grpc-ecosystem/grpc-gateway/utilities" - "google.golang.org/grpc/grpclog" -) - -var valuesKeyRegexp = regexp.MustCompile("^(.*)\\[(.*)\\]$") - -var currentQueryParser QueryParameterParser = &defaultQueryParser{} - -// QueryParameterParser defines interface for all query parameter parsers -type QueryParameterParser interface { - Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error -} - -// PopulateQueryParameters parses query parameters -// into "msg" using current query parser -func PopulateQueryParameters(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error { - return currentQueryParser.Parse(msg, values, filter) -} - -type defaultQueryParser struct{} - -// Parse populates "values" into "msg". -// A value is ignored if its key starts with one of the elements in "filter". -func (*defaultQueryParser) Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error { - for key, values := range values { - match := valuesKeyRegexp.FindStringSubmatch(key) - if len(match) == 3 { - key = match[1] - values = append([]string{match[2]}, values...) - } - fieldPath := strings.Split(key, ".") - if filter.HasCommonPrefix(fieldPath) { - continue - } - if err := populateFieldValueFromPath(msg, fieldPath, values); err != nil { - return err - } - } - return nil -} - -// PopulateFieldFromPath sets a value in a nested Protobuf structure. -// It instantiates missing protobuf fields as it goes. -func PopulateFieldFromPath(msg proto.Message, fieldPathString string, value string) error { - fieldPath := strings.Split(fieldPathString, ".") - return populateFieldValueFromPath(msg, fieldPath, []string{value}) -} - -func populateFieldValueFromPath(msg proto.Message, fieldPath []string, values []string) error { - m := reflect.ValueOf(msg) - if m.Kind() != reflect.Ptr { - return fmt.Errorf("unexpected type %T: %v", msg, msg) - } - var props *proto.Properties - m = m.Elem() - for i, fieldName := range fieldPath { - isLast := i == len(fieldPath)-1 - if !isLast && m.Kind() != reflect.Struct { - return fmt.Errorf("non-aggregate type in the mid of path: %s", strings.Join(fieldPath, ".")) - } - var f reflect.Value - var err error - f, props, err = fieldByProtoName(m, fieldName) - if err != nil { - return err - } else if !f.IsValid() { - grpclog.Infof("field not found in %T: %s", msg, strings.Join(fieldPath, ".")) - return nil - } - - switch f.Kind() { - case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, reflect.String, reflect.Uint32, reflect.Uint64: - if !isLast { - return fmt.Errorf("unexpected nested field %s in %s", fieldPath[i+1], strings.Join(fieldPath[:i+1], ".")) - } - m = f - case reflect.Slice: - if !isLast { - return fmt.Errorf("unexpected repeated field in %s", strings.Join(fieldPath, ".")) - } - // Handle []byte - if f.Type().Elem().Kind() == reflect.Uint8 { - m = f - break - } - return populateRepeatedField(f, values, props) - case reflect.Ptr: - if f.IsNil() { - m = reflect.New(f.Type().Elem()) - f.Set(m.Convert(f.Type())) - } - m = f.Elem() - continue - case reflect.Struct: - m = f - continue - case reflect.Map: - if !isLast { - return fmt.Errorf("unexpected nested field %s in %s", fieldPath[i+1], strings.Join(fieldPath[:i+1], ".")) - } - return populateMapField(f, values, props) - default: - return fmt.Errorf("unexpected type %s in %T", f.Type(), msg) - } - } - switch len(values) { - case 0: - return fmt.Errorf("no value of field: %s", strings.Join(fieldPath, ".")) - case 1: - default: - grpclog.Infof("too many field values: %s", strings.Join(fieldPath, ".")) - } - return populateField(m, values[0], props) -} - -// fieldByProtoName looks up a field whose corresponding protobuf field name is "name". -// "m" must be a struct value. It returns zero reflect.Value if no such field found. -func fieldByProtoName(m reflect.Value, name string) (reflect.Value, *proto.Properties, error) { - props := proto.GetProperties(m.Type()) - - // look up field name in oneof map - for _, op := range props.OneofTypes { - if name == op.Prop.OrigName || name == op.Prop.JSONName { - v := reflect.New(op.Type.Elem()) - field := m.Field(op.Field) - if !field.IsNil() { - return reflect.Value{}, nil, fmt.Errorf("field already set for %s oneof", props.Prop[op.Field].OrigName) - } - field.Set(v) - return v.Elem().Field(0), op.Prop, nil - } - } - - for _, p := range props.Prop { - if p.OrigName == name { - return m.FieldByName(p.Name), p, nil - } - if p.JSONName == name { - return m.FieldByName(p.Name), p, nil - } - } - return reflect.Value{}, nil, nil -} - -func populateMapField(f reflect.Value, values []string, props *proto.Properties) error { - if len(values) != 2 { - return fmt.Errorf("more than one value provided for key %s in map %s", values[0], props.Name) - } - - key, value := values[0], values[1] - keyType := f.Type().Key() - valueType := f.Type().Elem() - if f.IsNil() { - f.Set(reflect.MakeMap(f.Type())) - } - - keyConv, ok := convFromType[keyType.Kind()] - if !ok { - return fmt.Errorf("unsupported key type %s in map %s", keyType, props.Name) - } - valueConv, ok := convFromType[valueType.Kind()] - if !ok { - return fmt.Errorf("unsupported value type %s in map %s", valueType, props.Name) - } - - keyV := keyConv.Call([]reflect.Value{reflect.ValueOf(key)}) - if err := keyV[1].Interface(); err != nil { - return err.(error) - } - valueV := valueConv.Call([]reflect.Value{reflect.ValueOf(value)}) - if err := valueV[1].Interface(); err != nil { - return err.(error) - } - - f.SetMapIndex(keyV[0].Convert(keyType), valueV[0].Convert(valueType)) - - return nil -} - -func populateRepeatedField(f reflect.Value, values []string, props *proto.Properties) error { - elemType := f.Type().Elem() - - // is the destination field a slice of an enumeration type? - if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil { - return populateFieldEnumRepeated(f, values, enumValMap) - } - - conv, ok := convFromType[elemType.Kind()] - if !ok { - return fmt.Errorf("unsupported field type %s", elemType) - } - f.Set(reflect.MakeSlice(f.Type(), len(values), len(values)).Convert(f.Type())) - for i, v := range values { - result := conv.Call([]reflect.Value{reflect.ValueOf(v)}) - if err := result[1].Interface(); err != nil { - return err.(error) - } - f.Index(i).Set(result[0].Convert(f.Index(i).Type())) - } - return nil -} - -func populateField(f reflect.Value, value string, props *proto.Properties) error { - i := f.Addr().Interface() - - // Handle protobuf well known types - var name string - switch m := i.(type) { - case interface{ XXX_WellKnownType() string }: - name = m.XXX_WellKnownType() - case proto.Message: - const wktPrefix = "google.protobuf." - if fullName := proto.MessageName(m); strings.HasPrefix(fullName, wktPrefix) { - name = fullName[len(wktPrefix):] - } - } - switch name { - case "Timestamp": - if value == "null" { - f.FieldByName("Seconds").SetInt(0) - f.FieldByName("Nanos").SetInt(0) - return nil - } - - t, err := time.Parse(time.RFC3339Nano, value) - if err != nil { - return fmt.Errorf("bad Timestamp: %v", err) - } - f.FieldByName("Seconds").SetInt(int64(t.Unix())) - f.FieldByName("Nanos").SetInt(int64(t.Nanosecond())) - return nil - case "Duration": - if value == "null" { - f.FieldByName("Seconds").SetInt(0) - f.FieldByName("Nanos").SetInt(0) - return nil - } - d, err := time.ParseDuration(value) - if err != nil { - return fmt.Errorf("bad Duration: %v", err) - } - - ns := d.Nanoseconds() - s := ns / 1e9 - ns %= 1e9 - f.FieldByName("Seconds").SetInt(s) - f.FieldByName("Nanos").SetInt(ns) - return nil - case "DoubleValue": - fallthrough - case "FloatValue": - float64Val, err := strconv.ParseFloat(value, 64) - if err != nil { - return fmt.Errorf("bad DoubleValue: %s", value) - } - f.FieldByName("Value").SetFloat(float64Val) - return nil - case "Int64Value": - fallthrough - case "Int32Value": - int64Val, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return fmt.Errorf("bad DoubleValue: %s", value) - } - f.FieldByName("Value").SetInt(int64Val) - return nil - case "UInt64Value": - fallthrough - case "UInt32Value": - uint64Val, err := strconv.ParseUint(value, 10, 64) - if err != nil { - return fmt.Errorf("bad DoubleValue: %s", value) - } - f.FieldByName("Value").SetUint(uint64Val) - return nil - case "BoolValue": - if value == "true" { - f.FieldByName("Value").SetBool(true) - } else if value == "false" { - f.FieldByName("Value").SetBool(false) - } else { - return fmt.Errorf("bad BoolValue: %s", value) - } - return nil - case "StringValue": - f.FieldByName("Value").SetString(value) - return nil - case "BytesValue": - bytesVal, err := base64.StdEncoding.DecodeString(value) - if err != nil { - return fmt.Errorf("bad BytesValue: %s", value) - } - f.FieldByName("Value").SetBytes(bytesVal) - return nil - case "FieldMask": - p := f.FieldByName("Paths") - for _, v := range strings.Split(value, ",") { - if v != "" { - p.Set(reflect.Append(p, reflect.ValueOf(v))) - } - } - return nil - } - - // Handle Time and Duration stdlib types - switch t := i.(type) { - case *time.Time: - pt, err := time.Parse(time.RFC3339Nano, value) - if err != nil { - return fmt.Errorf("bad Timestamp: %v", err) - } - *t = pt - return nil - case *time.Duration: - d, err := time.ParseDuration(value) - if err != nil { - return fmt.Errorf("bad Duration: %v", err) - } - *t = d - return nil - } - - // is the destination field an enumeration type? - if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil { - return populateFieldEnum(f, value, enumValMap) - } - - conv, ok := convFromType[f.Kind()] - if !ok { - return fmt.Errorf("field type %T is not supported in query parameters", i) - } - result := conv.Call([]reflect.Value{reflect.ValueOf(value)}) - if err := result[1].Interface(); err != nil { - return err.(error) - } - f.Set(result[0].Convert(f.Type())) - return nil -} - -func convertEnum(value string, t reflect.Type, enumValMap map[string]int32) (reflect.Value, error) { - // see if it's an enumeration string - if enumVal, ok := enumValMap[value]; ok { - return reflect.ValueOf(enumVal).Convert(t), nil - } - - // check for an integer that matches an enumeration value - eVal, err := strconv.Atoi(value) - if err != nil { - return reflect.Value{}, fmt.Errorf("%s is not a valid %s", value, t) - } - for _, v := range enumValMap { - if v == int32(eVal) { - return reflect.ValueOf(eVal).Convert(t), nil - } - } - return reflect.Value{}, fmt.Errorf("%s is not a valid %s", value, t) -} - -func populateFieldEnum(f reflect.Value, value string, enumValMap map[string]int32) error { - cval, err := convertEnum(value, f.Type(), enumValMap) - if err != nil { - return err - } - f.Set(cval) - return nil -} - -func populateFieldEnumRepeated(f reflect.Value, values []string, enumValMap map[string]int32) error { - elemType := f.Type().Elem() - f.Set(reflect.MakeSlice(f.Type(), len(values), len(values)).Convert(f.Type())) - for i, v := range values { - result, err := convertEnum(v, elemType, enumValMap) - if err != nil { - return err - } - f.Index(i).Set(result) - } - return nil -} - -var ( - convFromType = map[reflect.Kind]reflect.Value{ - reflect.String: reflect.ValueOf(String), - reflect.Bool: reflect.ValueOf(Bool), - reflect.Float64: reflect.ValueOf(Float64), - reflect.Float32: reflect.ValueOf(Float32), - reflect.Int64: reflect.ValueOf(Int64), - reflect.Int32: reflect.ValueOf(Int32), - reflect.Uint64: reflect.ValueOf(Uint64), - reflect.Uint32: reflect.ValueOf(Uint32), - reflect.Slice: reflect.ValueOf(Bytes), - } -) diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/BUILD.bazel b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/BUILD.bazel deleted file mode 100644 index 7109d79323..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/BUILD.bazel +++ /dev/null @@ -1,21 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -package(default_visibility = ["//visibility:public"]) - -go_library( - name = "go_default_library", - srcs = [ - "doc.go", - "pattern.go", - "readerfactory.go", - "trie.go", - ], - importpath = "github.com/grpc-ecosystem/grpc-gateway/utilities", -) - -go_test( - name = "go_default_test", - size = "small", - srcs = ["trie_test.go"], - embed = [":go_default_library"], -) diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/doc.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/doc.go deleted file mode 100644 index cf79a4d588..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package utilities provides members for internal use in grpc-gateway. -package utilities diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/pattern.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/pattern.go deleted file mode 100644 index dfe7de4864..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/pattern.go +++ /dev/null @@ -1,22 +0,0 @@ -package utilities - -// An OpCode is a opcode of compiled path patterns. -type OpCode int - -// These constants are the valid values of OpCode. -const ( - // OpNop does nothing - OpNop = OpCode(iota) - // OpPush pushes a component to stack - OpPush - // OpLitPush pushes a component to stack if it matches to the literal - OpLitPush - // OpPushM concatenates the remaining components and pushes it to stack - OpPushM - // OpConcatN pops N items from stack, concatenates them and pushes it back to stack - OpConcatN - // OpCapture pops an item and binds it to the variable - OpCapture - // OpEnd is the least positive invalid opcode. - OpEnd -) diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/readerfactory.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/readerfactory.go deleted file mode 100644 index 6dd3854665..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/readerfactory.go +++ /dev/null @@ -1,20 +0,0 @@ -package utilities - -import ( - "bytes" - "io" - "io/ioutil" -) - -// IOReaderFactory takes in an io.Reader and returns a function that will allow you to create a new reader that begins -// at the start of the stream -func IOReaderFactory(r io.Reader) (func() io.Reader, error) { - b, err := ioutil.ReadAll(r) - if err != nil { - return nil, err - } - - return func() io.Reader { - return bytes.NewReader(b) - }, nil -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/trie.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/trie.go deleted file mode 100644 index c2b7b30dd9..0000000000 --- a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/utilities/trie.go +++ /dev/null @@ -1,177 +0,0 @@ -package utilities - -import ( - "sort" -) - -// DoubleArray is a Double Array implementation of trie on sequences of strings. -type DoubleArray struct { - // Encoding keeps an encoding from string to int - Encoding map[string]int - // Base is the base array of Double Array - Base []int - // Check is the check array of Double Array - Check []int -} - -// NewDoubleArray builds a DoubleArray from a set of sequences of strings. -func NewDoubleArray(seqs [][]string) *DoubleArray { - da := &DoubleArray{Encoding: make(map[string]int)} - if len(seqs) == 0 { - return da - } - - encoded := registerTokens(da, seqs) - sort.Sort(byLex(encoded)) - - root := node{row: -1, col: -1, left: 0, right: len(encoded)} - addSeqs(da, encoded, 0, root) - - for i := len(da.Base); i > 0; i-- { - if da.Check[i-1] != 0 { - da.Base = da.Base[:i] - da.Check = da.Check[:i] - break - } - } - return da -} - -func registerTokens(da *DoubleArray, seqs [][]string) [][]int { - var result [][]int - for _, seq := range seqs { - var encoded []int - for _, token := range seq { - if _, ok := da.Encoding[token]; !ok { - da.Encoding[token] = len(da.Encoding) - } - encoded = append(encoded, da.Encoding[token]) - } - result = append(result, encoded) - } - for i := range result { - result[i] = append(result[i], len(da.Encoding)) - } - return result -} - -type node struct { - row, col int - left, right int -} - -func (n node) value(seqs [][]int) int { - return seqs[n.row][n.col] -} - -func (n node) children(seqs [][]int) []*node { - var result []*node - lastVal := int(-1) - last := new(node) - for i := n.left; i < n.right; i++ { - if lastVal == seqs[i][n.col+1] { - continue - } - last.right = i - last = &node{ - row: i, - col: n.col + 1, - left: i, - } - result = append(result, last) - } - last.right = n.right - return result -} - -func addSeqs(da *DoubleArray, seqs [][]int, pos int, n node) { - ensureSize(da, pos) - - children := n.children(seqs) - var i int - for i = 1; ; i++ { - ok := func() bool { - for _, child := range children { - code := child.value(seqs) - j := i + code - ensureSize(da, j) - if da.Check[j] != 0 { - return false - } - } - return true - }() - if ok { - break - } - } - da.Base[pos] = i - for _, child := range children { - code := child.value(seqs) - j := i + code - da.Check[j] = pos + 1 - } - terminator := len(da.Encoding) - for _, child := range children { - code := child.value(seqs) - if code == terminator { - continue - } - j := i + code - addSeqs(da, seqs, j, *child) - } -} - -func ensureSize(da *DoubleArray, i int) { - for i >= len(da.Base) { - da.Base = append(da.Base, make([]int, len(da.Base)+1)...) - da.Check = append(da.Check, make([]int, len(da.Check)+1)...) - } -} - -type byLex [][]int - -func (l byLex) Len() int { return len(l) } -func (l byLex) Swap(i, j int) { l[i], l[j] = l[j], l[i] } -func (l byLex) Less(i, j int) bool { - si := l[i] - sj := l[j] - var k int - for k = 0; k < len(si) && k < len(sj); k++ { - if si[k] < sj[k] { - return true - } - if si[k] > sj[k] { - return false - } - } - if k < len(sj) { - return true - } - return false -} - -// HasCommonPrefix determines if any sequence in the DoubleArray is a prefix of the given sequence. -func (da *DoubleArray) HasCommonPrefix(seq []string) bool { - if len(da.Base) == 0 { - return false - } - - var i int - for _, t := range seq { - code, ok := da.Encoding[t] - if !ok { - break - } - j := da.Base[i] + code - if len(da.Check) <= j || da.Check[j] != i+1 { - break - } - i = j - } - j := da.Base[i] + len(da.Encoding) - if len(da.Check) <= j || da.Check[j] != i+1 { - return false - } - return true -} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/BUILD.bazel b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/BUILD.bazel new file mode 100644 index 0000000000..d71991e6e8 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/BUILD.bazel @@ -0,0 +1,44 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +package(default_visibility = ["//visibility:public"]) + +filegroup( + name = "options_proto_files", + srcs = [ + "annotations.proto", + "openapiv2.proto", + ], +) + +go_library( + name = "options", + embed = [":options_go_proto"], + importpath = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options", +) + +proto_library( + name = "options_proto", + srcs = [ + "annotations.proto", + "openapiv2.proto", + ], + deps = [ + "@com_google_protobuf//:descriptor_proto", + "@com_google_protobuf//:struct_proto", + ], +) + +go_proto_library( + name = "options_go_proto", + compilers = ["//:go_apiv2"], + importpath = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options", + proto = ":options_proto", +) + +alias( + name = "go_default_library", + actual = ":options", + visibility = ["//visibility:public"], +) diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations.pb.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations.pb.go new file mode 100644 index 0000000000..738c9754a6 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations.pb.go @@ -0,0 +1,269 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.0 +// protoc (unknown) +// source: protoc-gen-openapiv2/options/annotations.proto + +//go:build !protoopaque + +package options + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + descriptorpb "google.golang.org/protobuf/types/descriptorpb" + reflect "reflect" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +var file_protoc_gen_openapiv2_options_annotations_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*descriptorpb.FileOptions)(nil), + ExtensionType: (*Swagger)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger", + Tag: "bytes,1042,opt,name=openapiv2_swagger", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.MethodOptions)(nil), + ExtensionType: (*Operation)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation", + Tag: "bytes,1042,opt,name=openapiv2_operation", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.MessageOptions)(nil), + ExtensionType: (*Schema)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema", + Tag: "bytes,1042,opt,name=openapiv2_schema", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.EnumOptions)(nil), + ExtensionType: (*EnumSchema)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum", + Tag: "bytes,1042,opt,name=openapiv2_enum", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.ServiceOptions)(nil), + ExtensionType: (*Tag)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag", + Tag: "bytes,1042,opt,name=openapiv2_tag", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.FieldOptions)(nil), + ExtensionType: (*JSONSchema)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field", + Tag: "bytes,1042,opt,name=openapiv2_field", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, +} + +// Extension fields to descriptorpb.FileOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.Swagger openapiv2_swagger = 1042; + E_Openapiv2Swagger = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[0] +) + +// Extension fields to descriptorpb.MethodOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.Operation openapiv2_operation = 1042; + E_Openapiv2Operation = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[1] +) + +// Extension fields to descriptorpb.MessageOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.Schema openapiv2_schema = 1042; + E_Openapiv2Schema = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[2] +) + +// Extension fields to descriptorpb.EnumOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.EnumSchema openapiv2_enum = 1042; + E_Openapiv2Enum = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[3] +) + +// Extension fields to descriptorpb.ServiceOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.Tag openapiv2_tag = 1042; + E_Openapiv2Tag = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[4] +) + +// Extension fields to descriptorpb.FieldOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.JSONSchema openapiv2_field = 1042; + E_Openapiv2Field = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[5] +) + +var File_protoc_gen_openapiv2_options_annotations_proto protoreflect.FileDescriptor + +var file_protoc_gen_openapiv2_options_annotations_proto_rawDesc = []byte{ + 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x29, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x20, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x7e, 0x0a, 0x11, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x5f, 0x73, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, + 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x92, + 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x70, 0x65, 0x6e, 0x61, + 0x70, 0x69, 0x76, 0x32, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x3a, 0x86, 0x01, 0x0a, 0x13, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x12, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x7e, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, + 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x3a, 0x7b, 0x0a, 0x0e, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x45, 0x6e, 0x75, + 0x6d, 0x3a, 0x75, 0x0a, 0x0d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x5f, 0x74, + 0x61, 0x67, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x54, 0x61, 0x67, 0x52, 0x0c, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x54, 0x61, 0x67, 0x3a, 0x7e, 0x0a, 0x0f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, + 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x65, 0x63, 0x6f, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, + 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var file_protoc_gen_openapiv2_options_annotations_proto_goTypes = []any{ + (*descriptorpb.FileOptions)(nil), // 0: google.protobuf.FileOptions + (*descriptorpb.MethodOptions)(nil), // 1: google.protobuf.MethodOptions + (*descriptorpb.MessageOptions)(nil), // 2: google.protobuf.MessageOptions + (*descriptorpb.EnumOptions)(nil), // 3: google.protobuf.EnumOptions + (*descriptorpb.ServiceOptions)(nil), // 4: google.protobuf.ServiceOptions + (*descriptorpb.FieldOptions)(nil), // 5: google.protobuf.FieldOptions + (*Swagger)(nil), // 6: grpc.gateway.protoc_gen_openapiv2.options.Swagger + (*Operation)(nil), // 7: grpc.gateway.protoc_gen_openapiv2.options.Operation + (*Schema)(nil), // 8: grpc.gateway.protoc_gen_openapiv2.options.Schema + (*EnumSchema)(nil), // 9: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema + (*Tag)(nil), // 10: grpc.gateway.protoc_gen_openapiv2.options.Tag + (*JSONSchema)(nil), // 11: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema +} +var file_protoc_gen_openapiv2_options_annotations_proto_depIdxs = []int32{ + 0, // 0: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger:extendee -> google.protobuf.FileOptions + 1, // 1: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation:extendee -> google.protobuf.MethodOptions + 2, // 2: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema:extendee -> google.protobuf.MessageOptions + 3, // 3: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum:extendee -> google.protobuf.EnumOptions + 4, // 4: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag:extendee -> google.protobuf.ServiceOptions + 5, // 5: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field:extendee -> google.protobuf.FieldOptions + 6, // 6: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Swagger + 7, // 7: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Operation + 8, // 8: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Schema + 9, // 9: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum:type_name -> grpc.gateway.protoc_gen_openapiv2.options.EnumSchema + 10, // 10: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Tag + 11, // 11: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 6, // [6:12] is the sub-list for extension type_name + 0, // [0:6] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_protoc_gen_openapiv2_options_annotations_proto_init() } +func file_protoc_gen_openapiv2_options_annotations_proto_init() { + if File_protoc_gen_openapiv2_options_annotations_proto != nil { + return + } + file_protoc_gen_openapiv2_options_openapiv2_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_protoc_gen_openapiv2_options_annotations_proto_rawDesc, + NumEnums: 0, + NumMessages: 0, + NumExtensions: 6, + NumServices: 0, + }, + GoTypes: file_protoc_gen_openapiv2_options_annotations_proto_goTypes, + DependencyIndexes: file_protoc_gen_openapiv2_options_annotations_proto_depIdxs, + ExtensionInfos: file_protoc_gen_openapiv2_options_annotations_proto_extTypes, + }.Build() + File_protoc_gen_openapiv2_options_annotations_proto = out.File + file_protoc_gen_openapiv2_options_annotations_proto_rawDesc = nil + file_protoc_gen_openapiv2_options_annotations_proto_goTypes = nil + file_protoc_gen_openapiv2_options_annotations_proto_depIdxs = nil +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations.proto b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations.proto new file mode 100644 index 0000000000..aecc5e709c --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations.proto @@ -0,0 +1,51 @@ +syntax = "proto3"; + +package grpc.gateway.protoc_gen_openapiv2.options; + +import "google/protobuf/descriptor.proto"; +import "protoc-gen-openapiv2/options/openapiv2.proto"; + +option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"; + +extend google.protobuf.FileOptions { + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + Swagger openapiv2_swagger = 1042; +} +extend google.protobuf.MethodOptions { + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + Operation openapiv2_operation = 1042; +} +extend google.protobuf.MessageOptions { + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + Schema openapiv2_schema = 1042; +} +extend google.protobuf.EnumOptions { + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + EnumSchema openapiv2_enum = 1042; +} +extend google.protobuf.ServiceOptions { + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + Tag openapiv2_tag = 1042; +} +extend google.protobuf.FieldOptions { + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + JSONSchema openapiv2_field = 1042; +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations_protoopaque.pb.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations_protoopaque.pb.go new file mode 100644 index 0000000000..b570167836 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/annotations_protoopaque.pb.go @@ -0,0 +1,269 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.0 +// protoc (unknown) +// source: protoc-gen-openapiv2/options/annotations.proto + +//go:build protoopaque + +package options + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + descriptorpb "google.golang.org/protobuf/types/descriptorpb" + reflect "reflect" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +var file_protoc_gen_openapiv2_options_annotations_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*descriptorpb.FileOptions)(nil), + ExtensionType: (*Swagger)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger", + Tag: "bytes,1042,opt,name=openapiv2_swagger", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.MethodOptions)(nil), + ExtensionType: (*Operation)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation", + Tag: "bytes,1042,opt,name=openapiv2_operation", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.MessageOptions)(nil), + ExtensionType: (*Schema)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema", + Tag: "bytes,1042,opt,name=openapiv2_schema", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.EnumOptions)(nil), + ExtensionType: (*EnumSchema)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum", + Tag: "bytes,1042,opt,name=openapiv2_enum", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.ServiceOptions)(nil), + ExtensionType: (*Tag)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag", + Tag: "bytes,1042,opt,name=openapiv2_tag", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, + { + ExtendedType: (*descriptorpb.FieldOptions)(nil), + ExtensionType: (*JSONSchema)(nil), + Field: 1042, + Name: "grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field", + Tag: "bytes,1042,opt,name=openapiv2_field", + Filename: "protoc-gen-openapiv2/options/annotations.proto", + }, +} + +// Extension fields to descriptorpb.FileOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.Swagger openapiv2_swagger = 1042; + E_Openapiv2Swagger = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[0] +) + +// Extension fields to descriptorpb.MethodOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.Operation openapiv2_operation = 1042; + E_Openapiv2Operation = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[1] +) + +// Extension fields to descriptorpb.MessageOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.Schema openapiv2_schema = 1042; + E_Openapiv2Schema = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[2] +) + +// Extension fields to descriptorpb.EnumOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.EnumSchema openapiv2_enum = 1042; + E_Openapiv2Enum = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[3] +) + +// Extension fields to descriptorpb.ServiceOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.Tag openapiv2_tag = 1042; + E_Openapiv2Tag = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[4] +) + +// Extension fields to descriptorpb.FieldOptions. +var ( + // ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project. + // + // All IDs are the same, as assigned. It is okay that they are the same, as they extend + // different descriptor messages. + // + // optional grpc.gateway.protoc_gen_openapiv2.options.JSONSchema openapiv2_field = 1042; + E_Openapiv2Field = &file_protoc_gen_openapiv2_options_annotations_proto_extTypes[5] +) + +var File_protoc_gen_openapiv2_options_annotations_proto protoreflect.FileDescriptor + +var file_protoc_gen_openapiv2_options_annotations_proto_rawDesc = []byte{ + 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x29, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x20, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2c, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x7e, 0x0a, 0x11, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x5f, 0x73, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, + 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x92, + 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x52, 0x10, 0x6f, 0x70, 0x65, 0x6e, 0x61, + 0x70, 0x69, 0x76, 0x32, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x3a, 0x86, 0x01, 0x0a, 0x13, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x5f, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x12, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x7e, 0x0a, 0x10, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, + 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x52, 0x0f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x3a, 0x7b, 0x0a, 0x0e, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x5f, 0x65, 0x6e, 0x75, 0x6d, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x45, 0x6e, 0x75, + 0x6d, 0x3a, 0x75, 0x0a, 0x0d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x5f, 0x74, + 0x61, 0x67, 0x12, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x54, 0x61, 0x67, 0x52, 0x0c, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x54, 0x61, 0x67, 0x3a, 0x7e, 0x0a, 0x0f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, + 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x92, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, + 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0e, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x42, 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x65, 0x63, 0x6f, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, + 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var file_protoc_gen_openapiv2_options_annotations_proto_goTypes = []any{ + (*descriptorpb.FileOptions)(nil), // 0: google.protobuf.FileOptions + (*descriptorpb.MethodOptions)(nil), // 1: google.protobuf.MethodOptions + (*descriptorpb.MessageOptions)(nil), // 2: google.protobuf.MessageOptions + (*descriptorpb.EnumOptions)(nil), // 3: google.protobuf.EnumOptions + (*descriptorpb.ServiceOptions)(nil), // 4: google.protobuf.ServiceOptions + (*descriptorpb.FieldOptions)(nil), // 5: google.protobuf.FieldOptions + (*Swagger)(nil), // 6: grpc.gateway.protoc_gen_openapiv2.options.Swagger + (*Operation)(nil), // 7: grpc.gateway.protoc_gen_openapiv2.options.Operation + (*Schema)(nil), // 8: grpc.gateway.protoc_gen_openapiv2.options.Schema + (*EnumSchema)(nil), // 9: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema + (*Tag)(nil), // 10: grpc.gateway.protoc_gen_openapiv2.options.Tag + (*JSONSchema)(nil), // 11: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema +} +var file_protoc_gen_openapiv2_options_annotations_proto_depIdxs = []int32{ + 0, // 0: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger:extendee -> google.protobuf.FileOptions + 1, // 1: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation:extendee -> google.protobuf.MethodOptions + 2, // 2: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema:extendee -> google.protobuf.MessageOptions + 3, // 3: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum:extendee -> google.protobuf.EnumOptions + 4, // 4: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag:extendee -> google.protobuf.ServiceOptions + 5, // 5: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field:extendee -> google.protobuf.FieldOptions + 6, // 6: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Swagger + 7, // 7: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Operation + 8, // 8: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Schema + 9, // 9: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum:type_name -> grpc.gateway.protoc_gen_openapiv2.options.EnumSchema + 10, // 10: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Tag + 11, // 11: grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 6, // [6:12] is the sub-list for extension type_name + 0, // [0:6] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_protoc_gen_openapiv2_options_annotations_proto_init() } +func file_protoc_gen_openapiv2_options_annotations_proto_init() { + if File_protoc_gen_openapiv2_options_annotations_proto != nil { + return + } + file_protoc_gen_openapiv2_options_openapiv2_proto_init() + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_protoc_gen_openapiv2_options_annotations_proto_rawDesc, + NumEnums: 0, + NumMessages: 0, + NumExtensions: 6, + NumServices: 0, + }, + GoTypes: file_protoc_gen_openapiv2_options_annotations_proto_goTypes, + DependencyIndexes: file_protoc_gen_openapiv2_options_annotations_proto_depIdxs, + ExtensionInfos: file_protoc_gen_openapiv2_options_annotations_proto_extTypes, + }.Build() + File_protoc_gen_openapiv2_options_annotations_proto = out.File + file_protoc_gen_openapiv2_options_annotations_proto_rawDesc = nil + file_protoc_gen_openapiv2_options_annotations_proto_goTypes = nil + file_protoc_gen_openapiv2_options_annotations_proto_depIdxs = nil +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/buf.gen.yaml b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/buf.gen.yaml new file mode 100644 index 0000000000..07dfb958f1 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/buf.gen.yaml @@ -0,0 +1,7 @@ +version: v2 +plugins: + - remote: buf.build/protocolbuffers/go:v1.36.0 + out: . + opt: + - paths=source_relative + - default_api_level=API_HYBRID diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2.pb.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2.pb.go new file mode 100644 index 0000000000..3a34e664e0 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2.pb.go @@ -0,0 +1,4263 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.0 +// protoc (unknown) +// source: protoc-gen-openapiv2/options/openapiv2.proto + +//go:build !protoopaque + +package options + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + structpb "google.golang.org/protobuf/types/known/structpb" + reflect "reflect" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Scheme describes the schemes supported by the OpenAPI Swagger +// and Operation objects. +type Scheme int32 + +const ( + Scheme_UNKNOWN Scheme = 0 + Scheme_HTTP Scheme = 1 + Scheme_HTTPS Scheme = 2 + Scheme_WS Scheme = 3 + Scheme_WSS Scheme = 4 +) + +// Enum value maps for Scheme. +var ( + Scheme_name = map[int32]string{ + 0: "UNKNOWN", + 1: "HTTP", + 2: "HTTPS", + 3: "WS", + 4: "WSS", + } + Scheme_value = map[string]int32{ + "UNKNOWN": 0, + "HTTP": 1, + "HTTPS": 2, + "WS": 3, + "WSS": 4, + } +) + +func (x Scheme) Enum() *Scheme { + p := new(Scheme) + *p = x + return p +} + +func (x Scheme) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Scheme) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[0].Descriptor() +} + +func (Scheme) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[0] +} + +func (x Scheme) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// `Type` is a supported HTTP header type. +// See https://swagger.io/specification/v2/#parameterType. +type HeaderParameter_Type int32 + +const ( + HeaderParameter_UNKNOWN HeaderParameter_Type = 0 + HeaderParameter_STRING HeaderParameter_Type = 1 + HeaderParameter_NUMBER HeaderParameter_Type = 2 + HeaderParameter_INTEGER HeaderParameter_Type = 3 + HeaderParameter_BOOLEAN HeaderParameter_Type = 4 +) + +// Enum value maps for HeaderParameter_Type. +var ( + HeaderParameter_Type_name = map[int32]string{ + 0: "UNKNOWN", + 1: "STRING", + 2: "NUMBER", + 3: "INTEGER", + 4: "BOOLEAN", + } + HeaderParameter_Type_value = map[string]int32{ + "UNKNOWN": 0, + "STRING": 1, + "NUMBER": 2, + "INTEGER": 3, + "BOOLEAN": 4, + } +) + +func (x HeaderParameter_Type) Enum() *HeaderParameter_Type { + p := new(HeaderParameter_Type) + *p = x + return p +} + +func (x HeaderParameter_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HeaderParameter_Type) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[1].Descriptor() +} + +func (HeaderParameter_Type) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[1] +} + +func (x HeaderParameter_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +type JSONSchema_JSONSchemaSimpleTypes int32 + +const ( + JSONSchema_UNKNOWN JSONSchema_JSONSchemaSimpleTypes = 0 + JSONSchema_ARRAY JSONSchema_JSONSchemaSimpleTypes = 1 + JSONSchema_BOOLEAN JSONSchema_JSONSchemaSimpleTypes = 2 + JSONSchema_INTEGER JSONSchema_JSONSchemaSimpleTypes = 3 + JSONSchema_NULL JSONSchema_JSONSchemaSimpleTypes = 4 + JSONSchema_NUMBER JSONSchema_JSONSchemaSimpleTypes = 5 + JSONSchema_OBJECT JSONSchema_JSONSchemaSimpleTypes = 6 + JSONSchema_STRING JSONSchema_JSONSchemaSimpleTypes = 7 +) + +// Enum value maps for JSONSchema_JSONSchemaSimpleTypes. +var ( + JSONSchema_JSONSchemaSimpleTypes_name = map[int32]string{ + 0: "UNKNOWN", + 1: "ARRAY", + 2: "BOOLEAN", + 3: "INTEGER", + 4: "NULL", + 5: "NUMBER", + 6: "OBJECT", + 7: "STRING", + } + JSONSchema_JSONSchemaSimpleTypes_value = map[string]int32{ + "UNKNOWN": 0, + "ARRAY": 1, + "BOOLEAN": 2, + "INTEGER": 3, + "NULL": 4, + "NUMBER": 5, + "OBJECT": 6, + "STRING": 7, + } +) + +func (x JSONSchema_JSONSchemaSimpleTypes) Enum() *JSONSchema_JSONSchemaSimpleTypes { + p := new(JSONSchema_JSONSchemaSimpleTypes) + *p = x + return p +} + +func (x JSONSchema_JSONSchemaSimpleTypes) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (JSONSchema_JSONSchemaSimpleTypes) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[2].Descriptor() +} + +func (JSONSchema_JSONSchemaSimpleTypes) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[2] +} + +func (x JSONSchema_JSONSchemaSimpleTypes) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// The type of the security scheme. Valid values are "basic", +// "apiKey" or "oauth2". +type SecurityScheme_Type int32 + +const ( + SecurityScheme_TYPE_INVALID SecurityScheme_Type = 0 + SecurityScheme_TYPE_BASIC SecurityScheme_Type = 1 + SecurityScheme_TYPE_API_KEY SecurityScheme_Type = 2 + SecurityScheme_TYPE_OAUTH2 SecurityScheme_Type = 3 +) + +// Enum value maps for SecurityScheme_Type. +var ( + SecurityScheme_Type_name = map[int32]string{ + 0: "TYPE_INVALID", + 1: "TYPE_BASIC", + 2: "TYPE_API_KEY", + 3: "TYPE_OAUTH2", + } + SecurityScheme_Type_value = map[string]int32{ + "TYPE_INVALID": 0, + "TYPE_BASIC": 1, + "TYPE_API_KEY": 2, + "TYPE_OAUTH2": 3, + } +) + +func (x SecurityScheme_Type) Enum() *SecurityScheme_Type { + p := new(SecurityScheme_Type) + *p = x + return p +} + +func (x SecurityScheme_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SecurityScheme_Type) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[3].Descriptor() +} + +func (SecurityScheme_Type) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[3] +} + +func (x SecurityScheme_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// The location of the API key. Valid values are "query" or "header". +type SecurityScheme_In int32 + +const ( + SecurityScheme_IN_INVALID SecurityScheme_In = 0 + SecurityScheme_IN_QUERY SecurityScheme_In = 1 + SecurityScheme_IN_HEADER SecurityScheme_In = 2 +) + +// Enum value maps for SecurityScheme_In. +var ( + SecurityScheme_In_name = map[int32]string{ + 0: "IN_INVALID", + 1: "IN_QUERY", + 2: "IN_HEADER", + } + SecurityScheme_In_value = map[string]int32{ + "IN_INVALID": 0, + "IN_QUERY": 1, + "IN_HEADER": 2, + } +) + +func (x SecurityScheme_In) Enum() *SecurityScheme_In { + p := new(SecurityScheme_In) + *p = x + return p +} + +func (x SecurityScheme_In) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SecurityScheme_In) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[4].Descriptor() +} + +func (SecurityScheme_In) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[4] +} + +func (x SecurityScheme_In) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// The flow used by the OAuth2 security scheme. Valid values are +// "implicit", "password", "application" or "accessCode". +type SecurityScheme_Flow int32 + +const ( + SecurityScheme_FLOW_INVALID SecurityScheme_Flow = 0 + SecurityScheme_FLOW_IMPLICIT SecurityScheme_Flow = 1 + SecurityScheme_FLOW_PASSWORD SecurityScheme_Flow = 2 + SecurityScheme_FLOW_APPLICATION SecurityScheme_Flow = 3 + SecurityScheme_FLOW_ACCESS_CODE SecurityScheme_Flow = 4 +) + +// Enum value maps for SecurityScheme_Flow. +var ( + SecurityScheme_Flow_name = map[int32]string{ + 0: "FLOW_INVALID", + 1: "FLOW_IMPLICIT", + 2: "FLOW_PASSWORD", + 3: "FLOW_APPLICATION", + 4: "FLOW_ACCESS_CODE", + } + SecurityScheme_Flow_value = map[string]int32{ + "FLOW_INVALID": 0, + "FLOW_IMPLICIT": 1, + "FLOW_PASSWORD": 2, + "FLOW_APPLICATION": 3, + "FLOW_ACCESS_CODE": 4, + } +) + +func (x SecurityScheme_Flow) Enum() *SecurityScheme_Flow { + p := new(SecurityScheme_Flow) + *p = x + return p +} + +func (x SecurityScheme_Flow) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SecurityScheme_Flow) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[5].Descriptor() +} + +func (SecurityScheme_Flow) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[5] +} + +func (x SecurityScheme_Flow) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// `Swagger` is a representation of OpenAPI v2 specification's Swagger object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#swaggerObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// title: "Echo API"; +// version: "1.0"; +// description: ""; +// contact: { +// name: "gRPC-Gateway project"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// email: "none@example.com"; +// }; +// license: { +// name: "BSD 3-Clause License"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; +// }; +// }; +// schemes: HTTPS; +// consumes: "application/json"; +// produces: "application/json"; +// }; +type Swagger struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // Specifies the OpenAPI Specification version being used. It can be + // used by the OpenAPI UI and other clients to interpret the API listing. The + // value MUST be "2.0". + Swagger string `protobuf:"bytes,1,opt,name=swagger,proto3" json:"swagger,omitempty"` + // Provides metadata about the API. The metadata can be used by the + // clients if needed. + Info *Info `protobuf:"bytes,2,opt,name=info,proto3" json:"info,omitempty"` + // The host (name or ip) serving the API. This MUST be the host only and does + // not include the scheme nor sub-paths. It MAY include a port. If the host is + // not included, the host serving the documentation is to be used (including + // the port). The host does not support path templating. + Host string `protobuf:"bytes,3,opt,name=host,proto3" json:"host,omitempty"` + // The base path on which the API is served, which is relative to the host. If + // it is not included, the API is served directly under the host. The value + // MUST start with a leading slash (/). The basePath does not support path + // templating. + // Note that using `base_path` does not change the endpoint paths that are + // generated in the resulting OpenAPI file. If you wish to use `base_path` + // with relatively generated OpenAPI paths, the `base_path` prefix must be + // manually removed from your `google.api.http` paths and your code changed to + // serve the API from the `base_path`. + BasePath string `protobuf:"bytes,4,opt,name=base_path,json=basePath,proto3" json:"base_path,omitempty"` + // The transfer protocol of the API. Values MUST be from the list: "http", + // "https", "ws", "wss". If the schemes is not included, the default scheme to + // be used is the one used to access the OpenAPI definition itself. + Schemes []Scheme `protobuf:"varint,5,rep,packed,name=schemes,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.Scheme" json:"schemes,omitempty"` + // A list of MIME types the APIs can consume. This is global to all APIs but + // can be overridden on specific API calls. Value MUST be as described under + // Mime Types. + Consumes []string `protobuf:"bytes,6,rep,name=consumes,proto3" json:"consumes,omitempty"` + // A list of MIME types the APIs can produce. This is global to all APIs but + // can be overridden on specific API calls. Value MUST be as described under + // Mime Types. + Produces []string `protobuf:"bytes,7,rep,name=produces,proto3" json:"produces,omitempty"` + // An object to hold responses that can be used across operations. This + // property does not define global responses for all operations. + Responses map[string]*Response `protobuf:"bytes,10,rep,name=responses,proto3" json:"responses,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Security scheme definitions that can be used across the specification. + SecurityDefinitions *SecurityDefinitions `protobuf:"bytes,11,opt,name=security_definitions,json=securityDefinitions,proto3" json:"security_definitions,omitempty"` + // A declaration of which security schemes are applied for the API as a whole. + // The list of values describes alternative security schemes that can be used + // (that is, there is a logical OR between the security requirements). + // Individual operations can override this definition. + Security []*SecurityRequirement `protobuf:"bytes,12,rep,name=security,proto3" json:"security,omitempty"` + // A list of tags for API documentation control. Tags can be used for logical + // grouping of operations by resources or any other qualifier. + Tags []*Tag `protobuf:"bytes,13,rep,name=tags,proto3" json:"tags,omitempty"` + // Additional external documentation. + ExternalDocs *ExternalDocumentation `protobuf:"bytes,14,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value `protobuf:"bytes,15,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Swagger) Reset() { + *x = Swagger{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Swagger) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Swagger) ProtoMessage() {} + +func (x *Swagger) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Swagger) GetSwagger() string { + if x != nil { + return x.Swagger + } + return "" +} + +func (x *Swagger) GetInfo() *Info { + if x != nil { + return x.Info + } + return nil +} + +func (x *Swagger) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + +func (x *Swagger) GetBasePath() string { + if x != nil { + return x.BasePath + } + return "" +} + +func (x *Swagger) GetSchemes() []Scheme { + if x != nil { + return x.Schemes + } + return nil +} + +func (x *Swagger) GetConsumes() []string { + if x != nil { + return x.Consumes + } + return nil +} + +func (x *Swagger) GetProduces() []string { + if x != nil { + return x.Produces + } + return nil +} + +func (x *Swagger) GetResponses() map[string]*Response { + if x != nil { + return x.Responses + } + return nil +} + +func (x *Swagger) GetSecurityDefinitions() *SecurityDefinitions { + if x != nil { + return x.SecurityDefinitions + } + return nil +} + +func (x *Swagger) GetSecurity() []*SecurityRequirement { + if x != nil { + return x.Security + } + return nil +} + +func (x *Swagger) GetTags() []*Tag { + if x != nil { + return x.Tags + } + return nil +} + +func (x *Swagger) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.ExternalDocs + } + return nil +} + +func (x *Swagger) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.Extensions + } + return nil +} + +func (x *Swagger) SetSwagger(v string) { + x.Swagger = v +} + +func (x *Swagger) SetInfo(v *Info) { + x.Info = v +} + +func (x *Swagger) SetHost(v string) { + x.Host = v +} + +func (x *Swagger) SetBasePath(v string) { + x.BasePath = v +} + +func (x *Swagger) SetSchemes(v []Scheme) { + x.Schemes = v +} + +func (x *Swagger) SetConsumes(v []string) { + x.Consumes = v +} + +func (x *Swagger) SetProduces(v []string) { + x.Produces = v +} + +func (x *Swagger) SetResponses(v map[string]*Response) { + x.Responses = v +} + +func (x *Swagger) SetSecurityDefinitions(v *SecurityDefinitions) { + x.SecurityDefinitions = v +} + +func (x *Swagger) SetSecurity(v []*SecurityRequirement) { + x.Security = v +} + +func (x *Swagger) SetTags(v []*Tag) { + x.Tags = v +} + +func (x *Swagger) SetExternalDocs(v *ExternalDocumentation) { + x.ExternalDocs = v +} + +func (x *Swagger) SetExtensions(v map[string]*structpb.Value) { + x.Extensions = v +} + +func (x *Swagger) HasInfo() bool { + if x == nil { + return false + } + return x.Info != nil +} + +func (x *Swagger) HasSecurityDefinitions() bool { + if x == nil { + return false + } + return x.SecurityDefinitions != nil +} + +func (x *Swagger) HasExternalDocs() bool { + if x == nil { + return false + } + return x.ExternalDocs != nil +} + +func (x *Swagger) ClearInfo() { + x.Info = nil +} + +func (x *Swagger) ClearSecurityDefinitions() { + x.SecurityDefinitions = nil +} + +func (x *Swagger) ClearExternalDocs() { + x.ExternalDocs = nil +} + +type Swagger_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Specifies the OpenAPI Specification version being used. It can be + // used by the OpenAPI UI and other clients to interpret the API listing. The + // value MUST be "2.0". + Swagger string + // Provides metadata about the API. The metadata can be used by the + // clients if needed. + Info *Info + // The host (name or ip) serving the API. This MUST be the host only and does + // not include the scheme nor sub-paths. It MAY include a port. If the host is + // not included, the host serving the documentation is to be used (including + // the port). The host does not support path templating. + Host string + // The base path on which the API is served, which is relative to the host. If + // it is not included, the API is served directly under the host. The value + // MUST start with a leading slash (/). The basePath does not support path + // templating. + // Note that using `base_path` does not change the endpoint paths that are + // generated in the resulting OpenAPI file. If you wish to use `base_path` + // with relatively generated OpenAPI paths, the `base_path` prefix must be + // manually removed from your `google.api.http` paths and your code changed to + // serve the API from the `base_path`. + BasePath string + // The transfer protocol of the API. Values MUST be from the list: "http", + // "https", "ws", "wss". If the schemes is not included, the default scheme to + // be used is the one used to access the OpenAPI definition itself. + Schemes []Scheme + // A list of MIME types the APIs can consume. This is global to all APIs but + // can be overridden on specific API calls. Value MUST be as described under + // Mime Types. + Consumes []string + // A list of MIME types the APIs can produce. This is global to all APIs but + // can be overridden on specific API calls. Value MUST be as described under + // Mime Types. + Produces []string + // An object to hold responses that can be used across operations. This + // property does not define global responses for all operations. + Responses map[string]*Response + // Security scheme definitions that can be used across the specification. + SecurityDefinitions *SecurityDefinitions + // A declaration of which security schemes are applied for the API as a whole. + // The list of values describes alternative security schemes that can be used + // (that is, there is a logical OR between the security requirements). + // Individual operations can override this definition. + Security []*SecurityRequirement + // A list of tags for API documentation control. Tags can be used for logical + // grouping of operations by resources or any other qualifier. + Tags []*Tag + // Additional external documentation. + ExternalDocs *ExternalDocumentation + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 Swagger_builder) Build() *Swagger { + m0 := &Swagger{} + b, x := &b0, m0 + _, _ = b, x + x.Swagger = b.Swagger + x.Info = b.Info + x.Host = b.Host + x.BasePath = b.BasePath + x.Schemes = b.Schemes + x.Consumes = b.Consumes + x.Produces = b.Produces + x.Responses = b.Responses + x.SecurityDefinitions = b.SecurityDefinitions + x.Security = b.Security + x.Tags = b.Tags + x.ExternalDocs = b.ExternalDocs + x.Extensions = b.Extensions + return m0 +} + +// `Operation` is a representation of OpenAPI v2 specification's Operation object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#operationObject +// +// Example: +// +// service EchoService { +// rpc Echo(SimpleMessage) returns (SimpleMessage) { +// option (google.api.http) = { +// get: "/v1/example/echo/{id}" +// }; +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { +// summary: "Get a message."; +// operation_id: "getMessage"; +// tags: "echo"; +// responses: { +// key: "200" +// value: { +// description: "OK"; +// } +// } +// }; +// } +// } +type Operation struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // A list of tags for API documentation control. Tags can be used for logical + // grouping of operations by resources or any other qualifier. + Tags []string `protobuf:"bytes,1,rep,name=tags,proto3" json:"tags,omitempty"` + // A short summary of what the operation does. For maximum readability in the + // swagger-ui, this field SHOULD be less than 120 characters. + Summary string `protobuf:"bytes,2,opt,name=summary,proto3" json:"summary,omitempty"` + // A verbose explanation of the operation behavior. GFM syntax can be used for + // rich text representation. + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + // Additional external documentation for this operation. + ExternalDocs *ExternalDocumentation `protobuf:"bytes,4,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + // Unique string used to identify the operation. The id MUST be unique among + // all operations described in the API. Tools and libraries MAY use the + // operationId to uniquely identify an operation, therefore, it is recommended + // to follow common programming naming conventions. + OperationId string `protobuf:"bytes,5,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` + // A list of MIME types the operation can consume. This overrides the consumes + // definition at the OpenAPI Object. An empty value MAY be used to clear the + // global definition. Value MUST be as described under Mime Types. + Consumes []string `protobuf:"bytes,6,rep,name=consumes,proto3" json:"consumes,omitempty"` + // A list of MIME types the operation can produce. This overrides the produces + // definition at the OpenAPI Object. An empty value MAY be used to clear the + // global definition. Value MUST be as described under Mime Types. + Produces []string `protobuf:"bytes,7,rep,name=produces,proto3" json:"produces,omitempty"` + // The list of possible responses as they are returned from executing this + // operation. + Responses map[string]*Response `protobuf:"bytes,9,rep,name=responses,proto3" json:"responses,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // The transfer protocol for the operation. Values MUST be from the list: + // "http", "https", "ws", "wss". The value overrides the OpenAPI Object + // schemes definition. + Schemes []Scheme `protobuf:"varint,10,rep,packed,name=schemes,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.Scheme" json:"schemes,omitempty"` + // Declares this operation to be deprecated. Usage of the declared operation + // should be refrained. Default value is false. + Deprecated bool `protobuf:"varint,11,opt,name=deprecated,proto3" json:"deprecated,omitempty"` + // A declaration of which security schemes are applied for this operation. The + // list of values describes alternative security schemes that can be used + // (that is, there is a logical OR between the security requirements). This + // definition overrides any declared top-level security. To remove a top-level + // security declaration, an empty array can be used. + Security []*SecurityRequirement `protobuf:"bytes,12,rep,name=security,proto3" json:"security,omitempty"` + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value `protobuf:"bytes,13,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Custom parameters such as HTTP request headers. + // See: https://swagger.io/docs/specification/2-0/describing-parameters/ + // and https://swagger.io/specification/v2/#parameter-object. + Parameters *Parameters `protobuf:"bytes,14,opt,name=parameters,proto3" json:"parameters,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Operation) Reset() { + *x = Operation{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Operation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Operation) ProtoMessage() {} + +func (x *Operation) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Operation) GetTags() []string { + if x != nil { + return x.Tags + } + return nil +} + +func (x *Operation) GetSummary() string { + if x != nil { + return x.Summary + } + return "" +} + +func (x *Operation) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Operation) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.ExternalDocs + } + return nil +} + +func (x *Operation) GetOperationId() string { + if x != nil { + return x.OperationId + } + return "" +} + +func (x *Operation) GetConsumes() []string { + if x != nil { + return x.Consumes + } + return nil +} + +func (x *Operation) GetProduces() []string { + if x != nil { + return x.Produces + } + return nil +} + +func (x *Operation) GetResponses() map[string]*Response { + if x != nil { + return x.Responses + } + return nil +} + +func (x *Operation) GetSchemes() []Scheme { + if x != nil { + return x.Schemes + } + return nil +} + +func (x *Operation) GetDeprecated() bool { + if x != nil { + return x.Deprecated + } + return false +} + +func (x *Operation) GetSecurity() []*SecurityRequirement { + if x != nil { + return x.Security + } + return nil +} + +func (x *Operation) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.Extensions + } + return nil +} + +func (x *Operation) GetParameters() *Parameters { + if x != nil { + return x.Parameters + } + return nil +} + +func (x *Operation) SetTags(v []string) { + x.Tags = v +} + +func (x *Operation) SetSummary(v string) { + x.Summary = v +} + +func (x *Operation) SetDescription(v string) { + x.Description = v +} + +func (x *Operation) SetExternalDocs(v *ExternalDocumentation) { + x.ExternalDocs = v +} + +func (x *Operation) SetOperationId(v string) { + x.OperationId = v +} + +func (x *Operation) SetConsumes(v []string) { + x.Consumes = v +} + +func (x *Operation) SetProduces(v []string) { + x.Produces = v +} + +func (x *Operation) SetResponses(v map[string]*Response) { + x.Responses = v +} + +func (x *Operation) SetSchemes(v []Scheme) { + x.Schemes = v +} + +func (x *Operation) SetDeprecated(v bool) { + x.Deprecated = v +} + +func (x *Operation) SetSecurity(v []*SecurityRequirement) { + x.Security = v +} + +func (x *Operation) SetExtensions(v map[string]*structpb.Value) { + x.Extensions = v +} + +func (x *Operation) SetParameters(v *Parameters) { + x.Parameters = v +} + +func (x *Operation) HasExternalDocs() bool { + if x == nil { + return false + } + return x.ExternalDocs != nil +} + +func (x *Operation) HasParameters() bool { + if x == nil { + return false + } + return x.Parameters != nil +} + +func (x *Operation) ClearExternalDocs() { + x.ExternalDocs = nil +} + +func (x *Operation) ClearParameters() { + x.Parameters = nil +} + +type Operation_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // A list of tags for API documentation control. Tags can be used for logical + // grouping of operations by resources or any other qualifier. + Tags []string + // A short summary of what the operation does. For maximum readability in the + // swagger-ui, this field SHOULD be less than 120 characters. + Summary string + // A verbose explanation of the operation behavior. GFM syntax can be used for + // rich text representation. + Description string + // Additional external documentation for this operation. + ExternalDocs *ExternalDocumentation + // Unique string used to identify the operation. The id MUST be unique among + // all operations described in the API. Tools and libraries MAY use the + // operationId to uniquely identify an operation, therefore, it is recommended + // to follow common programming naming conventions. + OperationId string + // A list of MIME types the operation can consume. This overrides the consumes + // definition at the OpenAPI Object. An empty value MAY be used to clear the + // global definition. Value MUST be as described under Mime Types. + Consumes []string + // A list of MIME types the operation can produce. This overrides the produces + // definition at the OpenAPI Object. An empty value MAY be used to clear the + // global definition. Value MUST be as described under Mime Types. + Produces []string + // The list of possible responses as they are returned from executing this + // operation. + Responses map[string]*Response + // The transfer protocol for the operation. Values MUST be from the list: + // "http", "https", "ws", "wss". The value overrides the OpenAPI Object + // schemes definition. + Schemes []Scheme + // Declares this operation to be deprecated. Usage of the declared operation + // should be refrained. Default value is false. + Deprecated bool + // A declaration of which security schemes are applied for this operation. The + // list of values describes alternative security schemes that can be used + // (that is, there is a logical OR between the security requirements). This + // definition overrides any declared top-level security. To remove a top-level + // security declaration, an empty array can be used. + Security []*SecurityRequirement + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value + // Custom parameters such as HTTP request headers. + // See: https://swagger.io/docs/specification/2-0/describing-parameters/ + // and https://swagger.io/specification/v2/#parameter-object. + Parameters *Parameters +} + +func (b0 Operation_builder) Build() *Operation { + m0 := &Operation{} + b, x := &b0, m0 + _, _ = b, x + x.Tags = b.Tags + x.Summary = b.Summary + x.Description = b.Description + x.ExternalDocs = b.ExternalDocs + x.OperationId = b.OperationId + x.Consumes = b.Consumes + x.Produces = b.Produces + x.Responses = b.Responses + x.Schemes = b.Schemes + x.Deprecated = b.Deprecated + x.Security = b.Security + x.Extensions = b.Extensions + x.Parameters = b.Parameters + return m0 +} + +// `Parameters` is a representation of OpenAPI v2 specification's parameters object. +// Note: This technically breaks compatibility with the OpenAPI 2 definition structure as we only +// allow header parameters to be set here since we do not want users specifying custom non-header +// parameters beyond those inferred from the Protobuf schema. +// See: https://swagger.io/specification/v2/#parameter-object +type Parameters struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // `Headers` is one or more HTTP header parameter. + // See: https://swagger.io/docs/specification/2-0/describing-parameters/#header-parameters + Headers []*HeaderParameter `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Parameters) Reset() { + *x = Parameters{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Parameters) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Parameters) ProtoMessage() {} + +func (x *Parameters) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Parameters) GetHeaders() []*HeaderParameter { + if x != nil { + return x.Headers + } + return nil +} + +func (x *Parameters) SetHeaders(v []*HeaderParameter) { + x.Headers = v +} + +type Parameters_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // `Headers` is one or more HTTP header parameter. + // See: https://swagger.io/docs/specification/2-0/describing-parameters/#header-parameters + Headers []*HeaderParameter +} + +func (b0 Parameters_builder) Build() *Parameters { + m0 := &Parameters{} + b, x := &b0, m0 + _, _ = b, x + x.Headers = b.Headers + return m0 +} + +// `HeaderParameter` a HTTP header parameter. +// See: https://swagger.io/specification/v2/#parameter-object +type HeaderParameter struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // `Name` is the header name. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // `Description` is a short description of the header. + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // `Type` is the type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported. + // See: https://swagger.io/specification/v2/#parameterType. + Type HeaderParameter_Type `protobuf:"varint,3,opt,name=type,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter_Type" json:"type,omitempty"` + // `Format` The extending format for the previously mentioned type. + Format string `protobuf:"bytes,4,opt,name=format,proto3" json:"format,omitempty"` + // `Required` indicates if the header is optional + Required bool `protobuf:"varint,5,opt,name=required,proto3" json:"required,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HeaderParameter) Reset() { + *x = HeaderParameter{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HeaderParameter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeaderParameter) ProtoMessage() {} + +func (x *HeaderParameter) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *HeaderParameter) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *HeaderParameter) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *HeaderParameter) GetType() HeaderParameter_Type { + if x != nil { + return x.Type + } + return HeaderParameter_UNKNOWN +} + +func (x *HeaderParameter) GetFormat() string { + if x != nil { + return x.Format + } + return "" +} + +func (x *HeaderParameter) GetRequired() bool { + if x != nil { + return x.Required + } + return false +} + +func (x *HeaderParameter) SetName(v string) { + x.Name = v +} + +func (x *HeaderParameter) SetDescription(v string) { + x.Description = v +} + +func (x *HeaderParameter) SetType(v HeaderParameter_Type) { + x.Type = v +} + +func (x *HeaderParameter) SetFormat(v string) { + x.Format = v +} + +func (x *HeaderParameter) SetRequired(v bool) { + x.Required = v +} + +type HeaderParameter_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // `Name` is the header name. + Name string + // `Description` is a short description of the header. + Description string + // `Type` is the type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported. + // See: https://swagger.io/specification/v2/#parameterType. + Type HeaderParameter_Type + // `Format` The extending format for the previously mentioned type. + Format string + // `Required` indicates if the header is optional + Required bool +} + +func (b0 HeaderParameter_builder) Build() *HeaderParameter { + m0 := &HeaderParameter{} + b, x := &b0, m0 + _, _ = b, x + x.Name = b.Name + x.Description = b.Description + x.Type = b.Type + x.Format = b.Format + x.Required = b.Required + return m0 +} + +// `Header` is a representation of OpenAPI v2 specification's Header object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#headerObject +type Header struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // `Description` is a short description of the header. + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + // The type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported. + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + // `Format` The extending format for the previously mentioned type. + Format string `protobuf:"bytes,3,opt,name=format,proto3" json:"format,omitempty"` + // `Default` Declares the value of the header that the server will use if none is provided. + // See: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2. + // Unlike JSON Schema this value MUST conform to the defined type for the header. + Default string `protobuf:"bytes,6,opt,name=default,proto3" json:"default,omitempty"` + // 'Pattern' See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3. + Pattern string `protobuf:"bytes,13,opt,name=pattern,proto3" json:"pattern,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Header) Reset() { + *x = Header{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Header) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Header) ProtoMessage() {} + +func (x *Header) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Header) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Header) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *Header) GetFormat() string { + if x != nil { + return x.Format + } + return "" +} + +func (x *Header) GetDefault() string { + if x != nil { + return x.Default + } + return "" +} + +func (x *Header) GetPattern() string { + if x != nil { + return x.Pattern + } + return "" +} + +func (x *Header) SetDescription(v string) { + x.Description = v +} + +func (x *Header) SetType(v string) { + x.Type = v +} + +func (x *Header) SetFormat(v string) { + x.Format = v +} + +func (x *Header) SetDefault(v string) { + x.Default = v +} + +func (x *Header) SetPattern(v string) { + x.Pattern = v +} + +type Header_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // `Description` is a short description of the header. + Description string + // The type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported. + Type string + // `Format` The extending format for the previously mentioned type. + Format string + // `Default` Declares the value of the header that the server will use if none is provided. + // See: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2. + // Unlike JSON Schema this value MUST conform to the defined type for the header. + Default string + // 'Pattern' See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3. + Pattern string +} + +func (b0 Header_builder) Build() *Header { + m0 := &Header{} + b, x := &b0, m0 + _, _ = b, x + x.Description = b.Description + x.Type = b.Type + x.Format = b.Format + x.Default = b.Default + x.Pattern = b.Pattern + return m0 +} + +// `Response` is a representation of OpenAPI v2 specification's Response object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#responseObject +type Response struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // `Description` is a short description of the response. + // GFM syntax can be used for rich text representation. + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + // `Schema` optionally defines the structure of the response. + // If `Schema` is not provided, it means there is no content to the response. + Schema *Schema `protobuf:"bytes,2,opt,name=schema,proto3" json:"schema,omitempty"` + // `Headers` A list of headers that are sent with the response. + // `Header` name is expected to be a string in the canonical format of the MIME header key + // See: https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey + Headers map[string]*Header `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // `Examples` gives per-mimetype response examples. + // See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#example-object + Examples map[string]string `protobuf:"bytes,4,rep,name=examples,proto3" json:"examples,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value `protobuf:"bytes,5,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Response) Reset() { + *x = Response{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Response) ProtoMessage() {} + +func (x *Response) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Response) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Response) GetSchema() *Schema { + if x != nil { + return x.Schema + } + return nil +} + +func (x *Response) GetHeaders() map[string]*Header { + if x != nil { + return x.Headers + } + return nil +} + +func (x *Response) GetExamples() map[string]string { + if x != nil { + return x.Examples + } + return nil +} + +func (x *Response) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.Extensions + } + return nil +} + +func (x *Response) SetDescription(v string) { + x.Description = v +} + +func (x *Response) SetSchema(v *Schema) { + x.Schema = v +} + +func (x *Response) SetHeaders(v map[string]*Header) { + x.Headers = v +} + +func (x *Response) SetExamples(v map[string]string) { + x.Examples = v +} + +func (x *Response) SetExtensions(v map[string]*structpb.Value) { + x.Extensions = v +} + +func (x *Response) HasSchema() bool { + if x == nil { + return false + } + return x.Schema != nil +} + +func (x *Response) ClearSchema() { + x.Schema = nil +} + +type Response_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // `Description` is a short description of the response. + // GFM syntax can be used for rich text representation. + Description string + // `Schema` optionally defines the structure of the response. + // If `Schema` is not provided, it means there is no content to the response. + Schema *Schema + // `Headers` A list of headers that are sent with the response. + // `Header` name is expected to be a string in the canonical format of the MIME header key + // See: https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey + Headers map[string]*Header + // `Examples` gives per-mimetype response examples. + // See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#example-object + Examples map[string]string + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 Response_builder) Build() *Response { + m0 := &Response{} + b, x := &b0, m0 + _, _ = b, x + x.Description = b.Description + x.Schema = b.Schema + x.Headers = b.Headers + x.Examples = b.Examples + x.Extensions = b.Extensions + return m0 +} + +// `Info` is a representation of OpenAPI v2 specification's Info object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#infoObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// title: "Echo API"; +// version: "1.0"; +// description: ""; +// contact: { +// name: "gRPC-Gateway project"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// email: "none@example.com"; +// }; +// license: { +// name: "BSD 3-Clause License"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; +// }; +// }; +// ... +// }; +type Info struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // The title of the application. + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + // A short description of the application. GFM syntax can be used for rich + // text representation. + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // The Terms of Service for the API. + TermsOfService string `protobuf:"bytes,3,opt,name=terms_of_service,json=termsOfService,proto3" json:"terms_of_service,omitempty"` + // The contact information for the exposed API. + Contact *Contact `protobuf:"bytes,4,opt,name=contact,proto3" json:"contact,omitempty"` + // The license information for the exposed API. + License *License `protobuf:"bytes,5,opt,name=license,proto3" json:"license,omitempty"` + // Provides the version of the application API (not to be confused + // with the specification version). + Version string `protobuf:"bytes,6,opt,name=version,proto3" json:"version,omitempty"` + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value `protobuf:"bytes,7,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Info) Reset() { + *x = Info{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Info) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Info) ProtoMessage() {} + +func (x *Info) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Info) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *Info) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Info) GetTermsOfService() string { + if x != nil { + return x.TermsOfService + } + return "" +} + +func (x *Info) GetContact() *Contact { + if x != nil { + return x.Contact + } + return nil +} + +func (x *Info) GetLicense() *License { + if x != nil { + return x.License + } + return nil +} + +func (x *Info) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *Info) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.Extensions + } + return nil +} + +func (x *Info) SetTitle(v string) { + x.Title = v +} + +func (x *Info) SetDescription(v string) { + x.Description = v +} + +func (x *Info) SetTermsOfService(v string) { + x.TermsOfService = v +} + +func (x *Info) SetContact(v *Contact) { + x.Contact = v +} + +func (x *Info) SetLicense(v *License) { + x.License = v +} + +func (x *Info) SetVersion(v string) { + x.Version = v +} + +func (x *Info) SetExtensions(v map[string]*structpb.Value) { + x.Extensions = v +} + +func (x *Info) HasContact() bool { + if x == nil { + return false + } + return x.Contact != nil +} + +func (x *Info) HasLicense() bool { + if x == nil { + return false + } + return x.License != nil +} + +func (x *Info) ClearContact() { + x.Contact = nil +} + +func (x *Info) ClearLicense() { + x.License = nil +} + +type Info_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The title of the application. + Title string + // A short description of the application. GFM syntax can be used for rich + // text representation. + Description string + // The Terms of Service for the API. + TermsOfService string + // The contact information for the exposed API. + Contact *Contact + // The license information for the exposed API. + License *License + // Provides the version of the application API (not to be confused + // with the specification version). + Version string + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 Info_builder) Build() *Info { + m0 := &Info{} + b, x := &b0, m0 + _, _ = b, x + x.Title = b.Title + x.Description = b.Description + x.TermsOfService = b.TermsOfService + x.Contact = b.Contact + x.License = b.License + x.Version = b.Version + x.Extensions = b.Extensions + return m0 +} + +// `Contact` is a representation of OpenAPI v2 specification's Contact object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#contactObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// ... +// contact: { +// name: "gRPC-Gateway project"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// email: "none@example.com"; +// }; +// ... +// }; +// ... +// }; +type Contact struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // The identifying name of the contact person/organization. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // The URL pointing to the contact information. MUST be in the format of a + // URL. + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + // The email address of the contact person/organization. MUST be in the format + // of an email address. + Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Contact) Reset() { + *x = Contact{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Contact) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Contact) ProtoMessage() {} + +func (x *Contact) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Contact) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Contact) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *Contact) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +func (x *Contact) SetName(v string) { + x.Name = v +} + +func (x *Contact) SetUrl(v string) { + x.Url = v +} + +func (x *Contact) SetEmail(v string) { + x.Email = v +} + +type Contact_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The identifying name of the contact person/organization. + Name string + // The URL pointing to the contact information. MUST be in the format of a + // URL. + Url string + // The email address of the contact person/organization. MUST be in the format + // of an email address. + Email string +} + +func (b0 Contact_builder) Build() *Contact { + m0 := &Contact{} + b, x := &b0, m0 + _, _ = b, x + x.Name = b.Name + x.Url = b.Url + x.Email = b.Email + return m0 +} + +// `License` is a representation of OpenAPI v2 specification's License object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#licenseObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// ... +// license: { +// name: "BSD 3-Clause License"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; +// }; +// ... +// }; +// ... +// }; +type License struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // The license name used for the API. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // A URL to the license used for the API. MUST be in the format of a URL. + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *License) Reset() { + *x = License{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *License) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*License) ProtoMessage() {} + +func (x *License) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *License) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *License) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *License) SetName(v string) { + x.Name = v +} + +func (x *License) SetUrl(v string) { + x.Url = v +} + +type License_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The license name used for the API. + Name string + // A URL to the license used for the API. MUST be in the format of a URL. + Url string +} + +func (b0 License_builder) Build() *License { + m0 := &License{} + b, x := &b0, m0 + _, _ = b, x + x.Name = b.Name + x.Url = b.Url + return m0 +} + +// `ExternalDocumentation` is a representation of OpenAPI v2 specification's +// ExternalDocumentation object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#externalDocumentationObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// ... +// external_docs: { +// description: "More about gRPC-Gateway"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// } +// ... +// }; +type ExternalDocumentation struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // A short description of the target documentation. GFM syntax can be used for + // rich text representation. + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + // The URL for the target documentation. Value MUST be in the format + // of a URL. + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExternalDocumentation) Reset() { + *x = ExternalDocumentation{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExternalDocumentation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExternalDocumentation) ProtoMessage() {} + +func (x *ExternalDocumentation) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ExternalDocumentation) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *ExternalDocumentation) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +func (x *ExternalDocumentation) SetDescription(v string) { + x.Description = v +} + +func (x *ExternalDocumentation) SetUrl(v string) { + x.Url = v +} + +type ExternalDocumentation_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // A short description of the target documentation. GFM syntax can be used for + // rich text representation. + Description string + // The URL for the target documentation. Value MUST be in the format + // of a URL. + Url string +} + +func (b0 ExternalDocumentation_builder) Build() *ExternalDocumentation { + m0 := &ExternalDocumentation{} + b, x := &b0, m0 + _, _ = b, x + x.Description = b.Description + x.Url = b.Url + return m0 +} + +// `Schema` is a representation of OpenAPI v2 specification's Schema object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject +type Schema struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + JsonSchema *JSONSchema `protobuf:"bytes,1,opt,name=json_schema,json=jsonSchema,proto3" json:"json_schema,omitempty"` + // Adds support for polymorphism. The discriminator is the schema property + // name that is used to differentiate between other schema that inherit this + // schema. The property name used MUST be defined at this schema and it MUST + // be in the required property list. When used, the value MUST be the name of + // this schema or any schema that inherits it. + Discriminator string `protobuf:"bytes,2,opt,name=discriminator,proto3" json:"discriminator,omitempty"` + // Relevant only for Schema "properties" definitions. Declares the property as + // "read only". This means that it MAY be sent as part of a response but MUST + // NOT be sent as part of the request. Properties marked as readOnly being + // true SHOULD NOT be in the required list of the defined schema. Default + // value is false. + ReadOnly bool `protobuf:"varint,3,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` + // Additional external documentation for this schema. + ExternalDocs *ExternalDocumentation `protobuf:"bytes,5,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + // A free-form property to include an example of an instance for this schema in JSON. + // This is copied verbatim to the output. + Example string `protobuf:"bytes,6,opt,name=example,proto3" json:"example,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Schema) Reset() { + *x = Schema{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Schema) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Schema) ProtoMessage() {} + +func (x *Schema) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Schema) GetJsonSchema() *JSONSchema { + if x != nil { + return x.JsonSchema + } + return nil +} + +func (x *Schema) GetDiscriminator() string { + if x != nil { + return x.Discriminator + } + return "" +} + +func (x *Schema) GetReadOnly() bool { + if x != nil { + return x.ReadOnly + } + return false +} + +func (x *Schema) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.ExternalDocs + } + return nil +} + +func (x *Schema) GetExample() string { + if x != nil { + return x.Example + } + return "" +} + +func (x *Schema) SetJsonSchema(v *JSONSchema) { + x.JsonSchema = v +} + +func (x *Schema) SetDiscriminator(v string) { + x.Discriminator = v +} + +func (x *Schema) SetReadOnly(v bool) { + x.ReadOnly = v +} + +func (x *Schema) SetExternalDocs(v *ExternalDocumentation) { + x.ExternalDocs = v +} + +func (x *Schema) SetExample(v string) { + x.Example = v +} + +func (x *Schema) HasJsonSchema() bool { + if x == nil { + return false + } + return x.JsonSchema != nil +} + +func (x *Schema) HasExternalDocs() bool { + if x == nil { + return false + } + return x.ExternalDocs != nil +} + +func (x *Schema) ClearJsonSchema() { + x.JsonSchema = nil +} + +func (x *Schema) ClearExternalDocs() { + x.ExternalDocs = nil +} + +type Schema_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + JsonSchema *JSONSchema + // Adds support for polymorphism. The discriminator is the schema property + // name that is used to differentiate between other schema that inherit this + // schema. The property name used MUST be defined at this schema and it MUST + // be in the required property list. When used, the value MUST be the name of + // this schema or any schema that inherits it. + Discriminator string + // Relevant only for Schema "properties" definitions. Declares the property as + // "read only". This means that it MAY be sent as part of a response but MUST + // NOT be sent as part of the request. Properties marked as readOnly being + // true SHOULD NOT be in the required list of the defined schema. Default + // value is false. + ReadOnly bool + // Additional external documentation for this schema. + ExternalDocs *ExternalDocumentation + // A free-form property to include an example of an instance for this schema in JSON. + // This is copied verbatim to the output. + Example string +} + +func (b0 Schema_builder) Build() *Schema { + m0 := &Schema{} + b, x := &b0, m0 + _, _ = b, x + x.JsonSchema = b.JsonSchema + x.Discriminator = b.Discriminator + x.ReadOnly = b.ReadOnly + x.ExternalDocs = b.ExternalDocs + x.Example = b.Example + return m0 +} + +// `EnumSchema` is subset of fields from the OpenAPI v2 specification's Schema object. +// Only fields that are applicable to Enums are included +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum) = { +// ... +// title: "MyEnum"; +// description:"This is my nice enum"; +// example: "ZERO"; +// required: true; +// ... +// }; +type EnumSchema struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // A short description of the schema. + Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + Default string `protobuf:"bytes,2,opt,name=default,proto3" json:"default,omitempty"` + // The title of the schema. + Title string `protobuf:"bytes,3,opt,name=title,proto3" json:"title,omitempty"` + Required bool `protobuf:"varint,4,opt,name=required,proto3" json:"required,omitempty"` + ReadOnly bool `protobuf:"varint,5,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` + // Additional external documentation for this schema. + ExternalDocs *ExternalDocumentation `protobuf:"bytes,6,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + Example string `protobuf:"bytes,7,opt,name=example,proto3" json:"example,omitempty"` + // Ref is used to define an external reference to include in the message. + // This could be a fully qualified proto message reference, and that type must + // be imported into the protofile. If no message is identified, the Ref will + // be used verbatim in the output. + // For example: + // + // `ref: ".google.protobuf.Timestamp"`. + Ref string `protobuf:"bytes,8,opt,name=ref,proto3" json:"ref,omitempty"` + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value `protobuf:"bytes,9,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EnumSchema) Reset() { + *x = EnumSchema{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EnumSchema) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnumSchema) ProtoMessage() {} + +func (x *EnumSchema) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *EnumSchema) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *EnumSchema) GetDefault() string { + if x != nil { + return x.Default + } + return "" +} + +func (x *EnumSchema) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *EnumSchema) GetRequired() bool { + if x != nil { + return x.Required + } + return false +} + +func (x *EnumSchema) GetReadOnly() bool { + if x != nil { + return x.ReadOnly + } + return false +} + +func (x *EnumSchema) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.ExternalDocs + } + return nil +} + +func (x *EnumSchema) GetExample() string { + if x != nil { + return x.Example + } + return "" +} + +func (x *EnumSchema) GetRef() string { + if x != nil { + return x.Ref + } + return "" +} + +func (x *EnumSchema) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.Extensions + } + return nil +} + +func (x *EnumSchema) SetDescription(v string) { + x.Description = v +} + +func (x *EnumSchema) SetDefault(v string) { + x.Default = v +} + +func (x *EnumSchema) SetTitle(v string) { + x.Title = v +} + +func (x *EnumSchema) SetRequired(v bool) { + x.Required = v +} + +func (x *EnumSchema) SetReadOnly(v bool) { + x.ReadOnly = v +} + +func (x *EnumSchema) SetExternalDocs(v *ExternalDocumentation) { + x.ExternalDocs = v +} + +func (x *EnumSchema) SetExample(v string) { + x.Example = v +} + +func (x *EnumSchema) SetRef(v string) { + x.Ref = v +} + +func (x *EnumSchema) SetExtensions(v map[string]*structpb.Value) { + x.Extensions = v +} + +func (x *EnumSchema) HasExternalDocs() bool { + if x == nil { + return false + } + return x.ExternalDocs != nil +} + +func (x *EnumSchema) ClearExternalDocs() { + x.ExternalDocs = nil +} + +type EnumSchema_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // A short description of the schema. + Description string + Default string + // The title of the schema. + Title string + Required bool + ReadOnly bool + // Additional external documentation for this schema. + ExternalDocs *ExternalDocumentation + Example string + // Ref is used to define an external reference to include in the message. + // This could be a fully qualified proto message reference, and that type must + // be imported into the protofile. If no message is identified, the Ref will + // be used verbatim in the output. + // For example: + // + // `ref: ".google.protobuf.Timestamp"`. + Ref string + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 EnumSchema_builder) Build() *EnumSchema { + m0 := &EnumSchema{} + b, x := &b0, m0 + _, _ = b, x + x.Description = b.Description + x.Default = b.Default + x.Title = b.Title + x.Required = b.Required + x.ReadOnly = b.ReadOnly + x.ExternalDocs = b.ExternalDocs + x.Example = b.Example + x.Ref = b.Ref + x.Extensions = b.Extensions + return m0 +} + +// `JSONSchema` represents properties from JSON Schema taken, and as used, in +// the OpenAPI v2 spec. +// +// This includes changes made by OpenAPI v2. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject +// +// See also: https://cswr.github.io/JsonSchema/spec/basic_types/, +// https://github.com/json-schema-org/json-schema-spec/blob/master/schema.json +// +// Example: +// +// message SimpleMessage { +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { +// json_schema: { +// title: "SimpleMessage" +// description: "A simple message." +// required: ["id"] +// } +// }; +// +// // Id represents the message identifier. +// string id = 1; [ +// (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { +// description: "The unique identifier of the simple message." +// }]; +// } +type JSONSchema struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // Ref is used to define an external reference to include in the message. + // This could be a fully qualified proto message reference, and that type must + // be imported into the protofile. If no message is identified, the Ref will + // be used verbatim in the output. + // For example: + // + // `ref: ".google.protobuf.Timestamp"`. + Ref string `protobuf:"bytes,3,opt,name=ref,proto3" json:"ref,omitempty"` + // The title of the schema. + Title string `protobuf:"bytes,5,opt,name=title,proto3" json:"title,omitempty"` + // A short description of the schema. + Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` + Default string `protobuf:"bytes,7,opt,name=default,proto3" json:"default,omitempty"` + ReadOnly bool `protobuf:"varint,8,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` + // A free-form property to include a JSON example of this field. This is copied + // verbatim to the output swagger.json. Quotes must be escaped. + // This property is the same for 2.0 and 3.0.0 https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#schemaObject https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject + Example string `protobuf:"bytes,9,opt,name=example,proto3" json:"example,omitempty"` + MultipleOf float64 `protobuf:"fixed64,10,opt,name=multiple_of,json=multipleOf,proto3" json:"multiple_of,omitempty"` + // Maximum represents an inclusive upper limit for a numeric instance. The + // value of MUST be a number, + Maximum float64 `protobuf:"fixed64,11,opt,name=maximum,proto3" json:"maximum,omitempty"` + ExclusiveMaximum bool `protobuf:"varint,12,opt,name=exclusive_maximum,json=exclusiveMaximum,proto3" json:"exclusive_maximum,omitempty"` + // minimum represents an inclusive lower limit for a numeric instance. The + // value of MUST be a number, + Minimum float64 `protobuf:"fixed64,13,opt,name=minimum,proto3" json:"minimum,omitempty"` + ExclusiveMinimum bool `protobuf:"varint,14,opt,name=exclusive_minimum,json=exclusiveMinimum,proto3" json:"exclusive_minimum,omitempty"` + MaxLength uint64 `protobuf:"varint,15,opt,name=max_length,json=maxLength,proto3" json:"max_length,omitempty"` + MinLength uint64 `protobuf:"varint,16,opt,name=min_length,json=minLength,proto3" json:"min_length,omitempty"` + Pattern string `protobuf:"bytes,17,opt,name=pattern,proto3" json:"pattern,omitempty"` + MaxItems uint64 `protobuf:"varint,20,opt,name=max_items,json=maxItems,proto3" json:"max_items,omitempty"` + MinItems uint64 `protobuf:"varint,21,opt,name=min_items,json=minItems,proto3" json:"min_items,omitempty"` + UniqueItems bool `protobuf:"varint,22,opt,name=unique_items,json=uniqueItems,proto3" json:"unique_items,omitempty"` + MaxProperties uint64 `protobuf:"varint,24,opt,name=max_properties,json=maxProperties,proto3" json:"max_properties,omitempty"` + MinProperties uint64 `protobuf:"varint,25,opt,name=min_properties,json=minProperties,proto3" json:"min_properties,omitempty"` + Required []string `protobuf:"bytes,26,rep,name=required,proto3" json:"required,omitempty"` + // Items in 'array' must be unique. + Array []string `protobuf:"bytes,34,rep,name=array,proto3" json:"array,omitempty"` + Type []JSONSchema_JSONSchemaSimpleTypes `protobuf:"varint,35,rep,packed,name=type,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.JSONSchema_JSONSchemaSimpleTypes" json:"type,omitempty"` + // `Format` + Format string `protobuf:"bytes,36,opt,name=format,proto3" json:"format,omitempty"` + // Items in `enum` must be unique https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1 + Enum []string `protobuf:"bytes,46,rep,name=enum,proto3" json:"enum,omitempty"` + // Additional field level properties used when generating the OpenAPI v2 file. + FieldConfiguration *JSONSchema_FieldConfiguration `protobuf:"bytes,1001,opt,name=field_configuration,json=fieldConfiguration,proto3" json:"field_configuration,omitempty"` + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value `protobuf:"bytes,48,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JSONSchema) Reset() { + *x = JSONSchema{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JSONSchema) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JSONSchema) ProtoMessage() {} + +func (x *JSONSchema) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *JSONSchema) GetRef() string { + if x != nil { + return x.Ref + } + return "" +} + +func (x *JSONSchema) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *JSONSchema) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *JSONSchema) GetDefault() string { + if x != nil { + return x.Default + } + return "" +} + +func (x *JSONSchema) GetReadOnly() bool { + if x != nil { + return x.ReadOnly + } + return false +} + +func (x *JSONSchema) GetExample() string { + if x != nil { + return x.Example + } + return "" +} + +func (x *JSONSchema) GetMultipleOf() float64 { + if x != nil { + return x.MultipleOf + } + return 0 +} + +func (x *JSONSchema) GetMaximum() float64 { + if x != nil { + return x.Maximum + } + return 0 +} + +func (x *JSONSchema) GetExclusiveMaximum() bool { + if x != nil { + return x.ExclusiveMaximum + } + return false +} + +func (x *JSONSchema) GetMinimum() float64 { + if x != nil { + return x.Minimum + } + return 0 +} + +func (x *JSONSchema) GetExclusiveMinimum() bool { + if x != nil { + return x.ExclusiveMinimum + } + return false +} + +func (x *JSONSchema) GetMaxLength() uint64 { + if x != nil { + return x.MaxLength + } + return 0 +} + +func (x *JSONSchema) GetMinLength() uint64 { + if x != nil { + return x.MinLength + } + return 0 +} + +func (x *JSONSchema) GetPattern() string { + if x != nil { + return x.Pattern + } + return "" +} + +func (x *JSONSchema) GetMaxItems() uint64 { + if x != nil { + return x.MaxItems + } + return 0 +} + +func (x *JSONSchema) GetMinItems() uint64 { + if x != nil { + return x.MinItems + } + return 0 +} + +func (x *JSONSchema) GetUniqueItems() bool { + if x != nil { + return x.UniqueItems + } + return false +} + +func (x *JSONSchema) GetMaxProperties() uint64 { + if x != nil { + return x.MaxProperties + } + return 0 +} + +func (x *JSONSchema) GetMinProperties() uint64 { + if x != nil { + return x.MinProperties + } + return 0 +} + +func (x *JSONSchema) GetRequired() []string { + if x != nil { + return x.Required + } + return nil +} + +func (x *JSONSchema) GetArray() []string { + if x != nil { + return x.Array + } + return nil +} + +func (x *JSONSchema) GetType() []JSONSchema_JSONSchemaSimpleTypes { + if x != nil { + return x.Type + } + return nil +} + +func (x *JSONSchema) GetFormat() string { + if x != nil { + return x.Format + } + return "" +} + +func (x *JSONSchema) GetEnum() []string { + if x != nil { + return x.Enum + } + return nil +} + +func (x *JSONSchema) GetFieldConfiguration() *JSONSchema_FieldConfiguration { + if x != nil { + return x.FieldConfiguration + } + return nil +} + +func (x *JSONSchema) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.Extensions + } + return nil +} + +func (x *JSONSchema) SetRef(v string) { + x.Ref = v +} + +func (x *JSONSchema) SetTitle(v string) { + x.Title = v +} + +func (x *JSONSchema) SetDescription(v string) { + x.Description = v +} + +func (x *JSONSchema) SetDefault(v string) { + x.Default = v +} + +func (x *JSONSchema) SetReadOnly(v bool) { + x.ReadOnly = v +} + +func (x *JSONSchema) SetExample(v string) { + x.Example = v +} + +func (x *JSONSchema) SetMultipleOf(v float64) { + x.MultipleOf = v +} + +func (x *JSONSchema) SetMaximum(v float64) { + x.Maximum = v +} + +func (x *JSONSchema) SetExclusiveMaximum(v bool) { + x.ExclusiveMaximum = v +} + +func (x *JSONSchema) SetMinimum(v float64) { + x.Minimum = v +} + +func (x *JSONSchema) SetExclusiveMinimum(v bool) { + x.ExclusiveMinimum = v +} + +func (x *JSONSchema) SetMaxLength(v uint64) { + x.MaxLength = v +} + +func (x *JSONSchema) SetMinLength(v uint64) { + x.MinLength = v +} + +func (x *JSONSchema) SetPattern(v string) { + x.Pattern = v +} + +func (x *JSONSchema) SetMaxItems(v uint64) { + x.MaxItems = v +} + +func (x *JSONSchema) SetMinItems(v uint64) { + x.MinItems = v +} + +func (x *JSONSchema) SetUniqueItems(v bool) { + x.UniqueItems = v +} + +func (x *JSONSchema) SetMaxProperties(v uint64) { + x.MaxProperties = v +} + +func (x *JSONSchema) SetMinProperties(v uint64) { + x.MinProperties = v +} + +func (x *JSONSchema) SetRequired(v []string) { + x.Required = v +} + +func (x *JSONSchema) SetArray(v []string) { + x.Array = v +} + +func (x *JSONSchema) SetType(v []JSONSchema_JSONSchemaSimpleTypes) { + x.Type = v +} + +func (x *JSONSchema) SetFormat(v string) { + x.Format = v +} + +func (x *JSONSchema) SetEnum(v []string) { + x.Enum = v +} + +func (x *JSONSchema) SetFieldConfiguration(v *JSONSchema_FieldConfiguration) { + x.FieldConfiguration = v +} + +func (x *JSONSchema) SetExtensions(v map[string]*structpb.Value) { + x.Extensions = v +} + +func (x *JSONSchema) HasFieldConfiguration() bool { + if x == nil { + return false + } + return x.FieldConfiguration != nil +} + +func (x *JSONSchema) ClearFieldConfiguration() { + x.FieldConfiguration = nil +} + +type JSONSchema_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Ref is used to define an external reference to include in the message. + // This could be a fully qualified proto message reference, and that type must + // be imported into the protofile. If no message is identified, the Ref will + // be used verbatim in the output. + // For example: + // + // `ref: ".google.protobuf.Timestamp"`. + Ref string + // The title of the schema. + Title string + // A short description of the schema. + Description string + Default string + ReadOnly bool + // A free-form property to include a JSON example of this field. This is copied + // verbatim to the output swagger.json. Quotes must be escaped. + // This property is the same for 2.0 and 3.0.0 https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#schemaObject https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject + Example string + MultipleOf float64 + // Maximum represents an inclusive upper limit for a numeric instance. The + // value of MUST be a number, + Maximum float64 + ExclusiveMaximum bool + // minimum represents an inclusive lower limit for a numeric instance. The + // value of MUST be a number, + Minimum float64 + ExclusiveMinimum bool + MaxLength uint64 + MinLength uint64 + Pattern string + MaxItems uint64 + MinItems uint64 + UniqueItems bool + MaxProperties uint64 + MinProperties uint64 + Required []string + // Items in 'array' must be unique. + Array []string + Type []JSONSchema_JSONSchemaSimpleTypes + // `Format` + Format string + // Items in `enum` must be unique https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1 + Enum []string + // Additional field level properties used when generating the OpenAPI v2 file. + FieldConfiguration *JSONSchema_FieldConfiguration + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 JSONSchema_builder) Build() *JSONSchema { + m0 := &JSONSchema{} + b, x := &b0, m0 + _, _ = b, x + x.Ref = b.Ref + x.Title = b.Title + x.Description = b.Description + x.Default = b.Default + x.ReadOnly = b.ReadOnly + x.Example = b.Example + x.MultipleOf = b.MultipleOf + x.Maximum = b.Maximum + x.ExclusiveMaximum = b.ExclusiveMaximum + x.Minimum = b.Minimum + x.ExclusiveMinimum = b.ExclusiveMinimum + x.MaxLength = b.MaxLength + x.MinLength = b.MinLength + x.Pattern = b.Pattern + x.MaxItems = b.MaxItems + x.MinItems = b.MinItems + x.UniqueItems = b.UniqueItems + x.MaxProperties = b.MaxProperties + x.MinProperties = b.MinProperties + x.Required = b.Required + x.Array = b.Array + x.Type = b.Type + x.Format = b.Format + x.Enum = b.Enum + x.FieldConfiguration = b.FieldConfiguration + x.Extensions = b.Extensions + return m0 +} + +// `Tag` is a representation of OpenAPI v2 specification's Tag object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#tagObject +type Tag struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // The name of the tag. Use it to allow override of the name of a + // global Tag object, then use that name to reference the tag throughout the + // OpenAPI file. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // A short description for the tag. GFM syntax can be used for rich text + // representation. + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // Additional external documentation for this tag. + ExternalDocs *ExternalDocumentation `protobuf:"bytes,3,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value `protobuf:"bytes,4,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Tag) Reset() { + *x = Tag{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Tag) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Tag) ProtoMessage() {} + +func (x *Tag) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Tag) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Tag) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Tag) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.ExternalDocs + } + return nil +} + +func (x *Tag) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.Extensions + } + return nil +} + +func (x *Tag) SetName(v string) { + x.Name = v +} + +func (x *Tag) SetDescription(v string) { + x.Description = v +} + +func (x *Tag) SetExternalDocs(v *ExternalDocumentation) { + x.ExternalDocs = v +} + +func (x *Tag) SetExtensions(v map[string]*structpb.Value) { + x.Extensions = v +} + +func (x *Tag) HasExternalDocs() bool { + if x == nil { + return false + } + return x.ExternalDocs != nil +} + +func (x *Tag) ClearExternalDocs() { + x.ExternalDocs = nil +} + +type Tag_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The name of the tag. Use it to allow override of the name of a + // global Tag object, then use that name to reference the tag throughout the + // OpenAPI file. + Name string + // A short description for the tag. GFM syntax can be used for rich text + // representation. + Description string + // Additional external documentation for this tag. + ExternalDocs *ExternalDocumentation + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 Tag_builder) Build() *Tag { + m0 := &Tag{} + b, x := &b0, m0 + _, _ = b, x + x.Name = b.Name + x.Description = b.Description + x.ExternalDocs = b.ExternalDocs + x.Extensions = b.Extensions + return m0 +} + +// `SecurityDefinitions` is a representation of OpenAPI v2 specification's +// Security Definitions object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityDefinitionsObject +// +// A declaration of the security schemes available to be used in the +// specification. This does not enforce the security schemes on the operations +// and only serves to provide the relevant details for each scheme. +type SecurityDefinitions struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // A single security scheme definition, mapping a "name" to the scheme it + // defines. + Security map[string]*SecurityScheme `protobuf:"bytes,1,rep,name=security,proto3" json:"security,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecurityDefinitions) Reset() { + *x = SecurityDefinitions{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecurityDefinitions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecurityDefinitions) ProtoMessage() {} + +func (x *SecurityDefinitions) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *SecurityDefinitions) GetSecurity() map[string]*SecurityScheme { + if x != nil { + return x.Security + } + return nil +} + +func (x *SecurityDefinitions) SetSecurity(v map[string]*SecurityScheme) { + x.Security = v +} + +type SecurityDefinitions_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // A single security scheme definition, mapping a "name" to the scheme it + // defines. + Security map[string]*SecurityScheme +} + +func (b0 SecurityDefinitions_builder) Build() *SecurityDefinitions { + m0 := &SecurityDefinitions{} + b, x := &b0, m0 + _, _ = b, x + x.Security = b.Security + return m0 +} + +// `SecurityScheme` is a representation of OpenAPI v2 specification's +// Security Scheme object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securitySchemeObject +// +// Allows the definition of a security scheme that can be used by the +// operations. Supported schemes are basic authentication, an API key (either as +// a header or as a query parameter) and OAuth2's common flows (implicit, +// password, application and access code). +type SecurityScheme struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // The type of the security scheme. Valid values are "basic", + // "apiKey" or "oauth2". + Type SecurityScheme_Type `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme_Type" json:"type,omitempty"` + // A short description for security scheme. + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // The name of the header or query parameter to be used. + // Valid for apiKey. + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + // The location of the API key. Valid values are "query" or + // "header". + // Valid for apiKey. + In SecurityScheme_In `protobuf:"varint,4,opt,name=in,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme_In" json:"in,omitempty"` + // The flow used by the OAuth2 security scheme. Valid values are + // "implicit", "password", "application" or "accessCode". + // Valid for oauth2. + Flow SecurityScheme_Flow `protobuf:"varint,5,opt,name=flow,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme_Flow" json:"flow,omitempty"` + // The authorization URL to be used for this flow. This SHOULD be in + // the form of a URL. + // Valid for oauth2/implicit and oauth2/accessCode. + AuthorizationUrl string `protobuf:"bytes,6,opt,name=authorization_url,json=authorizationUrl,proto3" json:"authorization_url,omitempty"` + // The token URL to be used for this flow. This SHOULD be in the + // form of a URL. + // Valid for oauth2/password, oauth2/application and oauth2/accessCode. + TokenUrl string `protobuf:"bytes,7,opt,name=token_url,json=tokenUrl,proto3" json:"token_url,omitempty"` + // The available scopes for the OAuth2 security scheme. + // Valid for oauth2. + Scopes *Scopes `protobuf:"bytes,8,opt,name=scopes,proto3" json:"scopes,omitempty"` + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value `protobuf:"bytes,9,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecurityScheme) Reset() { + *x = SecurityScheme{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecurityScheme) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecurityScheme) ProtoMessage() {} + +func (x *SecurityScheme) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *SecurityScheme) GetType() SecurityScheme_Type { + if x != nil { + return x.Type + } + return SecurityScheme_TYPE_INVALID +} + +func (x *SecurityScheme) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *SecurityScheme) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *SecurityScheme) GetIn() SecurityScheme_In { + if x != nil { + return x.In + } + return SecurityScheme_IN_INVALID +} + +func (x *SecurityScheme) GetFlow() SecurityScheme_Flow { + if x != nil { + return x.Flow + } + return SecurityScheme_FLOW_INVALID +} + +func (x *SecurityScheme) GetAuthorizationUrl() string { + if x != nil { + return x.AuthorizationUrl + } + return "" +} + +func (x *SecurityScheme) GetTokenUrl() string { + if x != nil { + return x.TokenUrl + } + return "" +} + +func (x *SecurityScheme) GetScopes() *Scopes { + if x != nil { + return x.Scopes + } + return nil +} + +func (x *SecurityScheme) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.Extensions + } + return nil +} + +func (x *SecurityScheme) SetType(v SecurityScheme_Type) { + x.Type = v +} + +func (x *SecurityScheme) SetDescription(v string) { + x.Description = v +} + +func (x *SecurityScheme) SetName(v string) { + x.Name = v +} + +func (x *SecurityScheme) SetIn(v SecurityScheme_In) { + x.In = v +} + +func (x *SecurityScheme) SetFlow(v SecurityScheme_Flow) { + x.Flow = v +} + +func (x *SecurityScheme) SetAuthorizationUrl(v string) { + x.AuthorizationUrl = v +} + +func (x *SecurityScheme) SetTokenUrl(v string) { + x.TokenUrl = v +} + +func (x *SecurityScheme) SetScopes(v *Scopes) { + x.Scopes = v +} + +func (x *SecurityScheme) SetExtensions(v map[string]*structpb.Value) { + x.Extensions = v +} + +func (x *SecurityScheme) HasScopes() bool { + if x == nil { + return false + } + return x.Scopes != nil +} + +func (x *SecurityScheme) ClearScopes() { + x.Scopes = nil +} + +type SecurityScheme_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The type of the security scheme. Valid values are "basic", + // "apiKey" or "oauth2". + Type SecurityScheme_Type + // A short description for security scheme. + Description string + // The name of the header or query parameter to be used. + // Valid for apiKey. + Name string + // The location of the API key. Valid values are "query" or + // "header". + // Valid for apiKey. + In SecurityScheme_In + // The flow used by the OAuth2 security scheme. Valid values are + // "implicit", "password", "application" or "accessCode". + // Valid for oauth2. + Flow SecurityScheme_Flow + // The authorization URL to be used for this flow. This SHOULD be in + // the form of a URL. + // Valid for oauth2/implicit and oauth2/accessCode. + AuthorizationUrl string + // The token URL to be used for this flow. This SHOULD be in the + // form of a URL. + // Valid for oauth2/password, oauth2/application and oauth2/accessCode. + TokenUrl string + // The available scopes for the OAuth2 security scheme. + // Valid for oauth2. + Scopes *Scopes + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 SecurityScheme_builder) Build() *SecurityScheme { + m0 := &SecurityScheme{} + b, x := &b0, m0 + _, _ = b, x + x.Type = b.Type + x.Description = b.Description + x.Name = b.Name + x.In = b.In + x.Flow = b.Flow + x.AuthorizationUrl = b.AuthorizationUrl + x.TokenUrl = b.TokenUrl + x.Scopes = b.Scopes + x.Extensions = b.Extensions + return m0 +} + +// `SecurityRequirement` is a representation of OpenAPI v2 specification's +// Security Requirement object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityRequirementObject +// +// Lists the required security schemes to execute this operation. The object can +// have multiple security schemes declared in it which are all required (that +// is, there is a logical AND between the schemes). +// +// The name used for each property MUST correspond to a security scheme +// declared in the Security Definitions. +type SecurityRequirement struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // Each name must correspond to a security scheme which is declared in + // the Security Definitions. If the security scheme is of type "oauth2", + // then the value is a list of scope names required for the execution. + // For other security scheme types, the array MUST be empty. + SecurityRequirement map[string]*SecurityRequirement_SecurityRequirementValue `protobuf:"bytes,1,rep,name=security_requirement,json=securityRequirement,proto3" json:"security_requirement,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecurityRequirement) Reset() { + *x = SecurityRequirement{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecurityRequirement) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecurityRequirement) ProtoMessage() {} + +func (x *SecurityRequirement) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *SecurityRequirement) GetSecurityRequirement() map[string]*SecurityRequirement_SecurityRequirementValue { + if x != nil { + return x.SecurityRequirement + } + return nil +} + +func (x *SecurityRequirement) SetSecurityRequirement(v map[string]*SecurityRequirement_SecurityRequirementValue) { + x.SecurityRequirement = v +} + +type SecurityRequirement_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Each name must correspond to a security scheme which is declared in + // the Security Definitions. If the security scheme is of type "oauth2", + // then the value is a list of scope names required for the execution. + // For other security scheme types, the array MUST be empty. + SecurityRequirement map[string]*SecurityRequirement_SecurityRequirementValue +} + +func (b0 SecurityRequirement_builder) Build() *SecurityRequirement { + m0 := &SecurityRequirement{} + b, x := &b0, m0 + _, _ = b, x + x.SecurityRequirement = b.SecurityRequirement + return m0 +} + +// `Scopes` is a representation of OpenAPI v2 specification's Scopes object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#scopesObject +// +// Lists the available scopes for an OAuth2 security scheme. +type Scopes struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // Maps between a name of a scope to a short description of it (as the value + // of the property). + Scope map[string]string `protobuf:"bytes,1,rep,name=scope,proto3" json:"scope,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Scopes) Reset() { + *x = Scopes{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Scopes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Scopes) ProtoMessage() {} + +func (x *Scopes) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Scopes) GetScope() map[string]string { + if x != nil { + return x.Scope + } + return nil +} + +func (x *Scopes) SetScope(v map[string]string) { + x.Scope = v +} + +type Scopes_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Maps between a name of a scope to a short description of it (as the value + // of the property). + Scope map[string]string +} + +func (b0 Scopes_builder) Build() *Scopes { + m0 := &Scopes{} + b, x := &b0, m0 + _, _ = b, x + x.Scope = b.Scope + return m0 +} + +// 'FieldConfiguration' provides additional field level properties used when generating the OpenAPI v2 file. +// These properties are not defined by OpenAPIv2, but they are used to control the generation. +type JSONSchema_FieldConfiguration struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + // Alternative parameter name when used as path parameter. If set, this will + // be used as the complete parameter name when this field is used as a path + // parameter. Use this to avoid having auto generated path parameter names + // for overlapping paths. + PathParamName string `protobuf:"bytes,47,opt,name=path_param_name,json=pathParamName,proto3" json:"path_param_name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JSONSchema_FieldConfiguration) Reset() { + *x = JSONSchema_FieldConfiguration{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JSONSchema_FieldConfiguration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JSONSchema_FieldConfiguration) ProtoMessage() {} + +func (x *JSONSchema_FieldConfiguration) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[27] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *JSONSchema_FieldConfiguration) GetPathParamName() string { + if x != nil { + return x.PathParamName + } + return "" +} + +func (x *JSONSchema_FieldConfiguration) SetPathParamName(v string) { + x.PathParamName = v +} + +type JSONSchema_FieldConfiguration_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Alternative parameter name when used as path parameter. If set, this will + // be used as the complete parameter name when this field is used as a path + // parameter. Use this to avoid having auto generated path parameter names + // for overlapping paths. + PathParamName string +} + +func (b0 JSONSchema_FieldConfiguration_builder) Build() *JSONSchema_FieldConfiguration { + m0 := &JSONSchema_FieldConfiguration{} + b, x := &b0, m0 + _, _ = b, x + x.PathParamName = b.PathParamName + return m0 +} + +// If the security scheme is of type "oauth2", then the value is a list of +// scope names required for the execution. For other security scheme types, +// the array MUST be empty. +type SecurityRequirement_SecurityRequirementValue struct { + state protoimpl.MessageState `protogen:"hybrid.v1"` + Scope []string `protobuf:"bytes,1,rep,name=scope,proto3" json:"scope,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecurityRequirement_SecurityRequirementValue) Reset() { + *x = SecurityRequirement_SecurityRequirementValue{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecurityRequirement_SecurityRequirementValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecurityRequirement_SecurityRequirementValue) ProtoMessage() {} + +func (x *SecurityRequirement_SecurityRequirementValue) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[32] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *SecurityRequirement_SecurityRequirementValue) GetScope() []string { + if x != nil { + return x.Scope + } + return nil +} + +func (x *SecurityRequirement_SecurityRequirementValue) SetScope(v []string) { + x.Scope = v +} + +type SecurityRequirement_SecurityRequirementValue_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Scope []string +} + +func (b0 SecurityRequirement_SecurityRequirementValue_builder) Build() *SecurityRequirement_SecurityRequirementValue { + m0 := &SecurityRequirement_SecurityRequirementValue{} + b, x := &b0, m0 + _, _ = b, x + x.Scope = b.Scope + return m0 +} + +var File_protoc_gen_openapiv2_options_openapiv2_proto protoreflect.FileDescriptor + +var file_protoc_gen_openapiv2_options_openapiv2_proto_rawDesc = []byte{ + 0x0a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x29, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, + 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb3, 0x08, 0x0a, 0x07, 0x53, 0x77, 0x61, 0x67, + 0x67, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x12, 0x43, 0x0a, + 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, + 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x73, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x4b, 0x0a, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x52, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x73, 0x12, 0x5f, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x71, 0x0a, 0x14, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x44, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x13, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x08, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, + 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, + 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x54, 0x61, 0x67, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x65, 0x0a, 0x0d, + 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, + 0x6f, 0x63, 0x73, 0x12, 0x62, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x71, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x49, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0xd6, 0x07, + 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x0d, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x45, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, + 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, + 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x73, 0x12, 0x61, 0x0a, + 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x43, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, + 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, + 0x12, 0x4b, 0x0a, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, + 0x0e, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x65, 0x52, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, 0x12, 0x1e, 0x0a, + 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x5a, 0x0a, + 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x64, 0x0a, 0x0a, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x55, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x1a, 0x71, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x49, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, + 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x22, 0x62, 0x0a, 0x0a, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x73, 0x12, 0x54, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0xa3, 0x02, 0x0a, 0x0f, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x3f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2e, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x22, 0x45, 0x0a, + 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0a, + 0x0a, 0x06, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x45, 0x52, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x42, 0x4f, 0x4f, 0x4c, 0x45, + 0x41, 0x4e, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, + 0x22, 0xd8, 0x01, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x0d, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x4a, 0x04, 0x08, + 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x4a, + 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x4a, 0x04, 0x08, 0x0a, 0x10, + 0x0b, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, 0x4a, 0x04, 0x08, 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, + 0x0e, 0x10, 0x0f, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x4a, 0x04, 0x08, 0x10, 0x10, 0x11, 0x4a, + 0x04, 0x08, 0x11, 0x10, 0x12, 0x4a, 0x04, 0x08, 0x12, 0x10, 0x13, 0x22, 0x9a, 0x05, 0x0a, 0x08, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x06, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x06, 0x73, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x5a, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x73, 0x12, 0x5d, 0x0a, 0x08, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, + 0x12, 0x63, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6d, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3b, 0x0a, 0x0d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd6, 0x03, 0x0a, 0x04, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x65, 0x72, + 0x6d, 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x4f, 0x66, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, + 0x74, 0x12, 0x4c, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4c, + 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, 0x0a, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0x45, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x2f, 0x0a, 0x07, 0x4c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x4b, 0x0a, 0x15, 0x45, 0x78, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaa, 0x02, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x12, 0x56, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0a, 0x6a, + 0x73, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0d, 0x64, 0x69, 0x73, + 0x63, 0x72, 0x69, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x72, 0x69, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, + 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x65, 0x0a, 0x0d, + 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, + 0x6f, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x4a, 0x04, 0x08, + 0x04, 0x10, 0x05, 0x22, 0xe8, 0x03, 0x0a, 0x0a, 0x45, 0x6e, 0x75, 0x6d, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x65, 0x0a, + 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x44, 0x6f, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, + 0x12, 0x65, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x45, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd7, + 0x0a, 0x0a, 0x0a, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x10, 0x0a, + 0x03, 0x72, 0x65, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x6d, + 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x4f, 0x66, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x78, + 0x69, 0x6d, 0x75, 0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x69, + 0x6d, 0x75, 0x6d, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, + 0x5f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, + 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, + 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, + 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x6c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x78, + 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x69, 0x6e, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, + 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x14, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, + 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x08, 0x6d, 0x69, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x6e, 0x69, + 0x71, 0x75, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0b, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x25, 0x0a, 0x0e, + 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x18, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6d, 0x69, 0x6e, + 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x1a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, + 0x22, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, 0x72, 0x72, 0x61, 0x79, 0x12, 0x5f, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x23, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x4b, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x2e, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x04, 0x65, 0x6e, 0x75, 0x6d, 0x12, 0x7a, 0x0a, 0x13, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x30, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, + 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3c, 0x0a, 0x12, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x74, + 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0x77, 0x0a, 0x15, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, + 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x52, 0x52, 0x41, 0x59, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x02, 0x12, + 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, + 0x4e, 0x55, 0x4c, 0x4c, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, + 0x10, 0x05, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x06, 0x12, 0x0a, + 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, + 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x12, + 0x10, 0x13, 0x4a, 0x04, 0x08, 0x13, 0x10, 0x14, 0x4a, 0x04, 0x08, 0x17, 0x10, 0x18, 0x4a, 0x04, + 0x08, 0x1b, 0x10, 0x1c, 0x4a, 0x04, 0x08, 0x1c, 0x10, 0x1d, 0x4a, 0x04, 0x08, 0x1d, 0x10, 0x1e, + 0x4a, 0x04, 0x08, 0x1e, 0x10, 0x22, 0x4a, 0x04, 0x08, 0x25, 0x10, 0x2a, 0x4a, 0x04, 0x08, 0x2a, + 0x10, 0x2b, 0x4a, 0x04, 0x08, 0x2b, 0x10, 0x2e, 0x22, 0xd9, 0x02, 0x0a, 0x03, 0x54, 0x61, 0x67, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x73, 0x12, 0x5e, 0x0a, + 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x54, 0x61, + 0x67, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x55, 0x0a, + 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf7, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x68, 0x0a, 0x08, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4c, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, + 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x1a, 0x76, 0x0a, 0x0d, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4f, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, + 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xff, + 0x06, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x65, 0x12, 0x52, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4c, 0x0a, 0x02, 0x69, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x65, 0x2e, 0x49, 0x6e, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x52, 0x0a, 0x04, 0x66, 0x6c, 0x6f, + 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x65, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x2b, 0x0a, + 0x11, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, + 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x49, 0x0a, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x65, + 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x06, 0x73, 0x63, 0x6f, 0x70, + 0x65, 0x73, 0x12, 0x69, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x65, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x55, 0x0a, + 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4b, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0e, + 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, 0x53, 0x49, 0x43, 0x10, 0x01, 0x12, 0x10, + 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x02, + 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x41, 0x55, 0x54, 0x48, 0x32, 0x10, + 0x03, 0x22, 0x31, 0x0a, 0x02, 0x49, 0x6e, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x4e, 0x5f, 0x49, 0x4e, + 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x5f, 0x51, 0x55, + 0x45, 0x52, 0x59, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x49, 0x4e, 0x5f, 0x48, 0x45, 0x41, 0x44, + 0x45, 0x52, 0x10, 0x02, 0x22, 0x6a, 0x0a, 0x04, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x10, 0x0a, 0x0c, + 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x11, + 0x0a, 0x0d, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x49, 0x43, 0x49, 0x54, 0x10, + 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, + 0x52, 0x44, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x41, 0x50, 0x50, + 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x46, 0x4c, + 0x4f, 0x57, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x10, 0x04, + 0x22, 0xf6, 0x02, 0x0a, 0x13, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x8a, 0x01, 0x0a, 0x14, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x57, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x13, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x1a, 0x30, 0x0a, 0x18, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x1a, 0x9f, 0x01, 0x0a, 0x18, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x6d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x57, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x96, 0x01, 0x0a, 0x06, 0x53, 0x63, + 0x6f, 0x70, 0x65, 0x73, 0x12, 0x52, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x1a, 0x38, 0x0a, 0x0a, 0x53, 0x63, 0x6f, 0x70, + 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x2a, 0x3b, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x0b, 0x0a, 0x07, + 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, + 0x50, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, 0x54, 0x50, 0x53, 0x10, 0x02, 0x12, 0x06, + 0x0a, 0x02, 0x57, 0x53, 0x10, 0x03, 0x12, 0x07, 0x0a, 0x03, 0x57, 0x53, 0x53, 0x10, 0x04, 0x42, + 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x70, 0x63, 0x2d, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes = make([]protoimpl.EnumInfo, 6) +var file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes = make([]protoimpl.MessageInfo, 35) +var file_protoc_gen_openapiv2_options_openapiv2_proto_goTypes = []any{ + (Scheme)(0), // 0: grpc.gateway.protoc_gen_openapiv2.options.Scheme + (HeaderParameter_Type)(0), // 1: grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter.Type + (JSONSchema_JSONSchemaSimpleTypes)(0), // 2: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.JSONSchemaSimpleTypes + (SecurityScheme_Type)(0), // 3: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Type + (SecurityScheme_In)(0), // 4: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.In + (SecurityScheme_Flow)(0), // 5: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Flow + (*Swagger)(nil), // 6: grpc.gateway.protoc_gen_openapiv2.options.Swagger + (*Operation)(nil), // 7: grpc.gateway.protoc_gen_openapiv2.options.Operation + (*Parameters)(nil), // 8: grpc.gateway.protoc_gen_openapiv2.options.Parameters + (*HeaderParameter)(nil), // 9: grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter + (*Header)(nil), // 10: grpc.gateway.protoc_gen_openapiv2.options.Header + (*Response)(nil), // 11: grpc.gateway.protoc_gen_openapiv2.options.Response + (*Info)(nil), // 12: grpc.gateway.protoc_gen_openapiv2.options.Info + (*Contact)(nil), // 13: grpc.gateway.protoc_gen_openapiv2.options.Contact + (*License)(nil), // 14: grpc.gateway.protoc_gen_openapiv2.options.License + (*ExternalDocumentation)(nil), // 15: grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + (*Schema)(nil), // 16: grpc.gateway.protoc_gen_openapiv2.options.Schema + (*EnumSchema)(nil), // 17: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema + (*JSONSchema)(nil), // 18: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema + (*Tag)(nil), // 19: grpc.gateway.protoc_gen_openapiv2.options.Tag + (*SecurityDefinitions)(nil), // 20: grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions + (*SecurityScheme)(nil), // 21: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme + (*SecurityRequirement)(nil), // 22: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement + (*Scopes)(nil), // 23: grpc.gateway.protoc_gen_openapiv2.options.Scopes + nil, // 24: grpc.gateway.protoc_gen_openapiv2.options.Swagger.ResponsesEntry + nil, // 25: grpc.gateway.protoc_gen_openapiv2.options.Swagger.ExtensionsEntry + nil, // 26: grpc.gateway.protoc_gen_openapiv2.options.Operation.ResponsesEntry + nil, // 27: grpc.gateway.protoc_gen_openapiv2.options.Operation.ExtensionsEntry + nil, // 28: grpc.gateway.protoc_gen_openapiv2.options.Response.HeadersEntry + nil, // 29: grpc.gateway.protoc_gen_openapiv2.options.Response.ExamplesEntry + nil, // 30: grpc.gateway.protoc_gen_openapiv2.options.Response.ExtensionsEntry + nil, // 31: grpc.gateway.protoc_gen_openapiv2.options.Info.ExtensionsEntry + nil, // 32: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.ExtensionsEntry + (*JSONSchema_FieldConfiguration)(nil), // 33: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.FieldConfiguration + nil, // 34: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.ExtensionsEntry + nil, // 35: grpc.gateway.protoc_gen_openapiv2.options.Tag.ExtensionsEntry + nil, // 36: grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.SecurityEntry + nil, // 37: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.ExtensionsEntry + (*SecurityRequirement_SecurityRequirementValue)(nil), // 38: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementValue + nil, // 39: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementEntry + nil, // 40: grpc.gateway.protoc_gen_openapiv2.options.Scopes.ScopeEntry + (*structpb.Value)(nil), // 41: google.protobuf.Value +} +var file_protoc_gen_openapiv2_options_openapiv2_proto_depIdxs = []int32{ + 12, // 0: grpc.gateway.protoc_gen_openapiv2.options.Swagger.info:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Info + 0, // 1: grpc.gateway.protoc_gen_openapiv2.options.Swagger.schemes:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Scheme + 24, // 2: grpc.gateway.protoc_gen_openapiv2.options.Swagger.responses:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Swagger.ResponsesEntry + 20, // 3: grpc.gateway.protoc_gen_openapiv2.options.Swagger.security_definitions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions + 22, // 4: grpc.gateway.protoc_gen_openapiv2.options.Swagger.security:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement + 19, // 5: grpc.gateway.protoc_gen_openapiv2.options.Swagger.tags:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Tag + 15, // 6: grpc.gateway.protoc_gen_openapiv2.options.Swagger.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 25, // 7: grpc.gateway.protoc_gen_openapiv2.options.Swagger.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Swagger.ExtensionsEntry + 15, // 8: grpc.gateway.protoc_gen_openapiv2.options.Operation.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 26, // 9: grpc.gateway.protoc_gen_openapiv2.options.Operation.responses:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Operation.ResponsesEntry + 0, // 10: grpc.gateway.protoc_gen_openapiv2.options.Operation.schemes:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Scheme + 22, // 11: grpc.gateway.protoc_gen_openapiv2.options.Operation.security:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement + 27, // 12: grpc.gateway.protoc_gen_openapiv2.options.Operation.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Operation.ExtensionsEntry + 8, // 13: grpc.gateway.protoc_gen_openapiv2.options.Operation.parameters:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Parameters + 9, // 14: grpc.gateway.protoc_gen_openapiv2.options.Parameters.headers:type_name -> grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter + 1, // 15: grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter.type:type_name -> grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter.Type + 16, // 16: grpc.gateway.protoc_gen_openapiv2.options.Response.schema:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Schema + 28, // 17: grpc.gateway.protoc_gen_openapiv2.options.Response.headers:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response.HeadersEntry + 29, // 18: grpc.gateway.protoc_gen_openapiv2.options.Response.examples:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response.ExamplesEntry + 30, // 19: grpc.gateway.protoc_gen_openapiv2.options.Response.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response.ExtensionsEntry + 13, // 20: grpc.gateway.protoc_gen_openapiv2.options.Info.contact:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Contact + 14, // 21: grpc.gateway.protoc_gen_openapiv2.options.Info.license:type_name -> grpc.gateway.protoc_gen_openapiv2.options.License + 31, // 22: grpc.gateway.protoc_gen_openapiv2.options.Info.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Info.ExtensionsEntry + 18, // 23: grpc.gateway.protoc_gen_openapiv2.options.Schema.json_schema:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema + 15, // 24: grpc.gateway.protoc_gen_openapiv2.options.Schema.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 15, // 25: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 32, // 26: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.ExtensionsEntry + 2, // 27: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.type:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.JSONSchemaSimpleTypes + 33, // 28: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.field_configuration:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.FieldConfiguration + 34, // 29: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.ExtensionsEntry + 15, // 30: grpc.gateway.protoc_gen_openapiv2.options.Tag.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 35, // 31: grpc.gateway.protoc_gen_openapiv2.options.Tag.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Tag.ExtensionsEntry + 36, // 32: grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.security:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.SecurityEntry + 3, // 33: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.type:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Type + 4, // 34: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.in:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.In + 5, // 35: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.flow:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Flow + 23, // 36: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.scopes:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Scopes + 37, // 37: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.ExtensionsEntry + 39, // 38: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.security_requirement:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementEntry + 40, // 39: grpc.gateway.protoc_gen_openapiv2.options.Scopes.scope:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Scopes.ScopeEntry + 11, // 40: grpc.gateway.protoc_gen_openapiv2.options.Swagger.ResponsesEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response + 41, // 41: grpc.gateway.protoc_gen_openapiv2.options.Swagger.ExtensionsEntry.value:type_name -> google.protobuf.Value + 11, // 42: grpc.gateway.protoc_gen_openapiv2.options.Operation.ResponsesEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response + 41, // 43: grpc.gateway.protoc_gen_openapiv2.options.Operation.ExtensionsEntry.value:type_name -> google.protobuf.Value + 10, // 44: grpc.gateway.protoc_gen_openapiv2.options.Response.HeadersEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Header + 41, // 45: grpc.gateway.protoc_gen_openapiv2.options.Response.ExtensionsEntry.value:type_name -> google.protobuf.Value + 41, // 46: grpc.gateway.protoc_gen_openapiv2.options.Info.ExtensionsEntry.value:type_name -> google.protobuf.Value + 41, // 47: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.ExtensionsEntry.value:type_name -> google.protobuf.Value + 41, // 48: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.ExtensionsEntry.value:type_name -> google.protobuf.Value + 41, // 49: grpc.gateway.protoc_gen_openapiv2.options.Tag.ExtensionsEntry.value:type_name -> google.protobuf.Value + 21, // 50: grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.SecurityEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme + 41, // 51: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.ExtensionsEntry.value:type_name -> google.protobuf.Value + 38, // 52: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementValue + 53, // [53:53] is the sub-list for method output_type + 53, // [53:53] is the sub-list for method input_type + 53, // [53:53] is the sub-list for extension type_name + 53, // [53:53] is the sub-list for extension extendee + 0, // [0:53] is the sub-list for field type_name +} + +func init() { file_protoc_gen_openapiv2_options_openapiv2_proto_init() } +func file_protoc_gen_openapiv2_options_openapiv2_proto_init() { + if File_protoc_gen_openapiv2_options_openapiv2_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_protoc_gen_openapiv2_options_openapiv2_proto_rawDesc, + NumEnums: 6, + NumMessages: 35, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_protoc_gen_openapiv2_options_openapiv2_proto_goTypes, + DependencyIndexes: file_protoc_gen_openapiv2_options_openapiv2_proto_depIdxs, + EnumInfos: file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes, + MessageInfos: file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes, + }.Build() + File_protoc_gen_openapiv2_options_openapiv2_proto = out.File + file_protoc_gen_openapiv2_options_openapiv2_proto_rawDesc = nil + file_protoc_gen_openapiv2_options_openapiv2_proto_goTypes = nil + file_protoc_gen_openapiv2_options_openapiv2_proto_depIdxs = nil +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2.proto b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2.proto new file mode 100644 index 0000000000..5313f0818a --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2.proto @@ -0,0 +1,759 @@ +syntax = "proto3"; + +package grpc.gateway.protoc_gen_openapiv2.options; + +import "google/protobuf/struct.proto"; + +option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options"; + +// Scheme describes the schemes supported by the OpenAPI Swagger +// and Operation objects. +enum Scheme { + UNKNOWN = 0; + HTTP = 1; + HTTPS = 2; + WS = 3; + WSS = 4; +} + +// `Swagger` is a representation of OpenAPI v2 specification's Swagger object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#swaggerObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// title: "Echo API"; +// version: "1.0"; +// description: ""; +// contact: { +// name: "gRPC-Gateway project"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// email: "none@example.com"; +// }; +// license: { +// name: "BSD 3-Clause License"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; +// }; +// }; +// schemes: HTTPS; +// consumes: "application/json"; +// produces: "application/json"; +// }; +// +message Swagger { + // Specifies the OpenAPI Specification version being used. It can be + // used by the OpenAPI UI and other clients to interpret the API listing. The + // value MUST be "2.0". + string swagger = 1; + // Provides metadata about the API. The metadata can be used by the + // clients if needed. + Info info = 2; + // The host (name or ip) serving the API. This MUST be the host only and does + // not include the scheme nor sub-paths. It MAY include a port. If the host is + // not included, the host serving the documentation is to be used (including + // the port). The host does not support path templating. + string host = 3; + // The base path on which the API is served, which is relative to the host. If + // it is not included, the API is served directly under the host. The value + // MUST start with a leading slash (/). The basePath does not support path + // templating. + // Note that using `base_path` does not change the endpoint paths that are + // generated in the resulting OpenAPI file. If you wish to use `base_path` + // with relatively generated OpenAPI paths, the `base_path` prefix must be + // manually removed from your `google.api.http` paths and your code changed to + // serve the API from the `base_path`. + string base_path = 4; + // The transfer protocol of the API. Values MUST be from the list: "http", + // "https", "ws", "wss". If the schemes is not included, the default scheme to + // be used is the one used to access the OpenAPI definition itself. + repeated Scheme schemes = 5; + // A list of MIME types the APIs can consume. This is global to all APIs but + // can be overridden on specific API calls. Value MUST be as described under + // Mime Types. + repeated string consumes = 6; + // A list of MIME types the APIs can produce. This is global to all APIs but + // can be overridden on specific API calls. Value MUST be as described under + // Mime Types. + repeated string produces = 7; + // field 8 is reserved for 'paths'. + reserved 8; + // field 9 is reserved for 'definitions', which at this time are already + // exposed as and customizable as proto messages. + reserved 9; + // An object to hold responses that can be used across operations. This + // property does not define global responses for all operations. + map responses = 10; + // Security scheme definitions that can be used across the specification. + SecurityDefinitions security_definitions = 11; + // A declaration of which security schemes are applied for the API as a whole. + // The list of values describes alternative security schemes that can be used + // (that is, there is a logical OR between the security requirements). + // Individual operations can override this definition. + repeated SecurityRequirement security = 12; + // A list of tags for API documentation control. Tags can be used for logical + // grouping of operations by resources or any other qualifier. + repeated Tag tags = 13; + // Additional external documentation. + ExternalDocumentation external_docs = 14; + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + map extensions = 15; +} + +// `Operation` is a representation of OpenAPI v2 specification's Operation object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#operationObject +// +// Example: +// +// service EchoService { +// rpc Echo(SimpleMessage) returns (SimpleMessage) { +// option (google.api.http) = { +// get: "/v1/example/echo/{id}" +// }; +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { +// summary: "Get a message."; +// operation_id: "getMessage"; +// tags: "echo"; +// responses: { +// key: "200" +// value: { +// description: "OK"; +// } +// } +// }; +// } +// } +message Operation { + // A list of tags for API documentation control. Tags can be used for logical + // grouping of operations by resources or any other qualifier. + repeated string tags = 1; + // A short summary of what the operation does. For maximum readability in the + // swagger-ui, this field SHOULD be less than 120 characters. + string summary = 2; + // A verbose explanation of the operation behavior. GFM syntax can be used for + // rich text representation. + string description = 3; + // Additional external documentation for this operation. + ExternalDocumentation external_docs = 4; + // Unique string used to identify the operation. The id MUST be unique among + // all operations described in the API. Tools and libraries MAY use the + // operationId to uniquely identify an operation, therefore, it is recommended + // to follow common programming naming conventions. + string operation_id = 5; + // A list of MIME types the operation can consume. This overrides the consumes + // definition at the OpenAPI Object. An empty value MAY be used to clear the + // global definition. Value MUST be as described under Mime Types. + repeated string consumes = 6; + // A list of MIME types the operation can produce. This overrides the produces + // definition at the OpenAPI Object. An empty value MAY be used to clear the + // global definition. Value MUST be as described under Mime Types. + repeated string produces = 7; + // field 8 is reserved for 'parameters'. + reserved 8; + // The list of possible responses as they are returned from executing this + // operation. + map responses = 9; + // The transfer protocol for the operation. Values MUST be from the list: + // "http", "https", "ws", "wss". The value overrides the OpenAPI Object + // schemes definition. + repeated Scheme schemes = 10; + // Declares this operation to be deprecated. Usage of the declared operation + // should be refrained. Default value is false. + bool deprecated = 11; + // A declaration of which security schemes are applied for this operation. The + // list of values describes alternative security schemes that can be used + // (that is, there is a logical OR between the security requirements). This + // definition overrides any declared top-level security. To remove a top-level + // security declaration, an empty array can be used. + repeated SecurityRequirement security = 12; + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + map extensions = 13; + // Custom parameters such as HTTP request headers. + // See: https://swagger.io/docs/specification/2-0/describing-parameters/ + // and https://swagger.io/specification/v2/#parameter-object. + Parameters parameters = 14; +} + +// `Parameters` is a representation of OpenAPI v2 specification's parameters object. +// Note: This technically breaks compatibility with the OpenAPI 2 definition structure as we only +// allow header parameters to be set here since we do not want users specifying custom non-header +// parameters beyond those inferred from the Protobuf schema. +// See: https://swagger.io/specification/v2/#parameter-object +message Parameters { + // `Headers` is one or more HTTP header parameter. + // See: https://swagger.io/docs/specification/2-0/describing-parameters/#header-parameters + repeated HeaderParameter headers = 1; +} + +// `HeaderParameter` a HTTP header parameter. +// See: https://swagger.io/specification/v2/#parameter-object +message HeaderParameter { + // `Type` is a supported HTTP header type. + // See https://swagger.io/specification/v2/#parameterType. + enum Type { + UNKNOWN = 0; + STRING = 1; + NUMBER = 2; + INTEGER = 3; + BOOLEAN = 4; + } + + // `Name` is the header name. + string name = 1; + // `Description` is a short description of the header. + string description = 2; + // `Type` is the type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported. + // See: https://swagger.io/specification/v2/#parameterType. + Type type = 3; + // `Format` The extending format for the previously mentioned type. + string format = 4; + // `Required` indicates if the header is optional + bool required = 5; + // field 6 is reserved for 'items', but in OpenAPI-specific way. + reserved 6; + // field 7 is reserved `Collection Format`. Determines the format of the array if type array is used. + reserved 7; +} + +// `Header` is a representation of OpenAPI v2 specification's Header object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#headerObject +// +message Header { + // `Description` is a short description of the header. + string description = 1; + // The type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported. + string type = 2; + // `Format` The extending format for the previously mentioned type. + string format = 3; + // field 4 is reserved for 'items', but in OpenAPI-specific way. + reserved 4; + // field 5 is reserved `Collection Format` Determines the format of the array if type array is used. + reserved 5; + // `Default` Declares the value of the header that the server will use if none is provided. + // See: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2. + // Unlike JSON Schema this value MUST conform to the defined type for the header. + string default = 6; + // field 7 is reserved for 'maximum'. + reserved 7; + // field 8 is reserved for 'exclusiveMaximum'. + reserved 8; + // field 9 is reserved for 'minimum'. + reserved 9; + // field 10 is reserved for 'exclusiveMinimum'. + reserved 10; + // field 11 is reserved for 'maxLength'. + reserved 11; + // field 12 is reserved for 'minLength'. + reserved 12; + // 'Pattern' See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3. + string pattern = 13; + // field 14 is reserved for 'maxItems'. + reserved 14; + // field 15 is reserved for 'minItems'. + reserved 15; + // field 16 is reserved for 'uniqueItems'. + reserved 16; + // field 17 is reserved for 'enum'. + reserved 17; + // field 18 is reserved for 'multipleOf'. + reserved 18; +} + +// `Response` is a representation of OpenAPI v2 specification's Response object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#responseObject +// +message Response { + // `Description` is a short description of the response. + // GFM syntax can be used for rich text representation. + string description = 1; + // `Schema` optionally defines the structure of the response. + // If `Schema` is not provided, it means there is no content to the response. + Schema schema = 2; + // `Headers` A list of headers that are sent with the response. + // `Header` name is expected to be a string in the canonical format of the MIME header key + // See: https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey + map headers = 3; + // `Examples` gives per-mimetype response examples. + // See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#example-object + map examples = 4; + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + map extensions = 5; +} + +// `Info` is a representation of OpenAPI v2 specification's Info object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#infoObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// title: "Echo API"; +// version: "1.0"; +// description: ""; +// contact: { +// name: "gRPC-Gateway project"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// email: "none@example.com"; +// }; +// license: { +// name: "BSD 3-Clause License"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; +// }; +// }; +// ... +// }; +// +message Info { + // The title of the application. + string title = 1; + // A short description of the application. GFM syntax can be used for rich + // text representation. + string description = 2; + // The Terms of Service for the API. + string terms_of_service = 3; + // The contact information for the exposed API. + Contact contact = 4; + // The license information for the exposed API. + License license = 5; + // Provides the version of the application API (not to be confused + // with the specification version). + string version = 6; + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + map extensions = 7; +} + +// `Contact` is a representation of OpenAPI v2 specification's Contact object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#contactObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// ... +// contact: { +// name: "gRPC-Gateway project"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// email: "none@example.com"; +// }; +// ... +// }; +// ... +// }; +// +message Contact { + // The identifying name of the contact person/organization. + string name = 1; + // The URL pointing to the contact information. MUST be in the format of a + // URL. + string url = 2; + // The email address of the contact person/organization. MUST be in the format + // of an email address. + string email = 3; +} + +// `License` is a representation of OpenAPI v2 specification's License object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#licenseObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// ... +// license: { +// name: "BSD 3-Clause License"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; +// }; +// ... +// }; +// ... +// }; +// +message License { + // The license name used for the API. + string name = 1; + // A URL to the license used for the API. MUST be in the format of a URL. + string url = 2; +} + +// `ExternalDocumentation` is a representation of OpenAPI v2 specification's +// ExternalDocumentation object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#externalDocumentationObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// ... +// external_docs: { +// description: "More about gRPC-Gateway"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// } +// ... +// }; +// +message ExternalDocumentation { + // A short description of the target documentation. GFM syntax can be used for + // rich text representation. + string description = 1; + // The URL for the target documentation. Value MUST be in the format + // of a URL. + string url = 2; +} + +// `Schema` is a representation of OpenAPI v2 specification's Schema object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject +// +message Schema { + JSONSchema json_schema = 1; + // Adds support for polymorphism. The discriminator is the schema property + // name that is used to differentiate between other schema that inherit this + // schema. The property name used MUST be defined at this schema and it MUST + // be in the required property list. When used, the value MUST be the name of + // this schema or any schema that inherits it. + string discriminator = 2; + // Relevant only for Schema "properties" definitions. Declares the property as + // "read only". This means that it MAY be sent as part of a response but MUST + // NOT be sent as part of the request. Properties marked as readOnly being + // true SHOULD NOT be in the required list of the defined schema. Default + // value is false. + bool read_only = 3; + // field 4 is reserved for 'xml'. + reserved 4; + // Additional external documentation for this schema. + ExternalDocumentation external_docs = 5; + // A free-form property to include an example of an instance for this schema in JSON. + // This is copied verbatim to the output. + string example = 6; +} + +// `EnumSchema` is subset of fields from the OpenAPI v2 specification's Schema object. +// Only fields that are applicable to Enums are included +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum) = { +// ... +// title: "MyEnum"; +// description:"This is my nice enum"; +// example: "ZERO"; +// required: true; +// ... +// }; +// +message EnumSchema { + // A short description of the schema. + string description = 1; + string default = 2; + // The title of the schema. + string title = 3; + bool required = 4; + bool read_only = 5; + // Additional external documentation for this schema. + ExternalDocumentation external_docs = 6; + string example = 7; + // Ref is used to define an external reference to include in the message. + // This could be a fully qualified proto message reference, and that type must + // be imported into the protofile. If no message is identified, the Ref will + // be used verbatim in the output. + // For example: + // `ref: ".google.protobuf.Timestamp"`. + string ref = 8; + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + map extensions = 9; +} + +// `JSONSchema` represents properties from JSON Schema taken, and as used, in +// the OpenAPI v2 spec. +// +// This includes changes made by OpenAPI v2. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject +// +// See also: https://cswr.github.io/JsonSchema/spec/basic_types/, +// https://github.com/json-schema-org/json-schema-spec/blob/master/schema.json +// +// Example: +// +// message SimpleMessage { +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { +// json_schema: { +// title: "SimpleMessage" +// description: "A simple message." +// required: ["id"] +// } +// }; +// +// // Id represents the message identifier. +// string id = 1; [ +// (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { +// description: "The unique identifier of the simple message." +// }]; +// } +// +message JSONSchema { + // field 1 is reserved for '$id', omitted from OpenAPI v2. + reserved 1; + // field 2 is reserved for '$schema', omitted from OpenAPI v2. + reserved 2; + // Ref is used to define an external reference to include in the message. + // This could be a fully qualified proto message reference, and that type must + // be imported into the protofile. If no message is identified, the Ref will + // be used verbatim in the output. + // For example: + // `ref: ".google.protobuf.Timestamp"`. + string ref = 3; + // field 4 is reserved for '$comment', omitted from OpenAPI v2. + reserved 4; + // The title of the schema. + string title = 5; + // A short description of the schema. + string description = 6; + string default = 7; + bool read_only = 8; + // A free-form property to include a JSON example of this field. This is copied + // verbatim to the output swagger.json. Quotes must be escaped. + // This property is the same for 2.0 and 3.0.0 https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#schemaObject https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject + string example = 9; + double multiple_of = 10; + // Maximum represents an inclusive upper limit for a numeric instance. The + // value of MUST be a number, + double maximum = 11; + bool exclusive_maximum = 12; + // minimum represents an inclusive lower limit for a numeric instance. The + // value of MUST be a number, + double minimum = 13; + bool exclusive_minimum = 14; + uint64 max_length = 15; + uint64 min_length = 16; + string pattern = 17; + // field 18 is reserved for 'additionalItems', omitted from OpenAPI v2. + reserved 18; + // field 19 is reserved for 'items', but in OpenAPI-specific way. + // TODO(ivucica): add 'items'? + reserved 19; + uint64 max_items = 20; + uint64 min_items = 21; + bool unique_items = 22; + // field 23 is reserved for 'contains', omitted from OpenAPI v2. + reserved 23; + uint64 max_properties = 24; + uint64 min_properties = 25; + repeated string required = 26; + // field 27 is reserved for 'additionalProperties', but in OpenAPI-specific + // way. TODO(ivucica): add 'additionalProperties'? + reserved 27; + // field 28 is reserved for 'definitions', omitted from OpenAPI v2. + reserved 28; + // field 29 is reserved for 'properties', but in OpenAPI-specific way. + // TODO(ivucica): add 'additionalProperties'? + reserved 29; + // following fields are reserved, as the properties have been omitted from + // OpenAPI v2: + // patternProperties, dependencies, propertyNames, const + reserved 30 to 33; + // Items in 'array' must be unique. + repeated string array = 34; + + enum JSONSchemaSimpleTypes { + UNKNOWN = 0; + ARRAY = 1; + BOOLEAN = 2; + INTEGER = 3; + NULL = 4; + NUMBER = 5; + OBJECT = 6; + STRING = 7; + } + + repeated JSONSchemaSimpleTypes type = 35; + // `Format` + string format = 36; + // following fields are reserved, as the properties have been omitted from + // OpenAPI v2: contentMediaType, contentEncoding, if, then, else + reserved 37 to 41; + // field 42 is reserved for 'allOf', but in OpenAPI-specific way. + // TODO(ivucica): add 'allOf'? + reserved 42; + // following fields are reserved, as the properties have been omitted from + // OpenAPI v2: + // anyOf, oneOf, not + reserved 43 to 45; + // Items in `enum` must be unique https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1 + repeated string enum = 46; + + // Additional field level properties used when generating the OpenAPI v2 file. + FieldConfiguration field_configuration = 1001; + + // 'FieldConfiguration' provides additional field level properties used when generating the OpenAPI v2 file. + // These properties are not defined by OpenAPIv2, but they are used to control the generation. + message FieldConfiguration { + // Alternative parameter name when used as path parameter. If set, this will + // be used as the complete parameter name when this field is used as a path + // parameter. Use this to avoid having auto generated path parameter names + // for overlapping paths. + string path_param_name = 47; + } + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + map extensions = 48; +} + +// `Tag` is a representation of OpenAPI v2 specification's Tag object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#tagObject +// +message Tag { + // The name of the tag. Use it to allow override of the name of a + // global Tag object, then use that name to reference the tag throughout the + // OpenAPI file. + string name = 1; + // A short description for the tag. GFM syntax can be used for rich text + // representation. + string description = 2; + // Additional external documentation for this tag. + ExternalDocumentation external_docs = 3; + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + map extensions = 4; +} + +// `SecurityDefinitions` is a representation of OpenAPI v2 specification's +// Security Definitions object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityDefinitionsObject +// +// A declaration of the security schemes available to be used in the +// specification. This does not enforce the security schemes on the operations +// and only serves to provide the relevant details for each scheme. +message SecurityDefinitions { + // A single security scheme definition, mapping a "name" to the scheme it + // defines. + map security = 1; +} + +// `SecurityScheme` is a representation of OpenAPI v2 specification's +// Security Scheme object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securitySchemeObject +// +// Allows the definition of a security scheme that can be used by the +// operations. Supported schemes are basic authentication, an API key (either as +// a header or as a query parameter) and OAuth2's common flows (implicit, +// password, application and access code). +message SecurityScheme { + // The type of the security scheme. Valid values are "basic", + // "apiKey" or "oauth2". + enum Type { + TYPE_INVALID = 0; + TYPE_BASIC = 1; + TYPE_API_KEY = 2; + TYPE_OAUTH2 = 3; + } + + // The location of the API key. Valid values are "query" or "header". + enum In { + IN_INVALID = 0; + IN_QUERY = 1; + IN_HEADER = 2; + } + + // The flow used by the OAuth2 security scheme. Valid values are + // "implicit", "password", "application" or "accessCode". + enum Flow { + FLOW_INVALID = 0; + FLOW_IMPLICIT = 1; + FLOW_PASSWORD = 2; + FLOW_APPLICATION = 3; + FLOW_ACCESS_CODE = 4; + } + + // The type of the security scheme. Valid values are "basic", + // "apiKey" or "oauth2". + Type type = 1; + // A short description for security scheme. + string description = 2; + // The name of the header or query parameter to be used. + // Valid for apiKey. + string name = 3; + // The location of the API key. Valid values are "query" or + // "header". + // Valid for apiKey. + In in = 4; + // The flow used by the OAuth2 security scheme. Valid values are + // "implicit", "password", "application" or "accessCode". + // Valid for oauth2. + Flow flow = 5; + // The authorization URL to be used for this flow. This SHOULD be in + // the form of a URL. + // Valid for oauth2/implicit and oauth2/accessCode. + string authorization_url = 6; + // The token URL to be used for this flow. This SHOULD be in the + // form of a URL. + // Valid for oauth2/password, oauth2/application and oauth2/accessCode. + string token_url = 7; + // The available scopes for the OAuth2 security scheme. + // Valid for oauth2. + Scopes scopes = 8; + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + map extensions = 9; +} + +// `SecurityRequirement` is a representation of OpenAPI v2 specification's +// Security Requirement object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityRequirementObject +// +// Lists the required security schemes to execute this operation. The object can +// have multiple security schemes declared in it which are all required (that +// is, there is a logical AND between the schemes). +// +// The name used for each property MUST correspond to a security scheme +// declared in the Security Definitions. +message SecurityRequirement { + // If the security scheme is of type "oauth2", then the value is a list of + // scope names required for the execution. For other security scheme types, + // the array MUST be empty. + message SecurityRequirementValue { + repeated string scope = 1; + } + // Each name must correspond to a security scheme which is declared in + // the Security Definitions. If the security scheme is of type "oauth2", + // then the value is a list of scope names required for the execution. + // For other security scheme types, the array MUST be empty. + map security_requirement = 1; +} + +// `Scopes` is a representation of OpenAPI v2 specification's Scopes object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#scopesObject +// +// Lists the available scopes for an OAuth2 security scheme. +message Scopes { + // Maps between a name of a scope to a short description of it (as the value + // of the property). + map scope = 1; +} diff --git a/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2_protoopaque.pb.go b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2_protoopaque.pb.go new file mode 100644 index 0000000000..1f0e0c2691 --- /dev/null +++ b/etcd/vendor/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options/openapiv2_protoopaque.pb.go @@ -0,0 +1,4055 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.0 +// protoc (unknown) +// source: protoc-gen-openapiv2/options/openapiv2.proto + +//go:build protoopaque + +package options + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + structpb "google.golang.org/protobuf/types/known/structpb" + reflect "reflect" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Scheme describes the schemes supported by the OpenAPI Swagger +// and Operation objects. +type Scheme int32 + +const ( + Scheme_UNKNOWN Scheme = 0 + Scheme_HTTP Scheme = 1 + Scheme_HTTPS Scheme = 2 + Scheme_WS Scheme = 3 + Scheme_WSS Scheme = 4 +) + +// Enum value maps for Scheme. +var ( + Scheme_name = map[int32]string{ + 0: "UNKNOWN", + 1: "HTTP", + 2: "HTTPS", + 3: "WS", + 4: "WSS", + } + Scheme_value = map[string]int32{ + "UNKNOWN": 0, + "HTTP": 1, + "HTTPS": 2, + "WS": 3, + "WSS": 4, + } +) + +func (x Scheme) Enum() *Scheme { + p := new(Scheme) + *p = x + return p +} + +func (x Scheme) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Scheme) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[0].Descriptor() +} + +func (Scheme) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[0] +} + +func (x Scheme) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// `Type` is a supported HTTP header type. +// See https://swagger.io/specification/v2/#parameterType. +type HeaderParameter_Type int32 + +const ( + HeaderParameter_UNKNOWN HeaderParameter_Type = 0 + HeaderParameter_STRING HeaderParameter_Type = 1 + HeaderParameter_NUMBER HeaderParameter_Type = 2 + HeaderParameter_INTEGER HeaderParameter_Type = 3 + HeaderParameter_BOOLEAN HeaderParameter_Type = 4 +) + +// Enum value maps for HeaderParameter_Type. +var ( + HeaderParameter_Type_name = map[int32]string{ + 0: "UNKNOWN", + 1: "STRING", + 2: "NUMBER", + 3: "INTEGER", + 4: "BOOLEAN", + } + HeaderParameter_Type_value = map[string]int32{ + "UNKNOWN": 0, + "STRING": 1, + "NUMBER": 2, + "INTEGER": 3, + "BOOLEAN": 4, + } +) + +func (x HeaderParameter_Type) Enum() *HeaderParameter_Type { + p := new(HeaderParameter_Type) + *p = x + return p +} + +func (x HeaderParameter_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HeaderParameter_Type) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[1].Descriptor() +} + +func (HeaderParameter_Type) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[1] +} + +func (x HeaderParameter_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +type JSONSchema_JSONSchemaSimpleTypes int32 + +const ( + JSONSchema_UNKNOWN JSONSchema_JSONSchemaSimpleTypes = 0 + JSONSchema_ARRAY JSONSchema_JSONSchemaSimpleTypes = 1 + JSONSchema_BOOLEAN JSONSchema_JSONSchemaSimpleTypes = 2 + JSONSchema_INTEGER JSONSchema_JSONSchemaSimpleTypes = 3 + JSONSchema_NULL JSONSchema_JSONSchemaSimpleTypes = 4 + JSONSchema_NUMBER JSONSchema_JSONSchemaSimpleTypes = 5 + JSONSchema_OBJECT JSONSchema_JSONSchemaSimpleTypes = 6 + JSONSchema_STRING JSONSchema_JSONSchemaSimpleTypes = 7 +) + +// Enum value maps for JSONSchema_JSONSchemaSimpleTypes. +var ( + JSONSchema_JSONSchemaSimpleTypes_name = map[int32]string{ + 0: "UNKNOWN", + 1: "ARRAY", + 2: "BOOLEAN", + 3: "INTEGER", + 4: "NULL", + 5: "NUMBER", + 6: "OBJECT", + 7: "STRING", + } + JSONSchema_JSONSchemaSimpleTypes_value = map[string]int32{ + "UNKNOWN": 0, + "ARRAY": 1, + "BOOLEAN": 2, + "INTEGER": 3, + "NULL": 4, + "NUMBER": 5, + "OBJECT": 6, + "STRING": 7, + } +) + +func (x JSONSchema_JSONSchemaSimpleTypes) Enum() *JSONSchema_JSONSchemaSimpleTypes { + p := new(JSONSchema_JSONSchemaSimpleTypes) + *p = x + return p +} + +func (x JSONSchema_JSONSchemaSimpleTypes) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (JSONSchema_JSONSchemaSimpleTypes) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[2].Descriptor() +} + +func (JSONSchema_JSONSchemaSimpleTypes) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[2] +} + +func (x JSONSchema_JSONSchemaSimpleTypes) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// The type of the security scheme. Valid values are "basic", +// "apiKey" or "oauth2". +type SecurityScheme_Type int32 + +const ( + SecurityScheme_TYPE_INVALID SecurityScheme_Type = 0 + SecurityScheme_TYPE_BASIC SecurityScheme_Type = 1 + SecurityScheme_TYPE_API_KEY SecurityScheme_Type = 2 + SecurityScheme_TYPE_OAUTH2 SecurityScheme_Type = 3 +) + +// Enum value maps for SecurityScheme_Type. +var ( + SecurityScheme_Type_name = map[int32]string{ + 0: "TYPE_INVALID", + 1: "TYPE_BASIC", + 2: "TYPE_API_KEY", + 3: "TYPE_OAUTH2", + } + SecurityScheme_Type_value = map[string]int32{ + "TYPE_INVALID": 0, + "TYPE_BASIC": 1, + "TYPE_API_KEY": 2, + "TYPE_OAUTH2": 3, + } +) + +func (x SecurityScheme_Type) Enum() *SecurityScheme_Type { + p := new(SecurityScheme_Type) + *p = x + return p +} + +func (x SecurityScheme_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SecurityScheme_Type) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[3].Descriptor() +} + +func (SecurityScheme_Type) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[3] +} + +func (x SecurityScheme_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// The location of the API key. Valid values are "query" or "header". +type SecurityScheme_In int32 + +const ( + SecurityScheme_IN_INVALID SecurityScheme_In = 0 + SecurityScheme_IN_QUERY SecurityScheme_In = 1 + SecurityScheme_IN_HEADER SecurityScheme_In = 2 +) + +// Enum value maps for SecurityScheme_In. +var ( + SecurityScheme_In_name = map[int32]string{ + 0: "IN_INVALID", + 1: "IN_QUERY", + 2: "IN_HEADER", + } + SecurityScheme_In_value = map[string]int32{ + "IN_INVALID": 0, + "IN_QUERY": 1, + "IN_HEADER": 2, + } +) + +func (x SecurityScheme_In) Enum() *SecurityScheme_In { + p := new(SecurityScheme_In) + *p = x + return p +} + +func (x SecurityScheme_In) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SecurityScheme_In) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[4].Descriptor() +} + +func (SecurityScheme_In) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[4] +} + +func (x SecurityScheme_In) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// The flow used by the OAuth2 security scheme. Valid values are +// "implicit", "password", "application" or "accessCode". +type SecurityScheme_Flow int32 + +const ( + SecurityScheme_FLOW_INVALID SecurityScheme_Flow = 0 + SecurityScheme_FLOW_IMPLICIT SecurityScheme_Flow = 1 + SecurityScheme_FLOW_PASSWORD SecurityScheme_Flow = 2 + SecurityScheme_FLOW_APPLICATION SecurityScheme_Flow = 3 + SecurityScheme_FLOW_ACCESS_CODE SecurityScheme_Flow = 4 +) + +// Enum value maps for SecurityScheme_Flow. +var ( + SecurityScheme_Flow_name = map[int32]string{ + 0: "FLOW_INVALID", + 1: "FLOW_IMPLICIT", + 2: "FLOW_PASSWORD", + 3: "FLOW_APPLICATION", + 4: "FLOW_ACCESS_CODE", + } + SecurityScheme_Flow_value = map[string]int32{ + "FLOW_INVALID": 0, + "FLOW_IMPLICIT": 1, + "FLOW_PASSWORD": 2, + "FLOW_APPLICATION": 3, + "FLOW_ACCESS_CODE": 4, + } +) + +func (x SecurityScheme_Flow) Enum() *SecurityScheme_Flow { + p := new(SecurityScheme_Flow) + *p = x + return p +} + +func (x SecurityScheme_Flow) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SecurityScheme_Flow) Descriptor() protoreflect.EnumDescriptor { + return file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[5].Descriptor() +} + +func (SecurityScheme_Flow) Type() protoreflect.EnumType { + return &file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes[5] +} + +func (x SecurityScheme_Flow) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// `Swagger` is a representation of OpenAPI v2 specification's Swagger object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#swaggerObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// title: "Echo API"; +// version: "1.0"; +// description: ""; +// contact: { +// name: "gRPC-Gateway project"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// email: "none@example.com"; +// }; +// license: { +// name: "BSD 3-Clause License"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; +// }; +// }; +// schemes: HTTPS; +// consumes: "application/json"; +// produces: "application/json"; +// }; +type Swagger struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Swagger string `protobuf:"bytes,1,opt,name=swagger,proto3" json:"swagger,omitempty"` + xxx_hidden_Info *Info `protobuf:"bytes,2,opt,name=info,proto3" json:"info,omitempty"` + xxx_hidden_Host string `protobuf:"bytes,3,opt,name=host,proto3" json:"host,omitempty"` + xxx_hidden_BasePath string `protobuf:"bytes,4,opt,name=base_path,json=basePath,proto3" json:"base_path,omitempty"` + xxx_hidden_Schemes []Scheme `protobuf:"varint,5,rep,packed,name=schemes,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.Scheme" json:"schemes,omitempty"` + xxx_hidden_Consumes []string `protobuf:"bytes,6,rep,name=consumes,proto3" json:"consumes,omitempty"` + xxx_hidden_Produces []string `protobuf:"bytes,7,rep,name=produces,proto3" json:"produces,omitempty"` + xxx_hidden_Responses map[string]*Response `protobuf:"bytes,10,rep,name=responses,proto3" json:"responses,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + xxx_hidden_SecurityDefinitions *SecurityDefinitions `protobuf:"bytes,11,opt,name=security_definitions,json=securityDefinitions,proto3" json:"security_definitions,omitempty"` + xxx_hidden_Security *[]*SecurityRequirement `protobuf:"bytes,12,rep,name=security,proto3" json:"security,omitempty"` + xxx_hidden_Tags *[]*Tag `protobuf:"bytes,13,rep,name=tags,proto3" json:"tags,omitempty"` + xxx_hidden_ExternalDocs *ExternalDocumentation `protobuf:"bytes,14,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + xxx_hidden_Extensions map[string]*structpb.Value `protobuf:"bytes,15,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Swagger) Reset() { + *x = Swagger{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Swagger) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Swagger) ProtoMessage() {} + +func (x *Swagger) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Swagger) GetSwagger() string { + if x != nil { + return x.xxx_hidden_Swagger + } + return "" +} + +func (x *Swagger) GetInfo() *Info { + if x != nil { + return x.xxx_hidden_Info + } + return nil +} + +func (x *Swagger) GetHost() string { + if x != nil { + return x.xxx_hidden_Host + } + return "" +} + +func (x *Swagger) GetBasePath() string { + if x != nil { + return x.xxx_hidden_BasePath + } + return "" +} + +func (x *Swagger) GetSchemes() []Scheme { + if x != nil { + return x.xxx_hidden_Schemes + } + return nil +} + +func (x *Swagger) GetConsumes() []string { + if x != nil { + return x.xxx_hidden_Consumes + } + return nil +} + +func (x *Swagger) GetProduces() []string { + if x != nil { + return x.xxx_hidden_Produces + } + return nil +} + +func (x *Swagger) GetResponses() map[string]*Response { + if x != nil { + return x.xxx_hidden_Responses + } + return nil +} + +func (x *Swagger) GetSecurityDefinitions() *SecurityDefinitions { + if x != nil { + return x.xxx_hidden_SecurityDefinitions + } + return nil +} + +func (x *Swagger) GetSecurity() []*SecurityRequirement { + if x != nil { + if x.xxx_hidden_Security != nil { + return *x.xxx_hidden_Security + } + } + return nil +} + +func (x *Swagger) GetTags() []*Tag { + if x != nil { + if x.xxx_hidden_Tags != nil { + return *x.xxx_hidden_Tags + } + } + return nil +} + +func (x *Swagger) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.xxx_hidden_ExternalDocs + } + return nil +} + +func (x *Swagger) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.xxx_hidden_Extensions + } + return nil +} + +func (x *Swagger) SetSwagger(v string) { + x.xxx_hidden_Swagger = v +} + +func (x *Swagger) SetInfo(v *Info) { + x.xxx_hidden_Info = v +} + +func (x *Swagger) SetHost(v string) { + x.xxx_hidden_Host = v +} + +func (x *Swagger) SetBasePath(v string) { + x.xxx_hidden_BasePath = v +} + +func (x *Swagger) SetSchemes(v []Scheme) { + x.xxx_hidden_Schemes = v +} + +func (x *Swagger) SetConsumes(v []string) { + x.xxx_hidden_Consumes = v +} + +func (x *Swagger) SetProduces(v []string) { + x.xxx_hidden_Produces = v +} + +func (x *Swagger) SetResponses(v map[string]*Response) { + x.xxx_hidden_Responses = v +} + +func (x *Swagger) SetSecurityDefinitions(v *SecurityDefinitions) { + x.xxx_hidden_SecurityDefinitions = v +} + +func (x *Swagger) SetSecurity(v []*SecurityRequirement) { + x.xxx_hidden_Security = &v +} + +func (x *Swagger) SetTags(v []*Tag) { + x.xxx_hidden_Tags = &v +} + +func (x *Swagger) SetExternalDocs(v *ExternalDocumentation) { + x.xxx_hidden_ExternalDocs = v +} + +func (x *Swagger) SetExtensions(v map[string]*structpb.Value) { + x.xxx_hidden_Extensions = v +} + +func (x *Swagger) HasInfo() bool { + if x == nil { + return false + } + return x.xxx_hidden_Info != nil +} + +func (x *Swagger) HasSecurityDefinitions() bool { + if x == nil { + return false + } + return x.xxx_hidden_SecurityDefinitions != nil +} + +func (x *Swagger) HasExternalDocs() bool { + if x == nil { + return false + } + return x.xxx_hidden_ExternalDocs != nil +} + +func (x *Swagger) ClearInfo() { + x.xxx_hidden_Info = nil +} + +func (x *Swagger) ClearSecurityDefinitions() { + x.xxx_hidden_SecurityDefinitions = nil +} + +func (x *Swagger) ClearExternalDocs() { + x.xxx_hidden_ExternalDocs = nil +} + +type Swagger_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Specifies the OpenAPI Specification version being used. It can be + // used by the OpenAPI UI and other clients to interpret the API listing. The + // value MUST be "2.0". + Swagger string + // Provides metadata about the API. The metadata can be used by the + // clients if needed. + Info *Info + // The host (name or ip) serving the API. This MUST be the host only and does + // not include the scheme nor sub-paths. It MAY include a port. If the host is + // not included, the host serving the documentation is to be used (including + // the port). The host does not support path templating. + Host string + // The base path on which the API is served, which is relative to the host. If + // it is not included, the API is served directly under the host. The value + // MUST start with a leading slash (/). The basePath does not support path + // templating. + // Note that using `base_path` does not change the endpoint paths that are + // generated in the resulting OpenAPI file. If you wish to use `base_path` + // with relatively generated OpenAPI paths, the `base_path` prefix must be + // manually removed from your `google.api.http` paths and your code changed to + // serve the API from the `base_path`. + BasePath string + // The transfer protocol of the API. Values MUST be from the list: "http", + // "https", "ws", "wss". If the schemes is not included, the default scheme to + // be used is the one used to access the OpenAPI definition itself. + Schemes []Scheme + // A list of MIME types the APIs can consume. This is global to all APIs but + // can be overridden on specific API calls. Value MUST be as described under + // Mime Types. + Consumes []string + // A list of MIME types the APIs can produce. This is global to all APIs but + // can be overridden on specific API calls. Value MUST be as described under + // Mime Types. + Produces []string + // An object to hold responses that can be used across operations. This + // property does not define global responses for all operations. + Responses map[string]*Response + // Security scheme definitions that can be used across the specification. + SecurityDefinitions *SecurityDefinitions + // A declaration of which security schemes are applied for the API as a whole. + // The list of values describes alternative security schemes that can be used + // (that is, there is a logical OR between the security requirements). + // Individual operations can override this definition. + Security []*SecurityRequirement + // A list of tags for API documentation control. Tags can be used for logical + // grouping of operations by resources or any other qualifier. + Tags []*Tag + // Additional external documentation. + ExternalDocs *ExternalDocumentation + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 Swagger_builder) Build() *Swagger { + m0 := &Swagger{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Swagger = b.Swagger + x.xxx_hidden_Info = b.Info + x.xxx_hidden_Host = b.Host + x.xxx_hidden_BasePath = b.BasePath + x.xxx_hidden_Schemes = b.Schemes + x.xxx_hidden_Consumes = b.Consumes + x.xxx_hidden_Produces = b.Produces + x.xxx_hidden_Responses = b.Responses + x.xxx_hidden_SecurityDefinitions = b.SecurityDefinitions + x.xxx_hidden_Security = &b.Security + x.xxx_hidden_Tags = &b.Tags + x.xxx_hidden_ExternalDocs = b.ExternalDocs + x.xxx_hidden_Extensions = b.Extensions + return m0 +} + +// `Operation` is a representation of OpenAPI v2 specification's Operation object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#operationObject +// +// Example: +// +// service EchoService { +// rpc Echo(SimpleMessage) returns (SimpleMessage) { +// option (google.api.http) = { +// get: "/v1/example/echo/{id}" +// }; +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { +// summary: "Get a message."; +// operation_id: "getMessage"; +// tags: "echo"; +// responses: { +// key: "200" +// value: { +// description: "OK"; +// } +// } +// }; +// } +// } +type Operation struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Tags []string `protobuf:"bytes,1,rep,name=tags,proto3" json:"tags,omitempty"` + xxx_hidden_Summary string `protobuf:"bytes,2,opt,name=summary,proto3" json:"summary,omitempty"` + xxx_hidden_Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_ExternalDocs *ExternalDocumentation `protobuf:"bytes,4,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + xxx_hidden_OperationId string `protobuf:"bytes,5,opt,name=operation_id,json=operationId,proto3" json:"operation_id,omitempty"` + xxx_hidden_Consumes []string `protobuf:"bytes,6,rep,name=consumes,proto3" json:"consumes,omitempty"` + xxx_hidden_Produces []string `protobuf:"bytes,7,rep,name=produces,proto3" json:"produces,omitempty"` + xxx_hidden_Responses map[string]*Response `protobuf:"bytes,9,rep,name=responses,proto3" json:"responses,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + xxx_hidden_Schemes []Scheme `protobuf:"varint,10,rep,packed,name=schemes,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.Scheme" json:"schemes,omitempty"` + xxx_hidden_Deprecated bool `protobuf:"varint,11,opt,name=deprecated,proto3" json:"deprecated,omitempty"` + xxx_hidden_Security *[]*SecurityRequirement `protobuf:"bytes,12,rep,name=security,proto3" json:"security,omitempty"` + xxx_hidden_Extensions map[string]*structpb.Value `protobuf:"bytes,13,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + xxx_hidden_Parameters *Parameters `protobuf:"bytes,14,opt,name=parameters,proto3" json:"parameters,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Operation) Reset() { + *x = Operation{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Operation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Operation) ProtoMessage() {} + +func (x *Operation) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Operation) GetTags() []string { + if x != nil { + return x.xxx_hidden_Tags + } + return nil +} + +func (x *Operation) GetSummary() string { + if x != nil { + return x.xxx_hidden_Summary + } + return "" +} + +func (x *Operation) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *Operation) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.xxx_hidden_ExternalDocs + } + return nil +} + +func (x *Operation) GetOperationId() string { + if x != nil { + return x.xxx_hidden_OperationId + } + return "" +} + +func (x *Operation) GetConsumes() []string { + if x != nil { + return x.xxx_hidden_Consumes + } + return nil +} + +func (x *Operation) GetProduces() []string { + if x != nil { + return x.xxx_hidden_Produces + } + return nil +} + +func (x *Operation) GetResponses() map[string]*Response { + if x != nil { + return x.xxx_hidden_Responses + } + return nil +} + +func (x *Operation) GetSchemes() []Scheme { + if x != nil { + return x.xxx_hidden_Schemes + } + return nil +} + +func (x *Operation) GetDeprecated() bool { + if x != nil { + return x.xxx_hidden_Deprecated + } + return false +} + +func (x *Operation) GetSecurity() []*SecurityRequirement { + if x != nil { + if x.xxx_hidden_Security != nil { + return *x.xxx_hidden_Security + } + } + return nil +} + +func (x *Operation) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.xxx_hidden_Extensions + } + return nil +} + +func (x *Operation) GetParameters() *Parameters { + if x != nil { + return x.xxx_hidden_Parameters + } + return nil +} + +func (x *Operation) SetTags(v []string) { + x.xxx_hidden_Tags = v +} + +func (x *Operation) SetSummary(v string) { + x.xxx_hidden_Summary = v +} + +func (x *Operation) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *Operation) SetExternalDocs(v *ExternalDocumentation) { + x.xxx_hidden_ExternalDocs = v +} + +func (x *Operation) SetOperationId(v string) { + x.xxx_hidden_OperationId = v +} + +func (x *Operation) SetConsumes(v []string) { + x.xxx_hidden_Consumes = v +} + +func (x *Operation) SetProduces(v []string) { + x.xxx_hidden_Produces = v +} + +func (x *Operation) SetResponses(v map[string]*Response) { + x.xxx_hidden_Responses = v +} + +func (x *Operation) SetSchemes(v []Scheme) { + x.xxx_hidden_Schemes = v +} + +func (x *Operation) SetDeprecated(v bool) { + x.xxx_hidden_Deprecated = v +} + +func (x *Operation) SetSecurity(v []*SecurityRequirement) { + x.xxx_hidden_Security = &v +} + +func (x *Operation) SetExtensions(v map[string]*structpb.Value) { + x.xxx_hidden_Extensions = v +} + +func (x *Operation) SetParameters(v *Parameters) { + x.xxx_hidden_Parameters = v +} + +func (x *Operation) HasExternalDocs() bool { + if x == nil { + return false + } + return x.xxx_hidden_ExternalDocs != nil +} + +func (x *Operation) HasParameters() bool { + if x == nil { + return false + } + return x.xxx_hidden_Parameters != nil +} + +func (x *Operation) ClearExternalDocs() { + x.xxx_hidden_ExternalDocs = nil +} + +func (x *Operation) ClearParameters() { + x.xxx_hidden_Parameters = nil +} + +type Operation_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // A list of tags for API documentation control. Tags can be used for logical + // grouping of operations by resources or any other qualifier. + Tags []string + // A short summary of what the operation does. For maximum readability in the + // swagger-ui, this field SHOULD be less than 120 characters. + Summary string + // A verbose explanation of the operation behavior. GFM syntax can be used for + // rich text representation. + Description string + // Additional external documentation for this operation. + ExternalDocs *ExternalDocumentation + // Unique string used to identify the operation. The id MUST be unique among + // all operations described in the API. Tools and libraries MAY use the + // operationId to uniquely identify an operation, therefore, it is recommended + // to follow common programming naming conventions. + OperationId string + // A list of MIME types the operation can consume. This overrides the consumes + // definition at the OpenAPI Object. An empty value MAY be used to clear the + // global definition. Value MUST be as described under Mime Types. + Consumes []string + // A list of MIME types the operation can produce. This overrides the produces + // definition at the OpenAPI Object. An empty value MAY be used to clear the + // global definition. Value MUST be as described under Mime Types. + Produces []string + // The list of possible responses as they are returned from executing this + // operation. + Responses map[string]*Response + // The transfer protocol for the operation. Values MUST be from the list: + // "http", "https", "ws", "wss". The value overrides the OpenAPI Object + // schemes definition. + Schemes []Scheme + // Declares this operation to be deprecated. Usage of the declared operation + // should be refrained. Default value is false. + Deprecated bool + // A declaration of which security schemes are applied for this operation. The + // list of values describes alternative security schemes that can be used + // (that is, there is a logical OR between the security requirements). This + // definition overrides any declared top-level security. To remove a top-level + // security declaration, an empty array can be used. + Security []*SecurityRequirement + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value + // Custom parameters such as HTTP request headers. + // See: https://swagger.io/docs/specification/2-0/describing-parameters/ + // and https://swagger.io/specification/v2/#parameter-object. + Parameters *Parameters +} + +func (b0 Operation_builder) Build() *Operation { + m0 := &Operation{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Tags = b.Tags + x.xxx_hidden_Summary = b.Summary + x.xxx_hidden_Description = b.Description + x.xxx_hidden_ExternalDocs = b.ExternalDocs + x.xxx_hidden_OperationId = b.OperationId + x.xxx_hidden_Consumes = b.Consumes + x.xxx_hidden_Produces = b.Produces + x.xxx_hidden_Responses = b.Responses + x.xxx_hidden_Schemes = b.Schemes + x.xxx_hidden_Deprecated = b.Deprecated + x.xxx_hidden_Security = &b.Security + x.xxx_hidden_Extensions = b.Extensions + x.xxx_hidden_Parameters = b.Parameters + return m0 +} + +// `Parameters` is a representation of OpenAPI v2 specification's parameters object. +// Note: This technically breaks compatibility with the OpenAPI 2 definition structure as we only +// allow header parameters to be set here since we do not want users specifying custom non-header +// parameters beyond those inferred from the Protobuf schema. +// See: https://swagger.io/specification/v2/#parameter-object +type Parameters struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Headers *[]*HeaderParameter `protobuf:"bytes,1,rep,name=headers,proto3" json:"headers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Parameters) Reset() { + *x = Parameters{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Parameters) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Parameters) ProtoMessage() {} + +func (x *Parameters) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Parameters) GetHeaders() []*HeaderParameter { + if x != nil { + if x.xxx_hidden_Headers != nil { + return *x.xxx_hidden_Headers + } + } + return nil +} + +func (x *Parameters) SetHeaders(v []*HeaderParameter) { + x.xxx_hidden_Headers = &v +} + +type Parameters_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // `Headers` is one or more HTTP header parameter. + // See: https://swagger.io/docs/specification/2-0/describing-parameters/#header-parameters + Headers []*HeaderParameter +} + +func (b0 Parameters_builder) Build() *Parameters { + m0 := &Parameters{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Headers = &b.Headers + return m0 +} + +// `HeaderParameter` a HTTP header parameter. +// See: https://swagger.io/specification/v2/#parameter-object +type HeaderParameter struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + xxx_hidden_Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_Type HeaderParameter_Type `protobuf:"varint,3,opt,name=type,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter_Type" json:"type,omitempty"` + xxx_hidden_Format string `protobuf:"bytes,4,opt,name=format,proto3" json:"format,omitempty"` + xxx_hidden_Required bool `protobuf:"varint,5,opt,name=required,proto3" json:"required,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *HeaderParameter) Reset() { + *x = HeaderParameter{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *HeaderParameter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeaderParameter) ProtoMessage() {} + +func (x *HeaderParameter) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *HeaderParameter) GetName() string { + if x != nil { + return x.xxx_hidden_Name + } + return "" +} + +func (x *HeaderParameter) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *HeaderParameter) GetType() HeaderParameter_Type { + if x != nil { + return x.xxx_hidden_Type + } + return HeaderParameter_UNKNOWN +} + +func (x *HeaderParameter) GetFormat() string { + if x != nil { + return x.xxx_hidden_Format + } + return "" +} + +func (x *HeaderParameter) GetRequired() bool { + if x != nil { + return x.xxx_hidden_Required + } + return false +} + +func (x *HeaderParameter) SetName(v string) { + x.xxx_hidden_Name = v +} + +func (x *HeaderParameter) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *HeaderParameter) SetType(v HeaderParameter_Type) { + x.xxx_hidden_Type = v +} + +func (x *HeaderParameter) SetFormat(v string) { + x.xxx_hidden_Format = v +} + +func (x *HeaderParameter) SetRequired(v bool) { + x.xxx_hidden_Required = v +} + +type HeaderParameter_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // `Name` is the header name. + Name string + // `Description` is a short description of the header. + Description string + // `Type` is the type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported. + // See: https://swagger.io/specification/v2/#parameterType. + Type HeaderParameter_Type + // `Format` The extending format for the previously mentioned type. + Format string + // `Required` indicates if the header is optional + Required bool +} + +func (b0 HeaderParameter_builder) Build() *HeaderParameter { + m0 := &HeaderParameter{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Name = b.Name + x.xxx_hidden_Description = b.Description + x.xxx_hidden_Type = b.Type + x.xxx_hidden_Format = b.Format + x.xxx_hidden_Required = b.Required + return m0 +} + +// `Header` is a representation of OpenAPI v2 specification's Header object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#headerObject +type Header struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` + xxx_hidden_Format string `protobuf:"bytes,3,opt,name=format,proto3" json:"format,omitempty"` + xxx_hidden_Default string `protobuf:"bytes,6,opt,name=default,proto3" json:"default,omitempty"` + xxx_hidden_Pattern string `protobuf:"bytes,13,opt,name=pattern,proto3" json:"pattern,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Header) Reset() { + *x = Header{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Header) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Header) ProtoMessage() {} + +func (x *Header) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Header) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *Header) GetType() string { + if x != nil { + return x.xxx_hidden_Type + } + return "" +} + +func (x *Header) GetFormat() string { + if x != nil { + return x.xxx_hidden_Format + } + return "" +} + +func (x *Header) GetDefault() string { + if x != nil { + return x.xxx_hidden_Default + } + return "" +} + +func (x *Header) GetPattern() string { + if x != nil { + return x.xxx_hidden_Pattern + } + return "" +} + +func (x *Header) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *Header) SetType(v string) { + x.xxx_hidden_Type = v +} + +func (x *Header) SetFormat(v string) { + x.xxx_hidden_Format = v +} + +func (x *Header) SetDefault(v string) { + x.xxx_hidden_Default = v +} + +func (x *Header) SetPattern(v string) { + x.xxx_hidden_Pattern = v +} + +type Header_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // `Description` is a short description of the header. + Description string + // The type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported. + Type string + // `Format` The extending format for the previously mentioned type. + Format string + // `Default` Declares the value of the header that the server will use if none is provided. + // See: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2. + // Unlike JSON Schema this value MUST conform to the defined type for the header. + Default string + // 'Pattern' See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3. + Pattern string +} + +func (b0 Header_builder) Build() *Header { + m0 := &Header{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Description = b.Description + x.xxx_hidden_Type = b.Type + x.xxx_hidden_Format = b.Format + x.xxx_hidden_Default = b.Default + x.xxx_hidden_Pattern = b.Pattern + return m0 +} + +// `Response` is a representation of OpenAPI v2 specification's Response object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#responseObject +type Response struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_Schema *Schema `protobuf:"bytes,2,opt,name=schema,proto3" json:"schema,omitempty"` + xxx_hidden_Headers map[string]*Header `protobuf:"bytes,3,rep,name=headers,proto3" json:"headers,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + xxx_hidden_Examples map[string]string `protobuf:"bytes,4,rep,name=examples,proto3" json:"examples,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + xxx_hidden_Extensions map[string]*structpb.Value `protobuf:"bytes,5,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Response) Reset() { + *x = Response{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Response) ProtoMessage() {} + +func (x *Response) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Response) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *Response) GetSchema() *Schema { + if x != nil { + return x.xxx_hidden_Schema + } + return nil +} + +func (x *Response) GetHeaders() map[string]*Header { + if x != nil { + return x.xxx_hidden_Headers + } + return nil +} + +func (x *Response) GetExamples() map[string]string { + if x != nil { + return x.xxx_hidden_Examples + } + return nil +} + +func (x *Response) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.xxx_hidden_Extensions + } + return nil +} + +func (x *Response) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *Response) SetSchema(v *Schema) { + x.xxx_hidden_Schema = v +} + +func (x *Response) SetHeaders(v map[string]*Header) { + x.xxx_hidden_Headers = v +} + +func (x *Response) SetExamples(v map[string]string) { + x.xxx_hidden_Examples = v +} + +func (x *Response) SetExtensions(v map[string]*structpb.Value) { + x.xxx_hidden_Extensions = v +} + +func (x *Response) HasSchema() bool { + if x == nil { + return false + } + return x.xxx_hidden_Schema != nil +} + +func (x *Response) ClearSchema() { + x.xxx_hidden_Schema = nil +} + +type Response_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // `Description` is a short description of the response. + // GFM syntax can be used for rich text representation. + Description string + // `Schema` optionally defines the structure of the response. + // If `Schema` is not provided, it means there is no content to the response. + Schema *Schema + // `Headers` A list of headers that are sent with the response. + // `Header` name is expected to be a string in the canonical format of the MIME header key + // See: https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey + Headers map[string]*Header + // `Examples` gives per-mimetype response examples. + // See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#example-object + Examples map[string]string + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 Response_builder) Build() *Response { + m0 := &Response{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Description = b.Description + x.xxx_hidden_Schema = b.Schema + x.xxx_hidden_Headers = b.Headers + x.xxx_hidden_Examples = b.Examples + x.xxx_hidden_Extensions = b.Extensions + return m0 +} + +// `Info` is a representation of OpenAPI v2 specification's Info object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#infoObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// title: "Echo API"; +// version: "1.0"; +// description: ""; +// contact: { +// name: "gRPC-Gateway project"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// email: "none@example.com"; +// }; +// license: { +// name: "BSD 3-Clause License"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; +// }; +// }; +// ... +// }; +type Info struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + xxx_hidden_Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_TermsOfService string `protobuf:"bytes,3,opt,name=terms_of_service,json=termsOfService,proto3" json:"terms_of_service,omitempty"` + xxx_hidden_Contact *Contact `protobuf:"bytes,4,opt,name=contact,proto3" json:"contact,omitempty"` + xxx_hidden_License *License `protobuf:"bytes,5,opt,name=license,proto3" json:"license,omitempty"` + xxx_hidden_Version string `protobuf:"bytes,6,opt,name=version,proto3" json:"version,omitempty"` + xxx_hidden_Extensions map[string]*structpb.Value `protobuf:"bytes,7,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Info) Reset() { + *x = Info{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Info) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Info) ProtoMessage() {} + +func (x *Info) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Info) GetTitle() string { + if x != nil { + return x.xxx_hidden_Title + } + return "" +} + +func (x *Info) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *Info) GetTermsOfService() string { + if x != nil { + return x.xxx_hidden_TermsOfService + } + return "" +} + +func (x *Info) GetContact() *Contact { + if x != nil { + return x.xxx_hidden_Contact + } + return nil +} + +func (x *Info) GetLicense() *License { + if x != nil { + return x.xxx_hidden_License + } + return nil +} + +func (x *Info) GetVersion() string { + if x != nil { + return x.xxx_hidden_Version + } + return "" +} + +func (x *Info) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.xxx_hidden_Extensions + } + return nil +} + +func (x *Info) SetTitle(v string) { + x.xxx_hidden_Title = v +} + +func (x *Info) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *Info) SetTermsOfService(v string) { + x.xxx_hidden_TermsOfService = v +} + +func (x *Info) SetContact(v *Contact) { + x.xxx_hidden_Contact = v +} + +func (x *Info) SetLicense(v *License) { + x.xxx_hidden_License = v +} + +func (x *Info) SetVersion(v string) { + x.xxx_hidden_Version = v +} + +func (x *Info) SetExtensions(v map[string]*structpb.Value) { + x.xxx_hidden_Extensions = v +} + +func (x *Info) HasContact() bool { + if x == nil { + return false + } + return x.xxx_hidden_Contact != nil +} + +func (x *Info) HasLicense() bool { + if x == nil { + return false + } + return x.xxx_hidden_License != nil +} + +func (x *Info) ClearContact() { + x.xxx_hidden_Contact = nil +} + +func (x *Info) ClearLicense() { + x.xxx_hidden_License = nil +} + +type Info_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The title of the application. + Title string + // A short description of the application. GFM syntax can be used for rich + // text representation. + Description string + // The Terms of Service for the API. + TermsOfService string + // The contact information for the exposed API. + Contact *Contact + // The license information for the exposed API. + License *License + // Provides the version of the application API (not to be confused + // with the specification version). + Version string + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 Info_builder) Build() *Info { + m0 := &Info{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Title = b.Title + x.xxx_hidden_Description = b.Description + x.xxx_hidden_TermsOfService = b.TermsOfService + x.xxx_hidden_Contact = b.Contact + x.xxx_hidden_License = b.License + x.xxx_hidden_Version = b.Version + x.xxx_hidden_Extensions = b.Extensions + return m0 +} + +// `Contact` is a representation of OpenAPI v2 specification's Contact object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#contactObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// ... +// contact: { +// name: "gRPC-Gateway project"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// email: "none@example.com"; +// }; +// ... +// }; +// ... +// }; +type Contact struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + xxx_hidden_Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + xxx_hidden_Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Contact) Reset() { + *x = Contact{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Contact) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Contact) ProtoMessage() {} + +func (x *Contact) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Contact) GetName() string { + if x != nil { + return x.xxx_hidden_Name + } + return "" +} + +func (x *Contact) GetUrl() string { + if x != nil { + return x.xxx_hidden_Url + } + return "" +} + +func (x *Contact) GetEmail() string { + if x != nil { + return x.xxx_hidden_Email + } + return "" +} + +func (x *Contact) SetName(v string) { + x.xxx_hidden_Name = v +} + +func (x *Contact) SetUrl(v string) { + x.xxx_hidden_Url = v +} + +func (x *Contact) SetEmail(v string) { + x.xxx_hidden_Email = v +} + +type Contact_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The identifying name of the contact person/organization. + Name string + // The URL pointing to the contact information. MUST be in the format of a + // URL. + Url string + // The email address of the contact person/organization. MUST be in the format + // of an email address. + Email string +} + +func (b0 Contact_builder) Build() *Contact { + m0 := &Contact{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Name = b.Name + x.xxx_hidden_Url = b.Url + x.xxx_hidden_Email = b.Email + return m0 +} + +// `License` is a representation of OpenAPI v2 specification's License object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#licenseObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// info: { +// ... +// license: { +// name: "BSD 3-Clause License"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"; +// }; +// ... +// }; +// ... +// }; +type License struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + xxx_hidden_Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *License) Reset() { + *x = License{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *License) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*License) ProtoMessage() {} + +func (x *License) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *License) GetName() string { + if x != nil { + return x.xxx_hidden_Name + } + return "" +} + +func (x *License) GetUrl() string { + if x != nil { + return x.xxx_hidden_Url + } + return "" +} + +func (x *License) SetName(v string) { + x.xxx_hidden_Name = v +} + +func (x *License) SetUrl(v string) { + x.xxx_hidden_Url = v +} + +type License_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The license name used for the API. + Name string + // A URL to the license used for the API. MUST be in the format of a URL. + Url string +} + +func (b0 License_builder) Build() *License { + m0 := &License{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Name = b.Name + x.xxx_hidden_Url = b.Url + return m0 +} + +// `ExternalDocumentation` is a representation of OpenAPI v2 specification's +// ExternalDocumentation object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#externalDocumentationObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { +// ... +// external_docs: { +// description: "More about gRPC-Gateway"; +// url: "https://github.com/grpc-ecosystem/grpc-gateway"; +// } +// ... +// }; +type ExternalDocumentation struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExternalDocumentation) Reset() { + *x = ExternalDocumentation{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExternalDocumentation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExternalDocumentation) ProtoMessage() {} + +func (x *ExternalDocumentation) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *ExternalDocumentation) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *ExternalDocumentation) GetUrl() string { + if x != nil { + return x.xxx_hidden_Url + } + return "" +} + +func (x *ExternalDocumentation) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *ExternalDocumentation) SetUrl(v string) { + x.xxx_hidden_Url = v +} + +type ExternalDocumentation_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // A short description of the target documentation. GFM syntax can be used for + // rich text representation. + Description string + // The URL for the target documentation. Value MUST be in the format + // of a URL. + Url string +} + +func (b0 ExternalDocumentation_builder) Build() *ExternalDocumentation { + m0 := &ExternalDocumentation{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Description = b.Description + x.xxx_hidden_Url = b.Url + return m0 +} + +// `Schema` is a representation of OpenAPI v2 specification's Schema object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject +type Schema struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_JsonSchema *JSONSchema `protobuf:"bytes,1,opt,name=json_schema,json=jsonSchema,proto3" json:"json_schema,omitempty"` + xxx_hidden_Discriminator string `protobuf:"bytes,2,opt,name=discriminator,proto3" json:"discriminator,omitempty"` + xxx_hidden_ReadOnly bool `protobuf:"varint,3,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` + xxx_hidden_ExternalDocs *ExternalDocumentation `protobuf:"bytes,5,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + xxx_hidden_Example string `protobuf:"bytes,6,opt,name=example,proto3" json:"example,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Schema) Reset() { + *x = Schema{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Schema) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Schema) ProtoMessage() {} + +func (x *Schema) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Schema) GetJsonSchema() *JSONSchema { + if x != nil { + return x.xxx_hidden_JsonSchema + } + return nil +} + +func (x *Schema) GetDiscriminator() string { + if x != nil { + return x.xxx_hidden_Discriminator + } + return "" +} + +func (x *Schema) GetReadOnly() bool { + if x != nil { + return x.xxx_hidden_ReadOnly + } + return false +} + +func (x *Schema) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.xxx_hidden_ExternalDocs + } + return nil +} + +func (x *Schema) GetExample() string { + if x != nil { + return x.xxx_hidden_Example + } + return "" +} + +func (x *Schema) SetJsonSchema(v *JSONSchema) { + x.xxx_hidden_JsonSchema = v +} + +func (x *Schema) SetDiscriminator(v string) { + x.xxx_hidden_Discriminator = v +} + +func (x *Schema) SetReadOnly(v bool) { + x.xxx_hidden_ReadOnly = v +} + +func (x *Schema) SetExternalDocs(v *ExternalDocumentation) { + x.xxx_hidden_ExternalDocs = v +} + +func (x *Schema) SetExample(v string) { + x.xxx_hidden_Example = v +} + +func (x *Schema) HasJsonSchema() bool { + if x == nil { + return false + } + return x.xxx_hidden_JsonSchema != nil +} + +func (x *Schema) HasExternalDocs() bool { + if x == nil { + return false + } + return x.xxx_hidden_ExternalDocs != nil +} + +func (x *Schema) ClearJsonSchema() { + x.xxx_hidden_JsonSchema = nil +} + +func (x *Schema) ClearExternalDocs() { + x.xxx_hidden_ExternalDocs = nil +} + +type Schema_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + JsonSchema *JSONSchema + // Adds support for polymorphism. The discriminator is the schema property + // name that is used to differentiate between other schema that inherit this + // schema. The property name used MUST be defined at this schema and it MUST + // be in the required property list. When used, the value MUST be the name of + // this schema or any schema that inherits it. + Discriminator string + // Relevant only for Schema "properties" definitions. Declares the property as + // "read only". This means that it MAY be sent as part of a response but MUST + // NOT be sent as part of the request. Properties marked as readOnly being + // true SHOULD NOT be in the required list of the defined schema. Default + // value is false. + ReadOnly bool + // Additional external documentation for this schema. + ExternalDocs *ExternalDocumentation + // A free-form property to include an example of an instance for this schema in JSON. + // This is copied verbatim to the output. + Example string +} + +func (b0 Schema_builder) Build() *Schema { + m0 := &Schema{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_JsonSchema = b.JsonSchema + x.xxx_hidden_Discriminator = b.Discriminator + x.xxx_hidden_ReadOnly = b.ReadOnly + x.xxx_hidden_ExternalDocs = b.ExternalDocs + x.xxx_hidden_Example = b.Example + return m0 +} + +// `EnumSchema` is subset of fields from the OpenAPI v2 specification's Schema object. +// Only fields that are applicable to Enums are included +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject +// +// Example: +// +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum) = { +// ... +// title: "MyEnum"; +// description:"This is my nice enum"; +// example: "ZERO"; +// required: true; +// ... +// }; +type EnumSchema struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Description string `protobuf:"bytes,1,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_Default string `protobuf:"bytes,2,opt,name=default,proto3" json:"default,omitempty"` + xxx_hidden_Title string `protobuf:"bytes,3,opt,name=title,proto3" json:"title,omitempty"` + xxx_hidden_Required bool `protobuf:"varint,4,opt,name=required,proto3" json:"required,omitempty"` + xxx_hidden_ReadOnly bool `protobuf:"varint,5,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` + xxx_hidden_ExternalDocs *ExternalDocumentation `protobuf:"bytes,6,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + xxx_hidden_Example string `protobuf:"bytes,7,opt,name=example,proto3" json:"example,omitempty"` + xxx_hidden_Ref string `protobuf:"bytes,8,opt,name=ref,proto3" json:"ref,omitempty"` + xxx_hidden_Extensions map[string]*structpb.Value `protobuf:"bytes,9,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EnumSchema) Reset() { + *x = EnumSchema{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EnumSchema) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EnumSchema) ProtoMessage() {} + +func (x *EnumSchema) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *EnumSchema) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *EnumSchema) GetDefault() string { + if x != nil { + return x.xxx_hidden_Default + } + return "" +} + +func (x *EnumSchema) GetTitle() string { + if x != nil { + return x.xxx_hidden_Title + } + return "" +} + +func (x *EnumSchema) GetRequired() bool { + if x != nil { + return x.xxx_hidden_Required + } + return false +} + +func (x *EnumSchema) GetReadOnly() bool { + if x != nil { + return x.xxx_hidden_ReadOnly + } + return false +} + +func (x *EnumSchema) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.xxx_hidden_ExternalDocs + } + return nil +} + +func (x *EnumSchema) GetExample() string { + if x != nil { + return x.xxx_hidden_Example + } + return "" +} + +func (x *EnumSchema) GetRef() string { + if x != nil { + return x.xxx_hidden_Ref + } + return "" +} + +func (x *EnumSchema) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.xxx_hidden_Extensions + } + return nil +} + +func (x *EnumSchema) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *EnumSchema) SetDefault(v string) { + x.xxx_hidden_Default = v +} + +func (x *EnumSchema) SetTitle(v string) { + x.xxx_hidden_Title = v +} + +func (x *EnumSchema) SetRequired(v bool) { + x.xxx_hidden_Required = v +} + +func (x *EnumSchema) SetReadOnly(v bool) { + x.xxx_hidden_ReadOnly = v +} + +func (x *EnumSchema) SetExternalDocs(v *ExternalDocumentation) { + x.xxx_hidden_ExternalDocs = v +} + +func (x *EnumSchema) SetExample(v string) { + x.xxx_hidden_Example = v +} + +func (x *EnumSchema) SetRef(v string) { + x.xxx_hidden_Ref = v +} + +func (x *EnumSchema) SetExtensions(v map[string]*structpb.Value) { + x.xxx_hidden_Extensions = v +} + +func (x *EnumSchema) HasExternalDocs() bool { + if x == nil { + return false + } + return x.xxx_hidden_ExternalDocs != nil +} + +func (x *EnumSchema) ClearExternalDocs() { + x.xxx_hidden_ExternalDocs = nil +} + +type EnumSchema_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // A short description of the schema. + Description string + Default string + // The title of the schema. + Title string + Required bool + ReadOnly bool + // Additional external documentation for this schema. + ExternalDocs *ExternalDocumentation + Example string + // Ref is used to define an external reference to include in the message. + // This could be a fully qualified proto message reference, and that type must + // be imported into the protofile. If no message is identified, the Ref will + // be used verbatim in the output. + // For example: + // + // `ref: ".google.protobuf.Timestamp"`. + Ref string + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 EnumSchema_builder) Build() *EnumSchema { + m0 := &EnumSchema{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Description = b.Description + x.xxx_hidden_Default = b.Default + x.xxx_hidden_Title = b.Title + x.xxx_hidden_Required = b.Required + x.xxx_hidden_ReadOnly = b.ReadOnly + x.xxx_hidden_ExternalDocs = b.ExternalDocs + x.xxx_hidden_Example = b.Example + x.xxx_hidden_Ref = b.Ref + x.xxx_hidden_Extensions = b.Extensions + return m0 +} + +// `JSONSchema` represents properties from JSON Schema taken, and as used, in +// the OpenAPI v2 spec. +// +// This includes changes made by OpenAPI v2. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject +// +// See also: https://cswr.github.io/JsonSchema/spec/basic_types/, +// https://github.com/json-schema-org/json-schema-spec/blob/master/schema.json +// +// Example: +// +// message SimpleMessage { +// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { +// json_schema: { +// title: "SimpleMessage" +// description: "A simple message." +// required: ["id"] +// } +// }; +// +// // Id represents the message identifier. +// string id = 1; [ +// (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { +// description: "The unique identifier of the simple message." +// }]; +// } +type JSONSchema struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Ref string `protobuf:"bytes,3,opt,name=ref,proto3" json:"ref,omitempty"` + xxx_hidden_Title string `protobuf:"bytes,5,opt,name=title,proto3" json:"title,omitempty"` + xxx_hidden_Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_Default string `protobuf:"bytes,7,opt,name=default,proto3" json:"default,omitempty"` + xxx_hidden_ReadOnly bool `protobuf:"varint,8,opt,name=read_only,json=readOnly,proto3" json:"read_only,omitempty"` + xxx_hidden_Example string `protobuf:"bytes,9,opt,name=example,proto3" json:"example,omitempty"` + xxx_hidden_MultipleOf float64 `protobuf:"fixed64,10,opt,name=multiple_of,json=multipleOf,proto3" json:"multiple_of,omitempty"` + xxx_hidden_Maximum float64 `protobuf:"fixed64,11,opt,name=maximum,proto3" json:"maximum,omitempty"` + xxx_hidden_ExclusiveMaximum bool `protobuf:"varint,12,opt,name=exclusive_maximum,json=exclusiveMaximum,proto3" json:"exclusive_maximum,omitempty"` + xxx_hidden_Minimum float64 `protobuf:"fixed64,13,opt,name=minimum,proto3" json:"minimum,omitempty"` + xxx_hidden_ExclusiveMinimum bool `protobuf:"varint,14,opt,name=exclusive_minimum,json=exclusiveMinimum,proto3" json:"exclusive_minimum,omitempty"` + xxx_hidden_MaxLength uint64 `protobuf:"varint,15,opt,name=max_length,json=maxLength,proto3" json:"max_length,omitempty"` + xxx_hidden_MinLength uint64 `protobuf:"varint,16,opt,name=min_length,json=minLength,proto3" json:"min_length,omitempty"` + xxx_hidden_Pattern string `protobuf:"bytes,17,opt,name=pattern,proto3" json:"pattern,omitempty"` + xxx_hidden_MaxItems uint64 `protobuf:"varint,20,opt,name=max_items,json=maxItems,proto3" json:"max_items,omitempty"` + xxx_hidden_MinItems uint64 `protobuf:"varint,21,opt,name=min_items,json=minItems,proto3" json:"min_items,omitempty"` + xxx_hidden_UniqueItems bool `protobuf:"varint,22,opt,name=unique_items,json=uniqueItems,proto3" json:"unique_items,omitempty"` + xxx_hidden_MaxProperties uint64 `protobuf:"varint,24,opt,name=max_properties,json=maxProperties,proto3" json:"max_properties,omitempty"` + xxx_hidden_MinProperties uint64 `protobuf:"varint,25,opt,name=min_properties,json=minProperties,proto3" json:"min_properties,omitempty"` + xxx_hidden_Required []string `protobuf:"bytes,26,rep,name=required,proto3" json:"required,omitempty"` + xxx_hidden_Array []string `protobuf:"bytes,34,rep,name=array,proto3" json:"array,omitempty"` + xxx_hidden_Type []JSONSchema_JSONSchemaSimpleTypes `protobuf:"varint,35,rep,packed,name=type,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.JSONSchema_JSONSchemaSimpleTypes" json:"type,omitempty"` + xxx_hidden_Format string `protobuf:"bytes,36,opt,name=format,proto3" json:"format,omitempty"` + xxx_hidden_Enum []string `protobuf:"bytes,46,rep,name=enum,proto3" json:"enum,omitempty"` + xxx_hidden_FieldConfiguration *JSONSchema_FieldConfiguration `protobuf:"bytes,1001,opt,name=field_configuration,json=fieldConfiguration,proto3" json:"field_configuration,omitempty"` + xxx_hidden_Extensions map[string]*structpb.Value `protobuf:"bytes,48,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JSONSchema) Reset() { + *x = JSONSchema{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JSONSchema) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JSONSchema) ProtoMessage() {} + +func (x *JSONSchema) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *JSONSchema) GetRef() string { + if x != nil { + return x.xxx_hidden_Ref + } + return "" +} + +func (x *JSONSchema) GetTitle() string { + if x != nil { + return x.xxx_hidden_Title + } + return "" +} + +func (x *JSONSchema) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *JSONSchema) GetDefault() string { + if x != nil { + return x.xxx_hidden_Default + } + return "" +} + +func (x *JSONSchema) GetReadOnly() bool { + if x != nil { + return x.xxx_hidden_ReadOnly + } + return false +} + +func (x *JSONSchema) GetExample() string { + if x != nil { + return x.xxx_hidden_Example + } + return "" +} + +func (x *JSONSchema) GetMultipleOf() float64 { + if x != nil { + return x.xxx_hidden_MultipleOf + } + return 0 +} + +func (x *JSONSchema) GetMaximum() float64 { + if x != nil { + return x.xxx_hidden_Maximum + } + return 0 +} + +func (x *JSONSchema) GetExclusiveMaximum() bool { + if x != nil { + return x.xxx_hidden_ExclusiveMaximum + } + return false +} + +func (x *JSONSchema) GetMinimum() float64 { + if x != nil { + return x.xxx_hidden_Minimum + } + return 0 +} + +func (x *JSONSchema) GetExclusiveMinimum() bool { + if x != nil { + return x.xxx_hidden_ExclusiveMinimum + } + return false +} + +func (x *JSONSchema) GetMaxLength() uint64 { + if x != nil { + return x.xxx_hidden_MaxLength + } + return 0 +} + +func (x *JSONSchema) GetMinLength() uint64 { + if x != nil { + return x.xxx_hidden_MinLength + } + return 0 +} + +func (x *JSONSchema) GetPattern() string { + if x != nil { + return x.xxx_hidden_Pattern + } + return "" +} + +func (x *JSONSchema) GetMaxItems() uint64 { + if x != nil { + return x.xxx_hidden_MaxItems + } + return 0 +} + +func (x *JSONSchema) GetMinItems() uint64 { + if x != nil { + return x.xxx_hidden_MinItems + } + return 0 +} + +func (x *JSONSchema) GetUniqueItems() bool { + if x != nil { + return x.xxx_hidden_UniqueItems + } + return false +} + +func (x *JSONSchema) GetMaxProperties() uint64 { + if x != nil { + return x.xxx_hidden_MaxProperties + } + return 0 +} + +func (x *JSONSchema) GetMinProperties() uint64 { + if x != nil { + return x.xxx_hidden_MinProperties + } + return 0 +} + +func (x *JSONSchema) GetRequired() []string { + if x != nil { + return x.xxx_hidden_Required + } + return nil +} + +func (x *JSONSchema) GetArray() []string { + if x != nil { + return x.xxx_hidden_Array + } + return nil +} + +func (x *JSONSchema) GetType() []JSONSchema_JSONSchemaSimpleTypes { + if x != nil { + return x.xxx_hidden_Type + } + return nil +} + +func (x *JSONSchema) GetFormat() string { + if x != nil { + return x.xxx_hidden_Format + } + return "" +} + +func (x *JSONSchema) GetEnum() []string { + if x != nil { + return x.xxx_hidden_Enum + } + return nil +} + +func (x *JSONSchema) GetFieldConfiguration() *JSONSchema_FieldConfiguration { + if x != nil { + return x.xxx_hidden_FieldConfiguration + } + return nil +} + +func (x *JSONSchema) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.xxx_hidden_Extensions + } + return nil +} + +func (x *JSONSchema) SetRef(v string) { + x.xxx_hidden_Ref = v +} + +func (x *JSONSchema) SetTitle(v string) { + x.xxx_hidden_Title = v +} + +func (x *JSONSchema) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *JSONSchema) SetDefault(v string) { + x.xxx_hidden_Default = v +} + +func (x *JSONSchema) SetReadOnly(v bool) { + x.xxx_hidden_ReadOnly = v +} + +func (x *JSONSchema) SetExample(v string) { + x.xxx_hidden_Example = v +} + +func (x *JSONSchema) SetMultipleOf(v float64) { + x.xxx_hidden_MultipleOf = v +} + +func (x *JSONSchema) SetMaximum(v float64) { + x.xxx_hidden_Maximum = v +} + +func (x *JSONSchema) SetExclusiveMaximum(v bool) { + x.xxx_hidden_ExclusiveMaximum = v +} + +func (x *JSONSchema) SetMinimum(v float64) { + x.xxx_hidden_Minimum = v +} + +func (x *JSONSchema) SetExclusiveMinimum(v bool) { + x.xxx_hidden_ExclusiveMinimum = v +} + +func (x *JSONSchema) SetMaxLength(v uint64) { + x.xxx_hidden_MaxLength = v +} + +func (x *JSONSchema) SetMinLength(v uint64) { + x.xxx_hidden_MinLength = v +} + +func (x *JSONSchema) SetPattern(v string) { + x.xxx_hidden_Pattern = v +} + +func (x *JSONSchema) SetMaxItems(v uint64) { + x.xxx_hidden_MaxItems = v +} + +func (x *JSONSchema) SetMinItems(v uint64) { + x.xxx_hidden_MinItems = v +} + +func (x *JSONSchema) SetUniqueItems(v bool) { + x.xxx_hidden_UniqueItems = v +} + +func (x *JSONSchema) SetMaxProperties(v uint64) { + x.xxx_hidden_MaxProperties = v +} + +func (x *JSONSchema) SetMinProperties(v uint64) { + x.xxx_hidden_MinProperties = v +} + +func (x *JSONSchema) SetRequired(v []string) { + x.xxx_hidden_Required = v +} + +func (x *JSONSchema) SetArray(v []string) { + x.xxx_hidden_Array = v +} + +func (x *JSONSchema) SetType(v []JSONSchema_JSONSchemaSimpleTypes) { + x.xxx_hidden_Type = v +} + +func (x *JSONSchema) SetFormat(v string) { + x.xxx_hidden_Format = v +} + +func (x *JSONSchema) SetEnum(v []string) { + x.xxx_hidden_Enum = v +} + +func (x *JSONSchema) SetFieldConfiguration(v *JSONSchema_FieldConfiguration) { + x.xxx_hidden_FieldConfiguration = v +} + +func (x *JSONSchema) SetExtensions(v map[string]*structpb.Value) { + x.xxx_hidden_Extensions = v +} + +func (x *JSONSchema) HasFieldConfiguration() bool { + if x == nil { + return false + } + return x.xxx_hidden_FieldConfiguration != nil +} + +func (x *JSONSchema) ClearFieldConfiguration() { + x.xxx_hidden_FieldConfiguration = nil +} + +type JSONSchema_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Ref is used to define an external reference to include in the message. + // This could be a fully qualified proto message reference, and that type must + // be imported into the protofile. If no message is identified, the Ref will + // be used verbatim in the output. + // For example: + // + // `ref: ".google.protobuf.Timestamp"`. + Ref string + // The title of the schema. + Title string + // A short description of the schema. + Description string + Default string + ReadOnly bool + // A free-form property to include a JSON example of this field. This is copied + // verbatim to the output swagger.json. Quotes must be escaped. + // This property is the same for 2.0 and 3.0.0 https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#schemaObject https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject + Example string + MultipleOf float64 + // Maximum represents an inclusive upper limit for a numeric instance. The + // value of MUST be a number, + Maximum float64 + ExclusiveMaximum bool + // minimum represents an inclusive lower limit for a numeric instance. The + // value of MUST be a number, + Minimum float64 + ExclusiveMinimum bool + MaxLength uint64 + MinLength uint64 + Pattern string + MaxItems uint64 + MinItems uint64 + UniqueItems bool + MaxProperties uint64 + MinProperties uint64 + Required []string + // Items in 'array' must be unique. + Array []string + Type []JSONSchema_JSONSchemaSimpleTypes + // `Format` + Format string + // Items in `enum` must be unique https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1 + Enum []string + // Additional field level properties used when generating the OpenAPI v2 file. + FieldConfiguration *JSONSchema_FieldConfiguration + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 JSONSchema_builder) Build() *JSONSchema { + m0 := &JSONSchema{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Ref = b.Ref + x.xxx_hidden_Title = b.Title + x.xxx_hidden_Description = b.Description + x.xxx_hidden_Default = b.Default + x.xxx_hidden_ReadOnly = b.ReadOnly + x.xxx_hidden_Example = b.Example + x.xxx_hidden_MultipleOf = b.MultipleOf + x.xxx_hidden_Maximum = b.Maximum + x.xxx_hidden_ExclusiveMaximum = b.ExclusiveMaximum + x.xxx_hidden_Minimum = b.Minimum + x.xxx_hidden_ExclusiveMinimum = b.ExclusiveMinimum + x.xxx_hidden_MaxLength = b.MaxLength + x.xxx_hidden_MinLength = b.MinLength + x.xxx_hidden_Pattern = b.Pattern + x.xxx_hidden_MaxItems = b.MaxItems + x.xxx_hidden_MinItems = b.MinItems + x.xxx_hidden_UniqueItems = b.UniqueItems + x.xxx_hidden_MaxProperties = b.MaxProperties + x.xxx_hidden_MinProperties = b.MinProperties + x.xxx_hidden_Required = b.Required + x.xxx_hidden_Array = b.Array + x.xxx_hidden_Type = b.Type + x.xxx_hidden_Format = b.Format + x.xxx_hidden_Enum = b.Enum + x.xxx_hidden_FieldConfiguration = b.FieldConfiguration + x.xxx_hidden_Extensions = b.Extensions + return m0 +} + +// `Tag` is a representation of OpenAPI v2 specification's Tag object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#tagObject +type Tag struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + xxx_hidden_Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_ExternalDocs *ExternalDocumentation `protobuf:"bytes,3,opt,name=external_docs,json=externalDocs,proto3" json:"external_docs,omitempty"` + xxx_hidden_Extensions map[string]*structpb.Value `protobuf:"bytes,4,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Tag) Reset() { + *x = Tag{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Tag) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Tag) ProtoMessage() {} + +func (x *Tag) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Tag) GetName() string { + if x != nil { + return x.xxx_hidden_Name + } + return "" +} + +func (x *Tag) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *Tag) GetExternalDocs() *ExternalDocumentation { + if x != nil { + return x.xxx_hidden_ExternalDocs + } + return nil +} + +func (x *Tag) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.xxx_hidden_Extensions + } + return nil +} + +func (x *Tag) SetName(v string) { + x.xxx_hidden_Name = v +} + +func (x *Tag) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *Tag) SetExternalDocs(v *ExternalDocumentation) { + x.xxx_hidden_ExternalDocs = v +} + +func (x *Tag) SetExtensions(v map[string]*structpb.Value) { + x.xxx_hidden_Extensions = v +} + +func (x *Tag) HasExternalDocs() bool { + if x == nil { + return false + } + return x.xxx_hidden_ExternalDocs != nil +} + +func (x *Tag) ClearExternalDocs() { + x.xxx_hidden_ExternalDocs = nil +} + +type Tag_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The name of the tag. Use it to allow override of the name of a + // global Tag object, then use that name to reference the tag throughout the + // OpenAPI file. + Name string + // A short description for the tag. GFM syntax can be used for rich text + // representation. + Description string + // Additional external documentation for this tag. + ExternalDocs *ExternalDocumentation + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 Tag_builder) Build() *Tag { + m0 := &Tag{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Name = b.Name + x.xxx_hidden_Description = b.Description + x.xxx_hidden_ExternalDocs = b.ExternalDocs + x.xxx_hidden_Extensions = b.Extensions + return m0 +} + +// `SecurityDefinitions` is a representation of OpenAPI v2 specification's +// Security Definitions object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityDefinitionsObject +// +// A declaration of the security schemes available to be used in the +// specification. This does not enforce the security schemes on the operations +// and only serves to provide the relevant details for each scheme. +type SecurityDefinitions struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Security map[string]*SecurityScheme `protobuf:"bytes,1,rep,name=security,proto3" json:"security,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecurityDefinitions) Reset() { + *x = SecurityDefinitions{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecurityDefinitions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecurityDefinitions) ProtoMessage() {} + +func (x *SecurityDefinitions) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *SecurityDefinitions) GetSecurity() map[string]*SecurityScheme { + if x != nil { + return x.xxx_hidden_Security + } + return nil +} + +func (x *SecurityDefinitions) SetSecurity(v map[string]*SecurityScheme) { + x.xxx_hidden_Security = v +} + +type SecurityDefinitions_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // A single security scheme definition, mapping a "name" to the scheme it + // defines. + Security map[string]*SecurityScheme +} + +func (b0 SecurityDefinitions_builder) Build() *SecurityDefinitions { + m0 := &SecurityDefinitions{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Security = b.Security + return m0 +} + +// `SecurityScheme` is a representation of OpenAPI v2 specification's +// Security Scheme object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securitySchemeObject +// +// Allows the definition of a security scheme that can be used by the +// operations. Supported schemes are basic authentication, an API key (either as +// a header or as a query parameter) and OAuth2's common flows (implicit, +// password, application and access code). +type SecurityScheme struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Type SecurityScheme_Type `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme_Type" json:"type,omitempty"` + xxx_hidden_Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + xxx_hidden_Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + xxx_hidden_In SecurityScheme_In `protobuf:"varint,4,opt,name=in,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme_In" json:"in,omitempty"` + xxx_hidden_Flow SecurityScheme_Flow `protobuf:"varint,5,opt,name=flow,proto3,enum=grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme_Flow" json:"flow,omitempty"` + xxx_hidden_AuthorizationUrl string `protobuf:"bytes,6,opt,name=authorization_url,json=authorizationUrl,proto3" json:"authorization_url,omitempty"` + xxx_hidden_TokenUrl string `protobuf:"bytes,7,opt,name=token_url,json=tokenUrl,proto3" json:"token_url,omitempty"` + xxx_hidden_Scopes *Scopes `protobuf:"bytes,8,opt,name=scopes,proto3" json:"scopes,omitempty"` + xxx_hidden_Extensions map[string]*structpb.Value `protobuf:"bytes,9,rep,name=extensions,proto3" json:"extensions,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecurityScheme) Reset() { + *x = SecurityScheme{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecurityScheme) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecurityScheme) ProtoMessage() {} + +func (x *SecurityScheme) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *SecurityScheme) GetType() SecurityScheme_Type { + if x != nil { + return x.xxx_hidden_Type + } + return SecurityScheme_TYPE_INVALID +} + +func (x *SecurityScheme) GetDescription() string { + if x != nil { + return x.xxx_hidden_Description + } + return "" +} + +func (x *SecurityScheme) GetName() string { + if x != nil { + return x.xxx_hidden_Name + } + return "" +} + +func (x *SecurityScheme) GetIn() SecurityScheme_In { + if x != nil { + return x.xxx_hidden_In + } + return SecurityScheme_IN_INVALID +} + +func (x *SecurityScheme) GetFlow() SecurityScheme_Flow { + if x != nil { + return x.xxx_hidden_Flow + } + return SecurityScheme_FLOW_INVALID +} + +func (x *SecurityScheme) GetAuthorizationUrl() string { + if x != nil { + return x.xxx_hidden_AuthorizationUrl + } + return "" +} + +func (x *SecurityScheme) GetTokenUrl() string { + if x != nil { + return x.xxx_hidden_TokenUrl + } + return "" +} + +func (x *SecurityScheme) GetScopes() *Scopes { + if x != nil { + return x.xxx_hidden_Scopes + } + return nil +} + +func (x *SecurityScheme) GetExtensions() map[string]*structpb.Value { + if x != nil { + return x.xxx_hidden_Extensions + } + return nil +} + +func (x *SecurityScheme) SetType(v SecurityScheme_Type) { + x.xxx_hidden_Type = v +} + +func (x *SecurityScheme) SetDescription(v string) { + x.xxx_hidden_Description = v +} + +func (x *SecurityScheme) SetName(v string) { + x.xxx_hidden_Name = v +} + +func (x *SecurityScheme) SetIn(v SecurityScheme_In) { + x.xxx_hidden_In = v +} + +func (x *SecurityScheme) SetFlow(v SecurityScheme_Flow) { + x.xxx_hidden_Flow = v +} + +func (x *SecurityScheme) SetAuthorizationUrl(v string) { + x.xxx_hidden_AuthorizationUrl = v +} + +func (x *SecurityScheme) SetTokenUrl(v string) { + x.xxx_hidden_TokenUrl = v +} + +func (x *SecurityScheme) SetScopes(v *Scopes) { + x.xxx_hidden_Scopes = v +} + +func (x *SecurityScheme) SetExtensions(v map[string]*structpb.Value) { + x.xxx_hidden_Extensions = v +} + +func (x *SecurityScheme) HasScopes() bool { + if x == nil { + return false + } + return x.xxx_hidden_Scopes != nil +} + +func (x *SecurityScheme) ClearScopes() { + x.xxx_hidden_Scopes = nil +} + +type SecurityScheme_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // The type of the security scheme. Valid values are "basic", + // "apiKey" or "oauth2". + Type SecurityScheme_Type + // A short description for security scheme. + Description string + // The name of the header or query parameter to be used. + // Valid for apiKey. + Name string + // The location of the API key. Valid values are "query" or + // "header". + // Valid for apiKey. + In SecurityScheme_In + // The flow used by the OAuth2 security scheme. Valid values are + // "implicit", "password", "application" or "accessCode". + // Valid for oauth2. + Flow SecurityScheme_Flow + // The authorization URL to be used for this flow. This SHOULD be in + // the form of a URL. + // Valid for oauth2/implicit and oauth2/accessCode. + AuthorizationUrl string + // The token URL to be used for this flow. This SHOULD be in the + // form of a URL. + // Valid for oauth2/password, oauth2/application and oauth2/accessCode. + TokenUrl string + // The available scopes for the OAuth2 security scheme. + // Valid for oauth2. + Scopes *Scopes + // Custom properties that start with "x-" such as "x-foo" used to describe + // extra functionality that is not covered by the standard OpenAPI Specification. + // See: https://swagger.io/docs/specification/2-0/swagger-extensions/ + Extensions map[string]*structpb.Value +} + +func (b0 SecurityScheme_builder) Build() *SecurityScheme { + m0 := &SecurityScheme{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Type = b.Type + x.xxx_hidden_Description = b.Description + x.xxx_hidden_Name = b.Name + x.xxx_hidden_In = b.In + x.xxx_hidden_Flow = b.Flow + x.xxx_hidden_AuthorizationUrl = b.AuthorizationUrl + x.xxx_hidden_TokenUrl = b.TokenUrl + x.xxx_hidden_Scopes = b.Scopes + x.xxx_hidden_Extensions = b.Extensions + return m0 +} + +// `SecurityRequirement` is a representation of OpenAPI v2 specification's +// Security Requirement object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityRequirementObject +// +// Lists the required security schemes to execute this operation. The object can +// have multiple security schemes declared in it which are all required (that +// is, there is a logical AND between the schemes). +// +// The name used for each property MUST correspond to a security scheme +// declared in the Security Definitions. +type SecurityRequirement struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_SecurityRequirement map[string]*SecurityRequirement_SecurityRequirementValue `protobuf:"bytes,1,rep,name=security_requirement,json=securityRequirement,proto3" json:"security_requirement,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecurityRequirement) Reset() { + *x = SecurityRequirement{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecurityRequirement) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecurityRequirement) ProtoMessage() {} + +func (x *SecurityRequirement) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *SecurityRequirement) GetSecurityRequirement() map[string]*SecurityRequirement_SecurityRequirementValue { + if x != nil { + return x.xxx_hidden_SecurityRequirement + } + return nil +} + +func (x *SecurityRequirement) SetSecurityRequirement(v map[string]*SecurityRequirement_SecurityRequirementValue) { + x.xxx_hidden_SecurityRequirement = v +} + +type SecurityRequirement_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Each name must correspond to a security scheme which is declared in + // the Security Definitions. If the security scheme is of type "oauth2", + // then the value is a list of scope names required for the execution. + // For other security scheme types, the array MUST be empty. + SecurityRequirement map[string]*SecurityRequirement_SecurityRequirementValue +} + +func (b0 SecurityRequirement_builder) Build() *SecurityRequirement { + m0 := &SecurityRequirement{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_SecurityRequirement = b.SecurityRequirement + return m0 +} + +// `Scopes` is a representation of OpenAPI v2 specification's Scopes object. +// +// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#scopesObject +// +// Lists the available scopes for an OAuth2 security scheme. +type Scopes struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Scope map[string]string `protobuf:"bytes,1,rep,name=scope,proto3" json:"scope,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Scopes) Reset() { + *x = Scopes{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Scopes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Scopes) ProtoMessage() {} + +func (x *Scopes) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *Scopes) GetScope() map[string]string { + if x != nil { + return x.xxx_hidden_Scope + } + return nil +} + +func (x *Scopes) SetScope(v map[string]string) { + x.xxx_hidden_Scope = v +} + +type Scopes_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Maps between a name of a scope to a short description of it (as the value + // of the property). + Scope map[string]string +} + +func (b0 Scopes_builder) Build() *Scopes { + m0 := &Scopes{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Scope = b.Scope + return m0 +} + +// 'FieldConfiguration' provides additional field level properties used when generating the OpenAPI v2 file. +// These properties are not defined by OpenAPIv2, but they are used to control the generation. +type JSONSchema_FieldConfiguration struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_PathParamName string `protobuf:"bytes,47,opt,name=path_param_name,json=pathParamName,proto3" json:"path_param_name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *JSONSchema_FieldConfiguration) Reset() { + *x = JSONSchema_FieldConfiguration{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[27] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *JSONSchema_FieldConfiguration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*JSONSchema_FieldConfiguration) ProtoMessage() {} + +func (x *JSONSchema_FieldConfiguration) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[27] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *JSONSchema_FieldConfiguration) GetPathParamName() string { + if x != nil { + return x.xxx_hidden_PathParamName + } + return "" +} + +func (x *JSONSchema_FieldConfiguration) SetPathParamName(v string) { + x.xxx_hidden_PathParamName = v +} + +type JSONSchema_FieldConfiguration_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + // Alternative parameter name when used as path parameter. If set, this will + // be used as the complete parameter name when this field is used as a path + // parameter. Use this to avoid having auto generated path parameter names + // for overlapping paths. + PathParamName string +} + +func (b0 JSONSchema_FieldConfiguration_builder) Build() *JSONSchema_FieldConfiguration { + m0 := &JSONSchema_FieldConfiguration{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_PathParamName = b.PathParamName + return m0 +} + +// If the security scheme is of type "oauth2", then the value is a list of +// scope names required for the execution. For other security scheme types, +// the array MUST be empty. +type SecurityRequirement_SecurityRequirementValue struct { + state protoimpl.MessageState `protogen:"opaque.v1"` + xxx_hidden_Scope []string `protobuf:"bytes,1,rep,name=scope,proto3" json:"scope,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SecurityRequirement_SecurityRequirementValue) Reset() { + *x = SecurityRequirement_SecurityRequirementValue{} + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SecurityRequirement_SecurityRequirementValue) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SecurityRequirement_SecurityRequirementValue) ProtoMessage() {} + +func (x *SecurityRequirement_SecurityRequirementValue) ProtoReflect() protoreflect.Message { + mi := &file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes[32] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (x *SecurityRequirement_SecurityRequirementValue) GetScope() []string { + if x != nil { + return x.xxx_hidden_Scope + } + return nil +} + +func (x *SecurityRequirement_SecurityRequirementValue) SetScope(v []string) { + x.xxx_hidden_Scope = v +} + +type SecurityRequirement_SecurityRequirementValue_builder struct { + _ [0]func() // Prevents comparability and use of unkeyed literals for the builder. + + Scope []string +} + +func (b0 SecurityRequirement_SecurityRequirementValue_builder) Build() *SecurityRequirement_SecurityRequirementValue { + m0 := &SecurityRequirement_SecurityRequirementValue{} + b, x := &b0, m0 + _, _ = b, x + x.xxx_hidden_Scope = b.Scope + return m0 +} + +var File_protoc_gen_openapiv2_options_openapiv2_proto protoreflect.FileDescriptor + +var file_protoc_gen_openapiv2_options_openapiv2_proto_rawDesc = []byte{ + 0x0a, 0x2c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x29, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, + 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb3, 0x08, 0x0a, 0x07, 0x53, 0x77, 0x61, 0x67, + 0x67, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x12, 0x43, 0x0a, + 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x69, 0x6e, + 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x70, + 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x73, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x4b, 0x0a, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0e, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x52, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x73, 0x12, 0x5f, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, + 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x71, 0x0a, 0x14, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x44, 0x65, 0x66, 0x69, + 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x13, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x08, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, + 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, + 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x54, 0x61, 0x67, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x65, 0x0a, 0x0d, + 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, + 0x6f, 0x63, 0x73, 0x12, 0x62, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x77, 0x61, 0x67, 0x67, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x71, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x49, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0xd6, 0x07, + 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x61, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x0d, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x45, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, + 0x63, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, + 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, + 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x65, 0x73, 0x12, 0x61, 0x0a, + 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x43, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, + 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, + 0x12, 0x4b, 0x0a, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, + 0x0e, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x65, 0x52, 0x07, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x73, 0x12, 0x1e, 0x0a, + 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x5a, 0x0a, + 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x12, 0x64, 0x0a, 0x0a, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x55, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x1a, 0x71, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x49, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, + 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x22, 0x62, 0x0a, 0x0a, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x73, 0x12, 0x54, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x22, 0xa3, 0x02, 0x0a, 0x0f, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x3f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2e, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, + 0x6d, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x22, 0x45, 0x0a, + 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0a, + 0x0a, 0x06, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x45, 0x52, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x42, 0x4f, 0x4f, 0x4c, 0x45, + 0x41, 0x4e, 0x10, 0x04, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, + 0x22, 0xd8, 0x01, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, + 0x75, 0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x18, 0x0d, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x4a, 0x04, 0x08, + 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x4a, + 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x4a, 0x04, 0x08, 0x0a, 0x10, + 0x0b, 0x4a, 0x04, 0x08, 0x0b, 0x10, 0x0c, 0x4a, 0x04, 0x08, 0x0c, 0x10, 0x0d, 0x4a, 0x04, 0x08, + 0x0e, 0x10, 0x0f, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x4a, 0x04, 0x08, 0x10, 0x10, 0x11, 0x4a, + 0x04, 0x08, 0x11, 0x10, 0x12, 0x4a, 0x04, 0x08, 0x12, 0x10, 0x13, 0x22, 0x9a, 0x05, 0x0a, 0x08, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x06, 0x73, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x06, 0x73, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x5a, 0x0a, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x73, 0x12, 0x5d, 0x0a, 0x08, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, + 0x12, 0x63, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6d, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x3b, 0x0a, 0x0d, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd6, 0x03, 0x0a, 0x04, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x65, 0x72, + 0x6d, 0x73, 0x5f, 0x6f, 0x66, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x65, 0x72, 0x6d, 0x73, 0x4f, 0x66, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, + 0x74, 0x12, 0x4c, 0x0a, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, + 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4c, + 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, 0x0a, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x45, + 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, + 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0x45, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x72, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x2f, 0x0a, 0x07, 0x4c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0x4b, 0x0a, 0x15, 0x45, 0x78, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaa, 0x02, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x12, 0x56, 0x0a, 0x0b, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0a, 0x6a, + 0x73, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x24, 0x0a, 0x0d, 0x64, 0x69, 0x73, + 0x63, 0x72, 0x69, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x72, 0x69, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, + 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x65, 0x0a, 0x0d, + 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, + 0x6f, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x4a, 0x04, 0x08, + 0x04, 0x10, 0x05, 0x22, 0xe8, 0x03, 0x0a, 0x0a, 0x45, 0x6e, 0x75, 0x6d, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x65, 0x0a, + 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x44, 0x6f, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, + 0x12, 0x65, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, + 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x45, 0x78, 0x74, 0x65, + 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd7, + 0x0a, 0x0a, 0x0a, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x10, 0x0a, + 0x03, 0x72, 0x65, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, + 0x6c, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, + 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x61, 0x64, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x6d, + 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x4f, 0x66, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x78, + 0x69, 0x6d, 0x75, 0x6d, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x69, + 0x6d, 0x75, 0x6d, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, + 0x5f, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, + 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x4d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x18, 0x0d, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x78, + 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x5f, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, + 0x4d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x6c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x61, 0x78, + 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x18, 0x10, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6d, 0x69, 0x6e, 0x4c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, + 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x14, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x1b, 0x0a, 0x09, + 0x6d, 0x69, 0x6e, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x08, 0x6d, 0x69, 0x6e, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x75, 0x6e, 0x69, + 0x71, 0x75, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0b, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x25, 0x0a, 0x0e, + 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x18, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6d, 0x61, 0x78, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x70, 0x65, + 0x72, 0x74, 0x69, 0x65, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6d, 0x69, 0x6e, + 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x1a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, + 0x22, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x61, 0x72, 0x72, 0x61, 0x79, 0x12, 0x5f, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x23, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x4b, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x69, 0x6d, 0x70, + 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, + 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x6e, 0x75, 0x6d, 0x18, 0x2e, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x04, 0x65, 0x6e, 0x75, 0x6d, 0x12, 0x7a, 0x0a, 0x13, 0x66, 0x69, 0x65, + 0x6c, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0xe9, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x48, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x12, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x30, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, + 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3c, 0x0a, 0x12, + 0x46, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x74, + 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x55, 0x0a, 0x0f, 0x45, 0x78, + 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0x77, 0x0a, 0x15, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, + 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x52, 0x52, 0x41, 0x59, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x42, 0x4f, 0x4f, 0x4c, 0x45, 0x41, 0x4e, 0x10, 0x02, 0x12, + 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, + 0x4e, 0x55, 0x4c, 0x4c, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, + 0x10, 0x05, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x42, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x06, 0x12, 0x0a, + 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x07, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, + 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x12, + 0x10, 0x13, 0x4a, 0x04, 0x08, 0x13, 0x10, 0x14, 0x4a, 0x04, 0x08, 0x17, 0x10, 0x18, 0x4a, 0x04, + 0x08, 0x1b, 0x10, 0x1c, 0x4a, 0x04, 0x08, 0x1c, 0x10, 0x1d, 0x4a, 0x04, 0x08, 0x1d, 0x10, 0x1e, + 0x4a, 0x04, 0x08, 0x1e, 0x10, 0x22, 0x4a, 0x04, 0x08, 0x25, 0x10, 0x2a, 0x4a, 0x04, 0x08, 0x2a, + 0x10, 0x2b, 0x4a, 0x04, 0x08, 0x2b, 0x10, 0x2e, 0x22, 0xd9, 0x02, 0x0a, 0x03, 0x54, 0x61, 0x67, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x5f, 0x64, 0x6f, 0x63, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0c, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x44, 0x6f, 0x63, 0x73, 0x12, 0x5e, 0x0a, + 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, + 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x54, 0x61, + 0x67, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x55, 0x0a, + 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf7, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x68, 0x0a, 0x08, + 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4c, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, + 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, + 0x69, 0x74, 0x79, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, + 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x65, + 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x1a, 0x76, 0x0a, 0x0d, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, + 0x74, 0x79, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4f, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, + 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, + 0x65, 0x6d, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xff, + 0x06, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x65, 0x12, 0x52, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, + 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4c, 0x0a, 0x02, 0x69, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x65, 0x2e, 0x49, 0x6e, 0x52, 0x02, 0x69, 0x6e, 0x12, 0x52, 0x0a, 0x04, 0x66, 0x6c, 0x6f, + 0x77, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3e, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x65, 0x2e, 0x46, 0x6c, 0x6f, 0x77, 0x52, 0x04, 0x66, 0x6c, 0x6f, 0x77, 0x12, 0x2b, 0x0a, + 0x11, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x75, + 0x72, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x55, 0x72, 0x6c, 0x12, 0x49, 0x0a, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x65, + 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x06, 0x73, 0x63, 0x6f, 0x70, + 0x65, 0x73, 0x12, 0x69, 0x0a, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, + 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x65, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x55, 0x0a, + 0x0f, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x4b, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0e, + 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, 0x53, 0x49, 0x43, 0x10, 0x01, 0x12, 0x10, + 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x02, + 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x41, 0x55, 0x54, 0x48, 0x32, 0x10, + 0x03, 0x22, 0x31, 0x0a, 0x02, 0x49, 0x6e, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x4e, 0x5f, 0x49, 0x4e, + 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x5f, 0x51, 0x55, + 0x45, 0x52, 0x59, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x49, 0x4e, 0x5f, 0x48, 0x45, 0x41, 0x44, + 0x45, 0x52, 0x10, 0x02, 0x22, 0x6a, 0x0a, 0x04, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x10, 0x0a, 0x0c, + 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x00, 0x12, 0x11, + 0x0a, 0x0d, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x49, 0x4d, 0x50, 0x4c, 0x49, 0x43, 0x49, 0x54, 0x10, + 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, + 0x52, 0x44, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x46, 0x4c, 0x4f, 0x57, 0x5f, 0x41, 0x50, 0x50, + 0x4c, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x14, 0x0a, 0x10, 0x46, 0x4c, + 0x4f, 0x57, 0x5f, 0x41, 0x43, 0x43, 0x45, 0x53, 0x53, 0x5f, 0x43, 0x4f, 0x44, 0x45, 0x10, 0x04, + 0x22, 0xf6, 0x02, 0x0a, 0x13, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x8a, 0x01, 0x0a, 0x14, 0x73, 0x65, 0x63, + 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x57, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, + 0x6e, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x13, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x1a, 0x30, 0x0a, 0x18, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x1a, 0x9f, 0x01, 0x0a, 0x18, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x6d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x57, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, + 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x96, 0x01, 0x0a, 0x06, 0x53, 0x63, + 0x6f, 0x70, 0x65, 0x73, 0x12, 0x52, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x5f, 0x6f, 0x70, + 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, + 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x1a, 0x38, 0x0a, 0x0a, 0x53, 0x63, 0x6f, 0x70, + 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x2a, 0x3b, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x0b, 0x0a, 0x07, + 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, + 0x50, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, 0x54, 0x50, 0x53, 0x10, 0x02, 0x12, 0x06, + 0x0a, 0x02, 0x57, 0x53, 0x10, 0x03, 0x12, 0x07, 0x0a, 0x03, 0x57, 0x53, 0x53, 0x10, 0x04, 0x42, + 0x48, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x70, 0x63, 0x2d, 0x65, 0x63, 0x6f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, + 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes = make([]protoimpl.EnumInfo, 6) +var file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes = make([]protoimpl.MessageInfo, 35) +var file_protoc_gen_openapiv2_options_openapiv2_proto_goTypes = []any{ + (Scheme)(0), // 0: grpc.gateway.protoc_gen_openapiv2.options.Scheme + (HeaderParameter_Type)(0), // 1: grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter.Type + (JSONSchema_JSONSchemaSimpleTypes)(0), // 2: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.JSONSchemaSimpleTypes + (SecurityScheme_Type)(0), // 3: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Type + (SecurityScheme_In)(0), // 4: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.In + (SecurityScheme_Flow)(0), // 5: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Flow + (*Swagger)(nil), // 6: grpc.gateway.protoc_gen_openapiv2.options.Swagger + (*Operation)(nil), // 7: grpc.gateway.protoc_gen_openapiv2.options.Operation + (*Parameters)(nil), // 8: grpc.gateway.protoc_gen_openapiv2.options.Parameters + (*HeaderParameter)(nil), // 9: grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter + (*Header)(nil), // 10: grpc.gateway.protoc_gen_openapiv2.options.Header + (*Response)(nil), // 11: grpc.gateway.protoc_gen_openapiv2.options.Response + (*Info)(nil), // 12: grpc.gateway.protoc_gen_openapiv2.options.Info + (*Contact)(nil), // 13: grpc.gateway.protoc_gen_openapiv2.options.Contact + (*License)(nil), // 14: grpc.gateway.protoc_gen_openapiv2.options.License + (*ExternalDocumentation)(nil), // 15: grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + (*Schema)(nil), // 16: grpc.gateway.protoc_gen_openapiv2.options.Schema + (*EnumSchema)(nil), // 17: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema + (*JSONSchema)(nil), // 18: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema + (*Tag)(nil), // 19: grpc.gateway.protoc_gen_openapiv2.options.Tag + (*SecurityDefinitions)(nil), // 20: grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions + (*SecurityScheme)(nil), // 21: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme + (*SecurityRequirement)(nil), // 22: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement + (*Scopes)(nil), // 23: grpc.gateway.protoc_gen_openapiv2.options.Scopes + nil, // 24: grpc.gateway.protoc_gen_openapiv2.options.Swagger.ResponsesEntry + nil, // 25: grpc.gateway.protoc_gen_openapiv2.options.Swagger.ExtensionsEntry + nil, // 26: grpc.gateway.protoc_gen_openapiv2.options.Operation.ResponsesEntry + nil, // 27: grpc.gateway.protoc_gen_openapiv2.options.Operation.ExtensionsEntry + nil, // 28: grpc.gateway.protoc_gen_openapiv2.options.Response.HeadersEntry + nil, // 29: grpc.gateway.protoc_gen_openapiv2.options.Response.ExamplesEntry + nil, // 30: grpc.gateway.protoc_gen_openapiv2.options.Response.ExtensionsEntry + nil, // 31: grpc.gateway.protoc_gen_openapiv2.options.Info.ExtensionsEntry + nil, // 32: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.ExtensionsEntry + (*JSONSchema_FieldConfiguration)(nil), // 33: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.FieldConfiguration + nil, // 34: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.ExtensionsEntry + nil, // 35: grpc.gateway.protoc_gen_openapiv2.options.Tag.ExtensionsEntry + nil, // 36: grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.SecurityEntry + nil, // 37: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.ExtensionsEntry + (*SecurityRequirement_SecurityRequirementValue)(nil), // 38: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementValue + nil, // 39: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementEntry + nil, // 40: grpc.gateway.protoc_gen_openapiv2.options.Scopes.ScopeEntry + (*structpb.Value)(nil), // 41: google.protobuf.Value +} +var file_protoc_gen_openapiv2_options_openapiv2_proto_depIdxs = []int32{ + 12, // 0: grpc.gateway.protoc_gen_openapiv2.options.Swagger.info:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Info + 0, // 1: grpc.gateway.protoc_gen_openapiv2.options.Swagger.schemes:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Scheme + 24, // 2: grpc.gateway.protoc_gen_openapiv2.options.Swagger.responses:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Swagger.ResponsesEntry + 20, // 3: grpc.gateway.protoc_gen_openapiv2.options.Swagger.security_definitions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions + 22, // 4: grpc.gateway.protoc_gen_openapiv2.options.Swagger.security:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement + 19, // 5: grpc.gateway.protoc_gen_openapiv2.options.Swagger.tags:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Tag + 15, // 6: grpc.gateway.protoc_gen_openapiv2.options.Swagger.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 25, // 7: grpc.gateway.protoc_gen_openapiv2.options.Swagger.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Swagger.ExtensionsEntry + 15, // 8: grpc.gateway.protoc_gen_openapiv2.options.Operation.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 26, // 9: grpc.gateway.protoc_gen_openapiv2.options.Operation.responses:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Operation.ResponsesEntry + 0, // 10: grpc.gateway.protoc_gen_openapiv2.options.Operation.schemes:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Scheme + 22, // 11: grpc.gateway.protoc_gen_openapiv2.options.Operation.security:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement + 27, // 12: grpc.gateway.protoc_gen_openapiv2.options.Operation.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Operation.ExtensionsEntry + 8, // 13: grpc.gateway.protoc_gen_openapiv2.options.Operation.parameters:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Parameters + 9, // 14: grpc.gateway.protoc_gen_openapiv2.options.Parameters.headers:type_name -> grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter + 1, // 15: grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter.type:type_name -> grpc.gateway.protoc_gen_openapiv2.options.HeaderParameter.Type + 16, // 16: grpc.gateway.protoc_gen_openapiv2.options.Response.schema:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Schema + 28, // 17: grpc.gateway.protoc_gen_openapiv2.options.Response.headers:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response.HeadersEntry + 29, // 18: grpc.gateway.protoc_gen_openapiv2.options.Response.examples:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response.ExamplesEntry + 30, // 19: grpc.gateway.protoc_gen_openapiv2.options.Response.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response.ExtensionsEntry + 13, // 20: grpc.gateway.protoc_gen_openapiv2.options.Info.contact:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Contact + 14, // 21: grpc.gateway.protoc_gen_openapiv2.options.Info.license:type_name -> grpc.gateway.protoc_gen_openapiv2.options.License + 31, // 22: grpc.gateway.protoc_gen_openapiv2.options.Info.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Info.ExtensionsEntry + 18, // 23: grpc.gateway.protoc_gen_openapiv2.options.Schema.json_schema:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema + 15, // 24: grpc.gateway.protoc_gen_openapiv2.options.Schema.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 15, // 25: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 32, // 26: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.ExtensionsEntry + 2, // 27: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.type:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.JSONSchemaSimpleTypes + 33, // 28: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.field_configuration:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.FieldConfiguration + 34, // 29: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.ExtensionsEntry + 15, // 30: grpc.gateway.protoc_gen_openapiv2.options.Tag.external_docs:type_name -> grpc.gateway.protoc_gen_openapiv2.options.ExternalDocumentation + 35, // 31: grpc.gateway.protoc_gen_openapiv2.options.Tag.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Tag.ExtensionsEntry + 36, // 32: grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.security:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.SecurityEntry + 3, // 33: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.type:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Type + 4, // 34: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.in:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.In + 5, // 35: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.flow:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.Flow + 23, // 36: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.scopes:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Scopes + 37, // 37: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.extensions:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.ExtensionsEntry + 39, // 38: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.security_requirement:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementEntry + 40, // 39: grpc.gateway.protoc_gen_openapiv2.options.Scopes.scope:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Scopes.ScopeEntry + 11, // 40: grpc.gateway.protoc_gen_openapiv2.options.Swagger.ResponsesEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response + 41, // 41: grpc.gateway.protoc_gen_openapiv2.options.Swagger.ExtensionsEntry.value:type_name -> google.protobuf.Value + 11, // 42: grpc.gateway.protoc_gen_openapiv2.options.Operation.ResponsesEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Response + 41, // 43: grpc.gateway.protoc_gen_openapiv2.options.Operation.ExtensionsEntry.value:type_name -> google.protobuf.Value + 10, // 44: grpc.gateway.protoc_gen_openapiv2.options.Response.HeadersEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.Header + 41, // 45: grpc.gateway.protoc_gen_openapiv2.options.Response.ExtensionsEntry.value:type_name -> google.protobuf.Value + 41, // 46: grpc.gateway.protoc_gen_openapiv2.options.Info.ExtensionsEntry.value:type_name -> google.protobuf.Value + 41, // 47: grpc.gateway.protoc_gen_openapiv2.options.EnumSchema.ExtensionsEntry.value:type_name -> google.protobuf.Value + 41, // 48: grpc.gateway.protoc_gen_openapiv2.options.JSONSchema.ExtensionsEntry.value:type_name -> google.protobuf.Value + 41, // 49: grpc.gateway.protoc_gen_openapiv2.options.Tag.ExtensionsEntry.value:type_name -> google.protobuf.Value + 21, // 50: grpc.gateway.protoc_gen_openapiv2.options.SecurityDefinitions.SecurityEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme + 41, // 51: grpc.gateway.protoc_gen_openapiv2.options.SecurityScheme.ExtensionsEntry.value:type_name -> google.protobuf.Value + 38, // 52: grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementEntry.value:type_name -> grpc.gateway.protoc_gen_openapiv2.options.SecurityRequirement.SecurityRequirementValue + 53, // [53:53] is the sub-list for method output_type + 53, // [53:53] is the sub-list for method input_type + 53, // [53:53] is the sub-list for extension type_name + 53, // [53:53] is the sub-list for extension extendee + 0, // [0:53] is the sub-list for field type_name +} + +func init() { file_protoc_gen_openapiv2_options_openapiv2_proto_init() } +func file_protoc_gen_openapiv2_options_openapiv2_proto_init() { + if File_protoc_gen_openapiv2_options_openapiv2_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_protoc_gen_openapiv2_options_openapiv2_proto_rawDesc, + NumEnums: 6, + NumMessages: 35, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_protoc_gen_openapiv2_options_openapiv2_proto_goTypes, + DependencyIndexes: file_protoc_gen_openapiv2_options_openapiv2_proto_depIdxs, + EnumInfos: file_protoc_gen_openapiv2_options_openapiv2_proto_enumTypes, + MessageInfos: file_protoc_gen_openapiv2_options_openapiv2_proto_msgTypes, + }.Build() + File_protoc_gen_openapiv2_options_openapiv2_proto = out.File + file_protoc_gen_openapiv2_options_openapiv2_proto_rawDesc = nil + file_protoc_gen_openapiv2_options_openapiv2_proto_goTypes = nil + file_protoc_gen_openapiv2_options_openapiv2_proto_depIdxs = nil +} diff --git a/etcd/vendor/github.com/openshift/api/config/v1/types_cluster_version.go b/etcd/vendor/github.com/openshift/api/config/v1/types_cluster_version.go index cfac9689e4..e5aad151ea 100644 --- a/etcd/vendor/github.com/openshift/api/config/v1/types_cluster_version.go +++ b/etcd/vendor/github.com/openshift/api/config/v1/types_cluster_version.go @@ -72,8 +72,10 @@ type ClusterVersionSpec struct { // // If an upgrade fails the operator will halt and report status // about the failing component. Setting the desired update value back to - // the previous version will cause a rollback to be attempted. Not all - // rollbacks will succeed. + // the previous version will cause a rollback to be attempted if the + // previous version is within the current minor version. Not all + // rollbacks will succeed, and some may unrecoverably break the + // cluster. // // +optional DesiredUpdate *Update `json:"desiredUpdate,omitempty"` @@ -718,10 +720,14 @@ type Update struct { Image string `json:"image"` // force allows an administrator to update to an image that has failed - // verification or upgradeable checks. This option should only - // be used when the authenticity of the provided image has been verified out - // of band because the provided image will run with full administrative access - // to the cluster. Do not use this flag with images that comes from unknown + // verification or upgradeable checks that are designed to keep your + // cluster safe. Only use this if: + // * you are testing unsigned release images in short-lived test clusters or + // * you are working around a known bug in the cluster-version + // operator and you have verified the authenticity of the provided + // image yourself. + // The provided image will run with full administrative access + // to the cluster. Do not use this flag with images that come from unknown // or potentially malicious sources. // // +optional diff --git a/etcd/vendor/github.com/openshift/api/config/v1/types_infrastructure.go b/etcd/vendor/github.com/openshift/api/config/v1/types_infrastructure.go index effafde644..2f80945d38 100644 --- a/etcd/vendor/github.com/openshift/api/config/v1/types_infrastructure.go +++ b/etcd/vendor/github.com/openshift/api/config/v1/types_infrastructure.go @@ -183,6 +183,17 @@ const ( LoadBalancerTypeOpenShiftManagedDefault PlatformLoadBalancerType = "OpenShiftManagedDefault" ) +// DNSRecordsType defines whether api, api-int, and ingress records are provided by +// the internal DNS infrastructure or must be configured external to the cluster. +// +kubebuilder:validation:Enum=Internal;External +// +enum +type DNSRecordsType string + +const ( + DNSRecordsTypeExternal DNSRecordsType = "External" + DNSRecordsTypeInternal DNSRecordsType = "Internal" +) + // PlatformType is a specific supported infrastructure provider. // +kubebuilder:validation:Enum="";AWS;Azure;BareMetal;GCP;Libvirt;OpenStack;None;VSphere;oVirt;IBMCloud;KubeVirt;EquinixMetal;PowerVS;AlibabaCloud;Nutanix;External type PlatformType string @@ -491,6 +502,21 @@ type AWSServiceEndpoint struct { URL string `json:"url"` } +// IPFamilyType represents the IP protocol family that cloud platform resources should use. +// +kubebuilder:validation:Enum=IPv4;DualStackIPv6Primary;DualStackIPv4Primary +type IPFamilyType string + +const ( + // IPv4 indicates that cloud platform resources should use IPv4 addressing only. + IPv4 IPFamilyType = "IPv4" + + // DualStackIPv6Primary indicates that cloud platform resources should use dual-stack networking with IPv6 as primary. + DualStackIPv6Primary IPFamilyType = "DualStackIPv6Primary" + + // DualStackIPv4Primary indicates that cloud platform resources should use dual-stack networking with IPv4 as primary. + DualStackIPv4Primary IPFamilyType = "DualStackIPv4Primary" +) + // AWSPlatformSpec holds the desired state of the Amazon Web Services infrastructure provider. // This only includes fields that can be modified in the cluster. type AWSPlatformSpec struct { @@ -536,6 +562,18 @@ type AWSPlatformStatus struct { // +optional // +nullable CloudLoadBalancerConfig *CloudLoadBalancerConfig `json:"cloudLoadBalancerConfig,omitempty"` + + // ipFamily specifies the IP protocol family that should be used for AWS + // network resources. This controls whether AWS resources are created with + // IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary + // protocol family. + // + // +default="IPv4" + // +kubebuilder:default="IPv4" + // +kubebuilder:validation:XValidation:rule="oldSelf == '' || self == oldSelf",message="ipFamily is immutable once set" + // +openshift:enable:FeatureGate=AWSDualStackInstall + // +optional + IPFamily IPFamilyType `json:"ipFamily,omitempty"` } // AWSResourceTag is a tag to apply to AWS resources created for the cluster. @@ -607,6 +645,18 @@ type AzurePlatformStatus struct { // +openshift:enable:FeatureGate=AzureClusterHostedDNSInstall // +optional CloudLoadBalancerConfig *CloudLoadBalancerConfig `json:"cloudLoadBalancerConfig,omitempty"` + + // ipFamily specifies the IP protocol family that should be used for Azure + // network resources. This controls whether Azure resources are created with + // IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary + // protocol family. + // + // +default="IPv4" + // +kubebuilder:default="IPv4" + // +kubebuilder:validation:XValidation:rule="oldSelf == '' || self == oldSelf",message="ipFamily is immutable once set" + // +openshift:enable:FeatureGate=AzureDualStackInstall + // +optional + IPFamily IPFamilyType `json:"ipFamily,omitempty"` } // AzureResourceTag is a tag to apply to Azure resources created for the cluster. @@ -983,6 +1033,7 @@ type BareMetalPlatformSpec struct { // BareMetalPlatformStatus holds the current status of the BareMetal infrastructure provider. // For more information about the network architecture used with the BareMetal platform type, see: // https://github.com/openshift/installer/blob/master/docs/design/baremetal/networking-infrastructure.md +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type BareMetalPlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -1035,6 +1086,22 @@ type BareMetalPlatformStatus struct { // +optional LoadBalancer *BareMetalPlatformLoadBalancer `json:"loadBalancer,omitempty"` + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` + // machineNetworks are IP networks used to connect all the OpenShift cluster nodes. // +listType=atomic // +kubebuilder:validation:MaxItems=32 @@ -1111,6 +1178,7 @@ type OpenStackPlatformSpec struct { } // OpenStackPlatformStatus holds the current status of the OpenStack infrastructure provider. +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type OpenStackPlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -1167,6 +1235,22 @@ type OpenStackPlatformStatus struct { // +optional LoadBalancer *OpenStackPlatformLoadBalancer `json:"loadBalancer,omitempty"` + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` + // machineNetworks are IP networks used to connect all the OpenShift cluster nodes. // +listType=atomic // +kubebuilder:validation:MaxItems=32 @@ -1201,6 +1285,7 @@ type OvirtPlatformLoadBalancer struct { type OvirtPlatformSpec struct{} // OvirtPlatformStatus holds the current status of the oVirt infrastructure provider. +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type OvirtPlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -1247,6 +1332,22 @@ type OvirtPlatformStatus struct { // +kubebuilder:default={"type": "OpenShiftManagedDefault"} // +optional LoadBalancer *OvirtPlatformLoadBalancer `json:"loadBalancer,omitempty"` + + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` } // VSpherePlatformLoadBalancer defines the load balancer used by the cluster on VSphere platform. @@ -1644,6 +1745,7 @@ type VSpherePlatformSpec struct { } // VSpherePlatformStatus holds the current status of the vSphere infrastructure provider. +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type VSpherePlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -1696,6 +1798,22 @@ type VSpherePlatformStatus struct { // +optional LoadBalancer *VSpherePlatformLoadBalancer `json:"loadBalancer,omitempty"` + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` + // machineNetworks are IP networks used to connect all the OpenShift cluster nodes. // +listType=atomic // +kubebuilder:validation:MaxItems=32 @@ -2069,6 +2187,7 @@ type NutanixPrismElementEndpoint struct { } // NutanixPlatformStatus holds the current status of the Nutanix infrastructure provider. +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type NutanixPlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -2112,6 +2231,22 @@ type NutanixPlatformStatus struct { // +kubebuilder:default={"type": "OpenShiftManagedDefault"} // +optional LoadBalancer *NutanixPlatformLoadBalancer `json:"loadBalancer,omitempty"` + + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/etcd/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml b/etcd/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml index d8d6b502ee..a1d37f65d0 100644 --- a/etcd/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml +++ b/etcd/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml @@ -362,7 +362,9 @@ infrastructures.config.openshift.io: Category: "" FeatureGates: - AWSClusterHostedDNSInstall + - AWSDualStackInstall - AzureClusterHostedDNSInstall + - AzureDualStackInstall - DualReplica - DyanmicServiceEndpointIBMCloud - GCPClusterHostedDNSInstall @@ -370,6 +372,7 @@ infrastructures.config.openshift.io: - HighlyAvailableArbiter - HighlyAvailableArbiter+DualReplica - NutanixMultiSubnets + - OnPremDNSRecords - VSphereHostVMGroupZonal - VSphereMultiNetworks FilenameOperatorName: config-operator diff --git a/etcd/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go b/etcd/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go index 31aab4dfe8..b9d0799fbd 100644 --- a/etcd/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go +++ b/etcd/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go @@ -777,7 +777,7 @@ func (ClusterVersionList) SwaggerDoc() map[string]string { var map_ClusterVersionSpec = map[string]string{ "": "ClusterVersionSpec is the desired version state of the cluster. It includes the version the cluster should be at, how the cluster is identified, and where the cluster should look for version updates.", "clusterID": "clusterID uniquely identifies this cluster. This is expected to be an RFC4122 UUID value (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx in hexadecimal values). This is a required field.", - "desiredUpdate": "desiredUpdate is an optional field that indicates the desired value of the cluster version. Setting this value will trigger an upgrade (if the current version does not match the desired version). The set of recommended update values is listed as part of available updates in status, and setting values outside that range may cause the upgrade to fail.\n\nSome of the fields are inter-related with restrictions and meanings described here. 1. image is specified, version is specified, architecture is specified. API validation error. 2. image is specified, version is specified, architecture is not specified. The version extracted from the referenced image must match the specified version. 3. image is specified, version is not specified, architecture is specified. API validation error. 4. image is specified, version is not specified, architecture is not specified. image is used. 5. image is not specified, version is specified, architecture is specified. version and desired architecture are used to select an image. 6. image is not specified, version is specified, architecture is not specified. version and current architecture are used to select an image. 7. image is not specified, version is not specified, architecture is specified. API validation error. 8. image is not specified, version is not specified, architecture is not specified. API validation error.\n\nIf an upgrade fails the operator will halt and report status about the failing component. Setting the desired update value back to the previous version will cause a rollback to be attempted. Not all rollbacks will succeed.", + "desiredUpdate": "desiredUpdate is an optional field that indicates the desired value of the cluster version. Setting this value will trigger an upgrade (if the current version does not match the desired version). The set of recommended update values is listed as part of available updates in status, and setting values outside that range may cause the upgrade to fail.\n\nSome of the fields are inter-related with restrictions and meanings described here. 1. image is specified, version is specified, architecture is specified. API validation error. 2. image is specified, version is specified, architecture is not specified. The version extracted from the referenced image must match the specified version. 3. image is specified, version is not specified, architecture is specified. API validation error. 4. image is specified, version is not specified, architecture is not specified. image is used. 5. image is not specified, version is specified, architecture is specified. version and desired architecture are used to select an image. 6. image is not specified, version is specified, architecture is not specified. version and current architecture are used to select an image. 7. image is not specified, version is not specified, architecture is specified. API validation error. 8. image is not specified, version is not specified, architecture is not specified. API validation error.\n\nIf an upgrade fails the operator will halt and report status about the failing component. Setting the desired update value back to the previous version will cause a rollback to be attempted if the previous version is within the current minor version. Not all rollbacks will succeed, and some may unrecoverably break the cluster.", "upstream": "upstream may be used to specify the preferred update server. By default it will use the appropriate update server for the cluster and region.", "channel": "channel is an identifier for explicitly requesting a non-default set of updates to be applied to this cluster. The default channel will contain stable updates that are appropriate for production clusters.", "capabilities": "capabilities configures the installation of optional, core cluster components. A null value here is identical to an empty object; see the child properties for default semantics.", @@ -878,7 +878,7 @@ var map_Update = map[string]string{ "architecture": "architecture is an optional field that indicates the desired value of the cluster architecture. In this context cluster architecture means either a single architecture or a multi architecture. architecture can only be set to Multi thereby only allowing updates from single to multi architecture. If architecture is set, image cannot be set and version must be set. Valid values are 'Multi' and empty.", "version": "version is a semantic version identifying the update version. version is required if architecture is specified. If both version and image are set, the version extracted from the referenced image must match the specified version.", "image": "image is a container image location that contains the update. image should be used when the desired version does not exist in availableUpdates or history. When image is set, architecture cannot be specified. If both version and image are set, the version extracted from the referenced image must match the specified version.", - "force": "force allows an administrator to update to an image that has failed verification or upgradeable checks. This option should only be used when the authenticity of the provided image has been verified out of band because the provided image will run with full administrative access to the cluster. Do not use this flag with images that comes from unknown or potentially malicious sources.", + "force": "force allows an administrator to update to an image that has failed verification or upgradeable checks that are designed to keep your cluster safe. Only use this if: * you are testing unsigned release images in short-lived test clusters or * you are working around a known bug in the cluster-version\n operator and you have verified the authenticity of the provided\n image yourself.\nThe provided image will run with full administrative access to the cluster. Do not use this flag with images that come from unknown or potentially malicious sources.", } func (Update) SwaggerDoc() map[string]string { @@ -1410,6 +1410,7 @@ var map_AWSPlatformStatus = map[string]string{ "serviceEndpoints": "serviceEndpoints list contains custom endpoints which will override default service endpoint of AWS Services. There must be only one ServiceEndpoint for a service.", "resourceTags": "resourceTags is a list of additional tags to apply to AWS resources created for the cluster. See https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for information on tagging AWS resources. AWS supports a maximum of 50 tags per resource. OpenShift reserves 25 tags for its use, leaving 25 tags available for the user.", "cloudLoadBalancerConfig": "cloudLoadBalancerConfig holds configuration related to DNS and cloud load balancers. It allows configuration of in-cluster DNS as an alternative to the platform default DNS implementation. When using the ClusterHosted DNS type, Load Balancer IP addresses must be provided for the API and internal API load balancers as well as the ingress load balancer.", + "ipFamily": "ipFamily specifies the IP protocol family that should be used for AWS network resources. This controls whether AWS resources are created with IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary protocol family.", } func (AWSPlatformStatus) SwaggerDoc() map[string]string { @@ -1481,6 +1482,7 @@ var map_AzurePlatformStatus = map[string]string{ "armEndpoint": "armEndpoint specifies a URL to use for resource management in non-soverign clouds such as Azure Stack.", "resourceTags": "resourceTags is a list of additional tags to apply to Azure resources created for the cluster. See https://docs.microsoft.com/en-us/rest/api/resources/tags for information on tagging Azure resources. Due to limitations on Automation, Content Delivery Network, DNS Azure resources, a maximum of 15 tags may be applied. OpenShift reserves 5 tags for internal use, allowing 10 tags for user configuration.", "cloudLoadBalancerConfig": "cloudLoadBalancerConfig holds configuration related to DNS and cloud load balancers. It allows configuration of in-cluster DNS as an alternative to the platform default DNS implementation. When using the ClusterHosted DNS type, Load Balancer IP addresses must be provided for the API and internal API load balancers as well as the ingress load balancer.", + "ipFamily": "ipFamily specifies the IP protocol family that should be used for Azure network resources. This controls whether Azure resources are created with IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary protocol family.", } func (AzurePlatformStatus) SwaggerDoc() map[string]string { @@ -1525,6 +1527,7 @@ var map_BareMetalPlatformStatus = map[string]string{ "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "nodeDNSIP": "nodeDNSIP is the IP address for the internal DNS used by the nodes. Unlike the one managed by the DNS operator, `NodeDNSIP` provides name resolution for the nodes themselves. There is no DNS-as-a-service for BareMetal deployments. In order to minimize necessary changes to the datacenter DNS, a DNS service is hosted as a static pod to serve those hostnames to the nodes in the cluster.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", "machineNetworks": "machineNetworks are IP networks used to connect all the OpenShift cluster nodes.", } @@ -1787,6 +1790,7 @@ var map_NutanixPlatformStatus = map[string]string{ "ingressIP": "ingressIP is an external IP which routes to the default ingress controller. The IP is a suitable target of a wildcard DNS record used to resolve default route host names.\n\nDeprecated: Use IngressIPs instead.", "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", } func (NutanixPlatformStatus) SwaggerDoc() map[string]string { @@ -1853,6 +1857,7 @@ var map_OpenStackPlatformStatus = map[string]string{ "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "nodeDNSIP": "nodeDNSIP is the IP address for the internal DNS used by the nodes. Unlike the one managed by the DNS operator, `NodeDNSIP` provides name resolution for the nodes themselves. There is no DNS-as-a-service for OpenStack deployments. In order to minimize necessary changes to the datacenter DNS, a DNS service is hosted as a static pod to serve those hostnames to the nodes in the cluster.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", "machineNetworks": "machineNetworks are IP networks used to connect all the OpenShift cluster nodes.", } @@ -1885,6 +1890,7 @@ var map_OvirtPlatformStatus = map[string]string{ "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "nodeDNSIP": "deprecated: as of 4.6, this field is no longer set or honored. It will be removed in a future release.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", } func (OvirtPlatformStatus) SwaggerDoc() map[string]string { @@ -2067,6 +2073,7 @@ var map_VSpherePlatformStatus = map[string]string{ "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "nodeDNSIP": "nodeDNSIP is the IP address for the internal DNS used by the nodes. Unlike the one managed by the DNS operator, `NodeDNSIP` provides name resolution for the nodes themselves. There is no DNS-as-a-service for vSphere deployments. In order to minimize necessary changes to the datacenter DNS, a DNS service is hosted as a static pod to serve those hostnames to the nodes in the cluster.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", "machineNetworks": "machineNetworks are IP networks used to connect all the OpenShift cluster nodes.", } diff --git a/etcd/vendor/github.com/openshift/api/features/features.go b/etcd/vendor/github.com/openshift/api/features/features.go new file mode 100644 index 0000000000..9c74d4c2df --- /dev/null +++ b/etcd/vendor/github.com/openshift/api/features/features.go @@ -0,0 +1,926 @@ +package features + +import ( + "fmt" + + configv1 "github.com/openshift/api/config/v1" +) + +func FeatureSets(clusterProfile ClusterProfileName, featureSet configv1.FeatureSet) (*FeatureGateEnabledDisabled, error) { + byFeatureSet, ok := allFeatureGates[clusterProfile] + if !ok { + return nil, fmt.Errorf("no information found for ClusterProfile=%q", clusterProfile) + } + featureGates, ok := byFeatureSet[featureSet] + if !ok { + return nil, fmt.Errorf("no information found for FeatureSet=%q under ClusterProfile=%q", featureSet, clusterProfile) + } + return featureGates.DeepCopy(), nil +} + +func AllFeatureSets() map[ClusterProfileName]map[configv1.FeatureSet]*FeatureGateEnabledDisabled { + ret := map[ClusterProfileName]map[configv1.FeatureSet]*FeatureGateEnabledDisabled{} + + for clusterProfile, byFeatureSet := range allFeatureGates { + newByFeatureSet := map[configv1.FeatureSet]*FeatureGateEnabledDisabled{} + + for featureSet, enabledDisabled := range byFeatureSet { + newByFeatureSet[featureSet] = enabledDisabled.DeepCopy() + } + ret[clusterProfile] = newByFeatureSet + } + + return ret +} + +var ( + allFeatureGates = map[ClusterProfileName]map[configv1.FeatureSet]*FeatureGateEnabledDisabled{} + + FeatureGateConsolePluginCSP = newFeatureGate("ConsolePluginContentSecurityPolicy"). + reportProblemsToJiraComponent("Management Console"). + contactPerson("jhadvig"). + productScope(ocpSpecific). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + enhancementPR("https://github.com/openshift/enhancements/pull/1706"). + mustRegister() + + FeatureGateServiceAccountTokenNodeBinding = newFeatureGate("ServiceAccountTokenNodeBinding"). + reportProblemsToJiraComponent("apiserver-auth"). + contactPerson("ibihim"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/4193"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateMutatingAdmissionPolicy = newFeatureGate("MutatingAdmissionPolicy"). + reportProblemsToJiraComponent("kube-apiserver"). + contactPerson("benluddy"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/3962"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateGatewayAPI = newFeatureGate("GatewayAPI"). + reportProblemsToJiraComponent("Routing"). + contactPerson("miciah"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateOpenShiftPodSecurityAdmission = newFeatureGate("OpenShiftPodSecurityAdmission"). + reportProblemsToJiraComponent("auth"). + contactPerson("ibihim"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/899"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateBuildCSIVolumes = newFeatureGate("BuildCSIVolumes"). + reportProblemsToJiraComponent("builds"). + contactPerson("adkaplan"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateDynamicResourceAllocation = newFeatureGate("DynamicResourceAllocation"). + reportProblemsToJiraComponent("scheduling"). + contactPerson("jchaloup"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/4381"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAzureWorkloadIdentity = newFeatureGate("AzureWorkloadIdentity"). + reportProblemsToJiraComponent("cloud-credential-operator"). + contactPerson("abutcher"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAzureDedicatedHosts = newFeatureGate("AzureDedicatedHosts"). + reportProblemsToJiraComponent("installer"). + contactPerson("rvanderp3"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1783"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateMaxUnavailableStatefulSet = newFeatureGate("MaxUnavailableStatefulSet"). + reportProblemsToJiraComponent("apps"). + contactPerson("atiratree"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/961"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateEventedPLEG = newFeatureGate("EventedPLEG"). + reportProblemsToJiraComponent("node"). + contactPerson("sairameshv"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/3386"). + mustRegister() + + FeatureGateSigstoreImageVerification = newFeatureGate("SigstoreImageVerification"). + reportProblemsToJiraComponent("node"). + contactPerson("sgrunert"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateSigstoreImageVerificationPKI = newFeatureGate("SigstoreImageVerificationPKI"). + reportProblemsToJiraComponent("node"). + contactPerson("QiWang"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1658"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAlibabaPlatform = newFeatureGate("AlibabaPlatform"). + reportProblemsToJiraComponent("cloud-provider"). + contactPerson("jspeed"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateVSphereHostVMGroupZonal = newFeatureGate("VSphereHostVMGroupZonal"). + reportProblemsToJiraComponent("splat"). + contactPerson("jcpowermac"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1677"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateVSphereMultiDisk = newFeatureGate("VSphereMultiDisk"). + reportProblemsToJiraComponent("splat"). + contactPerson("vr4manta"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1709"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateRouteExternalCertificate = newFeatureGate("RouteExternalCertificate"). + reportProblemsToJiraComponent("router"). + contactPerson("chiragkyal"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateCPMSMachineNamePrefix = newFeatureGate("CPMSMachineNamePrefix"). + reportProblemsToJiraComponent("Cloud Compute / ControlPlaneMachineSet"). + contactPerson("chiragkyal"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1714"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAdminNetworkPolicy = newFeatureGate("AdminNetworkPolicy"). + reportProblemsToJiraComponent("Networking/ovn-kubernetes"). + contactPerson("tssurya"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateNetworkSegmentation = newFeatureGate("NetworkSegmentation"). + reportProblemsToJiraComponent("Networking/ovn-kubernetes"). + contactPerson("tssurya"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1623"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAdditionalRoutingCapabilities = newFeatureGate("AdditionalRoutingCapabilities"). + reportProblemsToJiraComponent("Networking/cluster-network-operator"). + contactPerson("jcaamano"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateRouteAdvertisements = newFeatureGate("RouteAdvertisements"). + reportProblemsToJiraComponent("Networking/ovn-kubernetes"). + contactPerson("jcaamano"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateNetworkLiveMigration = newFeatureGate("NetworkLiveMigration"). + reportProblemsToJiraComponent("Networking/ovn-kubernetes"). + contactPerson("pliu"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateNetworkDiagnosticsConfig = newFeatureGate("NetworkDiagnosticsConfig"). + reportProblemsToJiraComponent("Networking/cluster-network-operator"). + contactPerson("kyrtapz"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateOVNObservability = newFeatureGate("OVNObservability"). + reportProblemsToJiraComponent("Networking"). + contactPerson("npinaeva"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateBackendQuotaGiB = newFeatureGate("EtcdBackendQuota"). + reportProblemsToJiraComponent("etcd"). + contactPerson("hasbro17"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAutomatedEtcdBackup = newFeatureGate("AutomatedEtcdBackup"). + reportProblemsToJiraComponent("etcd"). + contactPerson("hasbro17"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateMachineAPIOperatorDisableMachineHealthCheckController = newFeatureGate("MachineAPIOperatorDisableMachineHealthCheckController"). + reportProblemsToJiraComponent("ecoproject"). + contactPerson("msluiter"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + mustRegister() + + FeatureGateDNSNameResolver = newFeatureGate("DNSNameResolver"). + reportProblemsToJiraComponent("dns"). + contactPerson("miciah"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateMachineConfigNodes = newFeatureGate("MachineConfigNodes"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("ijanssen"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1765"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateImageModeStatusReporting = newFeatureGate("ImageModeStatusReporting"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("ijanssen"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1809"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateClusterAPIInstall = newFeatureGate("ClusterAPIInstall"). + reportProblemsToJiraComponent("Installer"). + contactPerson("vincepri"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + mustRegister() + + FeatureGateGCPClusterHostedDNS = newFeatureGate("GCPClusterHostedDNS"). + reportProblemsToJiraComponent("Installer"). + contactPerson("barbacbd"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAWSClusterHostedDNS = newFeatureGate("AWSClusterHostedDNS"). + reportProblemsToJiraComponent("Installer"). + contactPerson("barbacbd"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAzureClusterHostedDNSInstall = newFeatureGate("AzureClusterHostedDNSInstall"). + reportProblemsToJiraComponent("Installer"). + contactPerson("sadasu"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1468"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateMixedCPUsAllocation = newFeatureGate("MixedCPUsAllocation"). + reportProblemsToJiraComponent("NodeTuningOperator"). + contactPerson("titzhak"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateManagedBootImages = newFeatureGate("ManagedBootImages"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("djoshy"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateManagedBootImagesAWS = newFeatureGate("ManagedBootImagesAWS"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("djoshy"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateManagedBootImagesvSphere = newFeatureGate("ManagedBootImagesvSphere"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("rsaini"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1496"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateManagedBootImagesAzure = newFeatureGate("ManagedBootImagesAzure"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("djoshy"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1761"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateManagedBootImagesCPMS = newFeatureGate("ManagedBootImagesCPMS"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("djoshy"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1818"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateBootImageSkewEnforcement = newFeatureGate("BootImageSkewEnforcement"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("djoshy"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1761"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateBootcNodeManagement = newFeatureGate("BootcNodeManagement"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("inesqyx"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateSignatureStores = newFeatureGate("SignatureStores"). + reportProblemsToJiraComponent("Cluster Version Operator"). + contactPerson("lmohanty"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateKMSv1 = newFeatureGate("KMSv1"). + reportProblemsToJiraComponent("kube-apiserver"). + contactPerson("dgrisonnet"). + productScope(kubernetes). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGatePinnedImages = newFeatureGate("PinnedImages"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("RishabhSaini"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateUpgradeStatus = newFeatureGate("UpgradeStatus"). + reportProblemsToJiraComponent("Cluster Version Operator"). + contactPerson("pmuller"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateTranslateStreamCloseWebsocketRequests = newFeatureGate("TranslateStreamCloseWebsocketRequests"). + reportProblemsToJiraComponent("kube-apiserver"). + contactPerson("akashem"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/4006"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateVolumeAttributesClass = newFeatureGate("VolumeAttributesClass"). + reportProblemsToJiraComponent("Storage / Kubernetes External Components"). + contactPerson("dfajmon"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/3751"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateVolumeGroupSnapshot = newFeatureGate("VolumeGroupSnapshot"). + reportProblemsToJiraComponent("Storage / Kubernetes External Components"). + contactPerson("fbertina"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/3476"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateExternalSnapshotMetadata = newFeatureGate("ExternalSnapshotMetadata"). + reportProblemsToJiraComponent("Storage / Kubernetes External Components"). + contactPerson("jdobson"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/3314"). + enableIn(configv1.DevPreviewNoUpgrade). + mustRegister() + + FeatureGateExternalOIDC = newFeatureGate("ExternalOIDC"). + reportProblemsToJiraComponent("authentication"). + contactPerson("liouk"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1596"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateExternalOIDCWithAdditionalClaimMappings = newFeatureGate("ExternalOIDCWithUIDAndExtraClaimMappings"). + reportProblemsToJiraComponent("authentication"). + contactPerson("bpalmer"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1777"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateExample = newFeatureGate("Example"). + reportProblemsToJiraComponent("cluster-config"). + contactPerson("deads"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateExample2 = newFeatureGate("Example2"). + reportProblemsToJiraComponent("cluster-config"). + contactPerson("JoelSpeed"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade). + mustRegister() + + FeatureGateNewOLM = newFeatureGate("NewOLM"). + reportProblemsToJiraComponent("olm"). + contactPerson("joe"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableForClusterProfile(SelfManaged, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateNewOLMCatalogdAPIV1Metas = newFeatureGate("NewOLMCatalogdAPIV1Metas"). + reportProblemsToJiraComponent("olm"). + contactPerson("jordank"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1749"). + enableForClusterProfile(SelfManaged, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateNewOLMPreflightPermissionChecks = newFeatureGate("NewOLMPreflightPermissionChecks"). + reportProblemsToJiraComponent("olm"). + contactPerson("tshort"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1768"). + enableForClusterProfile(SelfManaged, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateNewOLMOwnSingleNamespace = newFeatureGate("NewOLMOwnSingleNamespace"). + reportProblemsToJiraComponent("olm"). + contactPerson("nschieder"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1774"). + enableForClusterProfile(SelfManaged, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateNewOLMWebhookProviderOpenshiftServiceCA = newFeatureGate("NewOLMWebhookProviderOpenshiftServiceCA"). + reportProblemsToJiraComponent("olm"). + contactPerson("pegoncal"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1844"). + enableForClusterProfile(SelfManaged, configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateInsightsOnDemandDataGather = newFeatureGate("InsightsOnDemandDataGather"). + reportProblemsToJiraComponent("insights"). + contactPerson("tremes"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateInsightsConfig = newFeatureGate("InsightsConfig"). + reportProblemsToJiraComponent("insights"). + contactPerson("tremes"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateMetricsCollectionProfiles = newFeatureGate("MetricsCollectionProfiles"). + reportProblemsToJiraComponent("Monitoring"). + contactPerson("rexagod"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateClusterAPIInstallIBMCloud = newFeatureGate("ClusterAPIInstallIBMCloud"). + reportProblemsToJiraComponent("Installer"). + contactPerson("cjschaef"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateMachineAPIMigration = newFeatureGate("MachineAPIMigration"). + reportProblemsToJiraComponent("OCPCLOUD"). + contactPerson("jspeed"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateClusterAPIMachineManagement = newFeatureGate("ClusterAPIMachineManagement"). + reportProblemsToJiraComponent("Cloud Compute / Cluster API Providers"). + contactPerson("ddonati"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1465"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateClusterAPIMachineManagementVSphere = newFeatureGate("ClusterAPIMachineManagementVSphere"). + reportProblemsToJiraComponent("SPLAT"). + contactPerson("jcpowermac"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1465"). + enableIn(configv1.DevPreviewNoUpgrade). + mustRegister() + + FeatureGateClusterMonitoringConfig = newFeatureGate("ClusterMonitoringConfig"). + reportProblemsToJiraComponent("Monitoring"). + contactPerson("marioferh"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateMultiArchInstallAzure = newFeatureGate("MultiArchInstallAzure"). + reportProblemsToJiraComponent("Installer"). + contactPerson("r4f4"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + mustRegister() + + FeatureGateImageStreamImportMode = newFeatureGate("ImageStreamImportMode"). + reportProblemsToJiraComponent("Multi-Arch"). + contactPerson("psundara"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateUserNamespacesSupport = newFeatureGate("UserNamespacesSupport"). + reportProblemsToJiraComponent("Node"). + contactPerson("haircommander"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/127"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + // Note: this feature is perma-alpha, but it is safe and desireable to enable. + // It was an oversight in upstream to not remove the feature gate after the version skew became safe in 1.33. + // See https://github.com/kubernetes/enhancements/tree/d4226c42/keps/sig-node/127-user-namespaces#pod-security-standards-pss-integration + FeatureGateUserNamespacesPodSecurityStandards = newFeatureGate("UserNamespacesPodSecurityStandards"). + reportProblemsToJiraComponent("Node"). + contactPerson("haircommander"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/127"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateProcMountType = newFeatureGate("ProcMountType"). + reportProblemsToJiraComponent("Node"). + contactPerson("haircommander"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/4265"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateVSphereMultiNetworks = newFeatureGate("VSphereMultiNetworks"). + reportProblemsToJiraComponent("SPLAT"). + contactPerson("rvanderp"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateIngressControllerDynamicConfigurationManager = newFeatureGate("IngressControllerDynamicConfigurationManager"). + reportProblemsToJiraComponent("Networking/router"). + contactPerson("miciah"). + productScope(ocpSpecific). + enhancementPR(legacyFeatureGateWithoutEnhancement). + enableIn(configv1.DevPreviewNoUpgrade). + mustRegister() + + FeatureGateMinimumKubeletVersion = newFeatureGate("MinimumKubeletVersion"). + reportProblemsToJiraComponent("Node"). + contactPerson("haircommander"). + productScope(ocpSpecific). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + enhancementPR("https://github.com/openshift/enhancements/pull/1697"). + mustRegister() + + FeatureGateNutanixMultiSubnets = newFeatureGate("NutanixMultiSubnets"). + reportProblemsToJiraComponent("Cloud Compute / Nutanix Provider"). + contactPerson("yanhli"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1711"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateKMSEncryptionProvider = newFeatureGate("KMSEncryptionProvider"). + reportProblemsToJiraComponent("kube-apiserver"). + contactPerson("swghosh"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1682"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateHighlyAvailableArbiter = newFeatureGate("HighlyAvailableArbiter"). + reportProblemsToJiraComponent("Two Node with Arbiter"). + contactPerson("eggfoobar"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1674"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateCVOConfiguration = newFeatureGate("ClusterVersionOperatorConfiguration"). + reportProblemsToJiraComponent("Cluster Version Operator"). + contactPerson("dhurta"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1492"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateGCPCustomAPIEndpoints = newFeatureGate("GCPCustomAPIEndpoints"). + reportProblemsToJiraComponent("Installer"). + contactPerson("barbacbd"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1492"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateDyanmicServiceEndpointIBMCloud = newFeatureGate("DyanmicServiceEndpointIBMCloud"). + reportProblemsToJiraComponent("Cloud Compute / IBM Provider"). + contactPerson("jared-hayes-dev"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1712"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateSELinuxMount = newFeatureGate("SELinuxMount"). + reportProblemsToJiraComponent("Storage / Kubernetes"). + contactPerson("jsafrane"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/1710"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateDualReplica = newFeatureGate("DualReplica"). + reportProblemsToJiraComponent("Two Node Fencing"). + contactPerson("jaypoulz"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1675"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateGatewayAPIController = newFeatureGate("GatewayAPIController"). + reportProblemsToJiraComponent("Routing"). + contactPerson("miciah"). + productScope(ocpSpecific). + // Previously, the "GatewayAPI" feature gate managed both the GatewayAPI CRDs + // and the Gateway Controller. However, with the introduction of Gateway CRD + // lifecycle management (EP#1756), these responsibilities were separated. + // A dedicated feature gate now controls the Gateway Controller to distinguish + // its production readiness from that of the CRDs. + enhancementPR("https://github.com/openshift/enhancements/pull/1756"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureShortCertRotation = newFeatureGate("ShortCertRotation"). + reportProblemsToJiraComponent("kube-apiserver"). + contactPerson("vrutkovs"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1670"). + mustRegister() + + FeatureGateVSphereConfigurableMaxAllowedBlockVolumesPerNode = newFeatureGate("VSphereConfigurableMaxAllowedBlockVolumesPerNode"). + reportProblemsToJiraComponent("Storage / Kubernetes External Components"). + contactPerson("rbednar"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1748"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAzureMultiDisk = newFeatureGate("AzureMultiDisk"). + reportProblemsToJiraComponent("splat"). + contactPerson("jcpowermac"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1779"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateStoragePerformantSecurityPolicy = newFeatureGate("StoragePerformantSecurityPolicy"). + reportProblemsToJiraComponent("Storage / Kubernetes External Components"). + contactPerson("hekumar"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1804"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateMultiDiskSetup = newFeatureGate("MultiDiskSetup"). + reportProblemsToJiraComponent("splat"). + contactPerson("jcpowermac"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1805"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAWSDedicatedHosts = newFeatureGate("AWSDedicatedHosts"). + reportProblemsToJiraComponent("splat"). + contactPerson("rvanderp3"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1781"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateVSphereMixedNodeEnv = newFeatureGate("VSphereMixedNodeEnv"). + reportProblemsToJiraComponent("splat"). + contactPerson("vr4manta"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1772"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGatePreconfiguredUDNAddresses = newFeatureGate("PreconfiguredUDNAddresses"). + reportProblemsToJiraComponent("Networking/ovn-kubernetes"). + contactPerson("kyrtapz"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1793"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateAWSServiceLBNetworkSecurityGroup = newFeatureGate("AWSServiceLBNetworkSecurityGroup"). + reportProblemsToJiraComponent("Cloud Compute / Cloud Controller Manager"). + contactPerson("mtulio"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1802"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateImageVolume = newFeatureGate("ImageVolume"). + reportProblemsToJiraComponent("Node"). + contactPerson("haircommander"). + productScope(kubernetes). + enhancementPR("https://github.com/openshift/enhancements/pull/1792"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). + mustRegister() + + FeatureGateNoRegistryClusterOperations = newFeatureGate("NoRegistryClusterOperations"). + reportProblemsToJiraComponent("Installer / Agent based installation"). + contactPerson("andfasano"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1821"). + enableForClusterProfile(SelfManaged, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateGCPClusterHostedDNSInstall = newFeatureGate("GCPClusterHostedDNSInstall"). + reportProblemsToJiraComponent("Installer"). + contactPerson("barbacbd"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1468"). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAWSClusterHostedDNSInstall = newFeatureGate("AWSClusterHostedDNSInstall"). + reportProblemsToJiraComponent("Installer"). + contactPerson("barbacbd"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1468"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateGCPCustomAPIEndpointsInstall = newFeatureGate("GCPCustomAPIEndpointsInstall"). + reportProblemsToJiraComponent("Installer"). + contactPerson("barbacbd"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1492"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateIrreconcilableMachineConfig = newFeatureGate("IrreconcilableMachineConfig"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("pabrodri"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1785"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + FeatureGateAWSDualStackInstall = newFeatureGate("AWSDualStackInstall"). + reportProblemsToJiraComponent("Installer"). + contactPerson("sadasu"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1806"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateAzureDualStackInstall = newFeatureGate("AzureDualStackInstall"). + reportProblemsToJiraComponent("Installer"). + contactPerson("jhixson74"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1806"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateGCPDualStackInstall = newFeatureGate("GCPDualStackInstall"). + reportProblemsToJiraComponent("Installer"). + contactPerson("barbacbd"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1806"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureCBORServingAndStorage = newFeatureGate("CBORServingAndStorage"). + reportProblemsToJiraComponent("kube-apiserver"). + contactPerson("benluddy"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/4222"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureCBORClientsAllowCBOR = newFeatureGate("ClientsAllowCBOR"). + reportProblemsToJiraComponent("kube-apiserver"). + contactPerson("benluddy"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/4222"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureClientsPreferCBOR = newFeatureGate("ClientsPreferCBOR"). + reportProblemsToJiraComponent("kube-apiserver"). + contactPerson("benluddy"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/4222"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureEventTTL = newFeatureGate("EventTTL"). + reportProblemsToJiraComponent("kube-apiserver"). + contactPerson("tjungblu"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1857"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateMutableCSINodeAllocatableCount = newFeatureGate("MutableCSINodeAllocatableCount"). + reportProblemsToJiraComponent("Storage / Kubernetes External Components"). + contactPerson("jsafrane"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/4876"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + FeatureGateOSStreams = newFeatureGate("OSStreams"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("pabrodri"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1874"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateCRDCompatibilityRequirementOperator = newFeatureGate("CRDCompatibilityRequirementOperator"). + reportProblemsToJiraComponent("Cloud Compute / Cluster API Providers"). + contactPerson("ddonati"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1845"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + FeatureGateOnPremDNSRecords = newFeatureGate("OnPremDNSRecords"). + reportProblemsToJiraComponent("Networking / On-Prem DNS"). + contactPerson("bnemec"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1803"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() +) diff --git a/etcd/vendor/github.com/openshift/api/features/legacyfeaturegates.go b/etcd/vendor/github.com/openshift/api/features/legacyfeaturegates.go new file mode 100644 index 0000000000..dd11fdf663 --- /dev/null +++ b/etcd/vendor/github.com/openshift/api/features/legacyfeaturegates.go @@ -0,0 +1,119 @@ +package features + +import "k8s.io/apimachinery/pkg/util/sets" + +var legacyFeatureGates = sets.New( + "AWSClusterHostedDNS", + // never add to this list, if you think you have an exception ask @deads2k + "AWSEFSDriverVolumeMetrics", + // never add to this list, if you think you have an exception ask @deads2k + "AdditionalRoutingCapabilities", + // never add to this list, if you think you have an exception ask @deads2k + "AdminNetworkPolicy", + // never add to this list, if you think you have an exception ask @deads2k + "AlibabaPlatform", + // never add to this list, if you think you have an exception ask @deads2k + "AutomatedEtcdBackup", + // never add to this list, if you think you have an exception ask @deads2k + "AzureWorkloadIdentity", + // never add to this list, if you think you have an exception ask @deads2k + "BootcNodeManagement", + // never add to this list, if you think you have an exception ask @deads2k + "BuildCSIVolumes", + // never add to this list, if you think you have an exception ask @deads2k + "ClusterAPIInstall", + // never add to this list, if you think you have an exception ask @deads2k + "ClusterAPIInstallIBMCloud", + // never add to this list, if you think you have an exception ask @deads2k + "ClusterMonitoringConfig", + // never add to this list, if you think you have an exception ask @deads2k + "DNSNameResolver", + // never add to this list, if you think you have an exception ask @deads2k + "EtcdBackendQuota", + // never add to this list, if you think you have an exception ask @deads2k + "Example", + // never add to this list, if you think you have an exception ask @deads2k + "Example2", + // never add to this list, if you think you have an exception ask @deads2k + "GCPClusterHostedDNS", + // never add to this list, if you think you have an exception ask @deads2k + "GatewayAPI", + // never add to this list, if you think you have an exception ask @deads2k + "HardwareSpeed", + // never add to this list, if you think you have an exception ask @deads2k + "ImageStreamImportMode", + // never add to this list, if you think you have an exception ask @deads2k + "IngressControllerDynamicConfigurationManager", + // never add to this list, if you think you have an exception ask @deads2k + "IngressControllerLBSubnetsAWS", + // never add to this list, if you think you have an exception ask @deads2k + "InsightsConfig", + // never add to this list, if you think you have an exception ask @deads2k + "InsightsConfigAPI", + // never add to this list, if you think you have an exception ask @deads2k + "InsightsOnDemandDataGather", + // never add to this list, if you think you have an exception ask @deads2k + "InsightsRuntimeExtractor", + // never add to this list, if you think you have an exception ask @deads2k + "KMSv1", + // never add to this list, if you think you have an exception ask @deads2k + "MachineAPIMigration", + // never add to this list, if you think you have an exception ask @deads2k + "MachineAPIOperatorDisableMachineHealthCheckController", + // never add to this list, if you think you have an exception ask @deads2k + "MachineAPIProviderOpenStack", + // never add to this list, if you think you have an exception ask @deads2k + "MachineConfigNodes", + // never add to this list, if you think you have an exception ask @deads2k + "ManagedBootImages", + // never add to this list, if you think you have an exception ask @deads2k + "ManagedBootImagesAWS", + // never add to this list, if you think you have an exception ask @deads2k + "MetricsCollectionProfiles", + // never add to this list, if you think you have an exception ask @deads2k + "MixedCPUsAllocation", + // never add to this list, if you think you have an exception ask @deads2k + "MultiArchInstallAWS", + // never add to this list, if you think you have an exception ask @deads2k + "MultiArchInstallAzure", + // never add to this list, if you think you have an exception ask @deads2k + "MultiArchInstallGCP", + // never add to this list, if you think you have an exception ask @deads2k + "NetworkDiagnosticsConfig", + // never add to this list, if you think you have an exception ask @deads2k + "NetworkLiveMigration", + // never add to this list, if you think you have an exception ask @deads2k + "NetworkSegmentation", + // never add to this list, if you think you have an exception ask @deads2k + "NewOLM", + // never add to this list, if you think you have an exception ask @deads2k + "OVNObservability", + // never add to this list, if you think you have an exception ask @deads2k + "PersistentIPsForVirtualization", + // never add to this list, if you think you have an exception ask @deads2k + "PinnedImages", + // never add to this list, if you think you have an exception ask @deads2k + "PrivateHostedZoneAWS", + // never add to this list, if you think you have an exception ask @deads2k + "RouteAdvertisements", + // never add to this list, if you think you have an exception ask @deads2k + "RouteExternalCertificate", + // never add to this list, if you think you have an exception ask @deads2k + "SetEIPForNLBIngressController", + // never add to this list, if you think you have an exception ask @deads2k + "SignatureStores", + // never add to this list, if you think you have an exception ask @deads2k + "SigstoreImageVerification", + // never add to this list, if you think you have an exception ask @deads2k + "UpgradeStatus", + // never add to this list, if you think you have an exception ask @deads2k + "VSphereControlPlaneMachineSet", + // never add to this list, if you think you have an exception ask @deads2k + "VSphereDriverConfiguration", + // never add to this list, if you think you have an exception ask @deads2k + "VSphereMultiNetworks", + // never add to this list, if you think you have an exception ask @deads2k + "VSphereMultiVCenters", + // never add to this list, if you think you have an exception ask @deads2k + "VSphereStaticIPs", +) diff --git a/etcd/vendor/github.com/openshift/api/features/util.go b/etcd/vendor/github.com/openshift/api/features/util.go new file mode 100644 index 0000000000..59bb7bff40 --- /dev/null +++ b/etcd/vendor/github.com/openshift/api/features/util.go @@ -0,0 +1,224 @@ +package features + +import ( + "fmt" + configv1 "github.com/openshift/api/config/v1" + "net/url" + "strings" +) + +// FeatureGateDescription is a golang-only interface used to contains details for a feature gate. +type FeatureGateDescription struct { + // FeatureGateAttributes is the information that appears in the API + FeatureGateAttributes configv1.FeatureGateAttributes + + // OwningJiraComponent is the jira component that owns most of the impl and first assignment for the bug. + // This is the team that owns the feature long term. + OwningJiraComponent string + // ResponsiblePerson is the person who is on the hook for first contact. This is often, but not always, a team lead. + // It is someone who can make the promise on the behalf of the team. + ResponsiblePerson string + // OwningProduct is the product that owns the lifecycle of the gate. + OwningProduct OwningProduct + // EnhancementPR is the PR for the enhancement. + EnhancementPR string +} + +type FeatureGateEnabledDisabled struct { + Enabled []FeatureGateDescription + Disabled []FeatureGateDescription +} + +type ClusterProfileName string + +var ( + Hypershift = ClusterProfileName("include.release.openshift.io/ibm-cloud-managed") + SelfManaged = ClusterProfileName("include.release.openshift.io/self-managed-high-availability") + AllClusterProfiles = []ClusterProfileName{Hypershift, SelfManaged} +) + +type OwningProduct string + +var ( + ocpSpecific = OwningProduct("OCP") + kubernetes = OwningProduct("Kubernetes") +) + +type featureGateBuilder struct { + name string + owningJiraComponent string + responsiblePerson string + owningProduct OwningProduct + enhancementPRURL string + + statusByClusterProfileByFeatureSet map[ClusterProfileName]map[configv1.FeatureSet]bool +} + +const ( + legacyFeatureGateWithoutEnhancement = "FeatureGate predates 4.18" +) + +// newFeatureGate featuregate are disabled in every FeatureSet and selectively enabled +func newFeatureGate(name string) *featureGateBuilder { + b := &featureGateBuilder{ + name: name, + statusByClusterProfileByFeatureSet: map[ClusterProfileName]map[configv1.FeatureSet]bool{}, + } + for _, clusterProfile := range AllClusterProfiles { + byFeatureSet := map[configv1.FeatureSet]bool{} + for _, featureSet := range configv1.AllFixedFeatureSets { + byFeatureSet[featureSet] = false + } + b.statusByClusterProfileByFeatureSet[clusterProfile] = byFeatureSet + } + return b +} + +func (b *featureGateBuilder) reportProblemsToJiraComponent(owningJiraComponent string) *featureGateBuilder { + b.owningJiraComponent = owningJiraComponent + return b +} + +func (b *featureGateBuilder) contactPerson(responsiblePerson string) *featureGateBuilder { + b.responsiblePerson = responsiblePerson + return b +} + +func (b *featureGateBuilder) productScope(owningProduct OwningProduct) *featureGateBuilder { + b.owningProduct = owningProduct + return b +} + +func (b *featureGateBuilder) enhancementPR(url string) *featureGateBuilder { + b.enhancementPRURL = url + return b +} + +func (b *featureGateBuilder) enableIn(featureSets ...configv1.FeatureSet) *featureGateBuilder { + for clusterProfile := range b.statusByClusterProfileByFeatureSet { + for _, featureSet := range featureSets { + b.statusByClusterProfileByFeatureSet[clusterProfile][featureSet] = true + } + } + return b +} + +func (b *featureGateBuilder) enableForClusterProfile(clusterProfile ClusterProfileName, featureSets ...configv1.FeatureSet) *featureGateBuilder { + for _, featureSet := range featureSets { + b.statusByClusterProfileByFeatureSet[clusterProfile][featureSet] = true + } + return b +} + +func (b *featureGateBuilder) register() (configv1.FeatureGateName, error) { + if len(b.name) == 0 { + return "", fmt.Errorf("missing name") + } + if len(b.owningJiraComponent) == 0 { + return "", fmt.Errorf("missing owningJiraComponent") + } + if len(b.responsiblePerson) == 0 { + return "", fmt.Errorf("missing responsiblePerson") + } + if len(b.owningProduct) == 0 { + return "", fmt.Errorf("missing owningProduct") + } + _, enhancementPRErr := url.Parse(b.enhancementPRURL) + switch { + case b.enhancementPRURL == legacyFeatureGateWithoutEnhancement: + if !legacyFeatureGates.Has(b.name) { + return "", fmt.Errorf("FeatureGate/%s is a new feature gate, not an existing one. It must have an enhancementPR with GA Graduation Criteria like https://github.com/openshift/enhancements/pull/#### or https://github.com/kubernetes/enhancements/issues/####", b.name) + } + + case len(b.enhancementPRURL) == 0: + return "", fmt.Errorf("FeatureGate/%s is missing an enhancementPR with GA Graduation Criteria like https://github.com/openshift/enhancements/pull/#### or https://github.com/kubernetes/enhancements/issues/####", b.name) + + case !strings.HasPrefix(b.enhancementPRURL, "https://github.com/openshift/enhancements/pull/") && !strings.HasPrefix(b.enhancementPRURL, "https://github.com/kubernetes/enhancements/issues/"): + return "", fmt.Errorf("FeatureGate/%s enhancementPR format is incorrect; must be like https://github.com/openshift/enhancements/pull/#### or https://github.com/kubernetes/enhancements/issues/####", b.name) + + case enhancementPRErr != nil: + return "", fmt.Errorf("FeatureGate/%s is enhancementPR is invalid: %w", b.name, enhancementPRErr) + } + + featureGateName := configv1.FeatureGateName(b.name) + description := FeatureGateDescription{ + FeatureGateAttributes: configv1.FeatureGateAttributes{ + Name: featureGateName, + }, + OwningJiraComponent: b.owningJiraComponent, + ResponsiblePerson: b.responsiblePerson, + OwningProduct: b.owningProduct, + EnhancementPR: b.enhancementPRURL, + } + + // statusByClusterProfileByFeatureSet is initialized by constructor to be false for every combination + for clusterProfile, byFeatureSet := range b.statusByClusterProfileByFeatureSet { + for featureSet, enabled := range byFeatureSet { + if _, ok := allFeatureGates[clusterProfile]; !ok { + allFeatureGates[clusterProfile] = map[configv1.FeatureSet]*FeatureGateEnabledDisabled{} + } + if _, ok := allFeatureGates[clusterProfile][featureSet]; !ok { + allFeatureGates[clusterProfile][featureSet] = &FeatureGateEnabledDisabled{} + } + + if enabled { + allFeatureGates[clusterProfile][featureSet].Enabled = append(allFeatureGates[clusterProfile][featureSet].Enabled, description) + } else { + allFeatureGates[clusterProfile][featureSet].Disabled = append(allFeatureGates[clusterProfile][featureSet].Disabled, description) + } + } + } + + return featureGateName, nil +} + +func (b *featureGateBuilder) mustRegister() configv1.FeatureGateName { + ret, err := b.register() + if err != nil { + panic(err) + } + return ret +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FeatureGateEnabledDisabled) DeepCopyInto(out *FeatureGateEnabledDisabled) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = make([]FeatureGateDescription, len(*in)) + copy(*out, *in) + } + if in.Disabled != nil { + in, out := &in.Disabled, &out.Disabled + *out = make([]FeatureGateDescription, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureGateEnabledDisabled. +func (in *FeatureGateEnabledDisabled) DeepCopy() *FeatureGateEnabledDisabled { + if in == nil { + return nil + } + out := new(FeatureGateEnabledDisabled) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FeatureGateDescription) DeepCopyInto(out *FeatureGateDescription) { + *out = *in + out.FeatureGateAttributes = in.FeatureGateAttributes + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FeatureGateDescription. +func (in *FeatureGateDescription) DeepCopy() *FeatureGateDescription { + if in == nil { + return nil + } + out := new(FeatureGateDescription) + in.DeepCopyInto(out) + return out +} diff --git a/etcd/vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go b/etcd/vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go index 2799904482..53c71aabb6 100644 --- a/etcd/vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go +++ b/etcd/vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go @@ -81,7 +81,6 @@ const ( CinderCSIDriver CSIDriverName = "cinder.csi.openstack.org" VSphereCSIDriver CSIDriverName = "csi.vsphere.vmware.com" ManilaCSIDriver CSIDriverName = "manila.csi.openstack.org" - OvirtCSIDriver CSIDriverName = "csi.ovirt.org" KubevirtCSIDriver CSIDriverName = "csi.kubevirt.io" SharedResourcesCSIDriver CSIDriverName = "csi.sharedresource.openshift.io" AlibabaDiskCSIDriver CSIDriverName = "diskplugin.csi.alibabacloud.com" diff --git a/etcd/vendor/github.com/openshift/api/operator/v1/types_ingress.go b/etcd/vendor/github.com/openshift/api/operator/v1/types_ingress.go index 2dac08f099..46b906518d 100644 --- a/etcd/vendor/github.com/openshift/api/operator/v1/types_ingress.go +++ b/etcd/vendor/github.com/openshift/api/operator/v1/types_ingress.go @@ -35,6 +35,7 @@ import ( // // Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). // +openshift:compatibility-gen:level=1 +// +kubebuilder:validation:XValidation:rule="!has(self.spec.domain) || size('router-' + self.metadata.name + '.' + self.spec.domain) <= 253",message="The combined 'router-' + metadata.name + '.' + .spec.domain cannot exceed 253 characters" type IngressController struct { metav1.TypeMeta `json:",inline"` @@ -68,6 +69,22 @@ type IngressControllerSpec struct { // // If empty, defaults to ingress.config.openshift.io/cluster .spec.domain. // + // The domain value must be a valid DNS name. It must consist of lowercase + // alphanumeric characters, '-' or '.', and each label must start and end + // with an alphanumeric character and not exceed 63 characters. Maximum + // length of a valid DNS domain is 253 characters. + // + // The implementation may add a prefix such as "router-default." to the domain + // when constructing the router canonical hostname. To ensure the resulting + // hostname does not exceed the DNS maximum length of 253 characters, + // the domain length is additionally validated at the IngressController object + // level. For the maximum length of the domain value itself, the shortest + // possible variant of the prefix and the ingress controller name was considered + // for example "router-a." + // + // +kubebuilder:validation:MaxLength=244 + // +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character" + // +kubebuilder:validation:XValidation:rule="self.split('.').all(label, size(label) <= 63)",message="each DNS label must not exceed 63 characters" // +optional Domain string `json:"domain,omitempty"` diff --git a/etcd/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go b/etcd/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go index 483d9720da..d3475d9024 100644 --- a/etcd/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go +++ b/etcd/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go @@ -1063,7 +1063,7 @@ func (IngressControllerSetHTTPHeader) SwaggerDoc() map[string]string { var map_IngressControllerSpec = map[string]string{ "": "IngressControllerSpec is the specification of the desired behavior of the IngressController.", - "domain": "domain is a DNS name serviced by the ingress controller and is used to configure multiple features:\n\n* For the LoadBalancerService endpoint publishing strategy, domain is\n used to configure DNS records. See endpointPublishingStrategy.\n\n* When using a generated default certificate, the certificate will be valid\n for domain and its subdomains. See defaultCertificate.\n\n* The value is published to individual Route statuses so that end-users\n know where to target external DNS records.\n\ndomain must be unique among all IngressControllers, and cannot be updated.\n\nIf empty, defaults to ingress.config.openshift.io/cluster .spec.domain.", + "domain": "domain is a DNS name serviced by the ingress controller and is used to configure multiple features:\n\n* For the LoadBalancerService endpoint publishing strategy, domain is\n used to configure DNS records. See endpointPublishingStrategy.\n\n* When using a generated default certificate, the certificate will be valid\n for domain and its subdomains. See defaultCertificate.\n\n* The value is published to individual Route statuses so that end-users\n know where to target external DNS records.\n\ndomain must be unique among all IngressControllers, and cannot be updated.\n\nIf empty, defaults to ingress.config.openshift.io/cluster .spec.domain.\n\nThe domain value must be a valid DNS name. It must consist of lowercase alphanumeric characters, '-' or '.', and each label must start and end with an alphanumeric character and not exceed 63 characters. Maximum length of a valid DNS domain is 253 characters.\n\nThe implementation may add a prefix such as \"router-default.\" to the domain when constructing the router canonical hostname. To ensure the resulting hostname does not exceed the DNS maximum length of 253 characters, the domain length is additionally validated at the IngressController object level. For the maximum length of the domain value itself, the shortest possible variant of the prefix and the ingress controller name was considered for example \"router-a.\"", "httpErrorCodePages": "httpErrorCodePages specifies a configmap with custom error pages. The administrator must create this configmap in the openshift-config namespace. This configmap should have keys in the format \"error-page-.http\", where is an HTTP error code. For example, \"error-page-503.http\" defines an error page for HTTP 503 responses. Currently only error pages for 503 and 404 responses can be customized. Each value in the configmap should be the full response, including HTTP headers. Eg- https://raw.githubusercontent.com/openshift/router/fadab45747a9b30cc3f0a4b41ad2871f95827a93/images/router/haproxy/conf/error-page-503.http If this field is empty, the ingress controller uses the default error pages.", "replicas": "replicas is the desired number of ingress controller replicas. If unset, the default depends on the value of the defaultPlacement field in the cluster config.openshift.io/v1/ingresses status.\n\nThe value of replicas is set based on the value of a chosen field in the Infrastructure CR. If defaultPlacement is set to ControlPlane, the chosen field will be controlPlaneTopology. If it is set to Workers the chosen field will be infrastructureTopology. Replicas will then be set to 1 or 2 based whether the chosen field's value is SingleReplica or HighlyAvailable, respectively.\n\nThese defaults are subject to change.", "endpointPublishingStrategy": "endpointPublishingStrategy is used to publish the ingress controller endpoints to other networks, enable load balancer integrations, etc.\n\nIf unset, the default is based on infrastructure.config.openshift.io/cluster .status.platform:\n\n AWS: LoadBalancerService (with External scope)\n Azure: LoadBalancerService (with External scope)\n GCP: LoadBalancerService (with External scope)\n IBMCloud: LoadBalancerService (with External scope)\n AlibabaCloud: LoadBalancerService (with External scope)\n Libvirt: HostNetwork\n\nAny other platform types (including None) default to HostNetwork.\n\nendpointPublishingStrategy cannot be updated.", diff --git a/etcd/vendor/github.com/openshift/microshift/pkg/config/apiserver.go b/etcd/vendor/github.com/openshift/microshift/pkg/config/apiserver.go index 621950d391..cea5eb3be6 100644 --- a/etcd/vendor/github.com/openshift/microshift/pkg/config/apiserver.go +++ b/etcd/vendor/github.com/openshift/microshift/pkg/config/apiserver.go @@ -2,10 +2,14 @@ package config import ( "fmt" + "reflect" "slices" configv1 "github.com/openshift/api/config/v1" + featuresUtils "github.com/openshift/api/features" "github.com/openshift/library-go/pkg/crypto" + + "k8s.io/apimachinery/pkg/util/sets" ) type ApiServer struct { @@ -27,6 +31,8 @@ type ApiServer struct { TLS TLSConfig `json:"tls"` + FeatureGates FeatureGates `json:"featureGates"` + // The URL and Port of the API server cannot be changed by the user. URL string `json:"-"` Port int `json:"-"` @@ -127,3 +133,99 @@ func (t *TLSConfig) Validate() error { func getIANACipherSuites(suites []string) []string { return crypto.OpenSSLToIANACipherSuites(suites) } + +const ( + FeatureSetCustomNoUpgrade = "CustomNoUpgrade" + FeatureSetTechPreviewNoUpgrade = "TechPreviewNoUpgrade" + FeatureSetDevPreviewNoUpgrade = "DevPreviewNoUpgrade" +) + +type CustomNoUpgrade struct { + Enabled []string `json:"enabled"` + Disabled []string `json:"disabled"` +} + +// RequiredFeatureGates are the feature gates that are always enabled by MicroShift. They are defined here to enable config validation. +// They are injected into the feature-gates field later by the microshift kube-apiserver controller. +var RequiredFeatureGates = []string{"UserNamespacesSupport", "UserNamespacesPodSecurityStandards"} + +type FeatureGates struct { + FeatureSet string `json:"featureSet"` + CustomNoUpgrade CustomNoUpgrade `json:"customNoUpgrade"` +} + +func (fg FeatureGates) ToApiserverArgs() ([]string, error) { + ret := sets.NewString() + + switch fg.FeatureSet { + case FeatureSetCustomNoUpgrade: + for _, feature := range fg.CustomNoUpgrade.Enabled { + ret.Insert(fmt.Sprintf("%s=true", feature)) + } + for _, feature := range fg.CustomNoUpgrade.Disabled { + ret.Insert(fmt.Sprintf("%s=false", feature)) + } + case FeatureSetDevPreviewNoUpgrade, FeatureSetTechPreviewNoUpgrade: + fgEnabledDisabled, err := featuresUtils.FeatureSets(featuresUtils.SelfManaged, configv1.FeatureSet(fg.FeatureSet)) + if err != nil { + return nil, fmt.Errorf("failed to get feature set gates: %w", err) + } + for _, f := range fgEnabledDisabled.Enabled { + ret.Insert(fmt.Sprintf("%s=true", f.FeatureGateAttributes.Name)) + } + for _, f := range fgEnabledDisabled.Disabled { + ret.Insert(fmt.Sprintf("%s=false", f.FeatureGateAttributes.Name)) + } + } + return ret.List(), nil +} + +// Implement the GoStringer interface for better %#v printing +func (fg FeatureGates) GoString() string { + return fmt.Sprintf("FeatureGates{FeatureSet: %q, CustomNoUpgrade: %#v}", fg.FeatureSet, fg.CustomNoUpgrade) +} + +func (fg *FeatureGates) validateFeatureGates() error { + // FG is unset + if fg == nil || reflect.DeepEqual(*fg, FeatureGates{}) { + return nil + } + // Must use a recognized feature set, or else empty + if fg.FeatureSet != "" && fg.FeatureSet != FeatureSetCustomNoUpgrade && fg.FeatureSet != FeatureSetTechPreviewNoUpgrade && fg.FeatureSet != FeatureSetDevPreviewNoUpgrade { + return fmt.Errorf("invalid feature set: %s", fg.FeatureSet) + } + // Must set FeatureSet to CustomNoUpgrade to use custom feature gates + if fg.FeatureSet != FeatureSetCustomNoUpgrade && (len(fg.CustomNoUpgrade.Enabled) > 0 || len(fg.CustomNoUpgrade.Disabled) > 0) { + return fmt.Errorf("CustomNoUpgrade must be empty when FeatureSet is empty") + } + // Must set CustomNoUpgrade enabled or disabled lists when FeatureSet is CustomNoUpgrade + if fg.FeatureSet == FeatureSetCustomNoUpgrade && len(fg.CustomNoUpgrade.Enabled) == 0 && len(fg.CustomNoUpgrade.Disabled) == 0 { + return fmt.Errorf("CustomNoUpgrade enabled or disabled lists must be set when FeatureSet is CustomNoUpgrade") + } + + var errs = make(sets.Set[error], 0) + for _, requiredFG := range RequiredFeatureGates { + // Edge case: Users must not be allowed to explicitly disable required feature gates. + if sets.NewString(fg.CustomNoUpgrade.Disabled...).Has(requiredFG) { + errs.Insert(fmt.Errorf("required feature gate %s cannot be disabled: %s", requiredFG, fg.CustomNoUpgrade.Disabled)) + } + // Edge case: Users must not be allowed to explicitly enable required feature gates or else the config would be locked and the cluster + // would not be able to be upgraded. + if sets.New(fg.CustomNoUpgrade.Enabled...).Has(requiredFG) { + errs.Insert(fmt.Errorf("feature gate %s is explicitly enabled and cannot be enabled by the user", requiredFG)) + } + } + if errs.Len() > 0 { + return fmt.Errorf("invalid feature gates: %s", errs.UnsortedList()) + } + + // Must not have any feature gates that are enabled and disabled at the same time + enabledSet := sets.New(fg.CustomNoUpgrade.Enabled...) + disabledSet := sets.New(fg.CustomNoUpgrade.Disabled...) + inBothSets := enabledSet.Intersection(disabledSet) + if inBothSets.Len() > 0 { + return fmt.Errorf("featuregates cannot be enabled and disabled at the same time: %s", inBothSets.UnsortedList()) + } + + return nil +} diff --git a/etcd/vendor/github.com/openshift/microshift/pkg/config/config.go b/etcd/vendor/github.com/openshift/microshift/pkg/config/config.go index 8e9c645262..9313a048f6 100644 --- a/etcd/vendor/github.com/openshift/microshift/pkg/config/config.go +++ b/etcd/vendor/github.com/openshift/microshift/pkg/config/config.go @@ -56,7 +56,6 @@ type Config struct { Ingress IngressConfig `json:"ingress"` Storage Storage `json:"storage"` Telemetry Telemetry `json:"telemetry"` - // Settings specified in this section are transferred as-is into the Kubelet config. // +kubebuilder:validation:Schemaless Kubelet map[string]any `json:"kubelet"` @@ -123,9 +122,7 @@ func (c *Config) fillDefaults() error { HostnameOverride: hostname, NodeIP: nodeIP, } - c.DNS = DNS{ - BaseDomain: "example.com", - } + c.Network = Network{ ServiceNodePortRange: "30000-32767", } @@ -186,7 +183,7 @@ func (c *Config) fillDefaults() error { c.Kubelet = nil c.GenericDevicePlugin = genericDevicePluginDefaults() c.Telemetry = telemetryDefaults() - + c.DNS = dnsDefaults() return nil } @@ -418,6 +415,23 @@ func (c *Config) incorporateUserSettings(u *Config) { if u.Ingress.AccessLogging.HttpCaptureCookies != nil { c.Ingress.AccessLogging.HttpCaptureCookies = u.Ingress.AccessLogging.HttpCaptureCookies } + + // HostsWatcher configuration - only set if user provided it + if u.DNS.Hosts.Status != "" { + c.DNS.Hosts.Status = u.DNS.Hosts.Status + if u.DNS.Hosts.File != "" { + c.DNS.Hosts.File = u.DNS.Hosts.File + } + } + if u.ApiServer.FeatureGates.FeatureSet != "" { + c.ApiServer.FeatureGates.FeatureSet = u.ApiServer.FeatureGates.FeatureSet + } + if len(u.ApiServer.FeatureGates.CustomNoUpgrade.Enabled) > 0 { + c.ApiServer.FeatureGates.CustomNoUpgrade.Enabled = u.ApiServer.FeatureGates.CustomNoUpgrade.Enabled + } + if len(u.ApiServer.FeatureGates.CustomNoUpgrade.Disabled) > 0 { + c.ApiServer.FeatureGates.CustomNoUpgrade.Disabled = u.ApiServer.FeatureGates.CustomNoUpgrade.Disabled + } } // updateComputedValues examins the existing settings and converts any @@ -647,6 +661,13 @@ func (c *Config) validate() error { return fmt.Errorf("error validating Generic Device Plugin configuration: %v", err) } + if err := c.ApiServer.FeatureGates.validateFeatureGates(); err != nil { + return fmt.Errorf("error validating feature gates: %v", err) + } + + if err := c.DNS.validate(); err != nil { + return fmt.Errorf("error validating DNS: %v", err) + } return nil } diff --git a/etcd/vendor/github.com/openshift/microshift/pkg/config/dns.go b/etcd/vendor/github.com/openshift/microshift/pkg/config/dns.go index a0b9cd24d6..d8948449c9 100644 --- a/etcd/vendor/github.com/openshift/microshift/pkg/config/dns.go +++ b/etcd/vendor/github.com/openshift/microshift/pkg/config/dns.go @@ -1,5 +1,18 @@ package config +import ( + "fmt" + "os" + "path/filepath" +) + +const ( + HostsStatusEnabled HostsStatusEnum = "Enabled" + HostsStatusDisabled HostsStatusEnum = "Disabled" +) + +type HostsStatusEnum string + type DNS struct { // baseDomain is the base domain of the cluster. All managed DNS records will // be sub-domains of this base. @@ -13,4 +26,73 @@ type DNS struct { // +kubebuilder:default=example.com // +kubebuilder:example=microshift.example.com BaseDomain string `json:"baseDomain"` + + // Hosts contains configuration for the hosts file. + Hosts HostsConfig `json:"hosts,omitempty"` +} + +// HostsConfig contains configuration for the hosts file . +type HostsConfig struct { + // File is the path to the hosts file to monitor. + // If not specified, defaults to "/etc/hosts". + // +kubebuilder:default="/etc/hosts" + // +kubebuilder:example="/etc/hosts" + File string `json:"file,omitempty"` + + // Status controls whether the hosts file is enabled or disabled. + // Allowed values are "Enabled" and "Disabled". + // If not specified, defaults to "Disabled". + // +kubebuilder:default="Disabled" + // +kubebuilder:example="Enabled" + // +kubebuilder:validation:Enum=Enabled;Disabled + Status HostsStatusEnum `json:"status,omitempty"` +} + +func dnsDefaults() DNS { + return DNS{ + BaseDomain: "example.com", + Hosts: HostsConfig{ + File: "/etc/hosts", + Status: HostsStatusDisabled, + }, + } +} + +func (t *DNS) validate() error { + switch t.Hosts.Status { + case HostsStatusEnabled: + if t.Hosts.File == "" { + break + } + + cleanPath := filepath.Clean(t.Hosts.File) + + fi, err := os.Stat(cleanPath) + // Enforce ConfigMap requirement: the file must not exceed 1MiB, as it will be mounted into a ConfigMap. + if err == nil && fi.Size() > 1048576 { + return fmt.Errorf("hosts file %s exceeds 1MiB ConfigMap (and internal buffer) size limit (got %d bytes)", t.Hosts.File, fi.Size()) + } + if !filepath.IsAbs(cleanPath) { + return fmt.Errorf("hosts file path must be absolute: got %s", t.Hosts.File) + } + + _, err = os.Stat(cleanPath) + if os.IsNotExist(err) { + return fmt.Errorf("hosts file %s does not exist", t.Hosts.File) + } else if err != nil { + return fmt.Errorf("error checking hosts file %s: %v", t.Hosts.File, err) + } + + file, err := os.Open(t.Hosts.File) + if err != nil { + return fmt.Errorf("hosts file %s is not readable: %v", t.Hosts.File, err) + } + return file.Close() + + case HostsStatusDisabled: + return nil + default: + return fmt.Errorf("invalid hosts status: %s", t.Hosts.Status) + } + return nil } diff --git a/etcd/vendor/github.com/openshift/microshift/pkg/util/net.go b/etcd/vendor/github.com/openshift/microshift/pkg/util/net.go index 690ba82e8f..ba5c111c95 100644 --- a/etcd/vendor/github.com/openshift/microshift/pkg/util/net.go +++ b/etcd/vendor/github.com/openshift/microshift/pkg/util/net.go @@ -106,7 +106,7 @@ func RetryGet(ctx context.Context, url, additionalCAPath string) int { } } status := 0 - err = wait.PollUntilContextTimeout(ctx, 5*time.Second, 120*time.Second, false, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(ctx, time.Second, 120*time.Second, true, func(ctx context.Context) (bool, error) { c := http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ @@ -133,8 +133,8 @@ func RetryGet(ctx context.Context, url, additionalCAPath string) int { func RetryTCPConnection(ctx context.Context, host string, port string) bool { status := false - err := wait.PollUntilContextTimeout(ctx, 5*time.Second, 120*time.Second, false, func(ctx context.Context) (bool, error) { - timeout := 30 * time.Second + err := wait.PollUntilContextTimeout(ctx, time.Second, 120*time.Second, true, func(ctx context.Context) (bool, error) { + timeout := time.Second _, err := tcpnet.DialTimeout("tcp", tcpnet.JoinHostPort(host, port), timeout) if err == nil { diff --git a/etcd/vendor/go.etcd.io/bbolt/.go-version b/etcd/vendor/go.etcd.io/bbolt/.go-version index b6773170a5..7bdcec52d0 100644 --- a/etcd/vendor/go.etcd.io/bbolt/.go-version +++ b/etcd/vendor/go.etcd.io/bbolt/.go-version @@ -1 +1 @@ -1.23.10 +1.23.12 diff --git a/etcd/vendor/go.etcd.io/bbolt/tx.go b/etcd/vendor/go.etcd.io/bbolt/tx.go index 7123ded8fe..1669fb16a2 100644 --- a/etcd/vendor/go.etcd.io/bbolt/tx.go +++ b/etcd/vendor/go.etcd.io/bbolt/tx.go @@ -387,16 +387,43 @@ func (tx *Tx) Copy(w io.Writer) error { // WriteTo writes the entire database to a writer. // If err == nil then exactly tx.Size() bytes will be written into the writer. func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { - // Attempt to open reader with WriteFlag - f, err := tx.db.openFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0) - if err != nil { - return 0, err - } - defer func() { - if cerr := f.Close(); err == nil { - err = cerr + var f *os.File + // There is a risk that between the time a read-only transaction + // is created and the time the file is actually opened, the + // underlying db file at tx.db.path may have been replaced + // (e.g. via rename). In that case, opening the file again would + // unexpectedly point to a different file, rather than the one + // the transaction was based on. + // + // To overcome this, we reuse the already opened file handle when + // WritFlag not set. When the WriteFlag is set, we reopen the file + // but verify that it still refers to the same underlying file + // (by device and inode). If it does not, we fall back to + // reusing the existing already opened file handle. + if tx.WriteFlag != 0 { + // Attempt to open reader with WriteFlag + f, err = tx.db.openFile(tx.db.path, os.O_RDONLY|tx.WriteFlag, 0) + if err != nil { + return 0, err } - }() + + if ok, err := sameFile(tx.db.file, f); !ok { + lg := tx.db.Logger() + if cerr := f.Close(); cerr != nil { + lg.Errorf("failed to close the file (%s): %v", tx.db.path, cerr) + } + lg.Warningf("The underlying file has changed, so reuse the already opened file (%s): %v", tx.db.path, err) + f = tx.db.file + } else { + defer func() { + if cerr := f.Close(); err == nil { + err = cerr + } + }() + } + } else { + f = tx.db.file + } // Generate a meta page. We use the same page data for both meta pages. buf := make([]byte, tx.db.pageSize) @@ -423,13 +450,13 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { return n, fmt.Errorf("meta 1 copy: %s", err) } - // Move past the meta pages in the file. - if _, err := f.Seek(int64(tx.db.pageSize*2), io.SeekStart); err != nil { - return n, fmt.Errorf("seek: %s", err) - } + // Copy data pages using a SectionReader to avoid affecting f's offset. + dataOffset := int64(tx.db.pageSize * 2) + dataSize := tx.Size() - dataOffset + sr := io.NewSectionReader(f, dataOffset, dataSize) // Copy data pages. - wn, err := io.CopyN(w, f, tx.Size()-int64(tx.db.pageSize*2)) + wn, err := io.CopyN(w, sr, dataSize) n += wn if err != nil { return n, err @@ -438,6 +465,19 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { return n, nil } +func sameFile(f1, f2 *os.File) (bool, error) { + fi1, err := f1.Stat() + if err != nil { + return false, fmt.Errorf("failed to get fileInfo of the first file (%s): %w", f1.Name(), err) + } + fi2, err := f2.Stat() + if err != nil { + return false, fmt.Errorf("failed to get fileInfo of the second file (%s): %w", f2.Name(), err) + } + + return os.SameFile(fi1, fi2), nil +} + // CopyFile copies the entire database to file at the given path. // A reader transaction is maintained during the copy so it is safe to continue // using the database while a copy is in progress. diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/authpb/auth.pb.go b/etcd/vendor/go.etcd.io/etcd/api/v3/authpb/auth.pb.go index 16affcd62c..37374c5a71 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/authpb/auth.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/authpb/auth.pb.go @@ -232,29 +232,30 @@ func init() { func init() { proto.RegisterFile("auth.proto", fileDescriptor_8bbd6f3875b0e874) } var fileDescriptor_8bbd6f3875b0e874 = []byte{ - // 338 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xcf, 0x4e, 0xea, 0x40, - 0x14, 0xc6, 0x3b, 0xb4, 0x70, 0xdb, 0xc3, 0x85, 0x90, 0x13, 0x72, 0x6f, 0x83, 0x49, 0x6d, 0xba, - 0x6a, 0x5c, 0x54, 0x85, 0x8d, 0x5b, 0x8c, 0x2c, 0x5c, 0x49, 0x26, 0x18, 0x97, 0xa4, 0xa4, 0x13, - 0x24, 0xc0, 0x4c, 0x33, 0x83, 0x31, 0x6c, 0x7c, 0x0e, 0x17, 0x3e, 0x10, 0x4b, 0x1e, 0x41, 0xf0, - 0x45, 0x4c, 0x67, 0xf8, 0x13, 0xa2, 0xbb, 0xef, 0x7c, 0xe7, 0xfb, 0x66, 0x7e, 0x99, 0x01, 0x48, - 0x5f, 0x16, 0xcf, 0x49, 0x2e, 0xc5, 0x42, 0x60, 0xa5, 0xd0, 0xf9, 0xa8, 0xd5, 0x1c, 0x8b, 0xb1, - 0xd0, 0xd6, 0x65, 0xa1, 0xcc, 0x36, 0xba, 0x86, 0xfa, 0xa3, 0x62, 0xb2, 0x9b, 0x65, 0x0f, 0xf9, - 0x62, 0x22, 0xb8, 0xc2, 0x73, 0xa8, 0x72, 0x31, 0xcc, 0x53, 0xa5, 0x5e, 0x85, 0xcc, 0x7c, 0x12, - 0x92, 0xd8, 0xa5, 0xc0, 0x45, 0x7f, 0xe7, 0x44, 0x6f, 0xe0, 0x14, 0x15, 0x44, 0x70, 0x78, 0x3a, - 0x67, 0x3a, 0xf1, 0x97, 0x6a, 0x8d, 0x2d, 0x70, 0x0f, 0xcd, 0x92, 0xf6, 0x0f, 0x33, 0x36, 0xa1, - 0x2c, 0xc5, 0x8c, 0x29, 0xdf, 0x0e, 0xed, 0xd8, 0xa3, 0x66, 0xc0, 0x2b, 0xf8, 0x23, 0xcc, 0xcd, - 0xbe, 0x13, 0x92, 0xb8, 0xda, 0xfe, 0x97, 0x18, 0xe0, 0xe4, 0x94, 0x8b, 0xee, 0x63, 0xd1, 0x07, - 0x01, 0xe8, 0x33, 0x39, 0x9f, 0x28, 0x35, 0x11, 0x1c, 0x3b, 0xe0, 0xe6, 0x4c, 0xce, 0x07, 0xcb, - 0xdc, 0xa0, 0xd4, 0xdb, 0xff, 0xf7, 0x27, 0x1c, 0x53, 0x49, 0xb1, 0xa6, 0x87, 0x20, 0x36, 0xc0, - 0x9e, 0xb2, 0xe5, 0x0e, 0xb1, 0x90, 0x78, 0x06, 0x9e, 0x4c, 0xf9, 0x98, 0x0d, 0x19, 0xcf, 0x7c, - 0xdb, 0xa0, 0x6b, 0xa3, 0xc7, 0xb3, 0xe8, 0x02, 0x1c, 0x5d, 0x73, 0xc1, 0xa1, 0xbd, 0xee, 0x5d, - 0xc3, 0x42, 0x0f, 0xca, 0x4f, 0xf4, 0x7e, 0xd0, 0x6b, 0x10, 0xac, 0x81, 0x57, 0x98, 0x66, 0x2c, - 0x45, 0x03, 0x70, 0xa8, 0x98, 0xb1, 0x5f, 0x9f, 0xe7, 0x06, 0x6a, 0x53, 0xb6, 0x3c, 0x62, 0xf9, - 0xa5, 0xd0, 0x8e, 0xab, 0x6d, 0xfc, 0x09, 0x4c, 0x4f, 0x83, 0xb7, 0xfe, 0x6a, 0x13, 0x58, 0xeb, - 0x4d, 0x60, 0xad, 0xb6, 0x01, 0x59, 0x6f, 0x03, 0xf2, 0xb9, 0x0d, 0xc8, 0xfb, 0x57, 0x60, 0x8d, - 0x2a, 0xfa, 0x23, 0x3b, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x61, 0x66, 0xc6, 0x9d, 0xf4, 0x01, - 0x00, 0x00, + // 359 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xcf, 0x4e, 0xc2, 0x40, + 0x10, 0xc6, 0xbb, 0xb4, 0x60, 0x3b, 0x08, 0x21, 0x1b, 0xa2, 0x0d, 0xc6, 0xda, 0xf4, 0xd4, 0x78, + 0x68, 0x15, 0x0e, 0x7a, 0xc5, 0xc8, 0xc1, 0x93, 0x64, 0x83, 0x31, 0xf1, 0x42, 0x8a, 0xdd, 0xd4, + 0x06, 0xd8, 0x6d, 0xda, 0xaa, 0xe1, 0xe2, 0x73, 0x78, 0xf0, 0x81, 0x38, 0xf2, 0x08, 0x82, 0x2f, + 0x62, 0xba, 0xcb, 0x9f, 0x10, 0x3d, 0xed, 0x37, 0xdf, 0x7c, 0x33, 0xfb, 0xcb, 0x2e, 0x40, 0xf0, + 0x9a, 0xbf, 0x78, 0x49, 0xca, 0x73, 0x8e, 0x2b, 0x85, 0x4e, 0x46, 0xad, 0x66, 0xc4, 0x23, 0x2e, + 0x2c, 0xbf, 0x50, 0xb2, 0xeb, 0x5c, 0x42, 0xfd, 0x21, 0xa3, 0x69, 0x37, 0x0c, 0xef, 0x93, 0x3c, + 0xe6, 0x2c, 0xc3, 0x67, 0x50, 0x65, 0x7c, 0x98, 0x04, 0x59, 0xf6, 0xce, 0xd3, 0xd0, 0x44, 0x36, + 0x72, 0x75, 0x02, 0x8c, 0xf7, 0xd7, 0x8e, 0xf3, 0x01, 0x5a, 0x31, 0x82, 0x31, 0x68, 0x2c, 0x98, + 0x52, 0x91, 0x38, 0x24, 0x42, 0xe3, 0x16, 0xe8, 0xdb, 0xc9, 0x92, 0xf0, 0xb7, 0x35, 0x6e, 0x42, + 0x39, 0xe5, 0x13, 0x9a, 0x99, 0xaa, 0xad, 0xba, 0x06, 0x91, 0x05, 0xbe, 0x80, 0x03, 0x2e, 0x6f, + 0x36, 0x35, 0x1b, 0xb9, 0xd5, 0xf6, 0x91, 0x27, 0x81, 0xbd, 0x7d, 0x2e, 0xb2, 0x89, 0x39, 0x5f, + 0x08, 0xa0, 0x4f, 0xd3, 0x69, 0x9c, 0x65, 0x31, 0x67, 0xb8, 0x03, 0x7a, 0x42, 0xd3, 0xe9, 0x60, + 0x96, 0x48, 0x94, 0x7a, 0xfb, 0x78, 0xb3, 0x61, 0x97, 0xf2, 0x8a, 0x36, 0xd9, 0x06, 0x71, 0x03, + 0xd4, 0x31, 0x9d, 0xad, 0x11, 0x0b, 0x89, 0x4f, 0xc0, 0x48, 0x03, 0x16, 0xd1, 0x21, 0x65, 0xa1, + 0xa9, 0x4a, 0x74, 0x61, 0xf4, 0x58, 0xe8, 0x9c, 0x83, 0x26, 0xc6, 0x74, 0xd0, 0x48, 0xaf, 0x7b, + 0xdb, 0x50, 0xb0, 0x01, 0xe5, 0x47, 0x72, 0x37, 0xe8, 0x35, 0x10, 0xae, 0x81, 0x51, 0x98, 0xb2, + 0x2c, 0x39, 0x03, 0xd0, 0x08, 0x9f, 0xd0, 0x7f, 0x9f, 0xe7, 0x1a, 0x6a, 0x63, 0x3a, 0xdb, 0x61, + 0x99, 0x25, 0x5b, 0x75, 0xab, 0x6d, 0xfc, 0x17, 0x98, 0xec, 0x07, 0x6f, 0xae, 0xe6, 0x4b, 0x4b, + 0x59, 0x2c, 0x2d, 0x65, 0xbe, 0xb2, 0xd0, 0x62, 0x65, 0xa1, 0xef, 0x95, 0x85, 0x3e, 0x7f, 0x2c, + 0xe5, 0xe9, 0x34, 0xe2, 0x1e, 0xcd, 0x9f, 0x43, 0x2f, 0xe6, 0x7e, 0x71, 0xfa, 0x41, 0x12, 0xfb, + 0x6f, 0x1d, 0x5f, 0xae, 0x1c, 0x55, 0xc4, 0x3f, 0x77, 0x7e, 0x03, 0x00, 0x00, 0xff, 0xff, 0x61, + 0x5a, 0xfe, 0x48, 0x13, 0x02, 0x00, 0x00, } func (m *UserAddOptions) Marshal() (dAtA []byte, err error) { diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/authpb/auth.proto b/etcd/vendor/go.etcd.io/etcd/api/v3/authpb/auth.proto index 8f82b7cf1e..5a7856bb73 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/authpb/auth.proto +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/authpb/auth.proto @@ -3,6 +3,8 @@ package authpb; import "gogoproto/gogo.proto"; +option go_package = "go.etcd.io/etcd/api/v3/authpb"; + option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; option (gogoproto.unmarshaler_all) = true; diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/etcdserver.pb.go b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/etcdserver.pb.go index 38434d09c5..eaefa2d208 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/etcdserver.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/etcdserver.pb.go @@ -129,31 +129,33 @@ func init() { func init() { proto.RegisterFile("etcdserver.proto", fileDescriptor_09ffbeb3bebbce7e) } var fileDescriptor_09ffbeb3bebbce7e = []byte{ - // 380 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0xd2, 0xdd, 0x6e, 0xda, 0x30, - 0x14, 0x07, 0x70, 0x0c, 0xe1, 0xcb, 0x63, 0x1b, 0xb3, 0xd0, 0x74, 0x84, 0xa6, 0x2c, 0x42, 0xbb, - 0xc8, 0xd5, 0xf6, 0x0e, 0x2c, 0x5c, 0x44, 0x2a, 0x15, 0x0d, 0x15, 0xbd, 0x76, 0xc9, 0x29, 0x58, - 0x02, 0x4c, 0x1d, 0x07, 0xf1, 0x06, 0x7d, 0x85, 0x3e, 0x12, 0x97, 0x7d, 0x82, 0xaa, 0xa5, 0x2f, - 0x52, 0x39, 0x24, 0xc4, 0xed, 0x5d, 0xf4, 0xfb, 0x9f, 0x1c, 0x1f, 0x7f, 0xd0, 0x2e, 0xea, 0x79, - 0x9c, 0xa0, 0xda, 0xa1, 0xfa, 0xbb, 0x55, 0x52, 0x4b, 0xd6, 0x29, 0x65, 0x7b, 0xdb, 0xef, 0x2d, - 0xe4, 0x42, 0x66, 0xc1, 0x3f, 0xf3, 0x75, 0xaa, 0x19, 0x3c, 0x38, 0xb4, 0x19, 0xe1, 0x7d, 0x8a, - 0x89, 0x66, 0x3d, 0x5a, 0x0d, 0x03, 0x20, 0x1e, 0xf1, 0x9d, 0xa1, 0x73, 0x78, 0xfe, 0x5d, 0x89, - 0xaa, 0x61, 0xc0, 0x7e, 0xd1, 0xc6, 0x18, 0xf5, 0x52, 0xc6, 0x50, 0xf5, 0x88, 0xdf, 0xce, 0x93, - 0xdc, 0x18, 0x50, 0x67, 0xc2, 0xf5, 0x12, 0x6a, 0x56, 0x96, 0x09, 0xfb, 0x49, 0x6b, 0x33, 0xbe, - 0x02, 0xc7, 0x0a, 0x0c, 0x18, 0x0f, 0x84, 0x82, 0xba, 0x47, 0xfc, 0x56, 0xe1, 0x81, 0x50, 0x6c, - 0x40, 0xdb, 0x13, 0x85, 0xbb, 0x19, 0x5f, 0xa5, 0x08, 0x0d, 0xeb, 0xaf, 0x92, 0x8b, 0x9a, 0x70, - 0x13, 0xe3, 0x1e, 0x9a, 0xd6, 0xa0, 0x25, 0x17, 0x35, 0xa3, 0xbd, 0x48, 0x34, 0xb4, 0xce, 0xab, - 0x90, 0xa8, 0x64, 0xf6, 0x87, 0xd2, 0xd1, 0x7e, 0x2b, 0x14, 0xd7, 0x42, 0x6e, 0xa0, 0xed, 0x11, - 0xbf, 0x96, 0x37, 0xb2, 0xdc, 0xec, 0xed, 0x86, 0x0b, 0x0d, 0xd4, 0x1a, 0x35, 0x13, 0xd6, 0xa7, - 0xf5, 0xa9, 0xd8, 0xcc, 0x11, 0xbe, 0x58, 0x33, 0x9c, 0xc8, 0xac, 0x1f, 0xe1, 0x3c, 0x55, 0x89, - 0xd8, 0x21, 0x74, 0xac, 0x5f, 0x4b, 0x36, 0x67, 0x3a, 0x95, 0x4a, 0x63, 0x0c, 0x5f, 0xad, 0x82, - 0xdc, 0x4c, 0x7a, 0x95, 0x4a, 0x95, 0xae, 0xe1, 0x9b, 0x9d, 0x9e, 0xcc, 0x4c, 0x75, 0x2d, 0xd6, - 0x08, 0xdf, 0xad, 0xa9, 0x33, 0xc9, 0xba, 0x6a, 0x85, 0x7c, 0x0d, 0xdd, 0x0f, 0x5d, 0x33, 0x63, - 0xae, 0xb9, 0xe8, 0x3b, 0x85, 0xc9, 0x12, 0x7e, 0x58, 0xa7, 0x52, 0xe0, 0xe0, 0x82, 0xb6, 0xc6, - 0xa8, 0x79, 0xcc, 0x35, 0x37, 0x9d, 0x2e, 0x65, 0x8c, 0x9f, 0x5e, 0x43, 0x6e, 0x66, 0x87, 0xff, - 0x57, 0x69, 0xa2, 0x51, 0x85, 0x41, 0xf6, 0x28, 0xce, 0xb7, 0x70, 0xe6, 0x61, 0xef, 0xf0, 0xea, - 0x56, 0x0e, 0x47, 0x97, 0x3c, 0x1d, 0x5d, 0xf2, 0x72, 0x74, 0xc9, 0xe3, 0x9b, 0x5b, 0x79, 0x0f, - 0x00, 0x00, 0xff, 0xff, 0xee, 0x40, 0xba, 0xd6, 0xa4, 0x02, 0x00, 0x00, + // 402 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0xd2, 0x41, 0xef, 0xd2, 0x30, + 0x14, 0x00, 0x70, 0x0a, 0xfb, 0xff, 0x81, 0x8a, 0x8a, 0x0d, 0x31, 0x2f, 0xc4, 0xcc, 0x05, 0x3d, + 0xec, 0xc4, 0x0e, 0x9e, 0xbc, 0xe2, 0x38, 0x2c, 0x11, 0x83, 0xc3, 0x60, 0xe2, 0xad, 0xb2, 0x27, + 0x34, 0x01, 0x3a, 0xbb, 0x6e, 0xe1, 0x1b, 0xf8, 0x15, 0xfc, 0x48, 0x1c, 0xfd, 0x04, 0x46, 0xf1, + 0x8b, 0x98, 0x8e, 0x8d, 0x55, 0x4f, 0x5b, 0x7e, 0xef, 0xf5, 0xf5, 0xb5, 0x7d, 0x74, 0x88, 0x7a, + 0x93, 0x64, 0xa8, 0x0a, 0x54, 0xd3, 0x54, 0x49, 0x2d, 0xd9, 0xa0, 0x91, 0xf4, 0xf3, 0x78, 0xb4, + 0x95, 0x5b, 0x59, 0x06, 0x02, 0xf3, 0x77, 0xcd, 0x99, 0x7c, 0x73, 0x68, 0x37, 0xc6, 0xaf, 0x39, + 0x66, 0x9a, 0x8d, 0x68, 0x3b, 0x0a, 0x81, 0x78, 0xc4, 0x77, 0x66, 0xce, 0xf9, 0xe7, 0xf3, 0x56, + 0xdc, 0x8e, 0x42, 0xf6, 0x8c, 0xde, 0x2f, 0x50, 0xef, 0x64, 0x02, 0x6d, 0x8f, 0xf8, 0xfd, 0x2a, + 0x52, 0x19, 0x03, 0xea, 0x2c, 0xb9, 0xde, 0x41, 0xc7, 0x8a, 0x95, 0xc2, 0x9e, 0xd2, 0xce, 0x9a, + 0xef, 0xc1, 0xb1, 0x02, 0x06, 0x8c, 0x87, 0x42, 0xc1, 0x9d, 0x47, 0xfc, 0x5e, 0xed, 0xa1, 0x50, + 0x6c, 0x42, 0xfb, 0x4b, 0x85, 0xc5, 0x9a, 0xef, 0x73, 0x84, 0x7b, 0x6b, 0x55, 0xc3, 0x75, 0x4e, + 0x74, 0x4c, 0xf0, 0x04, 0x5d, 0xab, 0xd1, 0x86, 0xeb, 0x9c, 0xf9, 0x49, 0x64, 0x1a, 0x7a, 0xb7, + 0x5d, 0x48, 0xdc, 0x30, 0x7b, 0x49, 0xe9, 0xfc, 0x94, 0x0a, 0xc5, 0xb5, 0x90, 0x47, 0xe8, 0x7b, + 0xc4, 0xef, 0x54, 0x85, 0x2c, 0x37, 0x67, 0xfb, 0xc8, 0x85, 0x06, 0x6a, 0xb5, 0x5a, 0x0a, 0x1b, + 0xd3, 0xbb, 0x95, 0x38, 0x6e, 0x10, 0x1e, 0x58, 0x3d, 0x5c, 0xc9, 0xec, 0x1f, 0xe3, 0x26, 0x57, + 0x99, 0x28, 0x10, 0x06, 0xd6, 0xd2, 0x86, 0xcd, 0x9d, 0xae, 0xa4, 0xd2, 0x98, 0xc0, 0x43, 0x2b, + 0xa1, 0x32, 0x13, 0x7d, 0x9f, 0x4b, 0x95, 0x1f, 0xe0, 0x91, 0x1d, 0xbd, 0x9a, 0xe9, 0xea, 0x83, + 0x38, 0x20, 0x3c, 0xb6, 0xba, 0x2e, 0xa5, 0xac, 0xaa, 0x15, 0xf2, 0x03, 0x0c, 0xff, 0xa9, 0x5a, + 0x1a, 0x73, 0xcd, 0x43, 0x7f, 0x51, 0x98, 0xed, 0xe0, 0x89, 0x75, 0x2b, 0x35, 0x4e, 0xde, 0xd2, + 0xde, 0x02, 0x35, 0x4f, 0xb8, 0xe6, 0xa6, 0xd2, 0x3b, 0x99, 0xe0, 0x7f, 0xd3, 0x50, 0x99, 0x39, + 0xe1, 0x9b, 0x7d, 0x9e, 0x69, 0x54, 0x51, 0x58, 0x0e, 0xc5, 0xed, 0x15, 0x6e, 0x3c, 0x7b, 0x7d, + 0xfe, 0xed, 0xb6, 0xce, 0x17, 0x97, 0xfc, 0xb8, 0xb8, 0xe4, 0xd7, 0xc5, 0x25, 0xdf, 0xff, 0xb8, + 0xad, 0x4f, 0x2f, 0xb6, 0x72, 0x6a, 0x86, 0x72, 0x2a, 0x64, 0x60, 0xbe, 0x01, 0x4f, 0x45, 0x50, + 0xbc, 0x0a, 0xec, 0x41, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x2b, 0x79, 0xf9, 0xf5, 0xc9, 0x02, + 0x00, 0x00, } func (m *Request) Marshal() (dAtA []byte, err error) { diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/etcdserver.proto b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/etcdserver.proto index 25e0aca5d9..ff639b9c96 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/etcdserver.proto +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/etcdserver.proto @@ -3,6 +3,8 @@ package etcdserverpb; import "gogoproto/gogo.proto"; +option go_package = "go.etcd.io/etcd/api/v3/etcdserverpb"; + option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; option (gogoproto.unmarshaler_all) = true; diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/gw/rpc.pb.gw.go b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/gw/rpc.pb.gw.go index 62aba97cdb..6ad1e9d9c6 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/gw/rpc.pb.gw.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/gw/rpc.pb.gw.go @@ -9,232 +9,179 @@ It translates gRPC into RESTful JSON APIs. package gw import ( + protov1 "github.com/golang/protobuf/proto" + "context" + "errors" "go.etcd.io/etcd/api/v3/etcdserverpb" "io" "net/http" - "github.com/golang/protobuf/descriptor" - "github.com/golang/protobuf/proto" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/grpc-ecosystem/grpc-gateway/utilities" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_KV_Range_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.RangeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.RangeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Range(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_KV_Range_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.RangeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.RangeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Range(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_KV_Put_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.PutRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.PutRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Put(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_KV_Put_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.PutRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.PutRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Put(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_KV_DeleteRange_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.DeleteRangeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.DeleteRangeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.DeleteRange(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_KV_DeleteRange_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.DeleteRangeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.DeleteRangeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.DeleteRange(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_KV_Txn_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.TxnRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.TxnRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Txn(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_KV_Txn_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.TxnRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.TxnRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Txn(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_KV_Compact_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.KVClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.CompactionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.CompactionRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Compact(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_KV_Compact_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.KVServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.CompactionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.CompactionRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Compact(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Watch_Watch_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.WatchClient, req *http.Request, pathParams map[string]string) (etcdserverpb.Watch_WatchClient, runtime.ServerMetadata, error) { var metadata runtime.ServerMetadata stream, err := client.Watch(ctx) if err != nil { - grpclog.Infof("Failed to start streaming: %v", err) + grpclog.Errorf("Failed to start streaming: %v", err) return nil, metadata, err } dec := marshaler.NewDecoder(req.Body) handleSend := func() error { var protoReq etcdserverpb.WatchRequest - err := dec.Decode(&protoReq) - if err == io.EOF { + err := dec.Decode(protov1.MessageV2(&protoReq)) + if errors.Is(err, io.EOF) { return err } if err != nil { - grpclog.Infof("Failed to decode request: %v", err) - return err + grpclog.Errorf("Failed to decode request: %v", err) + return status.Errorf(codes.InvalidArgument, "Failed to decode request: %v", err) } if err := stream.Send(&protoReq); err != nil { - grpclog.Infof("Failed to send request: %v", err) + grpclog.Errorf("Failed to send request: %v", err) return err } return nil } - if err := handleSend(); err != nil { - if cerr := stream.CloseSend(); cerr != nil { - grpclog.Infof("Failed to terminate client stream: %v", cerr) - } - if err == io.EOF { - return stream, metadata, nil - } - return nil, metadata, err - } go func() { for { if err := handleSend(); err != nil { @@ -242,12 +189,12 @@ func request_Watch_Watch_0(ctx context.Context, marshaler runtime.Marshaler, cli } } if err := stream.CloseSend(); err != nil { - grpclog.Infof("Failed to terminate client stream: %v", err) + grpclog.Errorf("Failed to terminate client stream: %v", err) } }() header, err := stream.Header() if err != nil { - grpclog.Infof("Failed to get header from client: %v", err) + grpclog.Errorf("Failed to get header from client: %v", err) return nil, metadata, err } metadata.HeaderMD = header @@ -255,140 +202,101 @@ func request_Watch_Watch_0(ctx context.Context, marshaler runtime.Marshaler, cli } func request_Lease_LeaseGrant_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseGrantRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseGrantRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.LeaseGrant(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Lease_LeaseGrant_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseGrantRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseGrantRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.LeaseGrant(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Lease_LeaseRevoke_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseRevokeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseRevokeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.LeaseRevoke(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Lease_LeaseRevoke_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseRevokeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseRevokeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.LeaseRevoke(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Lease_LeaseRevoke_1(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseRevokeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseRevokeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.LeaseRevoke(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Lease_LeaseRevoke_1(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseRevokeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseRevokeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.LeaseRevoke(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Lease_LeaseKeepAlive_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (etcdserverpb.Lease_LeaseKeepAliveClient, runtime.ServerMetadata, error) { var metadata runtime.ServerMetadata stream, err := client.LeaseKeepAlive(ctx) if err != nil { - grpclog.Infof("Failed to start streaming: %v", err) + grpclog.Errorf("Failed to start streaming: %v", err) return nil, metadata, err } dec := marshaler.NewDecoder(req.Body) handleSend := func() error { var protoReq etcdserverpb.LeaseKeepAliveRequest - err := dec.Decode(&protoReq) - if err == io.EOF { + err := dec.Decode(protov1.MessageV2(&protoReq)) + if errors.Is(err, io.EOF) { return err } if err != nil { - grpclog.Infof("Failed to decode request: %v", err) - return err + grpclog.Errorf("Failed to decode request: %v", err) + return status.Errorf(codes.InvalidArgument, "Failed to decode request: %v", err) } if err := stream.Send(&protoReq); err != nil { - grpclog.Infof("Failed to send request: %v", err) + grpclog.Errorf("Failed to send request: %v", err) return err } return nil } - if err := handleSend(); err != nil { - if cerr := stream.CloseSend(); cerr != nil { - grpclog.Infof("Failed to terminate client stream: %v", cerr) - } - if err == io.EOF { - return stream, metadata, nil - } - return nil, metadata, err - } go func() { for { if err := handleSend(); err != nil { @@ -396,12 +304,12 @@ func request_Lease_LeaseKeepAlive_0(ctx context.Context, marshaler runtime.Marsh } } if err := stream.CloseSend(); err != nil { - grpclog.Infof("Failed to terminate client stream: %v", err) + grpclog.Errorf("Failed to terminate client stream: %v", err) } }() header, err := stream.Header() if err != nil { - grpclog.Infof("Failed to get header from client: %v", err) + grpclog.Errorf("Failed to get header from client: %v", err) return nil, metadata, err } metadata.HeaderMD = header @@ -409,493 +317,349 @@ func request_Lease_LeaseKeepAlive_0(ctx context.Context, marshaler runtime.Marsh } func request_Lease_LeaseTimeToLive_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseTimeToLiveRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseTimeToLiveRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.LeaseTimeToLive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Lease_LeaseTimeToLive_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseTimeToLiveRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseTimeToLiveRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.LeaseTimeToLive(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Lease_LeaseTimeToLive_1(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseTimeToLiveRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseTimeToLiveRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.LeaseTimeToLive(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Lease_LeaseTimeToLive_1(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseTimeToLiveRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseTimeToLiveRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.LeaseTimeToLive(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Lease_LeaseLeases_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseLeasesRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseLeasesRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.LeaseLeases(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Lease_LeaseLeases_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseLeasesRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseLeasesRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.LeaseLeases(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Lease_LeaseLeases_1(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.LeaseClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseLeasesRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseLeasesRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.LeaseLeases(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Lease_LeaseLeases_1(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.LeaseServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.LeaseLeasesRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.LeaseLeasesRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.LeaseLeases(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Cluster_MemberAdd_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberAddRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberAddRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.MemberAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Cluster_MemberAdd_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberAddRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberAddRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.MemberAdd(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Cluster_MemberRemove_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberRemoveRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberRemoveRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.MemberRemove(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Cluster_MemberRemove_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberRemoveRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberRemoveRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.MemberRemove(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Cluster_MemberUpdate_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberUpdateRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberUpdateRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.MemberUpdate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Cluster_MemberUpdate_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberUpdateRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberUpdateRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.MemberUpdate(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Cluster_MemberList_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberListRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberListRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.MemberList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Cluster_MemberList_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberListRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberListRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.MemberList(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Cluster_MemberPromote_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.ClusterClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberPromoteRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberPromoteRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.MemberPromote(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Cluster_MemberPromote_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.ClusterServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MemberPromoteRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MemberPromoteRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.MemberPromote(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Maintenance_Alarm_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AlarmRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AlarmRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Alarm(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Maintenance_Alarm_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AlarmRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AlarmRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Alarm(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Maintenance_Status_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.StatusRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.StatusRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Status(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Maintenance_Status_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.StatusRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.StatusRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Status(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Maintenance_Defragment_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.DefragmentRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.DefragmentRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Defragment(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Maintenance_Defragment_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.DefragmentRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.DefragmentRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Defragment(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Maintenance_Hash_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.HashRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.HashRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Hash(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Maintenance_Hash_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.HashRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.HashRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Hash(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Maintenance_HashKV_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.HashKVRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.HashKVRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.HashKV(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Maintenance_HashKV_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.HashKVRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.HashKVRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.HashKV(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Maintenance_Snapshot_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (etcdserverpb.Maintenance_SnapshotClient, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.SnapshotRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.SnapshotRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - stream, err := client.Snapshot(ctx, &protoReq) if err != nil { return nil, metadata, err @@ -906,758 +670,569 @@ func request_Maintenance_Snapshot_0(ctx context.Context, marshaler runtime.Marsh } metadata.HeaderMD = header return stream, metadata, nil - } func request_Maintenance_MoveLeader_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MoveLeaderRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MoveLeaderRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.MoveLeader(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Maintenance_MoveLeader_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.MoveLeaderRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.MoveLeaderRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.MoveLeader(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Maintenance_Downgrade_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.MaintenanceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.DowngradeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.DowngradeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Downgrade(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Maintenance_Downgrade_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.MaintenanceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.DowngradeRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.DowngradeRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Downgrade(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_AuthEnable_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthEnableRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthEnableRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.AuthEnable(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_AuthEnable_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthEnableRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthEnableRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.AuthEnable(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_AuthDisable_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthDisableRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthDisableRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.AuthDisable(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_AuthDisable_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthDisableRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthDisableRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.AuthDisable(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_AuthStatus_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthStatusRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthStatusRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.AuthStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_AuthStatus_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthStatusRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthStatusRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.AuthStatus(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_Authenticate_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthenticateRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthenticateRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Authenticate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_Authenticate_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthenticateRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthenticateRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Authenticate(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_UserAdd_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserAddRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserAddRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.UserAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_UserAdd_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserAddRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserAddRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.UserAdd(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_UserGet_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserGetRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserGetRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.UserGet(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_UserGet_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserGetRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserGetRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.UserGet(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_UserList_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserListRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserListRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.UserList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_UserList_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserListRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserListRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.UserList(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_UserDelete_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserDeleteRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserDeleteRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.UserDelete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_UserDelete_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserDeleteRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserDeleteRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.UserDelete(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_UserChangePassword_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserChangePasswordRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserChangePasswordRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.UserChangePassword(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_UserChangePassword_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserChangePasswordRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserChangePasswordRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.UserChangePassword(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_UserGrantRole_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserGrantRoleRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserGrantRoleRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.UserGrantRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_UserGrantRole_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserGrantRoleRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserGrantRoleRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.UserGrantRole(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_UserRevokeRole_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserRevokeRoleRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserRevokeRoleRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.UserRevokeRole(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_UserRevokeRole_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthUserRevokeRoleRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthUserRevokeRoleRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.UserRevokeRole(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_RoleAdd_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleAddRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleAddRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.RoleAdd(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_RoleAdd_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleAddRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleAddRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.RoleAdd(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_RoleGet_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleGetRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleGetRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.RoleGet(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_RoleGet_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleGetRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleGetRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.RoleGet(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_RoleList_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleListRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleListRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.RoleList(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_RoleList_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleListRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleListRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.RoleList(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_RoleDelete_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleDeleteRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleDeleteRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.RoleDelete(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_RoleDelete_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleDeleteRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleDeleteRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.RoleDelete(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_RoleGrantPermission_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleGrantPermissionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleGrantPermissionRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.RoleGrantPermission(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_RoleGrantPermission_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleGrantPermissionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleGrantPermissionRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.RoleGrantPermission(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Auth_RoleRevokePermission_0(ctx context.Context, marshaler runtime.Marshaler, client etcdserverpb.AuthClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleRevokePermissionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleRevokePermissionRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.RoleRevokePermission(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Auth_RoleRevokePermission_0(ctx context.Context, marshaler runtime.Marshaler, server etcdserverpb.AuthServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq etcdserverpb.AuthRoleRevokePermissionRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq etcdserverpb.AuthRoleRevokePermissionRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.RoleRevokePermission(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } // etcdserverpb.RegisterKVHandlerServer registers the http handlers for service KV to "mux". // UnaryRPC :call etcdserverpb.KVServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterKVHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterKVHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.KVServer) error { - - mux.Handle("POST", pattern_KV_Range_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_Range_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.KV/Range", runtime.WithHTTPPathPattern("/v3/kv/range")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_KV_Range_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_KV_Range_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_KV_Range_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_KV_Range_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_KV_Put_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_Put_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.KV/Put", runtime.WithHTTPPathPattern("/v3/kv/put")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_KV_Put_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_KV_Put_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_KV_Put_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_KV_Put_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_KV_DeleteRange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_DeleteRange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.KV/DeleteRange", runtime.WithHTTPPathPattern("/v3/kv/deleterange")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_KV_DeleteRange_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_KV_DeleteRange_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_KV_DeleteRange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_KV_DeleteRange_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_KV_Txn_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_Txn_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.KV/Txn", runtime.WithHTTPPathPattern("/v3/kv/txn")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_KV_Txn_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_KV_Txn_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_KV_Txn_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_KV_Txn_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_KV_Compact_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_Compact_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.KV/Compact", runtime.WithHTTPPathPattern("/v3/kv/compaction")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_KV_Compact_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_KV_Compact_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_KV_Compact_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_KV_Compact_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) return nil @@ -1666,9 +1241,10 @@ func RegisterKVHandlerServer(ctx context.Context, mux *runtime.ServeMux, server // etcdserverpb.RegisterWatchHandlerServer registers the http handlers for service Watch to "mux". // UnaryRPC :call etcdserverpb.WatchServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterWatchHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterWatchHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.WatchServer) error { - - mux.Handle("POST", pattern_Watch_Watch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Watch_Watch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) @@ -1681,153 +1257,155 @@ func RegisterWatchHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv // etcdserverpb.RegisterLeaseHandlerServer registers the http handlers for service Lease to "mux". // UnaryRPC :call etcdserverpb.LeaseServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterLeaseHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterLeaseHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.LeaseServer) error { - - mux.Handle("POST", pattern_Lease_LeaseGrant_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseGrant_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseGrant", runtime.WithHTTPPathPattern("/v3/lease/grant")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Lease_LeaseGrant_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Lease_LeaseGrant_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseGrant_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseGrant_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseRevoke_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseRevoke_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseRevoke", runtime.WithHTTPPathPattern("/v3/lease/revoke")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Lease_LeaseRevoke_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Lease_LeaseRevoke_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseRevoke_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseRevoke_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseRevoke_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseRevoke_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseRevoke", runtime.WithHTTPPathPattern("/v3/kv/lease/revoke")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Lease_LeaseRevoke_1(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Lease_LeaseRevoke_1(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseRevoke_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseRevoke_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle("POST", pattern_Lease_LeaseKeepAlive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseKeepAlive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return }) - - mux.Handle("POST", pattern_Lease_LeaseTimeToLive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseTimeToLive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseTimeToLive", runtime.WithHTTPPathPattern("/v3/lease/timetolive")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Lease_LeaseTimeToLive_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Lease_LeaseTimeToLive_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseTimeToLive_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseTimeToLive_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseTimeToLive_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseTimeToLive_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseTimeToLive", runtime.WithHTTPPathPattern("/v3/kv/lease/timetolive")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Lease_LeaseTimeToLive_1(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Lease_LeaseTimeToLive_1(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseTimeToLive_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseTimeToLive_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseLeases_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseLeases_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseLeases", runtime.WithHTTPPathPattern("/v3/lease/leases")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Lease_LeaseLeases_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Lease_LeaseLeases_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseLeases_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseLeases_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseLeases_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseLeases_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseLeases", runtime.WithHTTPPathPattern("/v3/kv/lease/leases")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Lease_LeaseLeases_1(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Lease_LeaseLeases_1(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseLeases_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseLeases_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) return nil @@ -1836,106 +1414,108 @@ func RegisterLeaseHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv // etcdserverpb.RegisterClusterHandlerServer registers the http handlers for service Cluster to "mux". // UnaryRPC :call etcdserverpb.ClusterServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterClusterHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterClusterHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.ClusterServer) error { - - mux.Handle("POST", pattern_Cluster_MemberAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberAdd", runtime.WithHTTPPathPattern("/v3/cluster/member/add")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Cluster_MemberAdd_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Cluster_MemberAdd_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberAdd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Cluster_MemberRemove_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberRemove_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberRemove", runtime.WithHTTPPathPattern("/v3/cluster/member/remove")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Cluster_MemberRemove_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Cluster_MemberRemove_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberRemove_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberRemove_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Cluster_MemberUpdate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberUpdate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberUpdate", runtime.WithHTTPPathPattern("/v3/cluster/member/update")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Cluster_MemberUpdate_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Cluster_MemberUpdate_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberUpdate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberUpdate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Cluster_MemberList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberList", runtime.WithHTTPPathPattern("/v3/cluster/member/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Cluster_MemberList_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Cluster_MemberList_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Cluster_MemberPromote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberPromote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberPromote", runtime.WithHTTPPathPattern("/v3/cluster/member/promote")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Cluster_MemberPromote_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Cluster_MemberPromote_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberPromote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberPromote_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) return nil @@ -1944,153 +1524,155 @@ func RegisterClusterHandlerServer(ctx context.Context, mux *runtime.ServeMux, se // etcdserverpb.RegisterMaintenanceHandlerServer registers the http handlers for service Maintenance to "mux". // UnaryRPC :call etcdserverpb.MaintenanceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterMaintenanceHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterMaintenanceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.MaintenanceServer) error { - - mux.Handle("POST", pattern_Maintenance_Alarm_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Alarm_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Maintenance/Alarm", runtime.WithHTTPPathPattern("/v3/maintenance/alarm")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Maintenance_Alarm_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Maintenance_Alarm_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Alarm_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Alarm_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_Status_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Status_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Maintenance/Status", runtime.WithHTTPPathPattern("/v3/maintenance/status")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Maintenance_Status_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Maintenance_Status_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Status_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Status_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_Defragment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Defragment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Maintenance/Defragment", runtime.WithHTTPPathPattern("/v3/maintenance/defragment")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Maintenance_Defragment_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Maintenance_Defragment_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Defragment_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Defragment_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_Hash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Hash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Maintenance/Hash", runtime.WithHTTPPathPattern("/v3/maintenance/hash")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Maintenance_Hash_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Maintenance_Hash_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Hash_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Hash_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_HashKV_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_HashKV_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Maintenance/HashKV", runtime.WithHTTPPathPattern("/v3/maintenance/hashkv")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Maintenance_HashKV_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Maintenance_HashKV_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_HashKV_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_HashKV_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle("POST", pattern_Maintenance_Snapshot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Snapshot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return }) - - mux.Handle("POST", pattern_Maintenance_MoveLeader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_MoveLeader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Maintenance/MoveLeader", runtime.WithHTTPPathPattern("/v3/maintenance/transfer-leadership")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Maintenance_MoveLeader_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Maintenance_MoveLeader_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_MoveLeader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_MoveLeader_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_Downgrade_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Downgrade_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Maintenance/Downgrade", runtime.WithHTTPPathPattern("/v3/maintenance/downgrade")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Maintenance_Downgrade_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Maintenance_Downgrade_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Downgrade_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Downgrade_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) return nil @@ -2099,346 +1681,348 @@ func RegisterMaintenanceHandlerServer(ctx context.Context, mux *runtime.ServeMux // etcdserverpb.RegisterAuthHandlerServer registers the http handlers for service Auth to "mux". // UnaryRPC :call etcdserverpb.AuthServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAuthHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterAuthHandlerServer(ctx context.Context, mux *runtime.ServeMux, server etcdserverpb.AuthServer) error { - - mux.Handle("POST", pattern_Auth_AuthEnable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_AuthEnable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/AuthEnable", runtime.WithHTTPPathPattern("/v3/auth/enable")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_AuthEnable_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_AuthEnable_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_AuthEnable_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_AuthEnable_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_AuthDisable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_AuthDisable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/AuthDisable", runtime.WithHTTPPathPattern("/v3/auth/disable")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_AuthDisable_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_AuthDisable_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_AuthDisable_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_AuthDisable_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_AuthStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_AuthStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/AuthStatus", runtime.WithHTTPPathPattern("/v3/auth/status")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_AuthStatus_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_AuthStatus_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_AuthStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_AuthStatus_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/Authenticate", runtime.WithHTTPPathPattern("/v3/auth/authenticate")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_Authenticate_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_Authenticate_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_Authenticate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_Authenticate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/UserAdd", runtime.WithHTTPPathPattern("/v3/auth/user/add")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_UserAdd_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_UserAdd_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserAdd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/UserGet", runtime.WithHTTPPathPattern("/v3/auth/user/get")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_UserGet_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_UserGet_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserGet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserGet_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/UserList", runtime.WithHTTPPathPattern("/v3/auth/user/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_UserList_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_UserList_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/UserDelete", runtime.WithHTTPPathPattern("/v3/auth/user/delete")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_UserDelete_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_UserDelete_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserDelete_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserDelete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserChangePassword_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserChangePassword_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/UserChangePassword", runtime.WithHTTPPathPattern("/v3/auth/user/changepw")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_UserChangePassword_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_UserChangePassword_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserChangePassword_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserChangePassword_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserGrantRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserGrantRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/UserGrantRole", runtime.WithHTTPPathPattern("/v3/auth/user/grant")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_UserGrantRole_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_UserGrantRole_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserGrantRole_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserGrantRole_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserRevokeRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserRevokeRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/UserRevokeRole", runtime.WithHTTPPathPattern("/v3/auth/user/revoke")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_UserRevokeRole_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_UserRevokeRole_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserRevokeRole_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserRevokeRole_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/RoleAdd", runtime.WithHTTPPathPattern("/v3/auth/role/add")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_RoleAdd_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_RoleAdd_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleAdd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/RoleGet", runtime.WithHTTPPathPattern("/v3/auth/role/get")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_RoleGet_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_RoleGet_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleGet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleGet_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/RoleList", runtime.WithHTTPPathPattern("/v3/auth/role/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_RoleList_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_RoleList_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/RoleDelete", runtime.WithHTTPPathPattern("/v3/auth/role/delete")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_RoleDelete_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_RoleDelete_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleDelete_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleDelete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleGrantPermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleGrantPermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/RoleGrantPermission", runtime.WithHTTPPathPattern("/v3/auth/role/grant")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_RoleGrantPermission_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_RoleGrantPermission_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleGrantPermission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleGrantPermission_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleRevokePermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleRevokePermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/etcdserverpb.Auth/RoleRevokePermission", runtime.WithHTTPPathPattern("/v3/auth/role/revoke")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Auth_RoleRevokePermission_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Auth_RoleRevokePermission_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleRevokePermission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleRevokePermission_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) return nil @@ -2447,25 +2031,24 @@ func RegisterAuthHandlerServer(ctx context.Context, mux *runtime.ServeMux, serve // RegisterKVHandlerFromEndpoint is same as RegisterKVHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterKVHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.NewClient(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } }() }() - return RegisterKVHandler(ctx, mux, conn) } @@ -2479,158 +2062,133 @@ func RegisterKVHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.Cl // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "KVClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "KVClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "KVClient" to call the correct interceptors. +// "KVClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterKVHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.KVClient) error { - - mux.Handle("POST", pattern_KV_Range_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_Range_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.KV/Range", runtime.WithHTTPPathPattern("/v3/kv/range")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_KV_Range_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_KV_Range_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_KV_Range_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_KV_Range_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_KV_Put_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_Put_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.KV/Put", runtime.WithHTTPPathPattern("/v3/kv/put")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_KV_Put_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_KV_Put_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return - } - - forward_KV_Put_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + } + forward_KV_Put_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_KV_DeleteRange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_DeleteRange_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.KV/DeleteRange", runtime.WithHTTPPathPattern("/v3/kv/deleterange")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_KV_DeleteRange_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_KV_DeleteRange_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_KV_DeleteRange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_KV_DeleteRange_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_KV_Txn_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_Txn_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.KV/Txn", runtime.WithHTTPPathPattern("/v3/kv/txn")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_KV_Txn_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_KV_Txn_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_KV_Txn_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_KV_Txn_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_KV_Compact_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_KV_Compact_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.KV/Compact", runtime.WithHTTPPathPattern("/v3/kv/compaction")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_KV_Compact_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_KV_Compact_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_KV_Compact_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_KV_Compact_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - return nil } var ( - pattern_KV_Range_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "range"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_KV_Put_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "put"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_KV_DeleteRange_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "deleterange"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_KV_Txn_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "txn"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_KV_Compact_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "compaction"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_KV_Range_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "range"}, "")) + pattern_KV_Put_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "put"}, "")) + pattern_KV_DeleteRange_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "deleterange"}, "")) + pattern_KV_Txn_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "txn"}, "")) + pattern_KV_Compact_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "kv", "compaction"}, "")) ) var ( - forward_KV_Range_0 = runtime.ForwardResponseMessage - - forward_KV_Put_0 = runtime.ForwardResponseMessage - + forward_KV_Range_0 = runtime.ForwardResponseMessage + forward_KV_Put_0 = runtime.ForwardResponseMessage forward_KV_DeleteRange_0 = runtime.ForwardResponseMessage - - forward_KV_Txn_0 = runtime.ForwardResponseMessage - - forward_KV_Compact_0 = runtime.ForwardResponseMessage + forward_KV_Txn_0 = runtime.ForwardResponseMessage + forward_KV_Compact_0 = runtime.ForwardResponseMessage ) // RegisterWatchHandlerFromEndpoint is same as RegisterWatchHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterWatchHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.NewClient(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } }() }() - return RegisterWatchHandler(ctx, mux, conn) } @@ -2644,34 +2202,33 @@ func RegisterWatchHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "WatchClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "WatchClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "WatchClient" to call the correct interceptors. +// "WatchClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterWatchHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.WatchClient) error { - - mux.Handle("POST", pattern_Watch_Watch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Watch_Watch_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Watch/Watch", runtime.WithHTTPPathPattern("/v3/watch")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Watch_Watch_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Watch_Watch_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Watch_Watch_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - + forward_Watch_Watch_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { + m1, err := resp.Recv() + return protov1.MessageV2(m1), err + }, mux.GetForwardResponseOptions()...) }) - return nil } var ( - pattern_Watch_Watch_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v3", "watch"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Watch_Watch_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v3", "watch"}, "")) ) var ( @@ -2681,25 +2238,24 @@ var ( // RegisterLeaseHandlerFromEndpoint is same as RegisterLeaseHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterLeaseHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.NewClient(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } }() }() - return RegisterLeaseHandler(ctx, mux, conn) } @@ -2713,230 +2269,193 @@ func RegisterLeaseHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "LeaseClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "LeaseClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "LeaseClient" to call the correct interceptors. +// "LeaseClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterLeaseHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.LeaseClient) error { - - mux.Handle("POST", pattern_Lease_LeaseGrant_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseGrant_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseGrant", runtime.WithHTTPPathPattern("/v3/lease/grant")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lease_LeaseGrant_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lease_LeaseGrant_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseGrant_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseGrant_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseRevoke_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseRevoke_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseRevoke", runtime.WithHTTPPathPattern("/v3/lease/revoke")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lease_LeaseRevoke_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lease_LeaseRevoke_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseRevoke_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseRevoke_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseRevoke_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseRevoke_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseRevoke", runtime.WithHTTPPathPattern("/v3/kv/lease/revoke")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lease_LeaseRevoke_1(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lease_LeaseRevoke_1(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseRevoke_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseRevoke_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseKeepAlive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseKeepAlive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseKeepAlive", runtime.WithHTTPPathPattern("/v3/lease/keepalive")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lease_LeaseKeepAlive_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lease_LeaseKeepAlive_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseKeepAlive_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseKeepAlive_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { + m1, err := resp.Recv() + return protov1.MessageV2(m1), err + }, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseTimeToLive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseTimeToLive_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseTimeToLive", runtime.WithHTTPPathPattern("/v3/lease/timetolive")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lease_LeaseTimeToLive_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lease_LeaseTimeToLive_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseTimeToLive_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseTimeToLive_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseTimeToLive_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseTimeToLive_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseTimeToLive", runtime.WithHTTPPathPattern("/v3/kv/lease/timetolive")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lease_LeaseTimeToLive_1(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lease_LeaseTimeToLive_1(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseTimeToLive_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseTimeToLive_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseLeases_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseLeases_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseLeases", runtime.WithHTTPPathPattern("/v3/lease/leases")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lease_LeaseLeases_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lease_LeaseLeases_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseLeases_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseLeases_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lease_LeaseLeases_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lease_LeaseLeases_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Lease/LeaseLeases", runtime.WithHTTPPathPattern("/v3/kv/lease/leases")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lease_LeaseLeases_1(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lease_LeaseLeases_1(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lease_LeaseLeases_1(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lease_LeaseLeases_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - return nil } var ( - pattern_Lease_LeaseGrant_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "grant"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Lease_LeaseRevoke_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "revoke"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Lease_LeaseRevoke_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "kv", "lease", "revoke"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Lease_LeaseKeepAlive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "keepalive"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Lease_LeaseTimeToLive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "timetolive"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Lease_LeaseTimeToLive_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "kv", "lease", "timetolive"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Lease_LeaseLeases_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "leases"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Lease_LeaseLeases_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "kv", "lease", "leases"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Lease_LeaseGrant_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "grant"}, "")) + pattern_Lease_LeaseRevoke_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "revoke"}, "")) + pattern_Lease_LeaseRevoke_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "kv", "lease", "revoke"}, "")) + pattern_Lease_LeaseKeepAlive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "keepalive"}, "")) + pattern_Lease_LeaseTimeToLive_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "timetolive"}, "")) + pattern_Lease_LeaseTimeToLive_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "kv", "lease", "timetolive"}, "")) + pattern_Lease_LeaseLeases_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lease", "leases"}, "")) + pattern_Lease_LeaseLeases_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "kv", "lease", "leases"}, "")) ) var ( - forward_Lease_LeaseGrant_0 = runtime.ForwardResponseMessage - - forward_Lease_LeaseRevoke_0 = runtime.ForwardResponseMessage - - forward_Lease_LeaseRevoke_1 = runtime.ForwardResponseMessage - - forward_Lease_LeaseKeepAlive_0 = runtime.ForwardResponseStream - + forward_Lease_LeaseGrant_0 = runtime.ForwardResponseMessage + forward_Lease_LeaseRevoke_0 = runtime.ForwardResponseMessage + forward_Lease_LeaseRevoke_1 = runtime.ForwardResponseMessage + forward_Lease_LeaseKeepAlive_0 = runtime.ForwardResponseStream forward_Lease_LeaseTimeToLive_0 = runtime.ForwardResponseMessage - forward_Lease_LeaseTimeToLive_1 = runtime.ForwardResponseMessage - - forward_Lease_LeaseLeases_0 = runtime.ForwardResponseMessage - - forward_Lease_LeaseLeases_1 = runtime.ForwardResponseMessage + forward_Lease_LeaseLeases_0 = runtime.ForwardResponseMessage + forward_Lease_LeaseLeases_1 = runtime.ForwardResponseMessage ) // RegisterClusterHandlerFromEndpoint is same as RegisterClusterHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterClusterHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.NewClient(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } }() }() - return RegisterClusterHandler(ctx, mux, conn) } @@ -2950,158 +2469,133 @@ func RegisterClusterHandler(ctx context.Context, mux *runtime.ServeMux, conn *gr // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ClusterClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ClusterClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "ClusterClient" to call the correct interceptors. +// "ClusterClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterClusterHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.ClusterClient) error { - - mux.Handle("POST", pattern_Cluster_MemberAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberAdd", runtime.WithHTTPPathPattern("/v3/cluster/member/add")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Cluster_MemberAdd_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Cluster_MemberAdd_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberAdd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Cluster_MemberRemove_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberRemove_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberRemove", runtime.WithHTTPPathPattern("/v3/cluster/member/remove")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Cluster_MemberRemove_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Cluster_MemberRemove_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberRemove_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberRemove_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Cluster_MemberUpdate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberUpdate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberUpdate", runtime.WithHTTPPathPattern("/v3/cluster/member/update")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Cluster_MemberUpdate_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Cluster_MemberUpdate_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberUpdate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberUpdate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Cluster_MemberList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberList", runtime.WithHTTPPathPattern("/v3/cluster/member/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Cluster_MemberList_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Cluster_MemberList_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Cluster_MemberPromote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Cluster_MemberPromote_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Cluster/MemberPromote", runtime.WithHTTPPathPattern("/v3/cluster/member/promote")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Cluster_MemberPromote_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Cluster_MemberPromote_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Cluster_MemberPromote_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Cluster_MemberPromote_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - return nil } var ( - pattern_Cluster_MemberAdd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "add"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Cluster_MemberRemove_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "remove"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Cluster_MemberUpdate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "update"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Cluster_MemberList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "list"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Cluster_MemberPromote_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "promote"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Cluster_MemberAdd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "add"}, "")) + pattern_Cluster_MemberRemove_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "remove"}, "")) + pattern_Cluster_MemberUpdate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "update"}, "")) + pattern_Cluster_MemberList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "list"}, "")) + pattern_Cluster_MemberPromote_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "cluster", "member", "promote"}, "")) ) var ( - forward_Cluster_MemberAdd_0 = runtime.ForwardResponseMessage - - forward_Cluster_MemberRemove_0 = runtime.ForwardResponseMessage - - forward_Cluster_MemberUpdate_0 = runtime.ForwardResponseMessage - - forward_Cluster_MemberList_0 = runtime.ForwardResponseMessage - + forward_Cluster_MemberAdd_0 = runtime.ForwardResponseMessage + forward_Cluster_MemberRemove_0 = runtime.ForwardResponseMessage + forward_Cluster_MemberUpdate_0 = runtime.ForwardResponseMessage + forward_Cluster_MemberList_0 = runtime.ForwardResponseMessage forward_Cluster_MemberPromote_0 = runtime.ForwardResponseMessage ) // RegisterMaintenanceHandlerFromEndpoint is same as RegisterMaintenanceHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterMaintenanceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.NewClient(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } }() }() - return RegisterMaintenanceHandler(ctx, mux, conn) } @@ -3115,230 +2609,193 @@ func RegisterMaintenanceHandler(ctx context.Context, mux *runtime.ServeMux, conn // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "MaintenanceClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "MaintenanceClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "MaintenanceClient" to call the correct interceptors. +// "MaintenanceClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterMaintenanceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.MaintenanceClient) error { - - mux.Handle("POST", pattern_Maintenance_Alarm_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Alarm_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Maintenance/Alarm", runtime.WithHTTPPathPattern("/v3/maintenance/alarm")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Maintenance_Alarm_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Maintenance_Alarm_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Alarm_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Alarm_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_Status_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Status_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Maintenance/Status", runtime.WithHTTPPathPattern("/v3/maintenance/status")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Maintenance_Status_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Maintenance_Status_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Status_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Status_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_Defragment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Defragment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Maintenance/Defragment", runtime.WithHTTPPathPattern("/v3/maintenance/defragment")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Maintenance_Defragment_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Maintenance_Defragment_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Defragment_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Defragment_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_Hash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Hash_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Maintenance/Hash", runtime.WithHTTPPathPattern("/v3/maintenance/hash")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Maintenance_Hash_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Maintenance_Hash_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Hash_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Hash_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_HashKV_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_HashKV_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Maintenance/HashKV", runtime.WithHTTPPathPattern("/v3/maintenance/hashkv")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Maintenance_HashKV_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Maintenance_HashKV_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_HashKV_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_HashKV_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_Snapshot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Snapshot_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Maintenance/Snapshot", runtime.WithHTTPPathPattern("/v3/maintenance/snapshot")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Maintenance_Snapshot_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Maintenance_Snapshot_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Snapshot_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Snapshot_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { + m1, err := resp.Recv() + return protov1.MessageV2(m1), err + }, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_MoveLeader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_MoveLeader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Maintenance/MoveLeader", runtime.WithHTTPPathPattern("/v3/maintenance/transfer-leadership")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Maintenance_MoveLeader_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Maintenance_MoveLeader_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_MoveLeader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_MoveLeader_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Maintenance_Downgrade_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Maintenance_Downgrade_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Maintenance/Downgrade", runtime.WithHTTPPathPattern("/v3/maintenance/downgrade")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Maintenance_Downgrade_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Maintenance_Downgrade_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Maintenance_Downgrade_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Maintenance_Downgrade_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - return nil } var ( - pattern_Maintenance_Alarm_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "alarm"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Maintenance_Status_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "status"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Maintenance_Defragment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "defragment"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Maintenance_Hash_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "hash"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Maintenance_HashKV_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "hashkv"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Maintenance_Snapshot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "snapshot"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Maintenance_MoveLeader_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "transfer-leadership"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Maintenance_Downgrade_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "downgrade"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Maintenance_Alarm_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "alarm"}, "")) + pattern_Maintenance_Status_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "status"}, "")) + pattern_Maintenance_Defragment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "defragment"}, "")) + pattern_Maintenance_Hash_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "hash"}, "")) + pattern_Maintenance_HashKV_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "hashkv"}, "")) + pattern_Maintenance_Snapshot_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "snapshot"}, "")) + pattern_Maintenance_MoveLeader_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "transfer-leadership"}, "")) + pattern_Maintenance_Downgrade_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "maintenance", "downgrade"}, "")) ) var ( - forward_Maintenance_Alarm_0 = runtime.ForwardResponseMessage - - forward_Maintenance_Status_0 = runtime.ForwardResponseMessage - + forward_Maintenance_Alarm_0 = runtime.ForwardResponseMessage + forward_Maintenance_Status_0 = runtime.ForwardResponseMessage forward_Maintenance_Defragment_0 = runtime.ForwardResponseMessage - - forward_Maintenance_Hash_0 = runtime.ForwardResponseMessage - - forward_Maintenance_HashKV_0 = runtime.ForwardResponseMessage - - forward_Maintenance_Snapshot_0 = runtime.ForwardResponseStream - + forward_Maintenance_Hash_0 = runtime.ForwardResponseMessage + forward_Maintenance_HashKV_0 = runtime.ForwardResponseMessage + forward_Maintenance_Snapshot_0 = runtime.ForwardResponseStream forward_Maintenance_MoveLeader_0 = runtime.ForwardResponseMessage - - forward_Maintenance_Downgrade_0 = runtime.ForwardResponseMessage + forward_Maintenance_Downgrade_0 = runtime.ForwardResponseMessage ) // RegisterAuthHandlerFromEndpoint is same as RegisterAuthHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterAuthHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.NewClient(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } }() }() - return RegisterAuthHandler(ctx, mux, conn) } @@ -3352,420 +2809,336 @@ func RegisterAuthHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc. // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "AuthClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "AuthClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "AuthClient" to call the correct interceptors. +// "AuthClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterAuthHandlerClient(ctx context.Context, mux *runtime.ServeMux, client etcdserverpb.AuthClient) error { - - mux.Handle("POST", pattern_Auth_AuthEnable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_AuthEnable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/AuthEnable", runtime.WithHTTPPathPattern("/v3/auth/enable")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_AuthEnable_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_AuthEnable_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_AuthEnable_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_AuthEnable_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_AuthDisable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_AuthDisable_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/AuthDisable", runtime.WithHTTPPathPattern("/v3/auth/disable")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_AuthDisable_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_AuthDisable_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_AuthDisable_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_AuthDisable_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_AuthStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_AuthStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/AuthStatus", runtime.WithHTTPPathPattern("/v3/auth/status")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_AuthStatus_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_AuthStatus_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_AuthStatus_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_AuthStatus_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_Authenticate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/Authenticate", runtime.WithHTTPPathPattern("/v3/auth/authenticate")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_Authenticate_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_Authenticate_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_Authenticate_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_Authenticate_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/UserAdd", runtime.WithHTTPPathPattern("/v3/auth/user/add")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_UserAdd_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_UserAdd_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserAdd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/UserGet", runtime.WithHTTPPathPattern("/v3/auth/user/get")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_UserGet_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_UserGet_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserGet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserGet_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/UserList", runtime.WithHTTPPathPattern("/v3/auth/user/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_UserList_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_UserList_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/UserDelete", runtime.WithHTTPPathPattern("/v3/auth/user/delete")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_UserDelete_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_UserDelete_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserDelete_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserDelete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserChangePassword_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserChangePassword_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/UserChangePassword", runtime.WithHTTPPathPattern("/v3/auth/user/changepw")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_UserChangePassword_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_UserChangePassword_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserChangePassword_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserChangePassword_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserGrantRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserGrantRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/UserGrantRole", runtime.WithHTTPPathPattern("/v3/auth/user/grant")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_UserGrantRole_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_UserGrantRole_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserGrantRole_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserGrantRole_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_UserRevokeRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_UserRevokeRole_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/UserRevokeRole", runtime.WithHTTPPathPattern("/v3/auth/user/revoke")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_UserRevokeRole_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_UserRevokeRole_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_UserRevokeRole_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_UserRevokeRole_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleAdd_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/RoleAdd", runtime.WithHTTPPathPattern("/v3/auth/role/add")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_RoleAdd_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_RoleAdd_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleAdd_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleAdd_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleGet_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/RoleGet", runtime.WithHTTPPathPattern("/v3/auth/role/get")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_RoleGet_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_RoleGet_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleGet_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleGet_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleList_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/RoleList", runtime.WithHTTPPathPattern("/v3/auth/role/list")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_RoleList_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_RoleList_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleList_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleList_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleDelete_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/RoleDelete", runtime.WithHTTPPathPattern("/v3/auth/role/delete")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_RoleDelete_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_RoleDelete_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleDelete_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleDelete_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleGrantPermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleGrantPermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/RoleGrantPermission", runtime.WithHTTPPathPattern("/v3/auth/role/grant")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_RoleGrantPermission_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_RoleGrantPermission_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleGrantPermission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleGrantPermission_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Auth_RoleRevokePermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Auth_RoleRevokePermission_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/etcdserverpb.Auth/RoleRevokePermission", runtime.WithHTTPPathPattern("/v3/auth/role/revoke")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Auth_RoleRevokePermission_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Auth_RoleRevokePermission_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Auth_RoleRevokePermission_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Auth_RoleRevokePermission_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - return nil } var ( - pattern_Auth_AuthEnable_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "enable"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_AuthDisable_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "disable"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_AuthStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "status"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_Authenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "authenticate"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_UserAdd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "add"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_UserGet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "get"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_UserList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "list"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_UserDelete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "delete"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_UserChangePassword_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "changepw"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_UserGrantRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "grant"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_UserRevokeRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "revoke"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_RoleAdd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "add"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_RoleGet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "get"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_RoleList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "list"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_RoleDelete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "delete"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_RoleGrantPermission_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "grant"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Auth_RoleRevokePermission_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "revoke"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Auth_AuthEnable_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "enable"}, "")) + pattern_Auth_AuthDisable_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "disable"}, "")) + pattern_Auth_AuthStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "status"}, "")) + pattern_Auth_Authenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "auth", "authenticate"}, "")) + pattern_Auth_UserAdd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "add"}, "")) + pattern_Auth_UserGet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "get"}, "")) + pattern_Auth_UserList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "list"}, "")) + pattern_Auth_UserDelete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "delete"}, "")) + pattern_Auth_UserChangePassword_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "changepw"}, "")) + pattern_Auth_UserGrantRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "grant"}, "")) + pattern_Auth_UserRevokeRole_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "user", "revoke"}, "")) + pattern_Auth_RoleAdd_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "add"}, "")) + pattern_Auth_RoleGet_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "get"}, "")) + pattern_Auth_RoleList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "list"}, "")) + pattern_Auth_RoleDelete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "delete"}, "")) + pattern_Auth_RoleGrantPermission_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "grant"}, "")) + pattern_Auth_RoleRevokePermission_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v3", "auth", "role", "revoke"}, "")) ) var ( - forward_Auth_AuthEnable_0 = runtime.ForwardResponseMessage - - forward_Auth_AuthDisable_0 = runtime.ForwardResponseMessage - - forward_Auth_AuthStatus_0 = runtime.ForwardResponseMessage - - forward_Auth_Authenticate_0 = runtime.ForwardResponseMessage - - forward_Auth_UserAdd_0 = runtime.ForwardResponseMessage - - forward_Auth_UserGet_0 = runtime.ForwardResponseMessage - - forward_Auth_UserList_0 = runtime.ForwardResponseMessage - - forward_Auth_UserDelete_0 = runtime.ForwardResponseMessage - - forward_Auth_UserChangePassword_0 = runtime.ForwardResponseMessage - - forward_Auth_UserGrantRole_0 = runtime.ForwardResponseMessage - - forward_Auth_UserRevokeRole_0 = runtime.ForwardResponseMessage - - forward_Auth_RoleAdd_0 = runtime.ForwardResponseMessage - - forward_Auth_RoleGet_0 = runtime.ForwardResponseMessage - - forward_Auth_RoleList_0 = runtime.ForwardResponseMessage - - forward_Auth_RoleDelete_0 = runtime.ForwardResponseMessage - - forward_Auth_RoleGrantPermission_0 = runtime.ForwardResponseMessage - + forward_Auth_AuthEnable_0 = runtime.ForwardResponseMessage + forward_Auth_AuthDisable_0 = runtime.ForwardResponseMessage + forward_Auth_AuthStatus_0 = runtime.ForwardResponseMessage + forward_Auth_Authenticate_0 = runtime.ForwardResponseMessage + forward_Auth_UserAdd_0 = runtime.ForwardResponseMessage + forward_Auth_UserGet_0 = runtime.ForwardResponseMessage + forward_Auth_UserList_0 = runtime.ForwardResponseMessage + forward_Auth_UserDelete_0 = runtime.ForwardResponseMessage + forward_Auth_UserChangePassword_0 = runtime.ForwardResponseMessage + forward_Auth_UserGrantRole_0 = runtime.ForwardResponseMessage + forward_Auth_UserRevokeRole_0 = runtime.ForwardResponseMessage + forward_Auth_RoleAdd_0 = runtime.ForwardResponseMessage + forward_Auth_RoleGet_0 = runtime.ForwardResponseMessage + forward_Auth_RoleList_0 = runtime.ForwardResponseMessage + forward_Auth_RoleDelete_0 = runtime.ForwardResponseMessage + forward_Auth_RoleGrantPermission_0 = runtime.ForwardResponseMessage forward_Auth_RoleRevokePermission_0 = runtime.ForwardResponseMessage ) diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal.pb.go b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal.pb.go index b94a7bfd9d..e1cd9ebecd 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal.pb.go @@ -12,6 +12,7 @@ import ( _ "github.com/gogo/protobuf/gogoproto" proto "github.com/golang/protobuf/proto" membershippb "go.etcd.io/etcd/api/v3/membershippb" + _ "go.etcd.io/etcd/api/v3/versionpb" ) // Reference imports to suppress errors if they are not otherwise used. @@ -104,6 +105,7 @@ type InternalRaftRequest struct { ClusterVersionSet *membershippb.ClusterVersionSetRequest `protobuf:"bytes,1300,opt,name=cluster_version_set,json=clusterVersionSet,proto3" json:"cluster_version_set,omitempty"` ClusterMemberAttrSet *membershippb.ClusterMemberAttrSetRequest `protobuf:"bytes,1301,opt,name=cluster_member_attr_set,json=clusterMemberAttrSet,proto3" json:"cluster_member_attr_set,omitempty"` DowngradeInfoSet *membershippb.DowngradeInfoSetRequest `protobuf:"bytes,1302,opt,name=downgrade_info_set,json=downgradeInfoSet,proto3" json:"downgrade_info_set,omitempty"` + DowngradeVersionTest *DowngradeVersionTestRequest `protobuf:"bytes,9900,opt,name=downgrade_version_test,json=downgradeVersionTest,proto3" json:"downgrade_version_test,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -237,70 +239,76 @@ func init() { func init() { proto.RegisterFile("raft_internal.proto", fileDescriptor_b4c9a9be0cfca103) } var fileDescriptor_b4c9a9be0cfca103 = []byte{ - // 1003 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x96, 0xd9, 0x72, 0x1b, 0x45, - 0x14, 0x86, 0x23, 0xc5, 0x71, 0xac, 0x96, 0xed, 0x38, 0x6d, 0x87, 0x34, 0x72, 0x95, 0x70, 0x1c, - 0x12, 0xcc, 0x66, 0x53, 0xca, 0x03, 0x80, 0x90, 0x5c, 0x8e, 0xab, 0x42, 0x70, 0x4d, 0xcc, 0x52, - 0xc5, 0xc5, 0xd0, 0x9a, 0x39, 0x96, 0x06, 0xcf, 0x46, 0x77, 0x4b, 0x31, 0xef, 0x11, 0x28, 0x1e, - 0x83, 0xed, 0x21, 0x72, 0xc1, 0x62, 0xe0, 0x05, 0xc0, 0xdc, 0x70, 0x0f, 0xdc, 0x53, 0xbd, 0xcc, - 0x26, 0xb5, 0x7c, 0xa7, 0xf9, 0xcf, 0x7f, 0xbe, 0x73, 0xba, 0xe7, 0xf4, 0xa8, 0xd1, 0x3a, 0xa3, - 0x27, 0xc2, 0x0d, 0x62, 0x01, 0x2c, 0xa6, 0xe1, 0x6e, 0xca, 0x12, 0x91, 0xe0, 0x65, 0x10, 0x9e, - 0xcf, 0x81, 0x4d, 0x80, 0xa5, 0x83, 0xd6, 0xc6, 0x30, 0x19, 0x26, 0x2a, 0xb0, 0x27, 0x7f, 0x69, - 0x4f, 0x6b, 0xad, 0xf0, 0x18, 0xa5, 0xc1, 0x52, 0xcf, 0xfc, 0xbc, 0x2f, 0x83, 0x7b, 0x34, 0x0d, - 0xf6, 0x22, 0x88, 0x06, 0xc0, 0xf8, 0x28, 0x48, 0xd3, 0x41, 0xe9, 0x41, 0xfb, 0xb6, 0x3f, 0x45, - 0x2b, 0x0e, 0x7c, 0x3e, 0x06, 0x2e, 0x1e, 0x02, 0xf5, 0x81, 0xe1, 0x55, 0x54, 0x3f, 0xec, 0x93, - 0xda, 0x56, 0x6d, 0x67, 0xc1, 0xa9, 0x1f, 0xf6, 0x71, 0x0b, 0x2d, 0x8d, 0xb9, 0x6c, 0x2d, 0x02, - 0x52, 0xdf, 0xaa, 0xed, 0x34, 0x9c, 0xfc, 0x19, 0xdf, 0x45, 0x2b, 0x74, 0x2c, 0x46, 0x2e, 0x83, - 0x49, 0xc0, 0x83, 0x24, 0x26, 0x57, 0x55, 0xda, 0xb2, 0x14, 0x1d, 0xa3, 0x6d, 0x3f, 0xc3, 0x68, - 0xfd, 0xd0, 0xac, 0xce, 0xa1, 0x27, 0xc2, 0x94, 0xc3, 0x0f, 0xd0, 0xe2, 0x48, 0x95, 0x24, 0xfe, - 0x56, 0x6d, 0xa7, 0xd9, 0xd9, 0xdc, 0x2d, 0xaf, 0x79, 0xb7, 0xd2, 0x95, 0x63, 0xac, 0x33, 0xdd, - 0xdd, 0x43, 0xf5, 0x49, 0x47, 0xf5, 0xd5, 0xec, 0xdc, 0xb2, 0x02, 0x9c, 0xfa, 0xa4, 0x83, 0xdf, - 0x42, 0xd7, 0x18, 0x8d, 0x87, 0xa0, 0x1a, 0x6c, 0x76, 0x5a, 0x53, 0x4e, 0x19, 0xca, 0xec, 0xda, - 0x88, 0x5f, 0x43, 0x57, 0xd3, 0xb1, 0x20, 0x0b, 0xca, 0x4f, 0xaa, 0xfe, 0xa3, 0x71, 0xb6, 0x08, - 0x47, 0x9a, 0x70, 0x0f, 0x2d, 0xfb, 0x10, 0x82, 0x00, 0x57, 0x17, 0xb9, 0xa6, 0x92, 0xb6, 0xaa, - 0x49, 0x7d, 0xe5, 0xa8, 0x94, 0x6a, 0xfa, 0x85, 0x26, 0x0b, 0x8a, 0xb3, 0x98, 0x2c, 0xda, 0x0a, - 0x1e, 0x9f, 0xc5, 0x79, 0x41, 0x71, 0x16, 0xe3, 0xb7, 0x11, 0xf2, 0x92, 0x28, 0xa5, 0x9e, 0x90, - 0x9b, 0x7e, 0x5d, 0xa5, 0xbc, 0x54, 0x4d, 0xe9, 0xe5, 0xf1, 0x2c, 0xb3, 0x94, 0x82, 0xdf, 0x41, - 0xcd, 0x10, 0x28, 0x07, 0x77, 0xc8, 0x68, 0x2c, 0xc8, 0x92, 0x8d, 0xf0, 0x48, 0x1a, 0x0e, 0x64, - 0x3c, 0x27, 0x84, 0xb9, 0x24, 0xd7, 0xac, 0x09, 0x0c, 0x26, 0xc9, 0x29, 0x90, 0x86, 0x6d, 0xcd, - 0x0a, 0xe1, 0x28, 0x43, 0xbe, 0xe6, 0xb0, 0xd0, 0xe4, 0x6b, 0xa1, 0x21, 0x65, 0x11, 0x41, 0xb6, - 0xd7, 0xd2, 0x95, 0xa1, 0xfc, 0xb5, 0x28, 0x23, 0x7e, 0x1f, 0xad, 0xe9, 0xb2, 0xde, 0x08, 0xbc, - 0xd3, 0x34, 0x09, 0x62, 0x41, 0x9a, 0x2a, 0xf9, 0x65, 0x4b, 0xe9, 0x5e, 0x6e, 0xca, 0x30, 0x37, - 0xc2, 0xaa, 0x8e, 0xbb, 0xa8, 0xa9, 0x46, 0x18, 0x62, 0x3a, 0x08, 0x81, 0xfc, 0x6d, 0xdd, 0xcc, - 0xee, 0x58, 0x8c, 0xf6, 0x95, 0x21, 0xdf, 0x0a, 0x9a, 0x4b, 0xb8, 0x8f, 0xd4, 0xc0, 0xbb, 0x7e, - 0xc0, 0x15, 0xe3, 0x9f, 0xeb, 0xb6, 0xbd, 0x90, 0x8c, 0xbe, 0x76, 0xe4, 0x7b, 0x41, 0x0b, 0x2d, - 0x6f, 0x84, 0x0b, 0x2a, 0xc6, 0x9c, 0xfc, 0x37, 0xb7, 0x91, 0x27, 0xca, 0x50, 0x69, 0x44, 0x4b, - 0xf8, 0xb1, 0x6e, 0x04, 0x62, 0x11, 0x78, 0x54, 0x00, 0xf9, 0x57, 0x33, 0x5e, 0xad, 0x32, 0xb2, - 0xb3, 0xd8, 0x2d, 0x59, 0x33, 0x5a, 0x25, 0x1f, 0xef, 0x9b, 0xe3, 0x2d, 0xcf, 0xbb, 0x4b, 0x7d, - 0x9f, 0xfc, 0xb8, 0x34, 0x6f, 0x65, 0x1f, 0x70, 0x60, 0x5d, 0xdf, 0xaf, 0xac, 0xcc, 0x68, 0xf8, - 0x31, 0x5a, 0x2b, 0x30, 0x7a, 0xe4, 0xc9, 0x4f, 0x9a, 0x74, 0xd7, 0x4e, 0x32, 0x67, 0xc5, 0xc0, - 0x56, 0x69, 0x45, 0xae, 0xb6, 0x35, 0x04, 0x41, 0x7e, 0xbe, 0xb4, 0xad, 0x03, 0x10, 0x33, 0x6d, - 0x1d, 0x80, 0xc0, 0x43, 0xf4, 0x62, 0x81, 0xf1, 0x46, 0xf2, 0x10, 0xba, 0x29, 0xe5, 0xfc, 0x69, - 0xc2, 0x7c, 0xf2, 0x8b, 0x46, 0xbe, 0x6e, 0x47, 0xf6, 0x94, 0xfb, 0xc8, 0x98, 0x33, 0xfa, 0x0b, - 0xd4, 0x1a, 0xc6, 0x1f, 0xa3, 0x8d, 0x52, 0xbf, 0xf2, 0xf4, 0xb8, 0x2c, 0x09, 0x81, 0x9c, 0xeb, - 0x1a, 0xf7, 0xe7, 0xb4, 0xad, 0x4e, 0x5e, 0x52, 0x4c, 0xcb, 0x4d, 0x3a, 0x1d, 0xc1, 0x9f, 0xa0, - 0x5b, 0x05, 0x59, 0x1f, 0x44, 0x8d, 0xfe, 0x55, 0xa3, 0x5f, 0xb1, 0xa3, 0xcd, 0x89, 0x2c, 0xb1, - 0x31, 0x9d, 0x09, 0xe1, 0x87, 0x68, 0xb5, 0x80, 0x87, 0x01, 0x17, 0xe4, 0x37, 0x4d, 0xbd, 0x63, - 0xa7, 0x3e, 0x0a, 0xb8, 0xa8, 0xcc, 0x51, 0x26, 0xe6, 0x24, 0xd9, 0x9a, 0x26, 0xfd, 0x3e, 0x97, - 0x24, 0x4b, 0xcf, 0x90, 0x32, 0x31, 0x7f, 0xf5, 0x8a, 0x24, 0x27, 0xf2, 0x9b, 0xc6, 0xbc, 0x57, - 0x2f, 0x73, 0xa6, 0x27, 0xd2, 0x68, 0xf9, 0x44, 0x2a, 0x8c, 0x99, 0xc8, 0x6f, 0x1b, 0xf3, 0x26, - 0x52, 0x66, 0x59, 0x26, 0xb2, 0x90, 0xab, 0x6d, 0xc9, 0x89, 0xfc, 0xee, 0xd2, 0xb6, 0xa6, 0x27, - 0xd2, 0x68, 0xf8, 0x33, 0xd4, 0x2a, 0x61, 0xd4, 0xa0, 0xa4, 0xc0, 0xa2, 0x80, 0xab, 0xff, 0xd6, - 0xef, 0x35, 0xf3, 0x8d, 0x39, 0x4c, 0x69, 0x3f, 0xca, 0xdd, 0x19, 0xff, 0x36, 0xb5, 0xc7, 0x71, - 0x84, 0x36, 0x8b, 0x5a, 0x66, 0x74, 0x4a, 0xc5, 0x7e, 0xd0, 0xc5, 0xde, 0xb4, 0x17, 0xd3, 0x53, - 0x32, 0x5b, 0x8d, 0xd0, 0x39, 0x06, 0xfc, 0x11, 0x5a, 0xf7, 0xc2, 0x31, 0x17, 0xc0, 0xdc, 0x09, - 0x30, 0x29, 0xb9, 0x1c, 0x04, 0x79, 0x86, 0xcc, 0x11, 0x28, 0x5f, 0x52, 0x76, 0x7b, 0xda, 0xf9, - 0xa1, 0x36, 0x3e, 0x29, 0x76, 0xeb, 0xa6, 0x37, 0x1d, 0xc1, 0x14, 0xdd, 0xce, 0xc0, 0x9a, 0xe1, - 0x52, 0x21, 0x98, 0x82, 0x7f, 0x89, 0xcc, 0xe7, 0xcf, 0x06, 0x7f, 0x4f, 0x69, 0x5d, 0x21, 0x58, - 0x89, 0xbf, 0xe1, 0x59, 0x82, 0xf8, 0x18, 0x61, 0x3f, 0x79, 0x1a, 0x0f, 0x19, 0xf5, 0xc1, 0x0d, - 0xe2, 0x93, 0x44, 0xd1, 0xbf, 0xd2, 0xf4, 0x7b, 0x55, 0x7a, 0x3f, 0x33, 0x1e, 0xc6, 0x27, 0x49, - 0x89, 0xbc, 0xe6, 0x4f, 0x05, 0xb6, 0x6f, 0xa0, 0x95, 0xfd, 0x28, 0x15, 0x5f, 0x38, 0xc0, 0xd3, - 0x24, 0xe6, 0xb0, 0x9d, 0xa2, 0xcd, 0x4b, 0x3e, 0xcd, 0x18, 0xa3, 0x05, 0x75, 0x07, 0xab, 0xa9, - 0x3b, 0x98, 0xfa, 0x2d, 0xef, 0x66, 0xf9, 0x17, 0xcb, 0xdc, 0xcd, 0xb2, 0x67, 0x7c, 0x07, 0x2d, - 0xf3, 0x20, 0x4a, 0x43, 0x70, 0x45, 0x72, 0x0a, 0xfa, 0x6a, 0xd6, 0x70, 0x9a, 0x5a, 0x3b, 0x96, - 0xd2, 0xbb, 0x1b, 0xcf, 0xff, 0x6c, 0x5f, 0x79, 0x7e, 0xd1, 0xae, 0x9d, 0x5f, 0xb4, 0x6b, 0x7f, - 0x5c, 0xb4, 0x6b, 0x5f, 0xff, 0xd5, 0xbe, 0x32, 0x58, 0x54, 0x17, 0xc3, 0x07, 0xff, 0x07, 0x00, - 0x00, 0xff, 0xff, 0x94, 0x6f, 0x64, 0x0a, 0x98, 0x0a, 0x00, 0x00, + // 1101 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x56, 0xcb, 0x72, 0x1b, 0x45, + 0x14, 0x8d, 0x6c, 0xc7, 0xb6, 0x5a, 0xb6, 0xe3, 0xb4, 0x9d, 0xa4, 0xb1, 0xab, 0x8c, 0xe3, 0x90, + 0x60, 0x20, 0xc8, 0xc1, 0x06, 0xaa, 0x60, 0x03, 0x8a, 0xe5, 0x72, 0x4c, 0x25, 0x29, 0xd7, 0xc4, + 0x50, 0x29, 0x28, 0x6a, 0x68, 0xcd, 0x5c, 0x4b, 0x13, 0x8f, 0x66, 0x86, 0xee, 0x96, 0xe2, 0x6c, + 0x59, 0xb2, 0x06, 0x8a, 0x8f, 0x60, 0xc1, 0x2b, 0xff, 0x90, 0x05, 0x8f, 0x00, 0x3f, 0x00, 0x66, + 0xc3, 0x1e, 0xd8, 0xa7, 0xfa, 0x31, 0x2f, 0xa9, 0xe5, 0xdd, 0xe8, 0xde, 0x73, 0xcf, 0x39, 0xdd, + 0x7d, 0xbb, 0x75, 0xd1, 0x02, 0xa3, 0x87, 0xc2, 0x0d, 0x22, 0x01, 0x2c, 0xa2, 0x61, 0x3d, 0x61, + 0xb1, 0x88, 0xf1, 0x0c, 0x08, 0xcf, 0xe7, 0xc0, 0xfa, 0xc0, 0x92, 0xd6, 0xd2, 0x62, 0x3b, 0x6e, + 0xc7, 0x2a, 0xb1, 0x21, 0xbf, 0x34, 0x66, 0x69, 0x3e, 0xc7, 0x98, 0x48, 0x95, 0x25, 0x9e, 0xf9, + 0x5c, 0x95, 0xc9, 0x0d, 0x9a, 0x04, 0x1b, 0x7d, 0x60, 0x3c, 0x88, 0xa3, 0xa4, 0x95, 0x7e, 0x19, + 0xc4, 0xb5, 0x0c, 0xd1, 0x85, 0x6e, 0x0b, 0x18, 0xef, 0x04, 0x49, 0xd2, 0x2a, 0xfc, 0xd0, 0xb8, + 0x35, 0x86, 0x66, 0x1d, 0xf8, 0xb4, 0x07, 0x5c, 0xdc, 0x02, 0xea, 0x03, 0xc3, 0x73, 0x68, 0x6c, + 0xaf, 0x49, 0x2a, 0xab, 0x95, 0xf5, 0x09, 0x67, 0x6c, 0xaf, 0x89, 0x97, 0xd0, 0x74, 0x8f, 0x4b, + 0xf3, 0x5d, 0x20, 0x63, 0xab, 0x95, 0xf5, 0xaa, 0x93, 0xfd, 0xc6, 0xd7, 0xd1, 0x2c, 0xed, 0x89, + 0x8e, 0xcb, 0xa0, 0x1f, 0x48, 0x6d, 0x32, 0x2e, 0xcb, 0x6e, 0x4e, 0x7d, 0xfe, 0x98, 0x8c, 0x6f, + 0xd5, 0x5f, 0x73, 0x66, 0x64, 0xd6, 0x31, 0xc9, 0xb7, 0xa7, 0x3e, 0x53, 0xe1, 0x1b, 0x6b, 0x8f, + 0x17, 0xd0, 0xc2, 0x9e, 0xd9, 0x11, 0x87, 0x1e, 0x0a, 0x63, 0x00, 0x6f, 0xa1, 0xc9, 0x8e, 0x32, + 0x41, 0xfc, 0xd5, 0xca, 0x7a, 0x6d, 0x73, 0xb9, 0x5e, 0xdc, 0xa7, 0x7a, 0xc9, 0xa7, 0x63, 0xa0, + 0x43, 0x7e, 0xaf, 0xa2, 0xb1, 0xfe, 0xa6, 0x72, 0x5a, 0xdb, 0xbc, 0x60, 0x25, 0x70, 0xc6, 0xfa, + 0x9b, 0xf8, 0x06, 0x3a, 0xcb, 0x68, 0xd4, 0x06, 0x65, 0xb9, 0xb6, 0xb9, 0x34, 0x80, 0x94, 0xa9, + 0x14, 0xae, 0x81, 0xf8, 0x65, 0x34, 0x9e, 0xf4, 0x04, 0x99, 0x50, 0x78, 0x52, 0xc6, 0xef, 0xf7, + 0xd2, 0x45, 0x38, 0x12, 0x84, 0xb7, 0xd1, 0x8c, 0x0f, 0x21, 0x08, 0x70, 0xb5, 0xc8, 0x59, 0x55, + 0xb4, 0x5a, 0x2e, 0x6a, 0x2a, 0x44, 0x49, 0xaa, 0xe6, 0xe7, 0x31, 0x29, 0x28, 0x8e, 0x23, 0x32, + 0x69, 0x13, 0x3c, 0x38, 0x8e, 0x32, 0x41, 0x71, 0x1c, 0xe1, 0x77, 0x10, 0xf2, 0xe2, 0x6e, 0x42, + 0x3d, 0x21, 0x8f, 0x61, 0x4a, 0x95, 0x3c, 0x5f, 0x2e, 0xd9, 0xce, 0xf2, 0x69, 0x65, 0xa1, 0x04, + 0xbf, 0x8b, 0x6a, 0x21, 0x50, 0x0e, 0x6e, 0x9b, 0xd1, 0x48, 0x90, 0x69, 0x1b, 0xc3, 0x6d, 0x09, + 0xd8, 0x95, 0xf9, 0x8c, 0x21, 0xcc, 0x42, 0x72, 0xcd, 0x9a, 0x81, 0x41, 0x3f, 0x3e, 0x02, 0x52, + 0xb5, 0xad, 0x59, 0x51, 0x38, 0x0a, 0x90, 0xad, 0x39, 0xcc, 0x63, 0xf2, 0x58, 0x68, 0x48, 0x59, + 0x97, 0x20, 0xdb, 0xb1, 0x34, 0x64, 0x2a, 0x3b, 0x16, 0x05, 0xc4, 0xf7, 0xd1, 0xbc, 0x96, 0xf5, + 0x3a, 0xe0, 0x1d, 0x25, 0x71, 0x10, 0x09, 0x52, 0x53, 0xc5, 0x2f, 0x58, 0xa4, 0xb7, 0x33, 0x90, + 0xa1, 0x49, 0x9b, 0xf5, 0x75, 0xe7, 0x5c, 0x58, 0x06, 0xe0, 0x06, 0xaa, 0xa9, 0xee, 0x86, 0x88, + 0xb6, 0x42, 0x20, 0xff, 0x58, 0x77, 0xb5, 0xd1, 0x13, 0x9d, 0x1d, 0x05, 0xc8, 0xf6, 0x84, 0x66, + 0x21, 0xdc, 0x44, 0xea, 0x0a, 0xb8, 0x7e, 0xc0, 0x15, 0xc7, 0xbf, 0x53, 0xb6, 0x4d, 0x91, 0x1c, + 0x4d, 0x8d, 0xc8, 0x36, 0x85, 0xe6, 0x31, 0xfc, 0x9e, 0x31, 0xc2, 0x05, 0x15, 0x3d, 0x4e, 0xfe, + 0x1f, 0x69, 0xe4, 0x9e, 0x02, 0x0c, 0xac, 0xec, 0x0d, 0xed, 0x48, 0xe7, 0xf0, 0x5d, 0xed, 0x08, + 0x22, 0x11, 0x78, 0x54, 0x00, 0xf9, 0x4f, 0x93, 0xbd, 0x54, 0x26, 0x4b, 0x6f, 0x67, 0xa3, 0x00, + 0x4d, 0xad, 0x95, 0xea, 0xf1, 0x8e, 0x79, 0x02, 0xe4, 0x9b, 0xe0, 0x52, 0xdf, 0x27, 0x3f, 0x4d, + 0x8f, 0x5a, 0xe2, 0xfb, 0x1c, 0x58, 0xc3, 0xf7, 0x4b, 0x4b, 0x34, 0x31, 0x7c, 0x17, 0xcd, 0xe7, + 0x34, 0xfa, 0x12, 0x90, 0x9f, 0x35, 0xd3, 0x15, 0x3b, 0x93, 0xb9, 0x3d, 0x86, 0x6c, 0x8e, 0x96, + 0xc2, 0x65, 0x5b, 0x6d, 0x10, 0xe4, 0x97, 0x53, 0x6d, 0xed, 0x82, 0x18, 0xb2, 0xb5, 0x0b, 0x02, + 0xb7, 0xd1, 0x73, 0x39, 0x8d, 0xd7, 0x91, 0xd7, 0xd2, 0x4d, 0x28, 0xe7, 0x0f, 0x63, 0xe6, 0x93, + 0x5f, 0x35, 0xe5, 0x2b, 0x76, 0xca, 0x6d, 0x85, 0xde, 0x37, 0xe0, 0x94, 0xfd, 0x22, 0xb5, 0xa6, + 0xf1, 0x7d, 0xb4, 0x58, 0xf0, 0x2b, 0xef, 0x93, 0xcb, 0xe2, 0x10, 0xc8, 0x53, 0xad, 0x71, 0x6d, + 0x84, 0x6d, 0x75, 0x17, 0xe3, 0xbc, 0x6d, 0xce, 0xd3, 0xc1, 0x0c, 0xfe, 0x08, 0x5d, 0xc8, 0x99, + 0xf5, 0xd5, 0xd4, 0xd4, 0xbf, 0x69, 0xea, 0x17, 0xed, 0xd4, 0xe6, 0x8e, 0x16, 0xb8, 0x31, 0x1d, + 0x4a, 0xe1, 0x5b, 0x68, 0x2e, 0x27, 0x0f, 0x03, 0x2e, 0xc8, 0xef, 0x9a, 0xf5, 0xb2, 0x9d, 0xf5, + 0x76, 0xc0, 0x45, 0xa9, 0x8f, 0xd2, 0x60, 0xc6, 0x24, 0xad, 0x69, 0xa6, 0x3f, 0x46, 0x32, 0x49, + 0xe9, 0x21, 0xa6, 0x34, 0x98, 0x1d, 0xbd, 0x62, 0x92, 0x1d, 0xf9, 0x6d, 0x75, 0xd4, 0xd1, 0xcb, + 0x9a, 0xc1, 0x8e, 0x34, 0xb1, 0xac, 0x23, 0x15, 0x8d, 0xe9, 0xc8, 0xef, 0xaa, 0xa3, 0x3a, 0x52, + 0x56, 0x59, 0x3a, 0x32, 0x0f, 0x97, 0x6d, 0xc9, 0x8e, 0xfc, 0xfe, 0x54, 0x5b, 0x83, 0x1d, 0x69, + 0x62, 0xf8, 0x01, 0x5a, 0x2a, 0xd0, 0xa8, 0x46, 0x49, 0x80, 0x75, 0x03, 0xae, 0xfe, 0x7f, 0x7f, + 0xd0, 0x9c, 0xd7, 0x47, 0x70, 0x4a, 0xf8, 0x7e, 0x86, 0x4e, 0xf9, 0x2f, 0x51, 0x7b, 0x1e, 0x77, + 0xd1, 0x72, 0xae, 0x65, 0x5a, 0xa7, 0x20, 0xf6, 0xa3, 0x16, 0x7b, 0xd5, 0x2e, 0xa6, 0xbb, 0x64, + 0x58, 0x8d, 0xd0, 0x11, 0x00, 0xfc, 0x09, 0x5a, 0xf0, 0xc2, 0x1e, 0x17, 0xc0, 0x5c, 0x33, 0xcb, + 0xb8, 0x1c, 0x04, 0xf9, 0x02, 0x99, 0x2b, 0x50, 0x1c, 0x64, 0xea, 0xdb, 0x1a, 0xf9, 0x81, 0x06, + 0xde, 0x03, 0x31, 0xf4, 0xea, 0x9d, 0xf7, 0x06, 0x21, 0xf8, 0x01, 0xba, 0x94, 0x2a, 0x68, 0x32, + 0x97, 0x0a, 0xc1, 0x94, 0xca, 0x97, 0xc8, 0xbc, 0x83, 0x36, 0x95, 0x3b, 0x2a, 0xd6, 0x10, 0x82, + 0xd9, 0x84, 0x16, 0x3d, 0x0b, 0x0a, 0x7f, 0x8c, 0xb0, 0x1f, 0x3f, 0x8c, 0xda, 0x8c, 0xfa, 0xe0, + 0x06, 0xd1, 0x61, 0xac, 0x64, 0xbe, 0xd2, 0x32, 0x57, 0xcb, 0x32, 0xcd, 0x14, 0xb8, 0x17, 0x1d, + 0xc6, 0x36, 0x89, 0x79, 0x7f, 0x00, 0x81, 0x03, 0x74, 0x31, 0xa7, 0x4f, 0xb7, 0x4b, 0x00, 0x17, + 0xe4, 0x9b, 0x3b, 0xb6, 0x17, 0x3d, 0x93, 0x30, 0xdb, 0x71, 0x00, 0x7c, 0x50, 0xe6, 0x4d, 0x67, + 0xd1, 0xb7, 0xa0, 0xf2, 0xb9, 0xed, 0x1c, 0x9a, 0xdd, 0xe9, 0x26, 0xe2, 0x91, 0x03, 0x3c, 0x89, + 0x23, 0x0e, 0x6b, 0x8f, 0xd0, 0xf2, 0x29, 0xff, 0x14, 0x18, 0xa3, 0x09, 0x35, 0x36, 0x56, 0xd4, + 0xd8, 0xa8, 0xbe, 0xe5, 0x38, 0x99, 0x3d, 0xa0, 0x66, 0x9c, 0x4c, 0x7f, 0xe3, 0xcb, 0x68, 0x86, + 0x07, 0xdd, 0x24, 0x04, 0x57, 0xc4, 0x47, 0xa0, 0xa7, 0xc9, 0xaa, 0x53, 0xd3, 0xb1, 0x03, 0x19, + 0xca, 0xbc, 0xdc, 0x7c, 0xeb, 0xc9, 0x5f, 0x2b, 0x67, 0x9e, 0x9c, 0xac, 0x54, 0x9e, 0x9e, 0xac, + 0x54, 0xfe, 0x3c, 0x59, 0xa9, 0x7c, 0xfd, 0xf7, 0xca, 0x99, 0x0f, 0xaf, 0xb4, 0x63, 0xb5, 0xec, + 0x7a, 0x10, 0x6f, 0xe4, 0x23, 0xf2, 0xd6, 0x46, 0x71, 0x2b, 0x5a, 0x93, 0x6a, 0xf2, 0xdd, 0x7a, + 0x16, 0x00, 0x00, 0xff, 0xff, 0xb2, 0xa0, 0x15, 0x1f, 0x9b, 0x0b, 0x00, 0x00, } func (m *RequestHeader) Marshal() (dAtA []byte, err error) { @@ -371,6 +379,22 @@ func (m *InternalRaftRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.DowngradeVersionTest != nil { + { + size, err := m.DowngradeVersionTest.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintRaftInternal(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x4 + i-- + dAtA[i] = 0xea + i-- + dAtA[i] = 0xe2 + } if m.DowngradeInfoSet != nil { { size, err := m.DowngradeInfoSet.MarshalToSizedBuffer(dAtA[:i]) @@ -1034,6 +1058,10 @@ func (m *InternalRaftRequest) Size() (n int) { l = m.DowngradeInfoSet.Size() n += 2 + l + sovRaftInternal(uint64(l)) } + if m.DowngradeVersionTest != nil { + l = m.DowngradeVersionTest.Size() + n += 3 + l + sovRaftInternal(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -2367,6 +2395,42 @@ func (m *InternalRaftRequest) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 9900: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DowngradeVersionTest", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaftInternal + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRaftInternal + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRaftInternal + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DowngradeVersionTest == nil { + m.DowngradeVersionTest = &DowngradeVersionTestRequest{} + } + if err := m.DowngradeVersionTest.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRaftInternal(dAtA[iNdEx:]) diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal.proto b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal.proto index 68926e59f6..88b8ab5279 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal.proto +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal.proto @@ -4,24 +4,31 @@ package etcdserverpb; import "gogoproto/gogo.proto"; import "etcdserver.proto"; import "rpc.proto"; +import "etcd/api/versionpb/version.proto"; import "etcd/api/membershippb/membership.proto"; +option go_package = "go.etcd.io/etcd/api/v3/etcdserverpb"; + option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; option (gogoproto.unmarshaler_all) = true; option (gogoproto.goproto_getters_all) = false; message RequestHeader { + option (versionpb.etcd_version_msg) = "3.0"; + uint64 ID = 1; // username is a username that is associated with an auth token of gRPC connection string username = 2; // auth_revision is a revision number of auth.authStore. It is not related to mvcc - uint64 auth_revision = 3; + uint64 auth_revision = 3 [(versionpb.etcd_version_field) = "3.1"]; } // An InternalRaftRequest is the union of all requests which can be // sent via raft. message InternalRaftRequest { + option (versionpb.etcd_version_msg) = "3.0"; + RequestHeader header = 100; uint64 ID = 1; @@ -38,11 +45,11 @@ message InternalRaftRequest { AlarmRequest alarm = 10; - LeaseCheckpointRequest lease_checkpoint = 11; + LeaseCheckpointRequest lease_checkpoint = 11 [(versionpb.etcd_version_field) = "3.4"]; AuthEnableRequest auth_enable = 1000; AuthDisableRequest auth_disable = 1011; - AuthStatusRequest auth_status = 1013; + AuthStatusRequest auth_status = 1013 [(versionpb.etcd_version_field) = "3.5"]; InternalAuthenticateRequest authenticate = 1012; @@ -61,9 +68,11 @@ message InternalRaftRequest { AuthRoleGrantPermissionRequest auth_role_grant_permission = 1203; AuthRoleRevokePermissionRequest auth_role_revoke_permission = 1204; - membershippb.ClusterVersionSetRequest cluster_version_set = 1300; - membershippb.ClusterMemberAttrSetRequest cluster_member_attr_set = 1301; - membershippb.DowngradeInfoSetRequest downgrade_info_set = 1302; + membershippb.ClusterVersionSetRequest cluster_version_set = 1300 [(versionpb.etcd_version_field) = "3.5"]; + membershippb.ClusterMemberAttrSetRequest cluster_member_attr_set = 1301 [(versionpb.etcd_version_field) = "3.5"]; + membershippb.DowngradeInfoSetRequest downgrade_info_set = 1302 [(versionpb.etcd_version_field) = "3.5"]; + + DowngradeVersionTestRequest downgrade_version_test = 9900 [(versionpb.etcd_version_field) = "3.6"]; } message EmptyResponse { @@ -73,6 +82,7 @@ message EmptyResponse { // InternalAuthenticateRequest has a member that is filled by etcdserver and shouldn't be user-facing. // For avoiding misusage the field, we have an internal version of AuthenticateRequest. message InternalAuthenticateRequest { + option (versionpb.etcd_version_msg) = "3.0"; string name = 1; string password = 2; diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal_stringer.go b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal_stringer.go index 31e121ee0a..a9431d5254 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal_stringer.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/raft_internal_stringer.go @@ -72,13 +72,13 @@ func (as *InternalRaftStringer) String() string { return as.Request.String() } -// txnRequestStringer implements a custom proto String to replace value bytes fields with value size -// fields in any nested txn and put operations. +// txnRequestStringer implements fmt.Stringer, a custom proto String to replace value bytes +// fields with value size fields in any nested txn and put operations. type txnRequestStringer struct { Request *TxnRequest } -func NewLoggableTxnRequest(request *TxnRequest) *txnRequestStringer { +func NewLoggableTxnRequest(request *TxnRequest) fmt.Stringer { return &txnRequestStringer{request} } @@ -155,8 +155,8 @@ func (m *loggableValueCompare) Reset() { *m = loggableValueCompare{} } func (m *loggableValueCompare) String() string { return proto.CompactTextString(m) } func (*loggableValueCompare) ProtoMessage() {} -// loggablePutRequest implements a custom proto String to replace value bytes field with a value -// size field. +// loggablePutRequest implements proto.Message, a custom proto String to replace value bytes +// field with a value size field. // To preserve proto encoding of the key bytes, a faked out proto type is used here. type loggablePutRequest struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3"` @@ -167,7 +167,7 @@ type loggablePutRequest struct { IgnoreLease bool `protobuf:"varint,6,opt,name=ignore_lease,proto3"` } -func NewLoggablePutRequest(request *PutRequest) *loggablePutRequest { +func NewLoggablePutRequest(request *PutRequest) proto.Message { return &loggablePutRequest{ request.Key, int64(len(request.Value)), diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.pb.go b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.pb.go index 8120907d91..42bf641db6 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.pb.go @@ -12,8 +12,10 @@ import ( _ "github.com/gogo/protobuf/gogoproto" proto "github.com/golang/protobuf/proto" + _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" authpb "go.etcd.io/etcd/api/v3/authpb" mvccpb "go.etcd.io/etcd/api/v3/mvccpb" + _ "go.etcd.io/etcd/api/v3/versionpb" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" @@ -274,9 +276,10 @@ type ResponseHeader struct { ClusterId uint64 `protobuf:"varint,1,opt,name=cluster_id,json=clusterId,proto3" json:"cluster_id,omitempty"` // member_id is the ID of the member which sent the response. MemberId uint64 `protobuf:"varint,2,opt,name=member_id,json=memberId,proto3" json:"member_id,omitempty"` - // revision is the key-value store revision when the request was applied. + // revision is the key-value store revision when the request was applied, and it's + // unset (so 0) in case of calls not interacting with key-value store. // For watch progress responses, the header.revision indicates progress. All future events - // recieved in this stream are guaranteed to have a higher revision number than the + // received in this stream are guaranteed to have a higher revision number than the // header.revision number. Revision int64 `protobuf:"varint,3,opt,name=revision,proto3" json:"revision,omitempty"` // raft_term is the raft term when the request was applied. @@ -526,7 +529,9 @@ type RangeResponse struct { Kvs []*mvccpb.KeyValue `protobuf:"bytes,2,rep,name=kvs,proto3" json:"kvs,omitempty"` // more indicates if there are more keys to return in the requested range. More bool `protobuf:"varint,3,opt,name=more,proto3" json:"more,omitempty"` - // count is set to the number of keys within the range when requested. + // count is set to the actual number of keys within the range when requested. + // Unlike Kvs, it is unaffected by limits and filters (e.g., Min/Max, Create/Modify, Revisions) + // and reflects the full count within the specified range. Count int64 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -1630,7 +1635,9 @@ type HashKVResponse struct { // hash is the hash value computed from the responding member's MVCC keys up to a given revision. Hash uint32 `protobuf:"varint,2,opt,name=hash,proto3" json:"hash,omitempty"` // compact_revision is the compacted revision of key-value store when hash begins. - CompactRevision int64 `protobuf:"varint,3,opt,name=compact_revision,json=compactRevision,proto3" json:"compact_revision,omitempty"` + CompactRevision int64 `protobuf:"varint,3,opt,name=compact_revision,json=compactRevision,proto3" json:"compact_revision,omitempty"` + // hash_revision is the revision up to which the hash is calculated. + HashRevision int64 `protobuf:"varint,4,opt,name=hash_revision,json=hashRevision,proto3" json:"hash_revision,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1690,6 +1697,13 @@ func (m *HashKVResponse) GetCompactRevision() int64 { return 0 } +func (m *HashKVResponse) GetHashRevision() int64 { + if m != nil { + return m.HashRevision + } + return 0 +} + type HashResponse struct { Header *ResponseHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` // hash is the hash value computed from the responding member's KV's backend. @@ -1792,7 +1806,11 @@ type SnapshotResponse struct { // remaining_bytes is the number of blob bytes to be sent after this message RemainingBytes uint64 `protobuf:"varint,2,opt,name=remaining_bytes,json=remainingBytes,proto3" json:"remaining_bytes,omitempty"` // blob contains the next chunk of the snapshot in the snapshot stream. - Blob []byte `protobuf:"bytes,3,opt,name=blob,proto3" json:"blob,omitempty"` + Blob []byte `protobuf:"bytes,3,opt,name=blob,proto3" json:"blob,omitempty"` + // local version of server that created the snapshot. + // In cluster with binaries with different version, each cluster can return different result. + // Informs which etcd server version should be used when restoring the snapshot. + Version string `protobuf:"bytes,4,opt,name=version,proto3" json:"version,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -1852,6 +1870,13 @@ func (m *SnapshotResponse) GetBlob() []byte { return nil } +func (m *SnapshotResponse) GetVersion() string { + if m != nil { + return m.Version + } + return "" +} + type WatchRequest struct { // request_union is a request to either create a new watcher or cancel an existing watcher. // @@ -2176,7 +2201,8 @@ type WatchResponse struct { // the created watcher from the same stream. // All events sent to the created watcher will attach with the same watch_id. Created bool `protobuf:"varint,3,opt,name=created,proto3" json:"created,omitempty"` - // canceled is set to true if the response is for a cancel watch request. + // canceled is set to true if the response is for a cancel watch request + // or if the start_revision has already been compacted. // No further events will be sent to the canceled watcher. Canceled bool `protobuf:"varint,4,opt,name=canceled,proto3" json:"canceled,omitempty"` // compact_revision is set to the minimum index if a watcher tries to watch @@ -4165,6 +4191,57 @@ func (m *DowngradeResponse) GetVersion() string { return "" } +// DowngradeVersionTestRequest is used for test only. The version in +// this request will be read as the WAL record version.If the downgrade +// target version is less than this version, then the downgrade(online) +// or migration(offline) isn't safe, so shouldn't be allowed. +type DowngradeVersionTestRequest struct { + Ver string `protobuf:"bytes,1,opt,name=ver,proto3" json:"ver,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DowngradeVersionTestRequest) Reset() { *m = DowngradeVersionTestRequest{} } +func (m *DowngradeVersionTestRequest) String() string { return proto.CompactTextString(m) } +func (*DowngradeVersionTestRequest) ProtoMessage() {} +func (*DowngradeVersionTestRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{59} +} +func (m *DowngradeVersionTestRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DowngradeVersionTestRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DowngradeVersionTestRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DowngradeVersionTestRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_DowngradeVersionTestRequest.Merge(m, src) +} +func (m *DowngradeVersionTestRequest) XXX_Size() int { + return m.Size() +} +func (m *DowngradeVersionTestRequest) XXX_DiscardUnknown() { + xxx_messageInfo_DowngradeVersionTestRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_DowngradeVersionTestRequest proto.InternalMessageInfo + +func (m *DowngradeVersionTestRequest) GetVer() string { + if m != nil { + return m.Ver + } + return "" +} + type StatusRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -4175,7 +4252,7 @@ func (m *StatusRequest) Reset() { *m = StatusRequest{} } func (m *StatusRequest) String() string { return proto.CompactTextString(m) } func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{59} + return fileDescriptor_77a6da22d6a3feb1, []int{60} } func (m *StatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4223,17 +4300,23 @@ type StatusResponse struct { // dbSizeInUse is the size of the backend database logically in use, in bytes, of the responding member. DbSizeInUse int64 `protobuf:"varint,9,opt,name=dbSizeInUse,proto3" json:"dbSizeInUse,omitempty"` // isLearner indicates if the member is raft learner. - IsLearner bool `protobuf:"varint,10,opt,name=isLearner,proto3" json:"isLearner,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + IsLearner bool `protobuf:"varint,10,opt,name=isLearner,proto3" json:"isLearner,omitempty"` + // storageVersion is the version of the db file. It might be updated with delay in relationship to the target cluster version. + StorageVersion string `protobuf:"bytes,11,opt,name=storageVersion,proto3" json:"storageVersion,omitempty"` + // dbSizeQuota is the configured etcd storage quota in bytes (the value passed to etcd instance by flag --quota-backend-bytes) + DbSizeQuota int64 `protobuf:"varint,12,opt,name=dbSizeQuota,proto3" json:"dbSizeQuota,omitempty"` + // downgradeInfo indicates if there is downgrade process. + DowngradeInfo *DowngradeInfo `protobuf:"bytes,13,opt,name=downgradeInfo,proto3" json:"downgradeInfo,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } func (m *StatusResponse) Reset() { *m = StatusResponse{} } func (m *StatusResponse) String() string { return proto.CompactTextString(m) } func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{60} + return fileDescriptor_77a6da22d6a3feb1, []int{61} } func (m *StatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4332,6 +4415,84 @@ func (m *StatusResponse) GetIsLearner() bool { return false } +func (m *StatusResponse) GetStorageVersion() string { + if m != nil { + return m.StorageVersion + } + return "" +} + +func (m *StatusResponse) GetDbSizeQuota() int64 { + if m != nil { + return m.DbSizeQuota + } + return 0 +} + +func (m *StatusResponse) GetDowngradeInfo() *DowngradeInfo { + if m != nil { + return m.DowngradeInfo + } + return nil +} + +type DowngradeInfo struct { + // enabled indicates whether the cluster is enabled to downgrade. + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + // targetVersion is the target downgrade version. + TargetVersion string `protobuf:"bytes,2,opt,name=targetVersion,proto3" json:"targetVersion,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *DowngradeInfo) Reset() { *m = DowngradeInfo{} } +func (m *DowngradeInfo) String() string { return proto.CompactTextString(m) } +func (*DowngradeInfo) ProtoMessage() {} +func (*DowngradeInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_77a6da22d6a3feb1, []int{62} +} +func (m *DowngradeInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DowngradeInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DowngradeInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DowngradeInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_DowngradeInfo.Merge(m, src) +} +func (m *DowngradeInfo) XXX_Size() int { + return m.Size() +} +func (m *DowngradeInfo) XXX_DiscardUnknown() { + xxx_messageInfo_DowngradeInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_DowngradeInfo proto.InternalMessageInfo + +func (m *DowngradeInfo) GetEnabled() bool { + if m != nil { + return m.Enabled + } + return false +} + +func (m *DowngradeInfo) GetTargetVersion() string { + if m != nil { + return m.TargetVersion + } + return "" +} + type AuthEnableRequest struct { XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` @@ -4342,7 +4503,7 @@ func (m *AuthEnableRequest) Reset() { *m = AuthEnableRequest{} } func (m *AuthEnableRequest) String() string { return proto.CompactTextString(m) } func (*AuthEnableRequest) ProtoMessage() {} func (*AuthEnableRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{61} + return fileDescriptor_77a6da22d6a3feb1, []int{63} } func (m *AuthEnableRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4381,7 +4542,7 @@ func (m *AuthDisableRequest) Reset() { *m = AuthDisableRequest{} } func (m *AuthDisableRequest) String() string { return proto.CompactTextString(m) } func (*AuthDisableRequest) ProtoMessage() {} func (*AuthDisableRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{62} + return fileDescriptor_77a6da22d6a3feb1, []int{64} } func (m *AuthDisableRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4420,7 +4581,7 @@ func (m *AuthStatusRequest) Reset() { *m = AuthStatusRequest{} } func (m *AuthStatusRequest) String() string { return proto.CompactTextString(m) } func (*AuthStatusRequest) ProtoMessage() {} func (*AuthStatusRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{63} + return fileDescriptor_77a6da22d6a3feb1, []int{65} } func (m *AuthStatusRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4461,7 +4622,7 @@ func (m *AuthenticateRequest) Reset() { *m = AuthenticateRequest{} } func (m *AuthenticateRequest) String() string { return proto.CompactTextString(m) } func (*AuthenticateRequest) ProtoMessage() {} func (*AuthenticateRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{64} + return fileDescriptor_77a6da22d6a3feb1, []int{66} } func (m *AuthenticateRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4518,7 +4679,7 @@ func (m *AuthUserAddRequest) Reset() { *m = AuthUserAddRequest{} } func (m *AuthUserAddRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserAddRequest) ProtoMessage() {} func (*AuthUserAddRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{65} + return fileDescriptor_77a6da22d6a3feb1, []int{67} } func (m *AuthUserAddRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4586,7 +4747,7 @@ func (m *AuthUserGetRequest) Reset() { *m = AuthUserGetRequest{} } func (m *AuthUserGetRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserGetRequest) ProtoMessage() {} func (*AuthUserGetRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{66} + return fileDescriptor_77a6da22d6a3feb1, []int{68} } func (m *AuthUserGetRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4634,7 +4795,7 @@ func (m *AuthUserDeleteRequest) Reset() { *m = AuthUserDeleteRequest{} } func (m *AuthUserDeleteRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserDeleteRequest) ProtoMessage() {} func (*AuthUserDeleteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{67} + return fileDescriptor_77a6da22d6a3feb1, []int{69} } func (m *AuthUserDeleteRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4686,7 +4847,7 @@ func (m *AuthUserChangePasswordRequest) Reset() { *m = AuthUserChangePas func (m *AuthUserChangePasswordRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserChangePasswordRequest) ProtoMessage() {} func (*AuthUserChangePasswordRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{68} + return fileDescriptor_77a6da22d6a3feb1, []int{70} } func (m *AuthUserChangePasswordRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4750,7 +4911,7 @@ func (m *AuthUserGrantRoleRequest) Reset() { *m = AuthUserGrantRoleReque func (m *AuthUserGrantRoleRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserGrantRoleRequest) ProtoMessage() {} func (*AuthUserGrantRoleRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{69} + return fileDescriptor_77a6da22d6a3feb1, []int{71} } func (m *AuthUserGrantRoleRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4805,7 +4966,7 @@ func (m *AuthUserRevokeRoleRequest) Reset() { *m = AuthUserRevokeRoleReq func (m *AuthUserRevokeRoleRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserRevokeRoleRequest) ProtoMessage() {} func (*AuthUserRevokeRoleRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{70} + return fileDescriptor_77a6da22d6a3feb1, []int{72} } func (m *AuthUserRevokeRoleRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4860,7 +5021,7 @@ func (m *AuthRoleAddRequest) Reset() { *m = AuthRoleAddRequest{} } func (m *AuthRoleAddRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleAddRequest) ProtoMessage() {} func (*AuthRoleAddRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{71} + return fileDescriptor_77a6da22d6a3feb1, []int{73} } func (m *AuthRoleAddRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4907,7 +5068,7 @@ func (m *AuthRoleGetRequest) Reset() { *m = AuthRoleGetRequest{} } func (m *AuthRoleGetRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleGetRequest) ProtoMessage() {} func (*AuthRoleGetRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{72} + return fileDescriptor_77a6da22d6a3feb1, []int{74} } func (m *AuthRoleGetRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4953,7 +5114,7 @@ func (m *AuthUserListRequest) Reset() { *m = AuthUserListRequest{} } func (m *AuthUserListRequest) String() string { return proto.CompactTextString(m) } func (*AuthUserListRequest) ProtoMessage() {} func (*AuthUserListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{73} + return fileDescriptor_77a6da22d6a3feb1, []int{75} } func (m *AuthUserListRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -4992,7 +5153,7 @@ func (m *AuthRoleListRequest) Reset() { *m = AuthRoleListRequest{} } func (m *AuthRoleListRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleListRequest) ProtoMessage() {} func (*AuthRoleListRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{74} + return fileDescriptor_77a6da22d6a3feb1, []int{76} } func (m *AuthRoleListRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5032,7 +5193,7 @@ func (m *AuthRoleDeleteRequest) Reset() { *m = AuthRoleDeleteRequest{} } func (m *AuthRoleDeleteRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleDeleteRequest) ProtoMessage() {} func (*AuthRoleDeleteRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{75} + return fileDescriptor_77a6da22d6a3feb1, []int{77} } func (m *AuthRoleDeleteRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5082,7 +5243,7 @@ func (m *AuthRoleGrantPermissionRequest) Reset() { *m = AuthRoleGrantPer func (m *AuthRoleGrantPermissionRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleGrantPermissionRequest) ProtoMessage() {} func (*AuthRoleGrantPermissionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{76} + return fileDescriptor_77a6da22d6a3feb1, []int{78} } func (m *AuthRoleGrantPermissionRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5138,7 +5299,7 @@ func (m *AuthRoleRevokePermissionRequest) Reset() { *m = AuthRoleRevokeP func (m *AuthRoleRevokePermissionRequest) String() string { return proto.CompactTextString(m) } func (*AuthRoleRevokePermissionRequest) ProtoMessage() {} func (*AuthRoleRevokePermissionRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{77} + return fileDescriptor_77a6da22d6a3feb1, []int{79} } func (m *AuthRoleRevokePermissionRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5199,7 +5360,7 @@ func (m *AuthEnableResponse) Reset() { *m = AuthEnableResponse{} } func (m *AuthEnableResponse) String() string { return proto.CompactTextString(m) } func (*AuthEnableResponse) ProtoMessage() {} func (*AuthEnableResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{78} + return fileDescriptor_77a6da22d6a3feb1, []int{80} } func (m *AuthEnableResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5246,7 +5407,7 @@ func (m *AuthDisableResponse) Reset() { *m = AuthDisableResponse{} } func (m *AuthDisableResponse) String() string { return proto.CompactTextString(m) } func (*AuthDisableResponse) ProtoMessage() {} func (*AuthDisableResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{79} + return fileDescriptor_77a6da22d6a3feb1, []int{81} } func (m *AuthDisableResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5296,7 +5457,7 @@ func (m *AuthStatusResponse) Reset() { *m = AuthStatusResponse{} } func (m *AuthStatusResponse) String() string { return proto.CompactTextString(m) } func (*AuthStatusResponse) ProtoMessage() {} func (*AuthStatusResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{80} + return fileDescriptor_77a6da22d6a3feb1, []int{82} } func (m *AuthStatusResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5359,7 +5520,7 @@ func (m *AuthenticateResponse) Reset() { *m = AuthenticateResponse{} } func (m *AuthenticateResponse) String() string { return proto.CompactTextString(m) } func (*AuthenticateResponse) ProtoMessage() {} func (*AuthenticateResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{81} + return fileDescriptor_77a6da22d6a3feb1, []int{83} } func (m *AuthenticateResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5413,7 +5574,7 @@ func (m *AuthUserAddResponse) Reset() { *m = AuthUserAddResponse{} } func (m *AuthUserAddResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserAddResponse) ProtoMessage() {} func (*AuthUserAddResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{82} + return fileDescriptor_77a6da22d6a3feb1, []int{84} } func (m *AuthUserAddResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5461,7 +5622,7 @@ func (m *AuthUserGetResponse) Reset() { *m = AuthUserGetResponse{} } func (m *AuthUserGetResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserGetResponse) ProtoMessage() {} func (*AuthUserGetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{83} + return fileDescriptor_77a6da22d6a3feb1, []int{85} } func (m *AuthUserGetResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5515,7 +5676,7 @@ func (m *AuthUserDeleteResponse) Reset() { *m = AuthUserDeleteResponse{} func (m *AuthUserDeleteResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserDeleteResponse) ProtoMessage() {} func (*AuthUserDeleteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{84} + return fileDescriptor_77a6da22d6a3feb1, []int{86} } func (m *AuthUserDeleteResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5562,7 +5723,7 @@ func (m *AuthUserChangePasswordResponse) Reset() { *m = AuthUserChangePa func (m *AuthUserChangePasswordResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserChangePasswordResponse) ProtoMessage() {} func (*AuthUserChangePasswordResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{85} + return fileDescriptor_77a6da22d6a3feb1, []int{87} } func (m *AuthUserChangePasswordResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5609,7 +5770,7 @@ func (m *AuthUserGrantRoleResponse) Reset() { *m = AuthUserGrantRoleResp func (m *AuthUserGrantRoleResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserGrantRoleResponse) ProtoMessage() {} func (*AuthUserGrantRoleResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{86} + return fileDescriptor_77a6da22d6a3feb1, []int{88} } func (m *AuthUserGrantRoleResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5656,7 +5817,7 @@ func (m *AuthUserRevokeRoleResponse) Reset() { *m = AuthUserRevokeRoleRe func (m *AuthUserRevokeRoleResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserRevokeRoleResponse) ProtoMessage() {} func (*AuthUserRevokeRoleResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{87} + return fileDescriptor_77a6da22d6a3feb1, []int{89} } func (m *AuthUserRevokeRoleResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5703,7 +5864,7 @@ func (m *AuthRoleAddResponse) Reset() { *m = AuthRoleAddResponse{} } func (m *AuthRoleAddResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleAddResponse) ProtoMessage() {} func (*AuthRoleAddResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{88} + return fileDescriptor_77a6da22d6a3feb1, []int{90} } func (m *AuthRoleAddResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5751,7 +5912,7 @@ func (m *AuthRoleGetResponse) Reset() { *m = AuthRoleGetResponse{} } func (m *AuthRoleGetResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleGetResponse) ProtoMessage() {} func (*AuthRoleGetResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{89} + return fileDescriptor_77a6da22d6a3feb1, []int{91} } func (m *AuthRoleGetResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5806,7 +5967,7 @@ func (m *AuthRoleListResponse) Reset() { *m = AuthRoleListResponse{} } func (m *AuthRoleListResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleListResponse) ProtoMessage() {} func (*AuthRoleListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{90} + return fileDescriptor_77a6da22d6a3feb1, []int{92} } func (m *AuthRoleListResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5861,7 +6022,7 @@ func (m *AuthUserListResponse) Reset() { *m = AuthUserListResponse{} } func (m *AuthUserListResponse) String() string { return proto.CompactTextString(m) } func (*AuthUserListResponse) ProtoMessage() {} func (*AuthUserListResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{91} + return fileDescriptor_77a6da22d6a3feb1, []int{93} } func (m *AuthUserListResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5915,7 +6076,7 @@ func (m *AuthRoleDeleteResponse) Reset() { *m = AuthRoleDeleteResponse{} func (m *AuthRoleDeleteResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleDeleteResponse) ProtoMessage() {} func (*AuthRoleDeleteResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{92} + return fileDescriptor_77a6da22d6a3feb1, []int{94} } func (m *AuthRoleDeleteResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -5962,7 +6123,7 @@ func (m *AuthRoleGrantPermissionResponse) Reset() { *m = AuthRoleGrantPe func (m *AuthRoleGrantPermissionResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleGrantPermissionResponse) ProtoMessage() {} func (*AuthRoleGrantPermissionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{93} + return fileDescriptor_77a6da22d6a3feb1, []int{95} } func (m *AuthRoleGrantPermissionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6009,7 +6170,7 @@ func (m *AuthRoleRevokePermissionResponse) Reset() { *m = AuthRoleRevoke func (m *AuthRoleRevokePermissionResponse) String() string { return proto.CompactTextString(m) } func (*AuthRoleRevokePermissionResponse) ProtoMessage() {} func (*AuthRoleRevokePermissionResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_77a6da22d6a3feb1, []int{94} + return fileDescriptor_77a6da22d6a3feb1, []int{96} } func (m *AuthRoleRevokePermissionResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -6113,8 +6274,10 @@ func init() { proto.RegisterType((*AlarmResponse)(nil), "etcdserverpb.AlarmResponse") proto.RegisterType((*DowngradeRequest)(nil), "etcdserverpb.DowngradeRequest") proto.RegisterType((*DowngradeResponse)(nil), "etcdserverpb.DowngradeResponse") + proto.RegisterType((*DowngradeVersionTestRequest)(nil), "etcdserverpb.DowngradeVersionTestRequest") proto.RegisterType((*StatusRequest)(nil), "etcdserverpb.StatusRequest") proto.RegisterType((*StatusResponse)(nil), "etcdserverpb.StatusResponse") + proto.RegisterType((*DowngradeInfo)(nil), "etcdserverpb.DowngradeInfo") proto.RegisterType((*AuthEnableRequest)(nil), "etcdserverpb.AuthEnableRequest") proto.RegisterType((*AuthDisableRequest)(nil), "etcdserverpb.AuthDisableRequest") proto.RegisterType((*AuthStatusRequest)(nil), "etcdserverpb.AuthStatusRequest") @@ -6154,264 +6317,293 @@ func init() { func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 4110 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x5b, 0xdd, 0x73, 0x1b, 0xc9, - 0x71, 0xe7, 0x02, 0x24, 0x01, 0x34, 0x3e, 0x08, 0x0e, 0x29, 0x0a, 0xc2, 0x49, 0x14, 0x6f, 0x74, - 0xd2, 0xf1, 0xa4, 0x3b, 0xe2, 0x4c, 0xdb, 0xb9, 0x2a, 0x25, 0x71, 0x0c, 0x91, 0x38, 0x89, 0x47, - 0x8a, 0xe4, 0x2d, 0x21, 0xdd, 0x47, 0xb9, 0xc2, 0x5a, 0x02, 0x23, 0x72, 0x43, 0x60, 0x17, 0xde, - 0x5d, 0x40, 0xe4, 0xe5, 0xc3, 0x2e, 0x97, 0xe3, 0x4a, 0x5e, 0xed, 0xaa, 0x54, 0xf2, 0x90, 0xbc, - 0xa4, 0x52, 0x2e, 0x3f, 0xf8, 0x39, 0xff, 0x42, 0x9e, 0xf2, 0x51, 0xf9, 0x07, 0x52, 0x17, 0xbf, - 0x24, 0x7f, 0x85, 0x6b, 0xbe, 0x76, 0x67, 0xf6, 0x83, 0x92, 0x8d, 0xbb, 0x7b, 0x11, 0x31, 0x3d, - 0x3d, 0xfd, 0xeb, 0xe9, 0x99, 0xe9, 0xee, 0xe9, 0x59, 0x41, 0xc9, 0x1b, 0xf5, 0x36, 0x46, 0x9e, - 0x1b, 0xb8, 0xa8, 0x42, 0x82, 0x5e, 0xdf, 0x27, 0xde, 0x84, 0x78, 0xa3, 0x93, 0xe6, 0xf2, 0xa9, - 0x7b, 0xea, 0xb2, 0x8e, 0x16, 0xfd, 0xc5, 0x79, 0x9a, 0x0d, 0xca, 0xd3, 0xb2, 0x46, 0x76, 0x6b, - 0x38, 0xe9, 0xf5, 0x46, 0x27, 0xad, 0xf3, 0x89, 0xe8, 0x69, 0x86, 0x3d, 0xd6, 0x38, 0x38, 0x1b, - 0x9d, 0xb0, 0x3f, 0xa2, 0xef, 0xe6, 0xa9, 0xeb, 0x9e, 0x0e, 0x08, 0xef, 0x75, 0x1c, 0x37, 0xb0, - 0x02, 0xdb, 0x75, 0x7c, 0xde, 0x8b, 0xff, 0xda, 0x80, 0x9a, 0x49, 0xfc, 0x91, 0xeb, 0xf8, 0xe4, - 0x09, 0xb1, 0xfa, 0xc4, 0x43, 0xb7, 0x00, 0x7a, 0x83, 0xb1, 0x1f, 0x10, 0xef, 0xd8, 0xee, 0x37, - 0x8c, 0x35, 0x63, 0x7d, 0xd6, 0x2c, 0x09, 0xca, 0x4e, 0x1f, 0xbd, 0x01, 0xa5, 0x21, 0x19, 0x9e, - 0xf0, 0xde, 0x1c, 0xeb, 0x2d, 0x72, 0xc2, 0x4e, 0x1f, 0x35, 0xa1, 0xe8, 0x91, 0x89, 0xed, 0xdb, - 0xae, 0xd3, 0xc8, 0xaf, 0x19, 0xeb, 0x79, 0x33, 0x6c, 0xd3, 0x81, 0x9e, 0xf5, 0x22, 0x38, 0x0e, - 0x88, 0x37, 0x6c, 0xcc, 0xf2, 0x81, 0x94, 0xd0, 0x25, 0xde, 0x10, 0xff, 0x74, 0x0e, 0x2a, 0xa6, - 0xe5, 0x9c, 0x12, 0x93, 0xfc, 0x70, 0x4c, 0xfc, 0x00, 0xd5, 0x21, 0x7f, 0x4e, 0x2e, 0x19, 0x7c, - 0xc5, 0xa4, 0x3f, 0xf9, 0x78, 0xe7, 0x94, 0x1c, 0x13, 0x87, 0x03, 0x57, 0xe8, 0x78, 0xe7, 0x94, - 0x74, 0x9c, 0x3e, 0x5a, 0x86, 0xb9, 0x81, 0x3d, 0xb4, 0x03, 0x81, 0xca, 0x1b, 0x9a, 0x3a, 0xb3, - 0x31, 0x75, 0xb6, 0x00, 0x7c, 0xd7, 0x0b, 0x8e, 0x5d, 0xaf, 0x4f, 0xbc, 0xc6, 0xdc, 0x9a, 0xb1, - 0x5e, 0xdb, 0x7c, 0x6b, 0x43, 0x5d, 0x86, 0x0d, 0x55, 0xa1, 0x8d, 0x23, 0xd7, 0x0b, 0x0e, 0x28, - 0xaf, 0x59, 0xf2, 0xe5, 0x4f, 0xf4, 0x21, 0x94, 0x99, 0x90, 0xc0, 0xf2, 0x4e, 0x49, 0xd0, 0x98, - 0x67, 0x52, 0xee, 0xbe, 0x42, 0x4a, 0x97, 0x31, 0x9b, 0x0c, 0x9e, 0xff, 0x46, 0x18, 0x2a, 0x3e, - 0xf1, 0x6c, 0x6b, 0x60, 0x7f, 0x61, 0x9d, 0x0c, 0x48, 0xa3, 0xb0, 0x66, 0xac, 0x17, 0x4d, 0x8d, - 0x46, 0xe7, 0x7f, 0x4e, 0x2e, 0xfd, 0x63, 0xd7, 0x19, 0x5c, 0x36, 0x8a, 0x8c, 0xa1, 0x48, 0x09, - 0x07, 0xce, 0xe0, 0x92, 0x2d, 0x9a, 0x3b, 0x76, 0x02, 0xde, 0x5b, 0x62, 0xbd, 0x25, 0x46, 0x61, - 0xdd, 0xeb, 0x50, 0x1f, 0xda, 0xce, 0xf1, 0xd0, 0xed, 0x1f, 0x87, 0x06, 0x01, 0x66, 0x90, 0xda, - 0xd0, 0x76, 0x9e, 0xba, 0x7d, 0x53, 0x9a, 0x85, 0x72, 0x5a, 0x17, 0x3a, 0x67, 0x59, 0x70, 0x5a, - 0x17, 0x2a, 0xe7, 0x06, 0x2c, 0x51, 0x99, 0x3d, 0x8f, 0x58, 0x01, 0x89, 0x98, 0x2b, 0x8c, 0x79, - 0x71, 0x68, 0x3b, 0x5b, 0xac, 0x47, 0xe3, 0xb7, 0x2e, 0x12, 0xfc, 0x55, 0xc1, 0x6f, 0x5d, 0xe8, - 0xfc, 0x78, 0x03, 0x4a, 0xa1, 0xcd, 0x51, 0x11, 0x66, 0xf7, 0x0f, 0xf6, 0x3b, 0xf5, 0x19, 0x04, - 0x30, 0xdf, 0x3e, 0xda, 0xea, 0xec, 0x6f, 0xd7, 0x0d, 0x54, 0x86, 0xc2, 0x76, 0x87, 0x37, 0x72, - 0xf8, 0x11, 0x40, 0x64, 0x5d, 0x54, 0x80, 0xfc, 0x6e, 0xe7, 0xb3, 0xfa, 0x0c, 0xe5, 0x79, 0xde, - 0x31, 0x8f, 0x76, 0x0e, 0xf6, 0xeb, 0x06, 0x1d, 0xbc, 0x65, 0x76, 0xda, 0xdd, 0x4e, 0x3d, 0x47, - 0x39, 0x9e, 0x1e, 0x6c, 0xd7, 0xf3, 0xa8, 0x04, 0x73, 0xcf, 0xdb, 0x7b, 0xcf, 0x3a, 0xf5, 0x59, - 0xfc, 0x0b, 0x03, 0xaa, 0x62, 0xbd, 0xf8, 0x99, 0x40, 0xdf, 0x81, 0xf9, 0x33, 0x76, 0x2e, 0xd8, - 0x56, 0x2c, 0x6f, 0xde, 0x8c, 0x2d, 0xae, 0x76, 0x76, 0x4c, 0xc1, 0x8b, 0x30, 0xe4, 0xcf, 0x27, - 0x7e, 0x23, 0xb7, 0x96, 0x5f, 0x2f, 0x6f, 0xd6, 0x37, 0xf8, 0x79, 0xdd, 0xd8, 0x25, 0x97, 0xcf, - 0xad, 0xc1, 0x98, 0x98, 0xb4, 0x13, 0x21, 0x98, 0x1d, 0xba, 0x1e, 0x61, 0x3b, 0xb6, 0x68, 0xb2, - 0xdf, 0x74, 0x1b, 0xb3, 0x45, 0x13, 0xbb, 0x95, 0x37, 0xf0, 0xaf, 0x0c, 0x80, 0xc3, 0x71, 0x90, - 0x7d, 0x34, 0x96, 0x61, 0x6e, 0x42, 0x05, 0x8b, 0x63, 0xc1, 0x1b, 0xec, 0x4c, 0x10, 0xcb, 0x27, - 0xe1, 0x99, 0xa0, 0x0d, 0x74, 0x1d, 0x0a, 0x23, 0x8f, 0x4c, 0x8e, 0xcf, 0x27, 0x0c, 0xa4, 0x68, - 0xce, 0xd3, 0xe6, 0xee, 0x04, 0xbd, 0x09, 0x15, 0xfb, 0xd4, 0x71, 0x3d, 0x72, 0xcc, 0x65, 0xcd, - 0xb1, 0xde, 0x32, 0xa7, 0x31, 0xbd, 0x15, 0x16, 0x2e, 0x78, 0x5e, 0x65, 0xd9, 0xa3, 0x24, 0xec, - 0x40, 0x99, 0xa9, 0x3a, 0x95, 0xf9, 0xde, 0x89, 0x74, 0xcc, 0xb1, 0x61, 0x49, 0x13, 0x0a, 0xad, - 0xf1, 0x0f, 0x00, 0x6d, 0x93, 0x01, 0x09, 0xc8, 0x34, 0xde, 0x43, 0xb1, 0x49, 0x5e, 0xb5, 0x09, - 0xfe, 0xb9, 0x01, 0x4b, 0x9a, 0xf8, 0xa9, 0xa6, 0xd5, 0x80, 0x42, 0x9f, 0x09, 0xe3, 0x1a, 0xe4, - 0x4d, 0xd9, 0x44, 0x0f, 0xa0, 0x28, 0x14, 0xf0, 0x1b, 0xf9, 0x8c, 0x4d, 0x53, 0xe0, 0x3a, 0xf9, - 0xf8, 0x57, 0x39, 0x28, 0x89, 0x89, 0x1e, 0x8c, 0x50, 0x1b, 0xaa, 0x1e, 0x6f, 0x1c, 0xb3, 0xf9, - 0x08, 0x8d, 0x9a, 0xd9, 0x4e, 0xe8, 0xc9, 0x8c, 0x59, 0x11, 0x43, 0x18, 0x19, 0xfd, 0x21, 0x94, - 0xa5, 0x88, 0xd1, 0x38, 0x10, 0x26, 0x6f, 0xe8, 0x02, 0xa2, 0xfd, 0xf7, 0x64, 0xc6, 0x04, 0xc1, - 0x7e, 0x38, 0x0e, 0x50, 0x17, 0x96, 0xe5, 0x60, 0x3e, 0x1b, 0xa1, 0x46, 0x9e, 0x49, 0x59, 0xd3, - 0xa5, 0x24, 0x97, 0xea, 0xc9, 0x8c, 0x89, 0xc4, 0x78, 0xa5, 0x53, 0x55, 0x29, 0xb8, 0xe0, 0xce, - 0x3b, 0xa1, 0x52, 0xf7, 0xc2, 0x49, 0xaa, 0xd4, 0xbd, 0x70, 0x1e, 0x95, 0xa0, 0x20, 0x5a, 0xf8, - 0x5f, 0x73, 0x00, 0x72, 0x35, 0x0e, 0x46, 0x68, 0x1b, 0x6a, 0x9e, 0x68, 0x69, 0xd6, 0x7a, 0x23, - 0xd5, 0x5a, 0x62, 0x11, 0x67, 0xcc, 0xaa, 0x1c, 0xc4, 0x95, 0xfb, 0x1e, 0x54, 0x42, 0x29, 0x91, - 0xc1, 0x6e, 0xa4, 0x18, 0x2c, 0x94, 0x50, 0x96, 0x03, 0xa8, 0xc9, 0x3e, 0x81, 0x6b, 0xe1, 0xf8, - 0x14, 0x9b, 0xbd, 0x79, 0x85, 0xcd, 0x42, 0x81, 0x4b, 0x52, 0x82, 0x6a, 0x35, 0x55, 0xb1, 0xc8, - 0x6c, 0x37, 0x52, 0xcc, 0x96, 0x54, 0x8c, 0x1a, 0x0e, 0x68, 0xbc, 0xe4, 0x4d, 0xfc, 0x7f, 0x79, - 0x28, 0x6c, 0xb9, 0xc3, 0x91, 0xe5, 0xd1, 0xd5, 0x98, 0xf7, 0x88, 0x3f, 0x1e, 0x04, 0xcc, 0x5c, - 0xb5, 0xcd, 0x3b, 0xba, 0x44, 0xc1, 0x26, 0xff, 0x9a, 0x8c, 0xd5, 0x14, 0x43, 0xe8, 0x60, 0x11, - 0x1e, 0x73, 0xaf, 0x31, 0x58, 0x04, 0x47, 0x31, 0x44, 0x1e, 0xe4, 0x7c, 0x74, 0x90, 0x9b, 0x50, - 0x98, 0x10, 0x2f, 0x0a, 0xe9, 0x4f, 0x66, 0x4c, 0x49, 0x40, 0xef, 0xc0, 0x42, 0x3c, 0xbc, 0xcc, - 0x09, 0x9e, 0x5a, 0x4f, 0x8f, 0x46, 0x77, 0xa0, 0xa2, 0xc5, 0xb8, 0x79, 0xc1, 0x57, 0x1e, 0x2a, - 0x21, 0x6e, 0x45, 0xfa, 0x55, 0x1a, 0x8f, 0x2b, 0x4f, 0x66, 0xa4, 0x67, 0x5d, 0x91, 0x9e, 0xb5, - 0x28, 0x46, 0x09, 0xdf, 0xaa, 0x39, 0x99, 0xef, 0xeb, 0x4e, 0x06, 0x7f, 0x1f, 0xaa, 0x9a, 0x81, - 0x68, 0xdc, 0xe9, 0x7c, 0xfc, 0xac, 0xbd, 0xc7, 0x83, 0xd4, 0x63, 0x16, 0x97, 0xcc, 0xba, 0x41, - 0x63, 0xdd, 0x5e, 0xe7, 0xe8, 0xa8, 0x9e, 0x43, 0x55, 0x28, 0xed, 0x1f, 0x74, 0x8f, 0x39, 0x57, - 0x1e, 0x3f, 0x0e, 0x25, 0x88, 0x20, 0xa7, 0xc4, 0xb6, 0x19, 0x25, 0xb6, 0x19, 0x32, 0xb6, 0xe5, - 0xa2, 0xd8, 0xc6, 0xc2, 0xdc, 0x5e, 0xa7, 0x7d, 0xd4, 0xa9, 0xcf, 0x3e, 0xaa, 0x41, 0x85, 0xdb, - 0xf7, 0x78, 0xec, 0xd0, 0x50, 0xfb, 0xcf, 0x06, 0x40, 0x74, 0x9a, 0x50, 0x0b, 0x0a, 0x3d, 0x8e, - 0xd3, 0x30, 0x98, 0x33, 0xba, 0x96, 0xba, 0x64, 0xa6, 0xe4, 0x42, 0xdf, 0x82, 0x82, 0x3f, 0xee, - 0xf5, 0x88, 0x2f, 0x43, 0xde, 0xf5, 0xb8, 0x3f, 0x14, 0xde, 0xca, 0x94, 0x7c, 0x74, 0xc8, 0x0b, - 0xcb, 0x1e, 0x8c, 0x59, 0x00, 0xbc, 0x7a, 0x88, 0xe0, 0xc3, 0xff, 0x60, 0x40, 0x59, 0xd9, 0xbc, - 0xbf, 0xa7, 0x13, 0xbe, 0x09, 0x25, 0xa6, 0x03, 0xe9, 0x0b, 0x37, 0x5c, 0x34, 0x23, 0x02, 0xfa, - 0x03, 0x28, 0xc9, 0x13, 0x20, 0x3d, 0x71, 0x23, 0x5d, 0xec, 0xc1, 0xc8, 0x8c, 0x58, 0xf1, 0x2e, - 0x2c, 0x32, 0xab, 0xf4, 0x68, 0x72, 0x2d, 0xed, 0xa8, 0xa6, 0x9f, 0x46, 0x2c, 0xfd, 0x6c, 0x42, - 0x71, 0x74, 0x76, 0xe9, 0xdb, 0x3d, 0x6b, 0x20, 0xb4, 0x08, 0xdb, 0xf8, 0x23, 0x40, 0xaa, 0xb0, - 0x69, 0xa6, 0x8b, 0xab, 0x50, 0x7e, 0x62, 0xf9, 0x67, 0x42, 0x25, 0xfc, 0x00, 0xaa, 0xb4, 0xb9, - 0xfb, 0xfc, 0x35, 0x74, 0x64, 0x97, 0x03, 0xc9, 0x3d, 0x95, 0xcd, 0x11, 0xcc, 0x9e, 0x59, 0xfe, - 0x19, 0x9b, 0x68, 0xd5, 0x64, 0xbf, 0xd1, 0x3b, 0x50, 0xef, 0xf1, 0x49, 0x1e, 0xc7, 0xae, 0x0c, - 0x0b, 0x82, 0x1e, 0x66, 0x82, 0x9f, 0x42, 0x85, 0xcf, 0xe1, 0xab, 0x56, 0x02, 0x2f, 0xc2, 0xc2, - 0x91, 0x63, 0x8d, 0xfc, 0x33, 0x57, 0x46, 0x37, 0x3a, 0xe9, 0x7a, 0x44, 0x9b, 0x0a, 0xf1, 0x6d, - 0x58, 0xf0, 0xc8, 0xd0, 0xb2, 0x1d, 0xdb, 0x39, 0x3d, 0x3e, 0xb9, 0x0c, 0x88, 0x2f, 0x2e, 0x4c, - 0xb5, 0x90, 0xfc, 0x88, 0x52, 0xa9, 0x6a, 0x27, 0x03, 0xf7, 0x44, 0xb8, 0x39, 0xf6, 0x1b, 0xff, - 0x2c, 0x07, 0x95, 0x4f, 0xac, 0xa0, 0x27, 0x97, 0x0e, 0xed, 0x40, 0x2d, 0x74, 0x6e, 0x8c, 0x22, - 0x74, 0x89, 0x85, 0x58, 0x36, 0x46, 0xa6, 0xd2, 0x32, 0x3a, 0x56, 0x7b, 0x2a, 0x81, 0x89, 0xb2, - 0x9c, 0x1e, 0x19, 0x84, 0xa2, 0x72, 0xd9, 0xa2, 0x18, 0xa3, 0x2a, 0x4a, 0x25, 0xa0, 0x03, 0xa8, - 0x8f, 0x3c, 0xf7, 0xd4, 0x23, 0xbe, 0x1f, 0x0a, 0xe3, 0x61, 0x0c, 0xa7, 0x08, 0x3b, 0x14, 0xac, - 0x91, 0xb8, 0x85, 0x91, 0x4e, 0x7a, 0xb4, 0x10, 0xe5, 0x33, 0xdc, 0x39, 0xfd, 0x57, 0x0e, 0x50, - 0x72, 0x52, 0xbf, 0x6b, 0x8a, 0x77, 0x17, 0x6a, 0x7e, 0x60, 0x79, 0x89, 0xcd, 0x56, 0x65, 0xd4, - 0xd0, 0xe3, 0xbf, 0x0d, 0xa1, 0x42, 0xc7, 0x8e, 0x1b, 0xd8, 0x2f, 0x2e, 0x45, 0x96, 0x5c, 0x93, - 0xe4, 0x7d, 0x46, 0x45, 0x1d, 0x28, 0xbc, 0xb0, 0x07, 0x01, 0xf1, 0xfc, 0xc6, 0xdc, 0x5a, 0x7e, - 0xbd, 0xb6, 0xf9, 0xe0, 0x55, 0xcb, 0xb0, 0xf1, 0x21, 0xe3, 0xef, 0x5e, 0x8e, 0x88, 0x29, 0xc7, - 0xaa, 0x99, 0xe7, 0xbc, 0x96, 0x8d, 0xdf, 0x80, 0xe2, 0x4b, 0x2a, 0x82, 0xde, 0xb2, 0x0b, 0x3c, - 0x59, 0x64, 0x6d, 0x7e, 0xc9, 0x7e, 0xe1, 0x59, 0xa7, 0x43, 0xe2, 0x04, 0xf2, 0x1e, 0x28, 0xdb, - 0xf8, 0x2e, 0x40, 0x04, 0x43, 0x5d, 0xfe, 0xfe, 0xc1, 0xe1, 0xb3, 0x6e, 0x7d, 0x06, 0x55, 0xa0, - 0xb8, 0x7f, 0xb0, 0xdd, 0xd9, 0xeb, 0xd0, 0xf8, 0x80, 0x5b, 0xd2, 0xa4, 0xda, 0x5a, 0xaa, 0x98, - 0x86, 0x86, 0x89, 0x57, 0x60, 0x39, 0x6d, 0x01, 0x69, 0x2e, 0x5a, 0x15, 0xbb, 0x74, 0xaa, 0xa3, - 0xa2, 0x42, 0xe7, 0xf4, 0xe9, 0x36, 0xa0, 0xc0, 0x77, 0x6f, 0x5f, 0x24, 0xe7, 0xb2, 0x49, 0x0d, - 0xc1, 0x37, 0x23, 0xe9, 0x8b, 0x55, 0x0a, 0xdb, 0xa9, 0xee, 0x65, 0x2e, 0xd5, 0xbd, 0xa0, 0x3b, - 0x50, 0x0d, 0x4f, 0x83, 0xe5, 0x8b, 0x5c, 0xa0, 0x64, 0x56, 0xe4, 0x46, 0xa7, 0x34, 0xcd, 0xe8, - 0x05, 0xdd, 0xe8, 0xe8, 0x2e, 0xcc, 0x93, 0x09, 0x71, 0x02, 0xbf, 0x51, 0x66, 0x11, 0xa3, 0x2a, - 0x73, 0xf7, 0x0e, 0xa5, 0x9a, 0xa2, 0x13, 0x7f, 0x17, 0x16, 0xd9, 0x1d, 0xe9, 0xb1, 0x67, 0x39, - 0xea, 0x65, 0xae, 0xdb, 0xdd, 0x13, 0xe6, 0xa6, 0x3f, 0x51, 0x0d, 0x72, 0x3b, 0xdb, 0xc2, 0x08, - 0xb9, 0x9d, 0x6d, 0xfc, 0x13, 0x03, 0x90, 0x3a, 0x6e, 0x2a, 0x3b, 0xc7, 0x84, 0x4b, 0xf8, 0x7c, - 0x04, 0xbf, 0x0c, 0x73, 0xc4, 0xf3, 0x5c, 0x8f, 0x59, 0xb4, 0x64, 0xf2, 0x06, 0x7e, 0x4b, 0xe8, - 0x60, 0x92, 0x89, 0x7b, 0x1e, 0x9e, 0x41, 0x2e, 0xcd, 0x08, 0x55, 0xdd, 0x85, 0x25, 0x8d, 0x6b, - 0xaa, 0xc8, 0xf5, 0x21, 0x2c, 0x30, 0x61, 0x5b, 0x67, 0xa4, 0x77, 0x3e, 0x72, 0x6d, 0x27, 0x81, - 0x47, 0x57, 0x2e, 0x72, 0xb0, 0x74, 0x1e, 0x7c, 0x62, 0x95, 0x90, 0xd8, 0xed, 0xee, 0xe1, 0xcf, - 0x60, 0x25, 0x26, 0x47, 0xaa, 0xff, 0x27, 0x50, 0xee, 0x85, 0x44, 0x5f, 0xe4, 0x3a, 0xb7, 0x74, - 0xe5, 0xe2, 0x43, 0xd5, 0x11, 0xf8, 0x00, 0xae, 0x27, 0x44, 0x4f, 0x35, 0xe7, 0xb7, 0xe1, 0x1a, - 0x13, 0xb8, 0x4b, 0xc8, 0xa8, 0x3d, 0xb0, 0x27, 0x99, 0x96, 0x1e, 0x89, 0x49, 0x29, 0x8c, 0x5f, - 0xef, 0xbe, 0xc0, 0x7f, 0x24, 0x10, 0xbb, 0xf6, 0x90, 0x74, 0xdd, 0xbd, 0x6c, 0xdd, 0x68, 0x34, - 0x3b, 0x27, 0x97, 0xbe, 0x48, 0x6b, 0xd8, 0x6f, 0xfc, 0x2f, 0x86, 0x30, 0x95, 0x3a, 0xfc, 0x6b, - 0xde, 0xc9, 0xab, 0x00, 0xa7, 0xf4, 0xc8, 0x90, 0x3e, 0xed, 0xe0, 0x15, 0x15, 0x85, 0x12, 0xea, - 0x49, 0xfd, 0x77, 0x45, 0xe8, 0xb9, 0x2c, 0xf6, 0x39, 0xfb, 0x27, 0xf4, 0x72, 0xb7, 0xa0, 0xcc, - 0x08, 0x47, 0x81, 0x15, 0x8c, 0xfd, 0xc4, 0x62, 0xfc, 0x95, 0xd8, 0xf6, 0x72, 0xd0, 0x54, 0xf3, - 0xfa, 0x16, 0xcc, 0xb3, 0xcb, 0x84, 0x4c, 0xa5, 0x6f, 0xa4, 0xec, 0x47, 0xae, 0x87, 0x29, 0x18, - 0xf1, 0xcf, 0x0c, 0x98, 0x7f, 0xca, 0x4a, 0xb0, 0x8a, 0x6a, 0xb3, 0x72, 0x2d, 0x1c, 0x6b, 0xc8, - 0x0b, 0x43, 0x25, 0x93, 0xfd, 0x66, 0xa9, 0x27, 0x21, 0xde, 0x33, 0x73, 0x8f, 0xa7, 0xb8, 0x25, - 0x33, 0x6c, 0x53, 0x9b, 0xf5, 0x06, 0x36, 0x71, 0x02, 0xd6, 0x3b, 0xcb, 0x7a, 0x15, 0x0a, 0xcd, - 0x9e, 0x6d, 0x7f, 0x8f, 0x58, 0x9e, 0x23, 0x8a, 0xa6, 0x45, 0x33, 0x22, 0xe0, 0x3d, 0xa8, 0x73, - 0x3d, 0xda, 0xfd, 0xbe, 0x92, 0x60, 0x86, 0x68, 0x46, 0x0c, 0x4d, 0x93, 0x96, 0x8b, 0x4b, 0xfb, - 0xa5, 0x01, 0x8b, 0x8a, 0xb8, 0xa9, 0xac, 0xfa, 0x2e, 0xcc, 0xf3, 0x22, 0xb5, 0xc8, 0x74, 0x96, - 0xf5, 0x51, 0x1c, 0xc6, 0x14, 0x3c, 0x68, 0x03, 0x0a, 0xfc, 0x97, 0xbc, 0x03, 0xa4, 0xb3, 0x4b, - 0x26, 0x7c, 0x17, 0x96, 0x04, 0x89, 0x0c, 0xdd, 0xb4, 0x83, 0xc1, 0x16, 0x03, 0xff, 0x05, 0x2c, - 0xeb, 0x6c, 0x53, 0x4d, 0x49, 0x51, 0x32, 0xf7, 0x3a, 0x4a, 0xb6, 0xa5, 0x92, 0xcf, 0x46, 0x7d, - 0x25, 0x8f, 0x8a, 0xef, 0x18, 0x75, 0xbd, 0x72, 0xfa, 0x7a, 0x45, 0x13, 0x90, 0x22, 0xbe, 0xd1, - 0x09, 0x7c, 0x20, 0xb7, 0xc3, 0x9e, 0xed, 0x87, 0x3e, 0x1c, 0x43, 0x65, 0x60, 0x3b, 0xc4, 0xf2, - 0x44, 0xe5, 0xdc, 0xe0, 0x95, 0x73, 0x95, 0x86, 0xbf, 0x00, 0xa4, 0x0e, 0xfc, 0x46, 0x95, 0xbe, - 0x27, 0x4d, 0x76, 0xe8, 0xb9, 0x43, 0x37, 0xd3, 0xec, 0xf8, 0x2f, 0xe1, 0x5a, 0x8c, 0xef, 0x1b, - 0x55, 0x73, 0x09, 0x16, 0xb7, 0x89, 0x4c, 0x68, 0xa4, 0xdb, 0xfb, 0x08, 0x90, 0x4a, 0x9c, 0x2a, - 0xb2, 0xb5, 0x60, 0xf1, 0xa9, 0x3b, 0xa1, 0x2e, 0x92, 0x52, 0x23, 0xdf, 0xc0, 0xeb, 0x10, 0xa1, - 0x29, 0xc2, 0x36, 0x05, 0x57, 0x07, 0x4c, 0x05, 0xfe, 0x1f, 0x06, 0x54, 0xda, 0x03, 0xcb, 0x1b, - 0x4a, 0xe0, 0xef, 0xc1, 0x3c, 0xbf, 0x5d, 0x8b, 0x82, 0xd6, 0x3d, 0x5d, 0x8c, 0xca, 0xcb, 0x1b, - 0x6d, 0x7e, 0x17, 0x17, 0xa3, 0xa8, 0xe2, 0xe2, 0xcd, 0x6b, 0x3b, 0xf6, 0x06, 0xb6, 0x8d, 0xde, - 0x83, 0x39, 0x8b, 0x0e, 0x61, 0xa1, 0xa8, 0x16, 0xaf, 0x6b, 0x30, 0x69, 0xec, 0x0e, 0xc0, 0xb9, - 0xf0, 0x77, 0xa0, 0xac, 0x20, 0xa0, 0x02, 0xe4, 0x1f, 0x77, 0x44, 0xc2, 0xde, 0xde, 0xea, 0xee, - 0x3c, 0xe7, 0x05, 0x9d, 0x1a, 0xc0, 0x76, 0x27, 0x6c, 0xe7, 0xf0, 0xa7, 0x62, 0x94, 0x70, 0xfb, - 0xaa, 0x3e, 0x46, 0x96, 0x3e, 0xb9, 0xd7, 0xd2, 0xe7, 0x02, 0xaa, 0x62, 0xfa, 0xd3, 0x86, 0x31, - 0x26, 0x2f, 0x23, 0x8c, 0x29, 0xca, 0x9b, 0x82, 0x11, 0xff, 0xda, 0x80, 0xfa, 0xb6, 0xfb, 0xd2, - 0x39, 0xf5, 0xac, 0x7e, 0x78, 0x4e, 0x3e, 0x8c, 0xad, 0xd4, 0x46, 0xac, 0x38, 0x1a, 0xe3, 0x8f, - 0x08, 0xb1, 0x15, 0x6b, 0x44, 0x65, 0x43, 0x1e, 0x0b, 0x65, 0x13, 0x7f, 0x00, 0x0b, 0xb1, 0x41, - 0xd4, 0xf6, 0xcf, 0xdb, 0x7b, 0x3b, 0xdb, 0xd4, 0xd6, 0xac, 0xb0, 0xd6, 0xd9, 0x6f, 0x3f, 0xda, - 0xeb, 0x88, 0x07, 0xa4, 0xf6, 0xfe, 0x56, 0x67, 0xaf, 0x9e, 0xc3, 0x3d, 0x58, 0x54, 0xe0, 0xa7, - 0x7d, 0x19, 0xc8, 0xd0, 0x6e, 0x01, 0xaa, 0x22, 0xda, 0x8b, 0x43, 0xf9, 0xef, 0x39, 0xa8, 0x49, - 0xca, 0xd7, 0x83, 0x89, 0x56, 0x60, 0xbe, 0x7f, 0x72, 0x64, 0x7f, 0x21, 0x5f, 0x8e, 0x44, 0x8b, - 0xd2, 0x07, 0x1c, 0x87, 0x3f, 0xdf, 0x8a, 0x16, 0x0d, 0xe3, 0x9e, 0xf5, 0x22, 0xd8, 0x71, 0xfa, - 0xe4, 0x82, 0x25, 0x05, 0xb3, 0x66, 0x44, 0x60, 0x15, 0x26, 0xf1, 0xcc, 0xcb, 0x6e, 0x56, 0xca, - 0xb3, 0x2f, 0xba, 0x0f, 0x75, 0xfa, 0xbb, 0x3d, 0x1a, 0x0d, 0x6c, 0xd2, 0xe7, 0x02, 0x0a, 0x8c, - 0x27, 0x41, 0xa7, 0xe8, 0xec, 0x2e, 0xe2, 0x37, 0x8a, 0x2c, 0x2c, 0x89, 0x16, 0x5a, 0x83, 0x32, - 0xd7, 0x6f, 0xc7, 0x79, 0xe6, 0x13, 0xf6, 0xf6, 0x99, 0x37, 0x55, 0x92, 0x9e, 0x66, 0x40, 0x3c, - 0xcd, 0x58, 0x82, 0xc5, 0xf6, 0x38, 0x38, 0xeb, 0x38, 0x34, 0x56, 0x48, 0x2b, 0x2f, 0x03, 0xa2, - 0xc4, 0x6d, 0xdb, 0x57, 0xa9, 0x82, 0x55, 0x5f, 0x90, 0x0e, 0x2c, 0x51, 0x22, 0x71, 0x02, 0xbb, - 0xa7, 0xc4, 0x55, 0x99, 0x79, 0x19, 0xb1, 0xcc, 0xcb, 0xf2, 0xfd, 0x97, 0xae, 0xd7, 0x17, 0x36, - 0x0f, 0xdb, 0xf8, 0x9f, 0x0c, 0x0e, 0xf9, 0xcc, 0xd7, 0xd2, 0xa7, 0xdf, 0x51, 0x0c, 0x7a, 0x1f, - 0x0a, 0xee, 0x88, 0xbd, 0xf0, 0x8b, 0x32, 0xcc, 0xca, 0x06, 0xff, 0x26, 0x60, 0x43, 0x08, 0x3e, - 0xe0, 0xbd, 0xa6, 0x64, 0x43, 0xf7, 0xa0, 0x76, 0x66, 0xf9, 0x67, 0xa4, 0x7f, 0x28, 0x65, 0xf2, - 0x9b, 0x5f, 0x8c, 0x8a, 0xd7, 0x23, 0xfd, 0x1e, 0x93, 0xe0, 0x0a, 0xfd, 0xf0, 0x03, 0xb8, 0x26, - 0x39, 0xc5, 0xeb, 0xc4, 0x15, 0xcc, 0x2f, 0xe1, 0x96, 0x64, 0xde, 0x3a, 0xb3, 0x9c, 0x53, 0x22, - 0x01, 0x7f, 0x5f, 0x0b, 0x24, 0xe7, 0x93, 0x4f, 0x9d, 0xcf, 0x23, 0x68, 0x84, 0xf3, 0x61, 0x37, - 0x6b, 0x77, 0xa0, 0x2a, 0x3a, 0xf6, 0xc5, 0x79, 0x2a, 0x99, 0xec, 0x37, 0xa5, 0x79, 0xee, 0x20, - 0x4c, 0xa5, 0xe9, 0x6f, 0xbc, 0x05, 0x37, 0xa4, 0x0c, 0x71, 0xe7, 0xd5, 0x85, 0x24, 0x14, 0x4f, - 0x13, 0x22, 0x0c, 0x4b, 0x87, 0x5e, 0xbd, 0xf0, 0x2a, 0xa7, 0xbe, 0x04, 0x4c, 0xa6, 0xa1, 0xc8, - 0xbc, 0xc6, 0x37, 0x25, 0x55, 0x4c, 0xc9, 0x96, 0x24, 0x99, 0x0a, 0x50, 0xc9, 0x62, 0xc1, 0x28, - 0x39, 0xb1, 0x60, 0x09, 0xd1, 0x3f, 0x80, 0xd5, 0x50, 0x09, 0x6a, 0xb7, 0x43, 0xe2, 0x0d, 0x6d, - 0xdf, 0x57, 0xea, 0xde, 0x69, 0x13, 0xbf, 0x07, 0xb3, 0x23, 0x22, 0x82, 0x50, 0x79, 0x13, 0xc9, - 0x4d, 0xa9, 0x0c, 0x66, 0xfd, 0xb8, 0x0f, 0xb7, 0xa5, 0x74, 0x6e, 0xd1, 0x54, 0xf1, 0x71, 0xa5, - 0x64, 0x35, 0x30, 0x97, 0x51, 0x0d, 0xcc, 0xc7, 0xde, 0x62, 0x3e, 0xe2, 0x86, 0x94, 0x67, 0x7e, - 0xaa, 0xe4, 0x62, 0x97, 0xdb, 0x34, 0x74, 0x15, 0x53, 0x09, 0xfb, 0x1b, 0xe1, 0x05, 0xbe, 0x2a, - 0x0f, 0x4f, 0xd8, 0x0c, 0xe5, 0x43, 0x87, 0x6c, 0xd2, 0xac, 0x99, 0x2e, 0x80, 0xa9, 0xd6, 0x42, - 0x67, 0x4d, 0x8d, 0x86, 0x4f, 0x60, 0x59, 0xf7, 0x6b, 0x53, 0xe9, 0xb2, 0x0c, 0x73, 0x81, 0x7b, - 0x4e, 0x64, 0xac, 0xe1, 0x0d, 0x69, 0xbb, 0xd0, 0xe7, 0x4d, 0x65, 0x3b, 0x2b, 0x12, 0xc6, 0x4e, - 0xc7, 0xb4, 0xfa, 0xd2, 0x8d, 0x25, 0xef, 0x40, 0xbc, 0x81, 0xf7, 0x61, 0x25, 0xee, 0xd9, 0xa6, - 0x52, 0xf9, 0x39, 0x3f, 0x4b, 0x69, 0xce, 0x6f, 0x2a, 0xb9, 0x1f, 0x47, 0x7e, 0x49, 0xf1, 0x6d, - 0x53, 0x89, 0x34, 0xa1, 0x99, 0xe6, 0xea, 0xbe, 0x8a, 0xa3, 0x13, 0x7a, 0xbe, 0xa9, 0x84, 0xf9, - 0x91, 0xb0, 0xe9, 0x97, 0x3f, 0x72, 0x57, 0xf9, 0x2b, 0xdd, 0x95, 0x38, 0x24, 0x91, 0x43, 0xfd, - 0x1a, 0x36, 0x9d, 0xc0, 0x88, 0x7c, 0xf9, 0xb4, 0x18, 0x34, 0x9c, 0x85, 0x18, 0xac, 0x21, 0x37, - 0xb6, 0x1a, 0x01, 0xa6, 0x5a, 0x8c, 0x4f, 0x22, 0x37, 0x9e, 0x08, 0x12, 0x53, 0x09, 0xfe, 0x14, - 0xd6, 0xb2, 0xe3, 0xc3, 0x34, 0x92, 0xef, 0xb7, 0xa0, 0x14, 0x5e, 0x86, 0x94, 0xef, 0xcd, 0xca, - 0x50, 0xd8, 0x3f, 0x38, 0x3a, 0x6c, 0x6f, 0x75, 0xf8, 0x07, 0x67, 0x5b, 0x07, 0xa6, 0xf9, 0xec, - 0xb0, 0x5b, 0xcf, 0x6d, 0xfe, 0x26, 0x0f, 0xb9, 0xdd, 0xe7, 0xe8, 0x33, 0x98, 0xe3, 0x5f, 0x5f, - 0x5c, 0xf1, 0xc9, 0x4d, 0xf3, 0xaa, 0x0f, 0x4c, 0xf0, 0xf5, 0x9f, 0xfc, 0xf7, 0x6f, 0x7e, 0x91, - 0x5b, 0xc4, 0x95, 0xd6, 0xe4, 0xdb, 0xad, 0xf3, 0x49, 0x8b, 0x85, 0xa9, 0x87, 0xc6, 0x7d, 0xf4, - 0x31, 0xe4, 0x0f, 0xc7, 0x01, 0xca, 0xfc, 0x14, 0xa7, 0x99, 0xfd, 0xcd, 0x09, 0xbe, 0xc6, 0x84, - 0x2e, 0x60, 0x10, 0x42, 0x47, 0xe3, 0x80, 0x8a, 0xfc, 0x21, 0x94, 0xd5, 0x2f, 0x46, 0x5e, 0xf9, - 0x7d, 0x4e, 0xf3, 0xd5, 0x5f, 0xa3, 0xe0, 0x5b, 0x0c, 0xea, 0x3a, 0x46, 0x02, 0x8a, 0x7f, 0xd3, - 0xa2, 0xce, 0xa2, 0x7b, 0xe1, 0xa0, 0xcc, 0xaf, 0x77, 0x9a, 0xd9, 0x1f, 0xa8, 0x24, 0x66, 0x11, - 0x5c, 0x38, 0x54, 0xe4, 0x9f, 0x89, 0x6f, 0x53, 0x7a, 0x01, 0xba, 0x9d, 0xf2, 0x6d, 0x82, 0xfa, - 0x0a, 0xdf, 0x5c, 0xcb, 0x66, 0x10, 0x20, 0x37, 0x19, 0xc8, 0x0a, 0x5e, 0x14, 0x20, 0xbd, 0x90, - 0xe5, 0xa1, 0x71, 0x7f, 0xb3, 0x07, 0x73, 0xec, 0x85, 0x0b, 0x7d, 0x2e, 0x7f, 0x34, 0x53, 0x9e, - 0xfa, 0x32, 0x16, 0x5a, 0x7b, 0x1b, 0xc3, 0xcb, 0x0c, 0xa8, 0x86, 0x4b, 0x14, 0x88, 0xbd, 0x6f, - 0x3d, 0x34, 0xee, 0xaf, 0x1b, 0xef, 0x1b, 0x9b, 0xbf, 0x9e, 0x83, 0x39, 0x56, 0xda, 0x45, 0xe7, - 0x00, 0xd1, 0x6b, 0x4f, 0x7c, 0x76, 0x89, 0xf7, 0xa3, 0xf8, 0xec, 0x92, 0x0f, 0x45, 0xb8, 0xc9, - 0x40, 0x97, 0xf1, 0x02, 0x05, 0x65, 0x15, 0xe3, 0x16, 0x2b, 0x82, 0x53, 0x3b, 0xfe, 0xad, 0x21, - 0x2a, 0xdb, 0xfc, 0x2c, 0xa1, 0x34, 0x69, 0xda, 0x93, 0x4f, 0x7c, 0x3b, 0xa4, 0x3c, 0xf7, 0xe0, - 0xef, 0x32, 0xc0, 0x16, 0xae, 0x47, 0x80, 0x1e, 0xe3, 0x78, 0x68, 0xdc, 0xff, 0xbc, 0x81, 0x97, - 0x84, 0x95, 0x63, 0x3d, 0xe8, 0x47, 0x50, 0xd3, 0x9f, 0x34, 0xd0, 0x9d, 0x14, 0xac, 0xf8, 0xcb, - 0x48, 0xf3, 0xad, 0xab, 0x99, 0x84, 0x4e, 0xab, 0x4c, 0x27, 0x01, 0xce, 0x91, 0xcf, 0x09, 0x19, - 0x59, 0x94, 0x49, 0xac, 0x01, 0xfa, 0x47, 0x43, 0xbc, 0x38, 0x45, 0x6f, 0x14, 0x28, 0x4d, 0x7a, - 0xe2, 0x05, 0xa4, 0x79, 0xf7, 0x15, 0x5c, 0x42, 0x89, 0x3f, 0x66, 0x4a, 0x7c, 0x80, 0x97, 0x23, - 0x25, 0x02, 0x7b, 0x48, 0x02, 0x57, 0x68, 0xf1, 0xf9, 0x4d, 0x7c, 0x5d, 0x33, 0x8e, 0xd6, 0x1b, - 0x2d, 0x16, 0x7f, 0x67, 0x48, 0x5d, 0x2c, 0xed, 0xdd, 0x22, 0x75, 0xb1, 0xf4, 0x47, 0x8a, 0xb4, - 0xc5, 0xe2, 0xaf, 0x0a, 0x69, 0x8b, 0x15, 0xf6, 0x6c, 0xfe, 0xff, 0x2c, 0x14, 0xb6, 0xf8, 0x37, - 0xe1, 0xc8, 0x85, 0x52, 0x58, 0xa6, 0x47, 0xab, 0x69, 0x75, 0xc6, 0xe8, 0x5a, 0xd3, 0xbc, 0x9d, - 0xd9, 0x2f, 0x14, 0x7a, 0x93, 0x29, 0xf4, 0x06, 0x5e, 0xa1, 0xc8, 0xe2, 0xb3, 0xf3, 0x16, 0x2f, - 0x66, 0xb5, 0xac, 0x7e, 0x9f, 0x1a, 0xe2, 0xcf, 0xa1, 0xa2, 0xd6, 0xd1, 0xd1, 0x9b, 0xa9, 0xb5, - 0x4d, 0xb5, 0x14, 0xdf, 0xc4, 0x57, 0xb1, 0x08, 0xe4, 0xb7, 0x18, 0xf2, 0x2a, 0xbe, 0x91, 0x82, - 0xec, 0x31, 0x56, 0x0d, 0x9c, 0xd7, 0xc0, 0xd3, 0xc1, 0xb5, 0x12, 0x7b, 0x3a, 0xb8, 0x5e, 0x42, - 0xbf, 0x12, 0x7c, 0xcc, 0x58, 0x29, 0xb8, 0x0f, 0x10, 0x55, 0xb2, 0x51, 0xaa, 0x2d, 0x95, 0x7b, - 0x5d, 0xdc, 0x39, 0x24, 0x8b, 0xe0, 0x18, 0x33, 0x58, 0xb1, 0xef, 0x62, 0xb0, 0x03, 0xdb, 0x0f, - 0xf8, 0xc1, 0xac, 0x6a, 0xa5, 0x69, 0x94, 0x3a, 0x1f, 0xbd, 0xbe, 0xdd, 0xbc, 0x73, 0x25, 0x8f, - 0x40, 0xbf, 0xcb, 0xd0, 0x6f, 0xe3, 0x66, 0x0a, 0xfa, 0x88, 0xf3, 0xd2, 0xcd, 0xf6, 0xe3, 0x02, - 0x94, 0x9f, 0x5a, 0xb6, 0x13, 0x10, 0xc7, 0x72, 0x7a, 0x04, 0x9d, 0xc0, 0x1c, 0x8b, 0xd4, 0x71, - 0x47, 0xac, 0x96, 0x6d, 0xe3, 0x8e, 0x58, 0xab, 0x69, 0xe2, 0x35, 0x06, 0xdc, 0xc4, 0xd7, 0x28, - 0xf0, 0x30, 0x12, 0xdd, 0x62, 0xa5, 0x48, 0x3a, 0xe9, 0x17, 0x30, 0x2f, 0x5e, 0xfb, 0x62, 0x82, - 0xb4, 0xe2, 0x4f, 0xf3, 0x66, 0x7a, 0x67, 0xda, 0x5e, 0x56, 0x61, 0x7c, 0xc6, 0x47, 0x71, 0x26, - 0x00, 0x51, 0x8d, 0x3d, 0xbe, 0xa2, 0x89, 0x92, 0x7c, 0x73, 0x2d, 0x9b, 0x21, 0xcd, 0xa6, 0x2a, - 0x66, 0x3f, 0xe4, 0xa5, 0xb8, 0x7f, 0x0a, 0xb3, 0x4f, 0x2c, 0xff, 0x0c, 0xc5, 0x62, 0xaf, 0xf2, - 0xad, 0x58, 0xb3, 0x99, 0xd6, 0x25, 0x50, 0x6e, 0x33, 0x94, 0x1b, 0xdc, 0x95, 0xa9, 0x28, 0x67, - 0x96, 0x7f, 0x26, 0xec, 0xc7, 0x3f, 0x1d, 0x8b, 0xdb, 0x4f, 0xfb, 0xfc, 0x2c, 0x6e, 0x3f, 0xfd, - 0x6b, 0xb3, 0x6c, 0xfb, 0x51, 0x94, 0xf3, 0x09, 0xc5, 0x19, 0x41, 0x51, 0x7e, 0xad, 0x85, 0x62, - 0x4f, 0xf7, 0xb1, 0x2f, 0xbb, 0x9a, 0xab, 0x59, 0xdd, 0x02, 0xed, 0x0e, 0x43, 0xbb, 0x85, 0x1b, - 0x89, 0xd5, 0x12, 0x9c, 0x0f, 0x8d, 0xfb, 0xef, 0x1b, 0xe8, 0x47, 0x00, 0xd1, 0xc3, 0x44, 0xe2, - 0x0c, 0xc6, 0xdf, 0x38, 0x12, 0x67, 0x30, 0xf1, 0xa6, 0x81, 0x37, 0x18, 0xee, 0x3a, 0xbe, 0x13, - 0xc7, 0x0d, 0x3c, 0xcb, 0xf1, 0x5f, 0x10, 0xef, 0x3d, 0x5e, 0x67, 0xf5, 0xcf, 0xec, 0x11, 0x9d, - 0xb2, 0x07, 0xa5, 0xb0, 0xee, 0x1c, 0xf7, 0xb7, 0xf1, 0x7a, 0x78, 0xdc, 0xdf, 0x26, 0x0a, 0xd6, - 0xba, 0xe3, 0xd1, 0xf6, 0x8b, 0x64, 0xa5, 0x47, 0xf0, 0x97, 0x75, 0x98, 0xa5, 0x79, 0x37, 0x4d, - 0x4f, 0xa2, 0xca, 0x49, 0x7c, 0xf6, 0x89, 0x3a, 0x6a, 0x7c, 0xf6, 0xc9, 0xa2, 0x8b, 0x9e, 0x9e, - 0xd0, 0x6b, 0x56, 0x8b, 0x17, 0x29, 0xe8, 0x4c, 0x5d, 0x28, 0x2b, 0xa5, 0x15, 0x94, 0x22, 0x4c, - 0x2f, 0xd0, 0xc6, 0x03, 0x5e, 0x4a, 0x5d, 0x06, 0xbf, 0xc1, 0xf0, 0xae, 0xf1, 0x80, 0xc7, 0xf0, - 0xfa, 0x9c, 0x83, 0x02, 0x8a, 0xd9, 0x89, 0x93, 0x9f, 0x32, 0x3b, 0xfd, 0xf4, 0xaf, 0x65, 0x33, - 0x64, 0xce, 0x2e, 0x3a, 0xfa, 0x2f, 0xa1, 0xa2, 0x16, 0x58, 0x50, 0x8a, 0xf2, 0xb1, 0xa2, 0x72, - 0x3c, 0x92, 0xa4, 0xd5, 0x67, 0x74, 0xdf, 0xc6, 0x20, 0x2d, 0x85, 0x8d, 0x02, 0x0f, 0xa0, 0x20, - 0x2a, 0x2e, 0x69, 0x26, 0xd5, 0x0b, 0xd0, 0x69, 0x26, 0x8d, 0x95, 0x6b, 0xf4, 0xfc, 0x99, 0x21, - 0xd2, 0x4b, 0xa5, 0x8c, 0xd6, 0x02, 0xed, 0x31, 0x09, 0xb2, 0xd0, 0xa2, 0x5a, 0x66, 0x16, 0x9a, - 0x72, 0xa1, 0xcf, 0x42, 0x3b, 0x25, 0x81, 0xf0, 0x07, 0xf2, 0xa2, 0x8c, 0x32, 0x84, 0xa9, 0x11, - 0x12, 0x5f, 0xc5, 0x92, 0x76, 0xbd, 0x89, 0x00, 0x65, 0x78, 0xbc, 0x00, 0x88, 0xea, 0x41, 0xf1, - 0x9c, 0x35, 0xb5, 0x0e, 0x1e, 0xcf, 0x59, 0xd3, 0x4b, 0x4a, 0xba, 0x8f, 0x8d, 0x70, 0xf9, 0xed, - 0x8a, 0x22, 0xff, 0xdc, 0x00, 0x94, 0x2c, 0x1d, 0xa1, 0x07, 0xe9, 0xd2, 0x53, 0xab, 0xeb, 0xcd, - 0x77, 0x5f, 0x8f, 0x39, 0xcd, 0x21, 0x47, 0x2a, 0xf5, 0x18, 0xf7, 0xe8, 0x25, 0x55, 0xea, 0xc7, - 0x06, 0x54, 0xb5, 0xba, 0x13, 0xba, 0x97, 0xb1, 0xa6, 0xb1, 0xa2, 0x7b, 0xf3, 0xed, 0x57, 0xf2, - 0xa5, 0x25, 0xf3, 0xca, 0x0e, 0x90, 0xb7, 0x9a, 0x9f, 0x1a, 0x50, 0xd3, 0xeb, 0x54, 0x28, 0x43, - 0x76, 0xa2, 0x68, 0xdf, 0x5c, 0x7f, 0x35, 0xe3, 0xd5, 0xcb, 0x13, 0x5d, 0x68, 0x06, 0x50, 0x10, - 0x95, 0xad, 0xb4, 0x8d, 0xaf, 0x97, 0xfb, 0xd3, 0x36, 0x7e, 0xac, 0x2c, 0x96, 0xb2, 0xf1, 0x3d, - 0x77, 0x40, 0x94, 0x63, 0x26, 0x4a, 0x5f, 0x59, 0x68, 0x57, 0x1f, 0xb3, 0x58, 0xdd, 0x2c, 0x0b, - 0x2d, 0x3a, 0x66, 0xb2, 0xe6, 0x85, 0x32, 0x84, 0xbd, 0xe2, 0x98, 0xc5, 0x4b, 0x66, 0x29, 0xc7, - 0x8c, 0x01, 0x2a, 0xc7, 0x2c, 0xaa, 0x4e, 0xa5, 0x1d, 0xb3, 0xc4, 0xeb, 0x45, 0xda, 0x31, 0x4b, - 0x16, 0xb8, 0x52, 0xd6, 0x91, 0xe1, 0x6a, 0xc7, 0x6c, 0x29, 0xa5, 0x90, 0x85, 0xde, 0xcd, 0x30, - 0x62, 0xea, 0xa3, 0x48, 0xf3, 0xbd, 0xd7, 0xe4, 0xce, 0xdc, 0xe3, 0xdc, 0xfc, 0x72, 0x8f, 0xff, - 0x9d, 0x01, 0xcb, 0x69, 0x45, 0x30, 0x94, 0x81, 0x93, 0xf1, 0x98, 0xd2, 0xdc, 0x78, 0x5d, 0xf6, - 0xab, 0xad, 0x15, 0xee, 0xfa, 0x47, 0xf5, 0x7f, 0xfb, 0x72, 0xd5, 0xf8, 0xcf, 0x2f, 0x57, 0x8d, - 0xff, 0xf9, 0x72, 0xd5, 0xf8, 0xfb, 0xff, 0x5d, 0x9d, 0x39, 0x99, 0x67, 0xff, 0xd5, 0xf8, 0xdb, - 0xbf, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x8b, 0x54, 0x11, 0xdf, 0xef, 0x3c, 0x00, 0x00, + // 4574 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x3c, 0x5d, 0x6f, 0x1b, 0x57, + 0x76, 0x1a, 0x92, 0x12, 0xc9, 0xc3, 0x0f, 0xd1, 0xd7, 0xb2, 0x4d, 0xd3, 0xb6, 0xac, 0x8c, 0xed, + 0xc4, 0x71, 0x62, 0xd1, 0x96, 0xec, 0x64, 0xeb, 0x22, 0xe9, 0xd2, 0x12, 0x63, 0x6b, 0x2d, 0x4b, + 0xca, 0x88, 0x76, 0x36, 0x2e, 0xb0, 0xea, 0x88, 0xbc, 0xa6, 0x66, 0x45, 0xce, 0x70, 0x67, 0x86, + 0xb4, 0x94, 0x3e, 0x6c, 0xba, 0xed, 0x76, 0xb1, 0x2d, 0xb0, 0x40, 0x53, 0xa0, 0x58, 0x14, 0xed, + 0x4b, 0x5b, 0xa0, 0x7d, 0x68, 0x8b, 0xf6, 0xa1, 0x0f, 0x45, 0x0b, 0xf4, 0xa1, 0x7d, 0x68, 0x1f, + 0x0a, 0x14, 0xe8, 0x1f, 0x68, 0xd3, 0x7d, 0xea, 0xaf, 0x58, 0xdc, 0xaf, 0xb9, 0x77, 0xbe, 0x24, + 0x67, 0xa5, 0x60, 0x5f, 0x62, 0xce, 0x3d, 0x9f, 0xf7, 0x9c, 0x7b, 0xcf, 0xb9, 0xf7, 0x9c, 0x1b, + 0x41, 0xd1, 0x1d, 0x75, 0x17, 0x47, 0xae, 0xe3, 0x3b, 0xa8, 0x8c, 0xfd, 0x6e, 0xcf, 0xc3, 0xee, + 0x04, 0xbb, 0xa3, 0xdd, 0xc6, 0x5c, 0xdf, 0xe9, 0x3b, 0x14, 0xd0, 0x24, 0xbf, 0x18, 0x4e, 0xa3, + 0x4e, 0x70, 0x9a, 0xe6, 0xc8, 0x6a, 0x0e, 0x27, 0xdd, 0xee, 0x68, 0xb7, 0xb9, 0x3f, 0xe1, 0x90, + 0x46, 0x00, 0x31, 0xc7, 0xfe, 0xde, 0x68, 0x97, 0xfe, 0xc3, 0x61, 0x0b, 0x01, 0x6c, 0x82, 0x5d, + 0xcf, 0x72, 0xec, 0xd1, 0xae, 0xf8, 0xc5, 0x31, 0x2e, 0xf7, 0x1d, 0xa7, 0x3f, 0xc0, 0x8c, 0xde, + 0xb6, 0x1d, 0xdf, 0xf4, 0x2d, 0xc7, 0xf6, 0x38, 0x94, 0xfd, 0xd3, 0xbd, 0xdd, 0xc7, 0xf6, 0x6d, + 0x67, 0x84, 0x6d, 0x73, 0x64, 0x4d, 0x96, 0x9a, 0xce, 0x88, 0xe2, 0xc4, 0xf1, 0xf5, 0x9f, 0x68, + 0x50, 0x35, 0xb0, 0x37, 0x72, 0x6c, 0x0f, 0x3f, 0xc6, 0x66, 0x0f, 0xbb, 0xe8, 0x0a, 0x40, 0x77, + 0x30, 0xf6, 0x7c, 0xec, 0xee, 0x58, 0xbd, 0xba, 0xb6, 0xa0, 0xdd, 0xcc, 0x19, 0x45, 0x3e, 0xb2, + 0xd6, 0x43, 0x97, 0xa0, 0x38, 0xc4, 0xc3, 0x5d, 0x06, 0xcd, 0x50, 0x68, 0x81, 0x0d, 0xac, 0xf5, + 0x50, 0x03, 0x0a, 0x2e, 0x9e, 0x58, 0x44, 0xdd, 0x7a, 0x76, 0x41, 0xbb, 0x99, 0x35, 0x82, 0x6f, + 0x42, 0xe8, 0x9a, 0x2f, 0xfd, 0x1d, 0x1f, 0xbb, 0xc3, 0x7a, 0x8e, 0x11, 0x92, 0x81, 0x0e, 0x76, + 0x87, 0x0f, 0xf2, 0x3f, 0xf8, 0x87, 0x7a, 0x76, 0x79, 0xf1, 0x8e, 0xfe, 0xaf, 0xd3, 0x50, 0x36, + 0x4c, 0xbb, 0x8f, 0x0d, 0xfc, 0xbd, 0x31, 0xf6, 0x7c, 0x54, 0x83, 0xec, 0x3e, 0x3e, 0xa4, 0x7a, + 0x94, 0x0d, 0xf2, 0x93, 0x31, 0xb2, 0xfb, 0x78, 0x07, 0xdb, 0x4c, 0x83, 0x32, 0x61, 0x64, 0xf7, + 0x71, 0xdb, 0xee, 0xa1, 0x39, 0x98, 0x1e, 0x58, 0x43, 0xcb, 0xe7, 0xe2, 0xd9, 0x47, 0x48, 0xaf, + 0x5c, 0x44, 0xaf, 0x15, 0x00, 0xcf, 0x71, 0xfd, 0x1d, 0xc7, 0xed, 0x61, 0xb7, 0x3e, 0xbd, 0xa0, + 0xdd, 0xac, 0x2e, 0x5d, 0x5f, 0x54, 0x3d, 0xbc, 0xa8, 0x2a, 0xb4, 0xb8, 0xed, 0xb8, 0xfe, 0x26, + 0xc1, 0x35, 0x8a, 0x9e, 0xf8, 0x89, 0x3e, 0x82, 0x12, 0x65, 0xe2, 0x9b, 0x6e, 0x1f, 0xfb, 0xf5, + 0x19, 0xca, 0xe5, 0xc6, 0x31, 0x5c, 0x3a, 0x14, 0xd9, 0xa0, 0xe2, 0xd9, 0x6f, 0xa4, 0x43, 0xd9, + 0xc3, 0xae, 0x65, 0x0e, 0xac, 0xcf, 0xcc, 0xdd, 0x01, 0xae, 0xe7, 0x17, 0xb4, 0x9b, 0x05, 0x23, + 0x34, 0x46, 0xe6, 0xbf, 0x8f, 0x0f, 0xbd, 0x1d, 0xc7, 0x1e, 0x1c, 0xd6, 0x0b, 0x14, 0xa1, 0x40, + 0x06, 0x36, 0xed, 0xc1, 0x21, 0xf5, 0x9e, 0x33, 0xb6, 0x7d, 0x06, 0x2d, 0x52, 0x68, 0x91, 0x8e, + 0x50, 0xf0, 0x5d, 0xa8, 0x0d, 0x2d, 0x7b, 0x67, 0xe8, 0xf4, 0x76, 0x02, 0x83, 0x00, 0x31, 0xc8, + 0xc3, 0xfc, 0xef, 0x51, 0x0f, 0xdc, 0x35, 0xaa, 0x43, 0xcb, 0x7e, 0xea, 0xf4, 0x0c, 0x61, 0x1f, + 0x42, 0x62, 0x1e, 0x84, 0x49, 0x4a, 0x51, 0x12, 0xf3, 0x40, 0x25, 0x79, 0x1f, 0xce, 0x12, 0x29, + 0x5d, 0x17, 0x9b, 0x3e, 0x96, 0x54, 0xe5, 0x30, 0xd5, 0x99, 0xa1, 0x65, 0xaf, 0x50, 0x94, 0x10, + 0xa1, 0x79, 0x10, 0x23, 0xac, 0x44, 0x09, 0xcd, 0x83, 0x30, 0xa1, 0xfe, 0x3e, 0x14, 0x03, 0xbf, + 0xa0, 0x02, 0xe4, 0x36, 0x36, 0x37, 0xda, 0xb5, 0x29, 0x04, 0x30, 0xd3, 0xda, 0x5e, 0x69, 0x6f, + 0xac, 0xd6, 0x34, 0x54, 0x82, 0xfc, 0x6a, 0x9b, 0x7d, 0x64, 0x1a, 0xf9, 0x2f, 0xf8, 0x7a, 0x7b, + 0x02, 0x20, 0x5d, 0x81, 0xf2, 0x90, 0x7d, 0xd2, 0xfe, 0xb4, 0x36, 0x45, 0x90, 0x9f, 0xb7, 0x8d, + 0xed, 0xb5, 0xcd, 0x8d, 0x9a, 0x46, 0xb8, 0xac, 0x18, 0xed, 0x56, 0xa7, 0x5d, 0xcb, 0x10, 0x8c, + 0xa7, 0x9b, 0xab, 0xb5, 0x2c, 0x2a, 0xc2, 0xf4, 0xf3, 0xd6, 0xfa, 0xb3, 0x76, 0x2d, 0x17, 0x30, + 0x93, 0xab, 0xf8, 0x4f, 0x34, 0xa8, 0x70, 0x77, 0xb3, 0xbd, 0x85, 0xee, 0xc1, 0xcc, 0x1e, 0xdd, + 0x5f, 0x74, 0x25, 0x97, 0x96, 0x2e, 0x47, 0xd6, 0x46, 0x68, 0x0f, 0x1a, 0x1c, 0x17, 0xe9, 0x90, + 0xdd, 0x9f, 0x78, 0xf5, 0xcc, 0x42, 0xf6, 0x66, 0x69, 0xa9, 0xb6, 0xc8, 0x22, 0xc9, 0xe2, 0x13, + 0x7c, 0xf8, 0xdc, 0x1c, 0x8c, 0xb1, 0x41, 0x80, 0x08, 0x41, 0x6e, 0xe8, 0xb8, 0x98, 0x2e, 0xf8, + 0x82, 0x41, 0x7f, 0x93, 0x5d, 0x40, 0x7d, 0xce, 0x17, 0x3b, 0xfb, 0x90, 0xea, 0xfd, 0xa7, 0x06, + 0xb0, 0x35, 0xf6, 0xd3, 0xb7, 0xd8, 0x1c, 0x4c, 0x4f, 0x88, 0x04, 0xbe, 0xbd, 0xd8, 0x07, 0xdd, + 0x5b, 0xd8, 0xf4, 0x70, 0xb0, 0xb7, 0xc8, 0x07, 0x5a, 0x80, 0xfc, 0xc8, 0xc5, 0x93, 0x9d, 0xfd, + 0x09, 0x95, 0x56, 0x90, 0x7e, 0x9a, 0x21, 0xe3, 0x4f, 0x26, 0xe8, 0x16, 0x94, 0xad, 0xbe, 0xed, + 0xb8, 0x78, 0x87, 0x31, 0x9d, 0x56, 0xd1, 0x96, 0x8c, 0x12, 0x03, 0xd2, 0x29, 0x29, 0xb8, 0x4c, + 0xd4, 0x4c, 0x22, 0xee, 0x3a, 0x81, 0xc9, 0xf9, 0x7c, 0xae, 0x41, 0x89, 0xce, 0xe7, 0x44, 0xc6, + 0x5e, 0x92, 0x13, 0xc9, 0x50, 0xb2, 0x98, 0xc1, 0x63, 0x53, 0x93, 0x2a, 0xd8, 0x80, 0x56, 0xf1, + 0x00, 0xfb, 0xf8, 0x24, 0xc1, 0x4b, 0x31, 0x65, 0x36, 0xd1, 0x94, 0x52, 0xde, 0x5f, 0x68, 0x70, + 0x36, 0x24, 0xf0, 0x44, 0x53, 0xaf, 0x43, 0xbe, 0x47, 0x99, 0x31, 0x9d, 0xb2, 0x86, 0xf8, 0x44, + 0xf7, 0xa0, 0xc0, 0x55, 0xf2, 0xea, 0xd9, 0xe4, 0x65, 0x28, 0xb5, 0xcc, 0x33, 0x2d, 0x3d, 0xa9, + 0xe6, 0x3f, 0x65, 0xa0, 0xc8, 0x8d, 0xb1, 0x39, 0x42, 0x2d, 0xa8, 0xb8, 0xec, 0x63, 0x87, 0xce, + 0x99, 0xeb, 0xd8, 0x48, 0x8f, 0x93, 0x8f, 0xa7, 0x8c, 0x32, 0x27, 0xa1, 0xc3, 0xe8, 0x57, 0xa1, + 0x24, 0x58, 0x8c, 0xc6, 0x3e, 0x77, 0x54, 0x3d, 0xcc, 0x40, 0x2e, 0xed, 0xc7, 0x53, 0x06, 0x70, + 0xf4, 0xad, 0xb1, 0x8f, 0x3a, 0x30, 0x27, 0x88, 0xd9, 0xfc, 0xb8, 0x1a, 0x59, 0xca, 0x65, 0x21, + 0xcc, 0x25, 0xee, 0xce, 0xc7, 0x53, 0x06, 0xe2, 0xf4, 0x0a, 0x10, 0xad, 0x4a, 0x95, 0xfc, 0x03, + 0x96, 0x5f, 0x62, 0x2a, 0x75, 0x0e, 0x6c, 0xce, 0x44, 0x58, 0x6b, 0x59, 0xd1, 0xad, 0x73, 0x60, + 0x07, 0x26, 0x7b, 0x58, 0x84, 0x3c, 0x1f, 0xd6, 0xff, 0x23, 0x03, 0x20, 0x3c, 0xb6, 0x39, 0x42, + 0xab, 0x50, 0x75, 0xf9, 0x57, 0xc8, 0x7e, 0x97, 0x12, 0xed, 0xc7, 0x1d, 0x3d, 0x65, 0x54, 0x04, + 0x11, 0x53, 0xf7, 0x43, 0x28, 0x07, 0x5c, 0xa4, 0x09, 0x2f, 0x26, 0x98, 0x30, 0xe0, 0x50, 0x12, + 0x04, 0xc4, 0x88, 0x9f, 0xc0, 0xb9, 0x80, 0x3e, 0xc1, 0x8a, 0x6f, 0x1c, 0x61, 0xc5, 0x80, 0xe1, + 0x59, 0xc1, 0x41, 0xb5, 0xe3, 0x23, 0x45, 0x31, 0x69, 0xc8, 0x8b, 0x09, 0x86, 0x64, 0x48, 0xaa, + 0x25, 0x03, 0x0d, 0x43, 0xa6, 0x04, 0x92, 0xf6, 0xd9, 0xb8, 0xfe, 0x57, 0x39, 0xc8, 0xaf, 0x38, + 0xc3, 0x91, 0xe9, 0x92, 0x45, 0x34, 0xe3, 0x62, 0x6f, 0x3c, 0xf0, 0xa9, 0x01, 0xab, 0x4b, 0xd7, + 0xc2, 0x32, 0x38, 0x9a, 0xf8, 0xd7, 0xa0, 0xa8, 0x06, 0x27, 0x21, 0xc4, 0x3c, 0xcb, 0x67, 0x5e, + 0x83, 0x98, 0xe7, 0x78, 0x4e, 0x22, 0x02, 0x42, 0x56, 0x06, 0x84, 0x06, 0xe4, 0xf9, 0x01, 0x8f, + 0x05, 0xeb, 0xc7, 0x53, 0x86, 0x18, 0x40, 0x6f, 0xc3, 0x6c, 0x34, 0x15, 0x4e, 0x73, 0x9c, 0x6a, + 0x37, 0x9c, 0x39, 0xaf, 0x41, 0x39, 0x94, 0xa1, 0x67, 0x38, 0x5e, 0x69, 0xa8, 0xe4, 0xe5, 0xf3, + 0x22, 0xac, 0x93, 0x63, 0x45, 0xf9, 0xf1, 0x94, 0x08, 0xec, 0x57, 0x45, 0x60, 0x2f, 0xa8, 0x89, + 0x96, 0xd8, 0x95, 0xc7, 0xf8, 0xeb, 0x6a, 0xd4, 0xfa, 0x26, 0x21, 0x0e, 0x90, 0x64, 0xf8, 0xd2, + 0x0d, 0xa8, 0x84, 0x4c, 0x46, 0x72, 0x64, 0xfb, 0xe3, 0x67, 0xad, 0x75, 0x96, 0x50, 0x1f, 0xd1, + 0x1c, 0x6a, 0xd4, 0x34, 0x92, 0xa0, 0xd7, 0xdb, 0xdb, 0xdb, 0xb5, 0x0c, 0x3a, 0x0f, 0xc5, 0x8d, + 0xcd, 0xce, 0x0e, 0xc3, 0xca, 0x36, 0xf2, 0x7f, 0xcc, 0x22, 0x89, 0xcc, 0xcf, 0x9f, 0x06, 0x3c, + 0x79, 0x8a, 0x56, 0x32, 0xf3, 0x94, 0x92, 0x99, 0x35, 0x91, 0x99, 0x33, 0x32, 0x33, 0x67, 0x11, + 0x82, 0xe9, 0xf5, 0x76, 0x6b, 0x9b, 0x26, 0x69, 0xc6, 0x7a, 0x39, 0x9e, 0xad, 0x1f, 0x56, 0xa1, + 0xcc, 0xdc, 0xb3, 0x33, 0xb6, 0xc9, 0x61, 0xe2, 0xaf, 0x35, 0x00, 0xb9, 0x61, 0x51, 0x13, 0xf2, + 0x5d, 0xa6, 0x42, 0x5d, 0xa3, 0x11, 0xf0, 0x5c, 0xa2, 0xc7, 0x0d, 0x81, 0x85, 0xee, 0x42, 0xde, + 0x1b, 0x77, 0xbb, 0xd8, 0x13, 0x99, 0xfb, 0x42, 0x34, 0x08, 0xf3, 0x80, 0x68, 0x08, 0x3c, 0x42, + 0xf2, 0xd2, 0xb4, 0x06, 0x63, 0x9a, 0xc7, 0x8f, 0x26, 0xe1, 0x78, 0x32, 0xc6, 0xfe, 0x99, 0x06, + 0x25, 0x65, 0x5b, 0xfc, 0x82, 0x29, 0xe0, 0x32, 0x14, 0xa9, 0x32, 0xb8, 0xc7, 0x93, 0x40, 0xc1, + 0x90, 0x03, 0xe8, 0x3d, 0x28, 0x8a, 0x9d, 0x24, 0xf2, 0x40, 0x3d, 0x99, 0xed, 0xe6, 0xc8, 0x90, + 0xa8, 0x52, 0xc9, 0x0e, 0x9c, 0xa1, 0x76, 0xea, 0x92, 0xdb, 0x87, 0xb0, 0xac, 0x7a, 0x2c, 0xd7, + 0x22, 0xc7, 0xf2, 0x06, 0x14, 0x46, 0x7b, 0x87, 0x9e, 0xd5, 0x35, 0x07, 0x5c, 0x9d, 0xe0, 0x5b, + 0x72, 0xdd, 0x06, 0xa4, 0x72, 0x3d, 0x89, 0x01, 0x24, 0xd3, 0xf3, 0x50, 0x7a, 0x6c, 0x7a, 0x7b, + 0x5c, 0x49, 0x39, 0x7e, 0x0f, 0x2a, 0x64, 0xfc, 0xc9, 0xf3, 0xd7, 0x50, 0x5f, 0x50, 0x2d, 0xeb, + 0xff, 0xac, 0x41, 0x55, 0x90, 0x9d, 0xc8, 0x41, 0x08, 0x72, 0x7b, 0xa6, 0xb7, 0x47, 0x8d, 0x51, + 0x31, 0xe8, 0x6f, 0xf4, 0x36, 0xd4, 0xba, 0x6c, 0xfe, 0x3b, 0x91, 0x7b, 0xd7, 0x2c, 0x1f, 0x0f, + 0xf6, 0xfe, 0xbb, 0x50, 0x21, 0x24, 0x3b, 0xe1, 0x7b, 0x90, 0xd8, 0xc6, 0xef, 0x19, 0xe5, 0x3d, + 0x3a, 0xe7, 0xa8, 0xfa, 0x26, 0x94, 0x99, 0x31, 0x4e, 0x5b, 0x77, 0x69, 0xd7, 0x06, 0xcc, 0x6e, + 0xdb, 0xe6, 0xc8, 0xdb, 0x73, 0xfc, 0x88, 0xcd, 0x97, 0xf5, 0xbf, 0xd7, 0xa0, 0x26, 0x81, 0x27, + 0xd2, 0xe1, 0x2d, 0x98, 0x75, 0xf1, 0xd0, 0xb4, 0x6c, 0xcb, 0xee, 0xef, 0xec, 0x1e, 0xfa, 0xd8, + 0xe3, 0xd7, 0xd7, 0x6a, 0x30, 0xfc, 0x90, 0x8c, 0x12, 0x65, 0x77, 0x07, 0xce, 0x2e, 0x0f, 0xd2, + 0xf4, 0x37, 0x7a, 0x23, 0x1c, 0xa5, 0x8b, 0xd2, 0x6e, 0x62, 0x5c, 0xea, 0xfc, 0xd3, 0x0c, 0x94, + 0x3f, 0x31, 0xfd, 0xae, 0x58, 0x41, 0x68, 0x0d, 0xaa, 0x41, 0x18, 0xa7, 0x23, 0x5c, 0xef, 0xc8, + 0x81, 0x83, 0xd2, 0x88, 0x7b, 0x8d, 0x38, 0x70, 0x54, 0xba, 0xea, 0x00, 0x65, 0x65, 0xda, 0x5d, + 0x3c, 0x08, 0x58, 0x65, 0xd2, 0x59, 0x51, 0x44, 0x95, 0x95, 0x3a, 0x80, 0xbe, 0x0d, 0xb5, 0x91, + 0xeb, 0xf4, 0x5d, 0xec, 0x79, 0x01, 0x33, 0x96, 0xc2, 0xf5, 0x04, 0x66, 0x5b, 0x1c, 0x35, 0x72, + 0x8a, 0xb9, 0xf7, 0x78, 0xca, 0x98, 0x1d, 0x85, 0x61, 0x32, 0xb0, 0xce, 0xca, 0xf3, 0x1e, 0x8b, + 0xac, 0x3f, 0xca, 0x02, 0x8a, 0x4f, 0xf3, 0xab, 0x1e, 0x93, 0x6f, 0x40, 0xd5, 0xf3, 0x4d, 0x37, + 0xb6, 0xe6, 0x2b, 0x74, 0x34, 0x58, 0xf1, 0x6f, 0x41, 0xa0, 0xd9, 0x8e, 0xed, 0xf8, 0xd6, 0xcb, + 0x43, 0x76, 0x41, 0x31, 0xaa, 0x62, 0x78, 0x83, 0x8e, 0xa2, 0x0d, 0xc8, 0xbf, 0xb4, 0x06, 0x3e, + 0x76, 0xbd, 0xfa, 0xf4, 0x42, 0xf6, 0x66, 0x75, 0xe9, 0x9d, 0xe3, 0x1c, 0xb3, 0xf8, 0x11, 0xc5, + 0xef, 0x1c, 0x8e, 0xd4, 0xd3, 0x2f, 0x67, 0xa2, 0x1e, 0xe3, 0x67, 0x92, 0x6f, 0x44, 0x3a, 0x14, + 0x5e, 0x11, 0xa6, 0x3b, 0x56, 0x8f, 0xe6, 0xe2, 0x60, 0x1f, 0xde, 0x33, 0xf2, 0x14, 0xb0, 0xd6, + 0x43, 0xd7, 0xa0, 0xf0, 0xd2, 0x35, 0xfb, 0x43, 0x6c, 0xfb, 0xec, 0x96, 0x2f, 0x71, 0x02, 0x80, + 0xbe, 0x08, 0x20, 0x55, 0x21, 0x99, 0x6f, 0x63, 0x73, 0xeb, 0x59, 0xa7, 0x36, 0x85, 0xca, 0x50, + 0xd8, 0xd8, 0x5c, 0x6d, 0xaf, 0xb7, 0x49, 0x6e, 0x14, 0x39, 0xef, 0xae, 0xdc, 0x74, 0x2d, 0xe1, + 0x88, 0xd0, 0x9a, 0x50, 0xf5, 0xd2, 0xc2, 0x97, 0x6e, 0xa1, 0x97, 0x60, 0x71, 0x57, 0xbf, 0x0a, + 0x73, 0x49, 0x4b, 0x43, 0x20, 0xdc, 0xd3, 0xff, 0x2d, 0x03, 0x15, 0xbe, 0x11, 0x4e, 0xb4, 0x73, + 0x2f, 0x2a, 0x5a, 0xf1, 0xeb, 0x89, 0x30, 0x52, 0x1d, 0xf2, 0x6c, 0x83, 0xf4, 0xf8, 0xfd, 0x57, + 0x7c, 0x92, 0xe0, 0xcc, 0xd6, 0x3b, 0xee, 0x71, 0xb7, 0x07, 0xdf, 0x89, 0x61, 0x73, 0x3a, 0x35, + 0x6c, 0x06, 0x1b, 0xce, 0xf4, 0xf8, 0xc1, 0xaa, 0x28, 0x5d, 0x51, 0x16, 0x9b, 0x8a, 0x00, 0x43, + 0x3e, 0xcb, 0xa7, 0xf8, 0x0c, 0xdd, 0x80, 0x19, 0x3c, 0xc1, 0xb6, 0xef, 0xd5, 0x4b, 0x34, 0x91, + 0x56, 0xc4, 0x85, 0xaa, 0x4d, 0x46, 0x0d, 0x0e, 0x94, 0xae, 0xfa, 0x10, 0xce, 0xd0, 0xfb, 0xee, + 0x23, 0xd7, 0xb4, 0xd5, 0x3b, 0x7b, 0xa7, 0xb3, 0xce, 0xd3, 0x0e, 0xf9, 0x89, 0xaa, 0x90, 0x59, + 0x5b, 0xe5, 0xf6, 0xc9, 0xac, 0xad, 0x4a, 0xfa, 0xdf, 0xd7, 0x00, 0xa9, 0x0c, 0x4e, 0xe4, 0x8b, + 0x88, 0x14, 0xa1, 0x47, 0x56, 0xea, 0x31, 0x07, 0xd3, 0xd8, 0x75, 0x1d, 0x97, 0x05, 0x4a, 0x83, + 0x7d, 0x48, 0x6d, 0x6e, 0x73, 0x65, 0x0c, 0x3c, 0x71, 0xf6, 0x83, 0x08, 0xc0, 0xd8, 0x6a, 0x71, + 0xe5, 0x3b, 0x70, 0x36, 0x84, 0x7e, 0x3a, 0x29, 0x7e, 0x13, 0x66, 0x29, 0xd7, 0x95, 0x3d, 0xdc, + 0xdd, 0x1f, 0x39, 0x96, 0x1d, 0xd3, 0x00, 0x5d, 0x23, 0xb1, 0x4b, 0xa4, 0x0b, 0x32, 0x45, 0x36, + 0xe7, 0x72, 0x30, 0xd8, 0xe9, 0xac, 0xcb, 0xa5, 0xbe, 0x0b, 0xe7, 0x23, 0x0c, 0xc5, 0xcc, 0x7e, + 0x0d, 0x4a, 0xdd, 0x60, 0xd0, 0xe3, 0x27, 0xc8, 0x2b, 0x61, 0x75, 0xa3, 0xa4, 0x2a, 0x85, 0x94, + 0xf1, 0x6d, 0xb8, 0x10, 0x93, 0x71, 0x1a, 0xe6, 0xb8, 0xa7, 0xdf, 0x81, 0x73, 0x94, 0xf3, 0x13, + 0x8c, 0x47, 0xad, 0x81, 0x35, 0x39, 0xde, 0x2d, 0x87, 0x7c, 0xbe, 0x0a, 0xc5, 0xd7, 0xbb, 0xac, + 0xa4, 0xe8, 0x36, 0x17, 0xdd, 0xb1, 0x86, 0xb8, 0xe3, 0xac, 0xa7, 0x6b, 0x4b, 0x12, 0xf9, 0x3e, + 0x3e, 0xf4, 0xf8, 0xf1, 0x91, 0xfe, 0x96, 0xd1, 0xeb, 0x6f, 0x35, 0x6e, 0x4e, 0x95, 0xcf, 0xd7, + 0xbc, 0x35, 0xe6, 0x01, 0xfa, 0x64, 0x0f, 0xe2, 0x1e, 0x01, 0xb0, 0xda, 0x9c, 0x32, 0x12, 0x28, + 0x4c, 0xb2, 0x50, 0x39, 0xaa, 0xf0, 0x15, 0xbe, 0x71, 0xe8, 0x7f, 0xbc, 0xd8, 0x49, 0xe9, 0x4d, + 0x28, 0x51, 0xc8, 0xb6, 0x6f, 0xfa, 0x63, 0x2f, 0xcd, 0x73, 0xcb, 0xfa, 0x8f, 0x34, 0xbe, 0xa3, + 0x04, 0x9f, 0x13, 0xcd, 0xf9, 0x2e, 0xcc, 0xd0, 0x1b, 0xa2, 0xb8, 0xe9, 0x5c, 0x4c, 0x58, 0xd8, + 0x4c, 0x23, 0x83, 0x23, 0x2a, 0xe7, 0x24, 0x0d, 0x66, 0x9e, 0xd2, 0xce, 0x81, 0xa2, 0x6d, 0x4e, + 0x78, 0xce, 0x36, 0x87, 0xac, 0xfc, 0x58, 0x34, 0xe8, 0x6f, 0x7a, 0x21, 0xc0, 0xd8, 0x7d, 0x66, + 0xac, 0xb3, 0x1b, 0x48, 0xd1, 0x08, 0xbe, 0x89, 0x61, 0xbb, 0x03, 0x0b, 0xdb, 0x3e, 0x85, 0xe6, + 0x28, 0x54, 0x19, 0x41, 0x37, 0xa0, 0x68, 0x79, 0xeb, 0xd8, 0x74, 0x6d, 0x5e, 0xe2, 0x57, 0x02, + 0xb3, 0x84, 0xc8, 0x35, 0xf6, 0x1d, 0xa8, 0x31, 0xcd, 0x5a, 0xbd, 0x9e, 0x72, 0xda, 0x0f, 0xe4, + 0x6b, 0x11, 0xf9, 0x21, 0xfe, 0x99, 0xe3, 0xf9, 0xff, 0x9d, 0x06, 0x67, 0x14, 0x01, 0x27, 0x72, + 0xc1, 0xbb, 0x30, 0xc3, 0xfa, 0x2f, 0xfc, 0x28, 0x38, 0x17, 0xa6, 0x62, 0x62, 0x0c, 0x8e, 0x83, + 0x16, 0x21, 0xcf, 0x7e, 0x89, 0x6b, 0x5c, 0x32, 0xba, 0x40, 0x92, 0x2a, 0x2f, 0xc2, 0x59, 0x0e, + 0xc3, 0x43, 0x27, 0x69, 0xcf, 0xe5, 0xc2, 0x11, 0xe2, 0x87, 0x1a, 0xcc, 0x85, 0x09, 0x4e, 0x34, + 0x4b, 0x45, 0xef, 0xcc, 0x57, 0xd2, 0xfb, 0x5b, 0x42, 0xef, 0x67, 0xa3, 0x9e, 0x72, 0xe4, 0x8c, + 0xae, 0x38, 0xd5, 0xbb, 0x99, 0xb0, 0x77, 0x25, 0xaf, 0x9f, 0x04, 0x73, 0x12, 0xcc, 0x4e, 0x34, + 0xa7, 0xf7, 0x5f, 0x6b, 0x4e, 0xca, 0x11, 0x2c, 0x36, 0xb9, 0x35, 0xb1, 0x8c, 0xd6, 0x2d, 0x2f, + 0xc8, 0x38, 0xef, 0x40, 0x79, 0x60, 0xd9, 0xd8, 0x74, 0x79, 0x0f, 0x49, 0x53, 0xd7, 0xe3, 0x7d, + 0x23, 0x04, 0x94, 0xac, 0x7e, 0x5b, 0x03, 0xa4, 0xf2, 0xfa, 0xe5, 0x78, 0xab, 0x29, 0x0c, 0xbc, + 0xe5, 0x3a, 0x43, 0xc7, 0x3f, 0x6e, 0x99, 0xdd, 0xd3, 0x7f, 0x57, 0x83, 0x73, 0x11, 0x8a, 0x5f, + 0x86, 0xe6, 0xf7, 0xf4, 0xcb, 0x70, 0x66, 0x15, 0x8b, 0x33, 0x5e, 0xac, 0x76, 0xb0, 0x0d, 0x48, + 0x85, 0x9e, 0xce, 0x29, 0xe6, 0x1b, 0x70, 0xe6, 0xa9, 0x33, 0x21, 0x81, 0x9c, 0x80, 0x65, 0x98, + 0x62, 0xc5, 0xac, 0xc0, 0x5e, 0xc1, 0xb7, 0x0c, 0xbd, 0xdb, 0x80, 0x54, 0xca, 0xd3, 0x50, 0x67, + 0x59, 0xff, 0x5f, 0x0d, 0xca, 0xad, 0x81, 0xe9, 0x0e, 0x85, 0x2a, 0x1f, 0xc2, 0x0c, 0xab, 0xcc, + 0xf0, 0x32, 0xeb, 0x9b, 0x61, 0x7e, 0x2a, 0x2e, 0xfb, 0x68, 0xb1, 0x3a, 0x0e, 0xa7, 0x22, 0x53, + 0xe1, 0x9d, 0xe5, 0xd5, 0x48, 0xa7, 0x79, 0x15, 0xdd, 0x86, 0x69, 0x93, 0x90, 0xd0, 0xf4, 0x5a, + 0x8d, 0x96, 0xcb, 0x28, 0x37, 0x72, 0x25, 0x32, 0x18, 0x96, 0xfe, 0x01, 0x94, 0x14, 0x09, 0x28, + 0x0f, 0xd9, 0x47, 0x6d, 0x7e, 0x4d, 0x6a, 0xad, 0x74, 0xd6, 0x9e, 0xb3, 0x12, 0x62, 0x15, 0x60, + 0xb5, 0x1d, 0x7c, 0x67, 0x12, 0x1a, 0x7b, 0x26, 0xe7, 0xc3, 0xf3, 0x96, 0xaa, 0xa1, 0x96, 0xa6, + 0x61, 0xe6, 0x75, 0x34, 0x94, 0x22, 0x7e, 0x4b, 0x83, 0x0a, 0x37, 0xcd, 0x49, 0x53, 0x33, 0xe5, + 0x9c, 0x92, 0x9a, 0x95, 0x69, 0x18, 0x1c, 0x51, 0xea, 0xf0, 0x2f, 0x1a, 0xd4, 0x56, 0x9d, 0x57, + 0x76, 0xdf, 0x35, 0x7b, 0xc1, 0x1e, 0xfc, 0x28, 0xe2, 0xce, 0xc5, 0x48, 0xa5, 0x3f, 0x82, 0x2f, + 0x07, 0x22, 0x6e, 0xad, 0xcb, 0x5a, 0x0a, 0xcb, 0xef, 0xe2, 0x53, 0xff, 0x26, 0xcc, 0x46, 0x88, + 0x88, 0x83, 0x9e, 0xb7, 0xd6, 0xd7, 0x56, 0x89, 0x43, 0x68, 0xbd, 0xb7, 0xbd, 0xd1, 0x7a, 0xb8, + 0xde, 0xe6, 0x5d, 0xd9, 0xd6, 0xc6, 0x4a, 0x7b, 0x5d, 0x3a, 0xea, 0xbe, 0x98, 0xc1, 0x7d, 0x7d, + 0x00, 0x67, 0x14, 0x85, 0x4e, 0xda, 0x1c, 0x4b, 0xd6, 0x57, 0x4a, 0xfb, 0x06, 0x5c, 0x0a, 0xa4, + 0x3d, 0x67, 0xc0, 0x0e, 0xf6, 0xd4, 0xcb, 0xda, 0x84, 0x0b, 0x2d, 0x1a, 0xe4, 0xa7, 0xa0, 0x7c, + 0x4f, 0xaf, 0x43, 0x85, 0x9f, 0x8f, 0xa2, 0x21, 0xe3, 0xcf, 0x73, 0x50, 0x15, 0xa0, 0xaf, 0x47, + 0x7f, 0x74, 0x1e, 0x66, 0x7a, 0xbb, 0xdb, 0xd6, 0x67, 0xa2, 0xa3, 0xcb, 0xbf, 0xc8, 0xf8, 0x80, + 0xc9, 0x61, 0xef, 0x34, 0xf8, 0x17, 0xba, 0xcc, 0x9e, 0x70, 0xac, 0xd9, 0x3d, 0x7c, 0x40, 0x8f, + 0x51, 0x39, 0x43, 0x0e, 0xd0, 0x72, 0x28, 0x7f, 0xcf, 0x41, 0x6f, 0xc9, 0xca, 0xfb, 0x0e, 0xb4, + 0x0c, 0x35, 0xf2, 0xbb, 0x35, 0x1a, 0x0d, 0x2c, 0xdc, 0x63, 0x0c, 0xc8, 0x05, 0x39, 0x27, 0xcf, + 0x49, 0x31, 0x04, 0x74, 0x15, 0x66, 0xe8, 0xe5, 0xd1, 0xab, 0x17, 0x48, 0x46, 0x96, 0xa8, 0x7c, + 0x18, 0xbd, 0x0d, 0x25, 0xa6, 0xf1, 0x9a, 0xfd, 0xcc, 0xc3, 0xf4, 0xb5, 0x83, 0x52, 0x49, 0x51, + 0x61, 0xe1, 0x13, 0x1a, 0xa4, 0x9d, 0xd0, 0x50, 0x13, 0xaa, 0x9e, 0xef, 0xb8, 0x66, 0x5f, 0xb8, + 0x91, 0x3e, 0x75, 0x50, 0xca, 0x7d, 0x11, 0xb0, 0x54, 0xe1, 0xe3, 0xb1, 0xe3, 0x9b, 0xe1, 0x27, + 0x0e, 0xef, 0x19, 0x2a, 0x0c, 0x7d, 0x0b, 0x2a, 0x3d, 0xb1, 0x48, 0xd6, 0xec, 0x97, 0x0e, 0x7d, + 0xd6, 0x10, 0xeb, 0xde, 0xad, 0xaa, 0x28, 0x92, 0x53, 0x98, 0x54, 0xbd, 0xc9, 0x56, 0x42, 0x14, + 0xc4, 0xdb, 0xd8, 0x26, 0xa9, 0x9d, 0x55, 0x70, 0x0a, 0x86, 0xf8, 0x44, 0xd7, 0xa1, 0xc2, 0x32, + 0xc1, 0xf3, 0xd0, 0x6a, 0x08, 0x0f, 0x92, 0x3c, 0xd6, 0x1a, 0xfb, 0x7b, 0x6d, 0x4a, 0x14, 0x5b, + 0x94, 0x57, 0x00, 0x11, 0xe8, 0xaa, 0xe5, 0x25, 0x82, 0x39, 0x71, 0xe2, 0x8a, 0xbe, 0xaf, 0x6f, + 0xc0, 0x59, 0x02, 0xc5, 0xb6, 0x6f, 0x75, 0x95, 0xa3, 0x98, 0x38, 0xec, 0x6b, 0x91, 0xc3, 0xbe, + 0xe9, 0x79, 0xaf, 0x1c, 0xb7, 0xc7, 0xd5, 0x0c, 0xbe, 0xa5, 0xb4, 0x7f, 0xd4, 0x98, 0x36, 0xcf, + 0xbc, 0xd0, 0x41, 0xfd, 0x2b, 0xf2, 0x43, 0xbf, 0x02, 0x79, 0xfe, 0x40, 0x8a, 0xd7, 0x3f, 0xcf, + 0x2f, 0xb2, 0x87, 0x59, 0x8b, 0x9c, 0xf1, 0x26, 0x83, 0x2a, 0x35, 0x3a, 0x8e, 0x4f, 0x96, 0xcb, + 0x9e, 0xe9, 0xed, 0xe1, 0xde, 0x96, 0x60, 0x1e, 0xaa, 0x0e, 0xdf, 0x37, 0x22, 0x60, 0xa9, 0xfb, + 0x5d, 0xa9, 0xfa, 0x23, 0xec, 0x1f, 0xa1, 0xba, 0xda, 0x7f, 0x38, 0x27, 0x48, 0x78, 0xdb, 0xf4, + 0x75, 0xa8, 0x7e, 0xac, 0xc1, 0x15, 0x41, 0xb6, 0xb2, 0x67, 0xda, 0x7d, 0x2c, 0x94, 0xf9, 0x45, + 0xed, 0x15, 0x9f, 0x74, 0xf6, 0x35, 0x27, 0xfd, 0x04, 0xea, 0xc1, 0xa4, 0x69, 0x2d, 0xca, 0x19, + 0xa8, 0x93, 0x18, 0x7b, 0x41, 0x90, 0xa4, 0xbf, 0xc9, 0x98, 0xeb, 0x0c, 0x82, 0x6b, 0x20, 0xf9, + 0x2d, 0x99, 0xad, 0xc3, 0x45, 0xc1, 0x8c, 0x17, 0x87, 0xc2, 0xdc, 0x62, 0x73, 0x3a, 0x92, 0x1b, + 0xf7, 0x07, 0xe1, 0x71, 0xf4, 0x52, 0x4a, 0x24, 0x09, 0xbb, 0x90, 0x4a, 0xd1, 0x92, 0xa4, 0xcc, + 0xb3, 0x1d, 0x40, 0x74, 0x56, 0x4e, 0xec, 0x31, 0x38, 0x61, 0x99, 0x08, 0xe7, 0x4b, 0x80, 0xc0, + 0x63, 0x4b, 0x20, 0x5d, 0x2a, 0x86, 0xf9, 0x40, 0x51, 0x62, 0xf6, 0x2d, 0xec, 0x0e, 0x2d, 0xcf, + 0x53, 0x1a, 0x71, 0x49, 0xe6, 0x7a, 0x13, 0x72, 0x23, 0xcc, 0x8f, 0x2f, 0xa5, 0x25, 0x24, 0xf6, + 0x84, 0x42, 0x4c, 0xe1, 0x52, 0xcc, 0x10, 0xae, 0x0a, 0x31, 0xcc, 0x21, 0x89, 0x72, 0xa2, 0x6a, + 0x8a, 0xe2, 0x7f, 0x26, 0xa5, 0xf8, 0x9f, 0x0d, 0x17, 0xff, 0x43, 0x47, 0x6a, 0x35, 0x50, 0x9d, + 0xce, 0x91, 0xba, 0xc3, 0x1c, 0x10, 0xc4, 0xb7, 0xd3, 0xe1, 0xfa, 0x07, 0x3c, 0x50, 0x9d, 0x56, + 0x3a, 0x17, 0x01, 0x3e, 0x13, 0x0e, 0xf0, 0x3a, 0x94, 0x89, 0x93, 0x0c, 0xb5, 0x2b, 0x92, 0x33, + 0x42, 0x63, 0x32, 0x18, 0xef, 0xc3, 0x5c, 0x38, 0x18, 0x9f, 0x48, 0xa9, 0x39, 0x98, 0xf6, 0x9d, + 0x7d, 0x2c, 0x72, 0x0a, 0xfb, 0x88, 0x99, 0x35, 0x08, 0xd4, 0xa7, 0x63, 0xd6, 0xef, 0x4a, 0xae, + 0x74, 0x03, 0x9e, 0x74, 0x06, 0x64, 0x39, 0x8a, 0xdb, 0x3f, 0xfb, 0x90, 0xb2, 0x3e, 0x81, 0xf3, + 0xd1, 0xe0, 0x7b, 0x3a, 0x93, 0xd8, 0x61, 0x9b, 0x33, 0x29, 0x3c, 0x9f, 0x8e, 0x80, 0x17, 0x32, + 0x4e, 0x2a, 0x41, 0xf7, 0x74, 0x78, 0xff, 0x3a, 0x34, 0x92, 0x62, 0xf0, 0xa9, 0xee, 0xc5, 0x20, + 0x24, 0x9f, 0x0e, 0xd7, 0x1f, 0x6a, 0x92, 0xad, 0xba, 0x6a, 0x3e, 0xf8, 0x2a, 0x6c, 0x45, 0xae, + 0xbb, 0x13, 0x2c, 0x9f, 0x66, 0x10, 0x2d, 0xb3, 0xc9, 0xd1, 0x52, 0x92, 0x50, 0x44, 0xb1, 0xff, + 0x64, 0xa8, 0xff, 0x3a, 0x57, 0x2f, 0x17, 0x26, 0xf3, 0xce, 0x49, 0x85, 0x91, 0xf4, 0x1c, 0x08, + 0xa3, 0x1f, 0xb1, 0xad, 0xa2, 0x26, 0xa9, 0xd3, 0x71, 0xdd, 0x6f, 0xc8, 0x04, 0x13, 0xcb, 0x63, + 0xa7, 0x23, 0xc1, 0x84, 0x85, 0xf4, 0x14, 0x76, 0x2a, 0x22, 0x6e, 0xb5, 0xa0, 0x18, 0xdc, 0xfd, + 0x95, 0x97, 0xca, 0x25, 0xc8, 0x6f, 0x6c, 0x6e, 0x6f, 0xb5, 0x56, 0xc8, 0xd5, 0x76, 0x0e, 0xf2, + 0x2b, 0x9b, 0x86, 0xf1, 0x6c, 0xab, 0x43, 0xee, 0xb6, 0xd1, 0x87, 0x4b, 0x4b, 0x3f, 0xcb, 0x42, + 0xe6, 0xc9, 0x73, 0xf4, 0x29, 0x4c, 0xb3, 0x87, 0x73, 0x47, 0xbc, 0x9f, 0x6c, 0x1c, 0xf5, 0x36, + 0x50, 0xbf, 0xf0, 0x83, 0xff, 0xfe, 0xd9, 0x1f, 0x66, 0xce, 0xe8, 0xe5, 0xe6, 0x64, 0xb9, 0xb9, + 0x3f, 0x69, 0xd2, 0x24, 0xfb, 0x40, 0xbb, 0x85, 0x3e, 0x86, 0xec, 0xd6, 0xd8, 0x47, 0xa9, 0xef, + 0x2a, 0x1b, 0xe9, 0xcf, 0x05, 0xf5, 0x73, 0x94, 0xe9, 0xac, 0x0e, 0x9c, 0xe9, 0x68, 0xec, 0x13, + 0x96, 0xdf, 0x83, 0x92, 0xfa, 0xd8, 0xef, 0xd8, 0xc7, 0x96, 0x8d, 0xe3, 0x1f, 0x12, 0xea, 0x57, + 0xa8, 0xa8, 0x0b, 0x3a, 0xe2, 0xa2, 0xd8, 0x73, 0x44, 0x75, 0x16, 0x9d, 0x03, 0x1b, 0xa5, 0x3e, + 0xc5, 0x6c, 0xa4, 0xbf, 0x2d, 0x8c, 0xcd, 0xc2, 0x3f, 0xb0, 0x09, 0xcb, 0xef, 0xf2, 0x47, 0x84, + 0x5d, 0x1f, 0x5d, 0x4d, 0x78, 0x05, 0xa6, 0xbe, 0x6e, 0x6a, 0x2c, 0xa4, 0x23, 0x70, 0x21, 0x97, + 0xa9, 0x90, 0xf3, 0xfa, 0x19, 0x2e, 0xa4, 0x1b, 0xa0, 0x3c, 0xd0, 0x6e, 0x2d, 0x75, 0x61, 0x9a, + 0x76, 0xcf, 0xd1, 0x0b, 0xf1, 0xa3, 0x91, 0xf0, 0x2e, 0x21, 0xc5, 0xd1, 0xa1, 0xbe, 0xbb, 0x3e, + 0x47, 0x05, 0x55, 0xf5, 0x22, 0x11, 0x44, 0x7b, 0xe7, 0x0f, 0xb4, 0x5b, 0x37, 0xb5, 0x3b, 0xda, + 0xd2, 0xdf, 0x4c, 0xc3, 0x34, 0xed, 0xd2, 0xa0, 0x7d, 0x00, 0xd9, 0x25, 0x8e, 0xce, 0x2e, 0xd6, + 0x80, 0x8e, 0xce, 0x2e, 0xde, 0x60, 0xd6, 0x1b, 0x54, 0xe8, 0x9c, 0x3e, 0x4b, 0x84, 0xd2, 0xe6, + 0x4f, 0x93, 0xf6, 0xba, 0x88, 0x1d, 0x7f, 0xac, 0xf1, 0x76, 0x15, 0xdb, 0x66, 0x28, 0x89, 0x5b, + 0xa8, 0x43, 0x1c, 0x5d, 0x0e, 0x09, 0x4d, 0x61, 0xfd, 0x3e, 0x15, 0xd8, 0xd4, 0x6b, 0x52, 0xa0, + 0x4b, 0x31, 0x1e, 0x68, 0xb7, 0x5e, 0xd4, 0xf5, 0xb3, 0xdc, 0xca, 0x11, 0x08, 0xfa, 0x3e, 0x54, + 0xc3, 0xbd, 0x4c, 0x74, 0x2d, 0x41, 0x56, 0xb4, 0x37, 0xda, 0xb8, 0x7e, 0x34, 0x12, 0xd7, 0x69, + 0x9e, 0xea, 0xc4, 0x85, 0x33, 0xc9, 0xfb, 0x18, 0x8f, 0x4c, 0x82, 0xc4, 0x7d, 0x80, 0xfe, 0x54, + 0xe3, 0xed, 0x68, 0xd9, 0x8a, 0x44, 0x49, 0xdc, 0x63, 0x1d, 0xcf, 0xc6, 0x8d, 0x63, 0xb0, 0xb8, + 0x12, 0x1f, 0x50, 0x25, 0xde, 0xd7, 0xe7, 0xa4, 0x12, 0xbe, 0x35, 0xc4, 0xbe, 0xc3, 0xb5, 0x78, + 0x71, 0x59, 0xbf, 0x10, 0x32, 0x4e, 0x08, 0x2a, 0x9d, 0xc5, 0x5a, 0x86, 0x89, 0xce, 0x0a, 0x75, + 0x25, 0x13, 0x9d, 0x15, 0xee, 0x37, 0x26, 0x39, 0x8b, 0x37, 0x08, 0x13, 0x9c, 0x15, 0x40, 0x96, + 0xfe, 0x3f, 0x07, 0xf9, 0x15, 0xf6, 0x3f, 0x23, 0x21, 0x07, 0x8a, 0x41, 0x13, 0x0d, 0xcd, 0x27, + 0xd5, 0xe9, 0xe5, 0x55, 0xae, 0x71, 0x35, 0x15, 0xce, 0x15, 0x7a, 0x83, 0x2a, 0x74, 0x49, 0x3f, + 0x4f, 0x24, 0xf3, 0xff, 0xdf, 0xa9, 0xc9, 0xaa, 0xb9, 0x4d, 0xb3, 0xd7, 0x23, 0x86, 0xf8, 0x4d, + 0x28, 0xab, 0x2d, 0x2d, 0xf4, 0x46, 0x62, 0x6f, 0x40, 0xed, 0x8f, 0x35, 0xf4, 0xa3, 0x50, 0xb8, + 0xe4, 0xeb, 0x54, 0xf2, 0xbc, 0x7e, 0x31, 0x41, 0xb2, 0x4b, 0x51, 0x43, 0xc2, 0x59, 0xef, 0x29, + 0x59, 0x78, 0xa8, 0xc9, 0x95, 0x2c, 0x3c, 0xdc, 0xba, 0x3a, 0x52, 0xf8, 0x98, 0xa2, 0x12, 0xe1, + 0x1e, 0x80, 0x6c, 0x0e, 0xa1, 0x44, 0x5b, 0x2a, 0x17, 0xd6, 0x68, 0x70, 0x88, 0xf7, 0x95, 0x74, + 0x9d, 0x8a, 0xe5, 0xeb, 0x2e, 0x22, 0x76, 0x60, 0x79, 0x3e, 0xdb, 0x98, 0x95, 0x50, 0x6b, 0x07, + 0x25, 0xce, 0x27, 0xdc, 0x29, 0x6a, 0x5c, 0x3b, 0x12, 0x87, 0x4b, 0xbf, 0x41, 0xa5, 0x5f, 0xd5, + 0x1b, 0x09, 0xd2, 0x47, 0x0c, 0x97, 0x2c, 0xb6, 0xcf, 0xf3, 0x50, 0x7a, 0x6a, 0x5a, 0xb6, 0x8f, + 0x6d, 0xd3, 0xee, 0x62, 0xb4, 0x0b, 0xd3, 0x34, 0x77, 0x47, 0x03, 0xb1, 0xda, 0xc9, 0x88, 0x06, + 0xe2, 0x50, 0x29, 0x5f, 0x5f, 0xa0, 0x82, 0x1b, 0xfa, 0x39, 0x22, 0x78, 0x28, 0x59, 0x37, 0x59, + 0x13, 0x40, 0xbb, 0x85, 0x5e, 0xc2, 0x0c, 0x6f, 0xe1, 0x47, 0x18, 0x85, 0x8a, 0x6a, 0x8d, 0xcb, + 0xc9, 0xc0, 0xa4, 0xb5, 0xac, 0x8a, 0xf1, 0x28, 0x1e, 0x91, 0x33, 0x01, 0x90, 0x1d, 0xa9, 0xa8, + 0x47, 0x63, 0x9d, 0xac, 0xc6, 0x42, 0x3a, 0x42, 0x92, 0x4d, 0x55, 0x99, 0xbd, 0x00, 0x97, 0xc8, + 0xfd, 0x0e, 0xe4, 0x1e, 0x9b, 0xde, 0x1e, 0x8a, 0xe4, 0x5e, 0xe5, 0xc5, 0x6d, 0xa3, 0x91, 0x04, + 0xe2, 0x52, 0xae, 0x52, 0x29, 0x17, 0x59, 0x28, 0x53, 0xa5, 0xd0, 0x37, 0xa5, 0xcc, 0x7e, 0xec, + 0xb9, 0x6d, 0xd4, 0x7e, 0xa1, 0xb7, 0xbb, 0x51, 0xfb, 0x85, 0x5f, 0xe8, 0xa6, 0xdb, 0x8f, 0x48, + 0xd9, 0x9f, 0x10, 0x39, 0x23, 0x28, 0x88, 0x87, 0xa9, 0x28, 0xf2, 0x9c, 0x27, 0xf2, 0x9a, 0xb5, + 0x31, 0x9f, 0x06, 0xe6, 0xd2, 0xae, 0x51, 0x69, 0x57, 0xf4, 0x7a, 0xcc, 0x5b, 0x1c, 0xf3, 0x81, + 0x76, 0xeb, 0x8e, 0x86, 0xbe, 0x0f, 0x20, 0x9b, 0x76, 0xb1, 0x3d, 0x18, 0x6d, 0x04, 0xc6, 0xf6, + 0x60, 0xac, 0xdf, 0xa7, 0x2f, 0x52, 0xb9, 0x37, 0xf5, 0x6b, 0x51, 0xb9, 0xbe, 0x6b, 0xda, 0xde, + 0x4b, 0xec, 0xde, 0x66, 0x75, 0x7f, 0x6f, 0xcf, 0x1a, 0x91, 0x29, 0xbb, 0x50, 0x0c, 0x6a, 0xcd, + 0xd1, 0x78, 0x1b, 0xed, 0xfe, 0x44, 0xe3, 0x6d, 0xac, 0x19, 0x13, 0x0e, 0x3c, 0xa1, 0xf5, 0x22, + 0x50, 0xc9, 0x16, 0xfc, 0xcb, 0x1a, 0xe4, 0xc8, 0x91, 0x9c, 0x1c, 0x4f, 0x64, 0xb9, 0x27, 0x3a, + 0xfb, 0x58, 0xc5, 0x3a, 0x3a, 0xfb, 0x78, 0xa5, 0x28, 0x7c, 0x3c, 0x21, 0xd7, 0xb5, 0x26, 0xab, + 0xa3, 0x90, 0x99, 0x3a, 0x50, 0x52, 0xca, 0x40, 0x28, 0x81, 0x59, 0xb8, 0x02, 0x1e, 0x4d, 0x78, + 0x09, 0x35, 0x24, 0xfd, 0x12, 0x95, 0x77, 0x8e, 0x25, 0x3c, 0x2a, 0xaf, 0xc7, 0x30, 0x88, 0x40, + 0x3e, 0x3b, 0xbe, 0xf3, 0x13, 0x66, 0x17, 0xde, 0xfd, 0x0b, 0xe9, 0x08, 0xa9, 0xb3, 0x93, 0x5b, + 0xff, 0x15, 0x94, 0xd5, 0xd2, 0x0f, 0x4a, 0x50, 0x3e, 0x52, 0xa3, 0x8f, 0x66, 0x92, 0xa4, 0xca, + 0x51, 0x38, 0xb6, 0x51, 0x91, 0xa6, 0x82, 0x46, 0x04, 0x0f, 0x20, 0xcf, 0x4b, 0x40, 0x49, 0x26, + 0x0d, 0x97, 0xf1, 0x93, 0x4c, 0x1a, 0xa9, 0x1f, 0x85, 0xcf, 0xcf, 0x54, 0x22, 0xb9, 0x8a, 0x8a, + 0x6c, 0xcd, 0xa5, 0x3d, 0xc2, 0x7e, 0x9a, 0x34, 0x59, 0xb6, 0x4d, 0x93, 0xa6, 0x54, 0x08, 0xd2, + 0xa4, 0xf5, 0xb1, 0xcf, 0xe3, 0x81, 0xb8, 0x5e, 0xa3, 0x14, 0x66, 0x6a, 0x86, 0xd4, 0x8f, 0x42, + 0x49, 0xba, 0xde, 0x48, 0x81, 0x22, 0x3d, 0x1e, 0x00, 0xc8, 0x72, 0x54, 0xf4, 0xcc, 0x9a, 0xd8, + 0x29, 0x88, 0x9e, 0x59, 0x93, 0x2b, 0x5a, 0xe1, 0x18, 0x2b, 0xe5, 0xb2, 0xdb, 0x15, 0x91, 0xfc, + 0x85, 0x06, 0x28, 0x5e, 0xb0, 0x42, 0xef, 0x24, 0x73, 0x4f, 0xec, 0x3a, 0x34, 0xde, 0x7d, 0x3d, + 0xe4, 0xa4, 0x80, 0x2c, 0x55, 0xea, 0x52, 0xec, 0xd1, 0x2b, 0xa2, 0xd4, 0xe7, 0x1a, 0x54, 0x42, + 0x45, 0x2e, 0xf4, 0x66, 0x8a, 0x4f, 0x23, 0xad, 0x87, 0xc6, 0x5b, 0xc7, 0xe2, 0x25, 0x1d, 0xe6, + 0x95, 0x15, 0x20, 0x6e, 0x35, 0xbf, 0xa3, 0x41, 0x35, 0x5c, 0x0b, 0x43, 0x29, 0xbc, 0x63, 0x1d, + 0x8b, 0xc6, 0xcd, 0xe3, 0x11, 0x8f, 0x76, 0x8f, 0xbc, 0xd0, 0x0c, 0x20, 0xcf, 0x8b, 0x66, 0x49, + 0x0b, 0x3f, 0xdc, 0xe2, 0x48, 0x5a, 0xf8, 0x91, 0x8a, 0x5b, 0xc2, 0xc2, 0x77, 0x9d, 0x01, 0x56, + 0xb6, 0x19, 0xaf, 0xa5, 0xa5, 0x49, 0x3b, 0x7a, 0x9b, 0x45, 0x0a, 0x71, 0x69, 0xd2, 0xe4, 0x36, + 0x13, 0x25, 0x33, 0x94, 0xc2, 0xec, 0x98, 0x6d, 0x16, 0xad, 0xb8, 0x25, 0x6c, 0x33, 0x2a, 0x50, + 0xd9, 0x66, 0xb2, 0x94, 0x95, 0xb4, 0xcd, 0x62, 0xdd, 0x98, 0xa4, 0x6d, 0x16, 0xaf, 0x86, 0x25, + 0xf8, 0x91, 0xca, 0x0d, 0x6d, 0xb3, 0xb3, 0x09, 0xc5, 0x2e, 0xf4, 0x6e, 0x8a, 0x11, 0x13, 0x7b, + 0x3b, 0x8d, 0xdb, 0xaf, 0x89, 0x9d, 0xba, 0xc6, 0x99, 0xf9, 0xc5, 0x1a, 0xff, 0x23, 0x0d, 0xe6, + 0x92, 0xea, 0x63, 0x28, 0x45, 0x4e, 0x4a, 0x2b, 0xa8, 0xb1, 0xf8, 0xba, 0xe8, 0x47, 0x5b, 0x2b, + 0x58, 0xf5, 0x0f, 0xfb, 0x5f, 0xb4, 0x9a, 0x2f, 0xae, 0xc2, 0x15, 0x98, 0x69, 0x8d, 0xac, 0x27, + 0xf8, 0x10, 0x9d, 0x2d, 0x64, 0x1a, 0x15, 0xc2, 0xd7, 0x71, 0xad, 0xcf, 0xe8, 0x5f, 0xbd, 0x58, + 0xc8, 0xec, 0x96, 0x01, 0x02, 0x84, 0xa9, 0x7f, 0xff, 0x72, 0x5e, 0xfb, 0xaf, 0x2f, 0xe7, 0xb5, + 0xff, 0xf9, 0x72, 0x5e, 0xfb, 0xe9, 0xff, 0xcd, 0x4f, 0xbd, 0xb8, 0xd6, 0x77, 0xa8, 0x5a, 0x8b, + 0x96, 0xd3, 0x94, 0x7f, 0x89, 0x63, 0xb9, 0xa9, 0xaa, 0xba, 0x3b, 0x43, 0xff, 0x74, 0xc6, 0xf2, + 0xcf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x82, 0x9b, 0xab, 0xde, 0x11, 0x44, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -9461,6 +9653,11 @@ func (m *HashKVResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.HashRevision != 0 { + i = encodeVarintRpc(dAtA, i, uint64(m.HashRevision)) + i-- + dAtA[i] = 0x20 + } if m.CompactRevision != 0 { i = encodeVarintRpc(dAtA, i, uint64(m.CompactRevision)) i-- @@ -9581,6 +9778,13 @@ func (m *SnapshotResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.Version) > 0 { + i -= len(m.Version) + copy(dAtA[i:], m.Version) + i = encodeVarintRpc(dAtA, i, uint64(len(m.Version))) + i-- + dAtA[i] = 0x22 + } if len(m.Blob) > 0 { i -= len(m.Blob) copy(dAtA[i:], m.Blob) @@ -11430,6 +11634,40 @@ func (m *DowngradeResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *DowngradeVersionTestRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DowngradeVersionTestRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DowngradeVersionTestRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.Ver) > 0 { + i -= len(m.Ver) + copy(dAtA[i:], m.Ver) + i = encodeVarintRpc(dAtA, i, uint64(len(m.Ver))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *StatusRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -11481,6 +11719,30 @@ func (m *StatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if m.DowngradeInfo != nil { + { + size, err := m.DowngradeInfo.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintRpc(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + } + if m.DbSizeQuota != 0 { + i = encodeVarintRpc(dAtA, i, uint64(m.DbSizeQuota)) + i-- + dAtA[i] = 0x60 + } + if len(m.StorageVersion) > 0 { + i -= len(m.StorageVersion) + copy(dAtA[i:], m.StorageVersion) + i = encodeVarintRpc(dAtA, i, uint64(len(m.StorageVersion))) + i-- + dAtA[i] = 0x5a + } if m.IsLearner { i-- if m.IsLearner { @@ -11552,6 +11814,50 @@ func (m *StatusResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *DowngradeInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DowngradeInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DowngradeInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.XXX_unrecognized != nil { + i -= len(m.XXX_unrecognized) + copy(dAtA[i:], m.XXX_unrecognized) + } + if len(m.TargetVersion) > 0 { + i -= len(m.TargetVersion) + copy(dAtA[i:], m.TargetVersion) + i = encodeVarintRpc(dAtA, i, uint64(len(m.TargetVersion))) + i-- + dAtA[i] = 0x12 + } + if m.Enabled { + i-- + if m.Enabled { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *AuthEnableRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -13459,6 +13765,9 @@ func (m *HashKVResponse) Size() (n int) { if m.CompactRevision != 0 { n += 1 + sovRpc(uint64(m.CompactRevision)) } + if m.HashRevision != 0 { + n += 1 + sovRpc(uint64(m.HashRevision)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -13513,6 +13822,10 @@ func (m *SnapshotResponse) Size() (n int) { if l > 0 { n += 1 + l + sovRpc(uint64(l)) } + l = len(m.Version) + if l > 0 { + n += 1 + l + sovRpc(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -14336,6 +14649,22 @@ func (m *DowngradeResponse) Size() (n int) { return n } +func (m *DowngradeVersionTestRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Ver) + if l > 0 { + n += 1 + l + sovRpc(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + func (m *StatusRequest) Size() (n int) { if m == nil { return 0 @@ -14389,6 +14718,36 @@ func (m *StatusResponse) Size() (n int) { if m.IsLearner { n += 2 } + l = len(m.StorageVersion) + if l > 0 { + n += 1 + l + sovRpc(uint64(l)) + } + if m.DbSizeQuota != 0 { + n += 1 + sovRpc(uint64(m.DbSizeQuota)) + } + if m.DowngradeInfo != nil { + l = m.DowngradeInfo.Size() + n += 1 + l + sovRpc(uint64(l)) + } + if m.XXX_unrecognized != nil { + n += len(m.XXX_unrecognized) + } + return n +} + +func (m *DowngradeInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Enabled { + n += 2 + } + l = len(m.TargetVersion) + if l > 0 { + n += 1 + l + sovRpc(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -17568,6 +17927,25 @@ func (m *HashKVResponse) Unmarshal(dAtA []byte) error { break } } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field HashRevision", wireType) + } + m.HashRevision = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.HashRevision |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -17865,6 +18243,38 @@ func (m *SnapshotResponse) Unmarshal(dAtA []byte) error { m.Blob = []byte{} } iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRpc + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRpc + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Version = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) @@ -22145,6 +22555,89 @@ func (m *DowngradeResponse) Unmarshal(dAtA []byte) error { } return nil } +func (m *DowngradeVersionTestRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DowngradeVersionTestRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DowngradeVersionTestRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRpc + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRpc + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRpc(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthRpc + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *StatusRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 @@ -22459,6 +22952,196 @@ func (m *StatusResponse) Unmarshal(dAtA []byte) error { } } m.IsLearner = bool(v != 0) + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StorageVersion", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRpc + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRpc + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.StorageVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 12: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field DbSizeQuota", wireType) + } + m.DbSizeQuota = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.DbSizeQuota |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DowngradeInfo", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRpc + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRpc + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.DowngradeInfo == nil { + m.DowngradeInfo = &DowngradeInfo{} + } + if err := m.DowngradeInfo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipRpc(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthRpc + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DowngradeInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DowngradeInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DowngradeInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Enabled", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Enabled = bool(v != 0) + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TargetVersion", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRpc + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthRpc + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthRpc + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TargetVersion = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRpc(dAtA[iNdEx:]) diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.proto b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.proto index 4ccc234744..983dc01725 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.proto +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/etcdserverpb/rpc.proto @@ -4,13 +4,36 @@ package etcdserverpb; import "gogoproto/gogo.proto"; import "etcd/api/mvccpb/kv.proto"; import "etcd/api/authpb/auth.proto"; +import "etcd/api/versionpb/version.proto"; // for grpc-gateway import "google/api/annotations.proto"; +import "protoc-gen-openapiv2/options/annotations.proto"; + +option go_package = "go.etcd.io/etcd/api/v3/etcdserverpb"; option (gogoproto.marshaler_all) = true; option (gogoproto.unmarshaler_all) = true; +option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { + security_definitions: { + security: { + key: "ApiKey"; + value: { + type: TYPE_API_KEY; + in: IN_HEADER; + name: "Authorization"; + } + } + } + security: { + security_requirement: { + key: "ApiKey"; + value: {}; + } + } +}; + service KV { // Range gets the keys in the range from the key-value store. rpc Range(RangeRequest) returns (RangeResponse) { @@ -388,13 +411,16 @@ service Auth { } message ResponseHeader { + option (versionpb.etcd_version_msg) = "3.0"; + // cluster_id is the ID of the cluster which sent the response. uint64 cluster_id = 1; // member_id is the ID of the member which sent the response. uint64 member_id = 2; - // revision is the key-value store revision when the request was applied. + // revision is the key-value store revision when the request was applied, and it's + // unset (so 0) in case of calls not interacting with key-value store. // For watch progress responses, the header.revision indicates progress. All future events - // recieved in this stream are guaranteed to have a higher revision number than the + // received in this stream are guaranteed to have a higher revision number than the // header.revision number. int64 revision = 3; // raft_term is the raft term when the request was applied. @@ -402,17 +428,21 @@ message ResponseHeader { } message RangeRequest { + option (versionpb.etcd_version_msg) = "3.0"; + enum SortOrder { - NONE = 0; // default, no sorting - ASCEND = 1; // lowest target value first - DESCEND = 2; // highest target value first + option (versionpb.etcd_version_enum) = "3.0"; + NONE = 0; // default, no sorting + ASCEND = 1; // lowest target value first + DESCEND = 2; // highest target value first } enum SortTarget { - KEY = 0; - VERSION = 1; - CREATE = 2; - MOD = 3; - VALUE = 4; + option (versionpb.etcd_version_enum) = "3.0"; + KEY = 0; + VERSION = 1; + CREATE = 2; + MOD = 3; + VALUE = 4; } // key is the first key for the range. If range_end is not given, the request only looks up key. @@ -453,33 +483,39 @@ message RangeRequest { // min_mod_revision is the lower bound for returned key mod revisions; all keys with // lesser mod revisions will be filtered away. - int64 min_mod_revision = 10; + int64 min_mod_revision = 10 [(versionpb.etcd_version_field)="3.1"]; // max_mod_revision is the upper bound for returned key mod revisions; all keys with // greater mod revisions will be filtered away. - int64 max_mod_revision = 11; + int64 max_mod_revision = 11 [(versionpb.etcd_version_field)="3.1"]; // min_create_revision is the lower bound for returned key create revisions; all keys with // lesser create revisions will be filtered away. - int64 min_create_revision = 12; + int64 min_create_revision = 12 [(versionpb.etcd_version_field)="3.1"]; // max_create_revision is the upper bound for returned key create revisions; all keys with // greater create revisions will be filtered away. - int64 max_create_revision = 13; + int64 max_create_revision = 13 [(versionpb.etcd_version_field)="3.1"]; } message RangeResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // kvs is the list of key-value pairs matched by the range request. // kvs is empty when count is requested. repeated mvccpb.KeyValue kvs = 2; // more indicates if there are more keys to return in the requested range. bool more = 3; - // count is set to the number of keys within the range when requested. + // count is set to the actual number of keys within the range when requested. + // Unlike Kvs, it is unaffected by limits and filters (e.g., Min/Max, Create/Modify, Revisions) + // and reflects the full count within the specified range. int64 count = 4; } message PutRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // key is the key, in bytes, to put into the key-value store. bytes key = 1; // value is the value, in bytes, to associate with the key in the key-value store. @@ -490,24 +526,28 @@ message PutRequest { // If prev_kv is set, etcd gets the previous key-value pair before changing it. // The previous key-value pair will be returned in the put response. - bool prev_kv = 4; + bool prev_kv = 4 [(versionpb.etcd_version_field)="3.1"]; // If ignore_value is set, etcd updates the key using its current value. // Returns an error if the key does not exist. - bool ignore_value = 5; + bool ignore_value = 5 [(versionpb.etcd_version_field)="3.2"]; // If ignore_lease is set, etcd updates the key using its current lease. // Returns an error if the key does not exist. - bool ignore_lease = 6; + bool ignore_lease = 6 [(versionpb.etcd_version_field)="3.2"]; } message PutResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // if prev_kv is set in the request, the previous key-value pair will be returned. - mvccpb.KeyValue prev_kv = 2; + mvccpb.KeyValue prev_kv = 2 [(versionpb.etcd_version_field)="3.1"]; } message DeleteRangeRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // key is the first key to delete in the range. bytes key = 1; // range_end is the key following the last key to delete for the range [key, range_end). @@ -519,50 +559,61 @@ message DeleteRangeRequest { // If prev_kv is set, etcd gets the previous key-value pairs before deleting it. // The previous key-value pairs will be returned in the delete response. - bool prev_kv = 3; + bool prev_kv = 3 [(versionpb.etcd_version_field)="3.1"]; } message DeleteRangeResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // deleted is the number of keys deleted by the delete range request. int64 deleted = 2; // if prev_kv is set in the request, the previous key-value pairs will be returned. - repeated mvccpb.KeyValue prev_kvs = 3; + repeated mvccpb.KeyValue prev_kvs = 3 [(versionpb.etcd_version_field)="3.1"]; } message RequestOp { + option (versionpb.etcd_version_msg) = "3.0"; // request is a union of request types accepted by a transaction. oneof request { RangeRequest request_range = 1; PutRequest request_put = 2; DeleteRangeRequest request_delete_range = 3; - TxnRequest request_txn = 4; + TxnRequest request_txn = 4 [(versionpb.etcd_version_field)="3.3"]; } } message ResponseOp { + option (versionpb.etcd_version_msg) = "3.0"; + // response is a union of response types returned by a transaction. oneof response { RangeResponse response_range = 1; PutResponse response_put = 2; DeleteRangeResponse response_delete_range = 3; - TxnResponse response_txn = 4; + TxnResponse response_txn = 4 [(versionpb.etcd_version_field)="3.3"]; } } message Compare { + option (versionpb.etcd_version_msg) = "3.0"; + enum CompareResult { + option (versionpb.etcd_version_enum) = "3.0"; + EQUAL = 0; GREATER = 1; LESS = 2; - NOT_EQUAL = 3; + NOT_EQUAL = 3 [(versionpb.etcd_version_enum_value)="3.1"]; } enum CompareTarget { + option (versionpb.etcd_version_enum) = "3.0"; + VERSION = 0; CREATE = 1; MOD = 2; VALUE = 3; - LEASE = 4; + LEASE = 4 [(versionpb.etcd_version_enum_value)="3.3"]; } // result is logical comparison operation for this comparison. CompareResult result = 1; @@ -580,13 +631,13 @@ message Compare { // value is the value of the given key, in bytes. bytes value = 7; // lease is the lease id of the given key. - int64 lease = 8; + int64 lease = 8 [(versionpb.etcd_version_field)="3.3"]; // leave room for more target_union field tags, jump to 64 } // range_end compares the given target to all keys in the range [key, range_end). // See RangeRequest for more details on key ranges. - bytes range_end = 64; + bytes range_end = 64 [(versionpb.etcd_version_field)="3.3"]; // TODO: fill out with most of the rest of RangeRequest fields when needed. } @@ -606,6 +657,8 @@ message Compare { // true. // 3. A list of database operations called f op. Like t op, but executed if guard evaluates to false. message TxnRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // compare is a list of predicates representing a conjunction of terms. // If the comparisons succeed, then the success requests will be processed in order, // and the response will contain their respective responses in order. @@ -619,6 +672,8 @@ message TxnRequest { } message TxnResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // succeeded is set to true if the compare evaluated to true or false otherwise. bool succeeded = 2; @@ -630,6 +685,8 @@ message TxnResponse { // CompactionRequest compacts the key-value store up to a given revision. All superseded keys // with a revision less than the compaction revision will be removed. message CompactionRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // revision is the key-value store revision for the compaction operation. int64 revision = 1; // physical is set so the RPC will wait until the compaction is physically @@ -639,35 +696,48 @@ message CompactionRequest { } message CompactionResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message HashRequest { + option (versionpb.etcd_version_msg) = "3.0"; } message HashKVRequest { + option (versionpb.etcd_version_msg) = "3.3"; // revision is the key-value store revision for the hash operation. int64 revision = 1; } message HashKVResponse { + option (versionpb.etcd_version_msg) = "3.3"; + ResponseHeader header = 1; // hash is the hash value computed from the responding member's MVCC keys up to a given revision. uint32 hash = 2; // compact_revision is the compacted revision of key-value store when hash begins. int64 compact_revision = 3; + // hash_revision is the revision up to which the hash is calculated. + int64 hash_revision = 4 [(versionpb.etcd_version_field)="3.6"]; } message HashResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // hash is the hash value computed from the responding member's KV's backend. uint32 hash = 2; } message SnapshotRequest { + option (versionpb.etcd_version_msg) = "3.3"; } message SnapshotResponse { + option (versionpb.etcd_version_msg) = "3.3"; + // header has the current key-value store information. The first header in the snapshot // stream indicates the point in time of the snapshot. ResponseHeader header = 1; @@ -677,18 +747,26 @@ message SnapshotResponse { // blob contains the next chunk of the snapshot in the snapshot stream. bytes blob = 3; + + // local version of server that created the snapshot. + // In cluster with binaries with different version, each cluster can return different result. + // Informs which etcd server version should be used when restoring the snapshot. + string version = 4 [(versionpb.etcd_version_field)="3.6"]; } message WatchRequest { + option (versionpb.etcd_version_msg) = "3.0"; // request_union is a request to either create a new watcher or cancel an existing watcher. oneof request_union { WatchCreateRequest create_request = 1; WatchCancelRequest cancel_request = 2; - WatchProgressRequest progress_request = 3; + WatchProgressRequest progress_request = 3 [(versionpb.etcd_version_field)="3.4"]; } } message WatchCreateRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // key is the key to register for watching. bytes key = 1; @@ -709,6 +787,8 @@ message WatchCreateRequest { bool progress_notify = 4; enum FilterType { + option (versionpb.etcd_version_enum) = "3.1"; + // filter out put event. NOPUT = 0; // filter out delete event. @@ -716,34 +796,38 @@ message WatchCreateRequest { } // filters filter the events at server side before it sends back to the watcher. - repeated FilterType filters = 5; + repeated FilterType filters = 5 [(versionpb.etcd_version_field)="3.1"]; // If prev_kv is set, created watcher gets the previous KV before the event happens. // If the previous KV is already compacted, nothing will be returned. - bool prev_kv = 6; + bool prev_kv = 6 [(versionpb.etcd_version_field)="3.1"]; // If watch_id is provided and non-zero, it will be assigned to this watcher. // Since creating a watcher in etcd is not a synchronous operation, // this can be used ensure that ordering is correct when creating multiple // watchers on the same stream. Creating a watcher with an ID already in // use on the stream will cause an error to be returned. - int64 watch_id = 7; + int64 watch_id = 7 [(versionpb.etcd_version_field)="3.4"]; // fragment enables splitting large revisions into multiple watch responses. - bool fragment = 8; + bool fragment = 8 [(versionpb.etcd_version_field)="3.4"]; } message WatchCancelRequest { + option (versionpb.etcd_version_msg) = "3.1"; // watch_id is the watcher id to cancel so that no more events are transmitted. - int64 watch_id = 1; + int64 watch_id = 1 [(versionpb.etcd_version_field)="3.1"]; } // Requests the a watch stream progress status be sent in the watch response stream as soon as // possible. message WatchProgressRequest { + option (versionpb.etcd_version_msg) = "3.4"; } message WatchResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // watch_id is the ID of the watcher that corresponds to the response. int64 watch_id = 2; @@ -754,7 +838,8 @@ message WatchResponse { // All events sent to the created watcher will attach with the same watch_id. bool created = 3; - // canceled is set to true if the response is for a cancel watch request. + // canceled is set to true if the response is for a cancel watch request + // or if the start_revision has already been compacted. // No further events will be sent to the canceled watcher. bool canceled = 4; @@ -769,15 +854,17 @@ message WatchResponse { int64 compact_revision = 5; // cancel_reason indicates the reason for canceling the watcher. - string cancel_reason = 6; + string cancel_reason = 6 [(versionpb.etcd_version_field)="3.4"]; // framgment is true if large watch response was split over multiple responses. - bool fragment = 7; + bool fragment = 7 [(versionpb.etcd_version_field)="3.4"]; repeated mvccpb.Event events = 11; } message LeaseGrantRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // TTL is the advisory time-to-live in seconds. Expired lease will return -1. int64 TTL = 1; // ID is the requested ID for the lease. If ID is set to 0, the lessor chooses an ID. @@ -785,6 +872,8 @@ message LeaseGrantRequest { } message LeaseGrantResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // ID is the lease ID for the granted lease. int64 ID = 2; @@ -794,15 +883,21 @@ message LeaseGrantResponse { } message LeaseRevokeRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // ID is the lease ID to revoke. When the ID is revoked, all associated keys will be deleted. int64 ID = 1; } message LeaseRevokeResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message LeaseCheckpoint { + option (versionpb.etcd_version_msg) = "3.4"; + // ID is the lease ID to checkpoint. int64 ID = 1; @@ -811,19 +906,26 @@ message LeaseCheckpoint { } message LeaseCheckpointRequest { + option (versionpb.etcd_version_msg) = "3.4"; + repeated LeaseCheckpoint checkpoints = 1; } message LeaseCheckpointResponse { + option (versionpb.etcd_version_msg) = "3.4"; + ResponseHeader header = 1; } message LeaseKeepAliveRequest { + option (versionpb.etcd_version_msg) = "3.0"; // ID is the lease ID for the lease to keep alive. int64 ID = 1; } message LeaseKeepAliveResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // ID is the lease ID from the keep alive request. int64 ID = 2; @@ -832,6 +934,7 @@ message LeaseKeepAliveResponse { } message LeaseTimeToLiveRequest { + option (versionpb.etcd_version_msg) = "3.1"; // ID is the lease ID for the lease. int64 ID = 1; // keys is true to query all the keys attached to this lease. @@ -839,6 +942,8 @@ message LeaseTimeToLiveRequest { } message LeaseTimeToLiveResponse { + option (versionpb.etcd_version_msg) = "3.1"; + ResponseHeader header = 1; // ID is the lease ID from the keep alive request. int64 ID = 2; @@ -851,19 +956,26 @@ message LeaseTimeToLiveResponse { } message LeaseLeasesRequest { + option (versionpb.etcd_version_msg) = "3.3"; } message LeaseStatus { + option (versionpb.etcd_version_msg) = "3.3"; + int64 ID = 1; // TODO: int64 TTL = 2; } message LeaseLeasesResponse { + option (versionpb.etcd_version_msg) = "3.3"; + ResponseHeader header = 1; repeated LeaseStatus leases = 2; } message Member { + option (versionpb.etcd_version_msg) = "3.0"; + // ID is the member ID for this member. uint64 ID = 1; // name is the human-readable name of the member. If the member is not started, the name will be an empty string. @@ -873,17 +985,21 @@ message Member { // clientURLs is the list of URLs the member exposes to clients for communication. If the member is not started, clientURLs will be empty. repeated string clientURLs = 4; // isLearner indicates if the member is raft learner. - bool isLearner = 5; + bool isLearner = 5 [(versionpb.etcd_version_field)="3.4"]; } message MemberAddRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // peerURLs is the list of URLs the added member will use to communicate with the cluster. repeated string peerURLs = 1; // isLearner indicates if the added member is raft learner. - bool isLearner = 2; + bool isLearner = 2 [(versionpb.etcd_version_field)="3.4"]; } message MemberAddResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // member is the member information for the added member. Member member = 2; @@ -892,17 +1008,22 @@ message MemberAddResponse { } message MemberRemoveRequest { + option (versionpb.etcd_version_msg) = "3.0"; // ID is the member ID of the member to remove. uint64 ID = 1; } message MemberRemoveResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // members is a list of all members after removing the member. repeated Member members = 2; } message MemberUpdateRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // ID is the member ID of the member to update. uint64 ID = 1; // peerURLs is the new list of URLs the member will use to communicate with the cluster. @@ -910,59 +1031,80 @@ message MemberUpdateRequest { } message MemberUpdateResponse{ + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // members is a list of all members after updating the member. - repeated Member members = 2; + repeated Member members = 2 [(versionpb.etcd_version_field)="3.1"]; } message MemberListRequest { - bool linearizable = 1; + option (versionpb.etcd_version_msg) = "3.0"; + + bool linearizable = 1 [(versionpb.etcd_version_field)="3.5"]; } message MemberListResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // members is a list of all members associated with the cluster. repeated Member members = 2; } message MemberPromoteRequest { + option (versionpb.etcd_version_msg) = "3.4"; // ID is the member ID of the member to promote. uint64 ID = 1; } message MemberPromoteResponse { + option (versionpb.etcd_version_msg) = "3.4"; + ResponseHeader header = 1; // members is a list of all members after promoting the member. repeated Member members = 2; } message DefragmentRequest { + option (versionpb.etcd_version_msg) = "3.0"; } message DefragmentResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message MoveLeaderRequest { + option (versionpb.etcd_version_msg) = "3.3"; // targetID is the node ID for the new leader. uint64 targetID = 1; } message MoveLeaderResponse { + option (versionpb.etcd_version_msg) = "3.3"; + ResponseHeader header = 1; } enum AlarmType { + option (versionpb.etcd_version_enum) = "3.0"; + NONE = 0; // default, used to query if any alarm is active NOSPACE = 1; // space quota is exhausted - CORRUPT = 2; // kv store corruption detected + CORRUPT = 2 [(versionpb.etcd_version_enum_value)="3.3"]; // kv store corruption detected } message AlarmRequest { + option (versionpb.etcd_version_msg) = "3.0"; + enum AlarmAction { - GET = 0; - ACTIVATE = 1; - DEACTIVATE = 2; + option (versionpb.etcd_version_enum) = "3.0"; + + GET = 0; + ACTIVATE = 1; + DEACTIVATE = 2; } // action is the kind of alarm request to issue. The action // may GET alarm statuses, ACTIVATE an alarm, or DEACTIVATE a @@ -976,6 +1118,7 @@ message AlarmRequest { } message AlarmMember { + option (versionpb.etcd_version_msg) = "3.0"; // memberID is the ID of the member associated with the raised alarm. uint64 memberID = 1; // alarm is the type of alarm which has been raised. @@ -983,13 +1126,19 @@ message AlarmMember { } message AlarmResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // alarms is a list of alarms associated with the alarm request. repeated AlarmMember alarms = 2; } message DowngradeRequest { + option (versionpb.etcd_version_msg) = "3.5"; + enum DowngradeAction { + option (versionpb.etcd_version_enum) = "3.5"; + VALIDATE = 0; ENABLE = 1; CANCEL = 2; @@ -1004,15 +1153,30 @@ message DowngradeRequest { } message DowngradeResponse { + option (versionpb.etcd_version_msg) = "3.5"; + ResponseHeader header = 1; // version is the current cluster version. string version = 2; } +// DowngradeVersionTestRequest is used for test only. The version in +// this request will be read as the WAL record version.If the downgrade +// target version is less than this version, then the downgrade(online) +// or migration(offline) isn't safe, so shouldn't be allowed. +message DowngradeVersionTestRequest { + option (versionpb.etcd_version_msg) = "3.6"; + + string ver = 1; +} + message StatusRequest { + option (versionpb.etcd_version_msg) = "3.0"; } message StatusResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // version is the cluster protocol version used by the responding member. string version = 2; @@ -1025,55 +1189,82 @@ message StatusResponse { // raftTerm is the current raft term of the responding member. uint64 raftTerm = 6; // raftAppliedIndex is the current raft applied index of the responding member. - uint64 raftAppliedIndex = 7; + uint64 raftAppliedIndex = 7 [(versionpb.etcd_version_field)="3.4"]; // errors contains alarm/health information and status. - repeated string errors = 8; + repeated string errors = 8 [(versionpb.etcd_version_field)="3.4"]; // dbSizeInUse is the size of the backend database logically in use, in bytes, of the responding member. - int64 dbSizeInUse = 9; + int64 dbSizeInUse = 9 [(versionpb.etcd_version_field)="3.4"]; // isLearner indicates if the member is raft learner. - bool isLearner = 10; + bool isLearner = 10 [(versionpb.etcd_version_field)="3.4"]; + // storageVersion is the version of the db file. It might be updated with delay in relationship to the target cluster version. + string storageVersion = 11 [(versionpb.etcd_version_field)="3.6"]; + // dbSizeQuota is the configured etcd storage quota in bytes (the value passed to etcd instance by flag --quota-backend-bytes) + int64 dbSizeQuota = 12 [(versionpb.etcd_version_field)="3.6"]; + // downgradeInfo indicates if there is downgrade process. + DowngradeInfo downgradeInfo = 13 [(versionpb.etcd_version_field)="3.6"]; +} + +message DowngradeInfo { + // enabled indicates whether the cluster is enabled to downgrade. + bool enabled = 1; + // targetVersion is the target downgrade version. + string targetVersion = 2; } message AuthEnableRequest { + option (versionpb.etcd_version_msg) = "3.0"; } message AuthDisableRequest { + option (versionpb.etcd_version_msg) = "3.0"; } message AuthStatusRequest { + option (versionpb.etcd_version_msg) = "3.5"; } message AuthenticateRequest { + option (versionpb.etcd_version_msg) = "3.0"; + string name = 1; string password = 2; } message AuthUserAddRequest { + option (versionpb.etcd_version_msg) = "3.0"; + string name = 1; string password = 2; - authpb.UserAddOptions options = 3; - string hashedPassword = 4; + authpb.UserAddOptions options = 3 [(versionpb.etcd_version_field)="3.4"]; + string hashedPassword = 4 [(versionpb.etcd_version_field)="3.5"]; } message AuthUserGetRequest { + option (versionpb.etcd_version_msg) = "3.0"; + string name = 1; } message AuthUserDeleteRequest { + option (versionpb.etcd_version_msg) = "3.0"; // name is the name of the user to delete. string name = 1; } message AuthUserChangePasswordRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // name is the name of the user whose password is being changed. string name = 1; // password is the new password for the user. Note that this field will be removed in the API layer. string password = 2; // hashedPassword is the new password for the user. Note that this field will be initialized in the API layer. - string hashedPassword = 3; + string hashedPassword = 3 [(versionpb.etcd_version_field)="3.5"]; } message AuthUserGrantRoleRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // user is the name of the user which should be granted a given role. string user = 1; // role is the name of the role to grant to the user. @@ -1081,30 +1272,42 @@ message AuthUserGrantRoleRequest { } message AuthUserRevokeRoleRequest { + option (versionpb.etcd_version_msg) = "3.0"; + string name = 1; string role = 2; } message AuthRoleAddRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // name is the name of the role to add to the authentication system. string name = 1; } message AuthRoleGetRequest { + option (versionpb.etcd_version_msg) = "3.0"; + string role = 1; } message AuthUserListRequest { + option (versionpb.etcd_version_msg) = "3.0"; } message AuthRoleListRequest { + option (versionpb.etcd_version_msg) = "3.0"; } message AuthRoleDeleteRequest { + option (versionpb.etcd_version_msg) = "3.0"; + string role = 1; } message AuthRoleGrantPermissionRequest { + option (versionpb.etcd_version_msg) = "3.0"; + // name is the name of the role which will be granted the permission. string name = 1; // perm is the permission to grant to the role. @@ -1112,20 +1315,28 @@ message AuthRoleGrantPermissionRequest { } message AuthRoleRevokePermissionRequest { + option (versionpb.etcd_version_msg) = "3.0"; + string role = 1; bytes key = 2; bytes range_end = 3; } message AuthEnableResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthDisableResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthStatusResponse { + option (versionpb.etcd_version_msg) = "3.5"; + ResponseHeader header = 1; bool enabled = 2; // authRevision is the current revision of auth store @@ -1133,67 +1344,93 @@ message AuthStatusResponse { } message AuthenticateResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; // token is an authorized token that can be used in succeeding RPCs string token = 2; } message AuthUserAddResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthUserGetResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; repeated string roles = 2; } message AuthUserDeleteResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthUserChangePasswordResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthUserGrantRoleResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthUserRevokeRoleResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthRoleAddResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthRoleGetResponse { - ResponseHeader header = 1; + ResponseHeader header = 1 [(versionpb.etcd_version_field)="3.0"]; - repeated authpb.Permission perm = 2; + repeated authpb.Permission perm = 2 [(versionpb.etcd_version_field)="3.0"]; } message AuthRoleListResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; repeated string roles = 2; } message AuthUserListResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; repeated string users = 2; } message AuthRoleDeleteResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthRoleGrantPermissionResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } message AuthRoleRevokePermissionResponse { + option (versionpb.etcd_version_msg) = "3.0"; + ResponseHeader header = 1; } diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/membershippb/membership.pb.go b/etcd/vendor/go.etcd.io/etcd/api/v3/membershippb/membership.pb.go index cf0d428180..85a2a741f3 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/membershippb/membership.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/membershippb/membership.pb.go @@ -11,6 +11,7 @@ import ( _ "github.com/gogo/protobuf/gogoproto" proto "github.com/golang/protobuf/proto" + _ "go.etcd.io/etcd/api/v3/versionpb" ) // Reference imports to suppress errors if they are not otherwise used. @@ -286,30 +287,34 @@ func init() { func init() { proto.RegisterFile("membership.proto", fileDescriptor_949fe0d019050ef5) } var fileDescriptor_949fe0d019050ef5 = []byte{ - // 367 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x92, 0xc1, 0x4e, 0xf2, 0x40, - 0x14, 0x85, 0x99, 0x42, 0xf8, 0xdb, 0xcb, 0x1f, 0xc4, 0x09, 0x89, 0x8d, 0x68, 0x25, 0x5d, 0xb1, - 0x30, 0x98, 0xe8, 0x13, 0xa0, 0xb0, 0x20, 0x81, 0xcd, 0x18, 0xdd, 0x92, 0x56, 0x2e, 0xd8, 0xa4, - 0x74, 0xea, 0xcc, 0x54, 0xd7, 0xbe, 0x85, 0x4f, 0xe0, 0xb3, 0xb0, 0xf4, 0x11, 0x14, 0x5f, 0xc4, - 0x74, 0x5a, 0x4a, 0x49, 0xdc, 0xb8, 0xbb, 0x3d, 0xbd, 0xf7, 0x9c, 0xf3, 0x35, 0x85, 0xd6, 0x0a, - 0x57, 0x3e, 0x0a, 0xf9, 0x18, 0xc4, 0xfd, 0x58, 0x70, 0xc5, 0xe9, 0xff, 0x9d, 0x12, 0xfb, 0xc7, - 0xed, 0x25, 0x5f, 0x72, 0xfd, 0xe2, 0x22, 0x9d, 0xb2, 0x1d, 0x77, 0x02, 0x4d, 0xe6, 0x2d, 0xd4, - 0x40, 0x29, 0x11, 0xf8, 0x89, 0x42, 0x49, 0x3b, 0x60, 0xc5, 0x88, 0x62, 0x96, 0x88, 0x50, 0xda, - 0xa4, 0x5b, 0xed, 0x59, 0xcc, 0x4c, 0x85, 0x3b, 0x11, 0x4a, 0x7a, 0x0a, 0x10, 0xc8, 0x59, 0x88, - 0x9e, 0x88, 0x50, 0xd8, 0x46, 0x97, 0xf4, 0x4c, 0x66, 0x05, 0x72, 0x92, 0x09, 0xee, 0x00, 0xa0, - 0xe4, 0x44, 0xa1, 0x16, 0x79, 0x2b, 0xb4, 0x49, 0x97, 0xf4, 0x2c, 0xa6, 0x67, 0x7a, 0x06, 0x8d, - 0x87, 0x30, 0xc0, 0x48, 0x65, 0xfe, 0x86, 0xf6, 0x87, 0x4c, 0x4a, 0x13, 0xdc, 0x77, 0x02, 0xf5, - 0xa9, 0xee, 0x4d, 0x9b, 0x60, 0x8c, 0x87, 0xfa, 0xba, 0xc6, 0x8c, 0xf1, 0x90, 0x8e, 0xe0, 0x40, - 0x78, 0x0b, 0x35, 0xf3, 0x8a, 0x08, 0xdd, 0xa0, 0x71, 0x79, 0xd2, 0x2f, 0x93, 0xf6, 0xf7, 0x81, - 0x58, 0x53, 0xec, 0x03, 0x8e, 0xe0, 0x30, 0x5b, 0x2f, 0x1b, 0x55, 0xb5, 0x91, 0xbd, 0x6f, 0x54, - 0x32, 0xc9, 0xbf, 0xee, 0x4e, 0x71, 0xcf, 0xc1, 0xbe, 0x09, 0x13, 0xa9, 0x50, 0xdc, 0xa3, 0x90, - 0x01, 0x8f, 0x6e, 0x51, 0x31, 0x7c, 0x4a, 0x50, 0x2a, 0xda, 0x82, 0xea, 0x33, 0x8a, 0x1c, 0x3c, - 0x1d, 0xdd, 0x57, 0x02, 0x9d, 0x7c, 0x7d, 0x5a, 0x38, 0x95, 0x2e, 0x3a, 0x60, 0xe5, 0xa5, 0x0a, - 0x64, 0x33, 0x13, 0x34, 0xf8, 0x2f, 0x8d, 0x8d, 0x3f, 0x37, 0x1e, 0xc1, 0xd1, 0x90, 0xbf, 0x44, - 0x4b, 0xe1, 0xcd, 0x71, 0x1c, 0x2d, 0x78, 0x29, 0xde, 0x86, 0x7f, 0x18, 0x79, 0x7e, 0x88, 0x73, - 0x1d, 0x6e, 0xb2, 0xed, 0xe3, 0x16, 0xc5, 0x28, 0x50, 0xae, 0xdb, 0xeb, 0x2f, 0xa7, 0xb2, 0xde, - 0x38, 0xe4, 0x63, 0xe3, 0x90, 0xcf, 0x8d, 0x43, 0xde, 0xbe, 0x9d, 0x8a, 0x5f, 0xd7, 0xff, 0xd3, - 0xd5, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x93, 0x7d, 0x0b, 0x87, 0x02, 0x00, 0x00, + // 422 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0xc1, 0x6e, 0xd3, 0x40, + 0x10, 0xed, 0x3a, 0x55, 0x6b, 0x4f, 0x51, 0x28, 0x2b, 0x24, 0xac, 0x06, 0x8c, 0x55, 0x2e, 0x39, + 0xd9, 0x12, 0x51, 0x0f, 0x70, 0x03, 0xd2, 0x43, 0x10, 0xe5, 0xb0, 0xa8, 0x1c, 0xb8, 0x44, 0xeb, + 0x66, 0x62, 0x56, 0x72, 0xbc, 0x66, 0x77, 0x5d, 0xee, 0x1c, 0xf9, 0x02, 0xfe, 0x82, 0x13, 0xff, + 0xd0, 0x23, 0x9f, 0x00, 0xe1, 0x47, 0x90, 0x77, 0x9d, 0xd8, 0x11, 0x9c, 0x7a, 0x1b, 0x3f, 0xcf, + 0xbc, 0x79, 0xef, 0xed, 0xc0, 0xf1, 0x0a, 0x57, 0x19, 0x2a, 0xfd, 0x51, 0x54, 0x49, 0xa5, 0xa4, + 0x91, 0xf4, 0x4e, 0x87, 0x54, 0xd9, 0xc9, 0xfd, 0x5c, 0xe6, 0xd2, 0xfe, 0x48, 0x9b, 0xca, 0xf5, + 0x9c, 0xc4, 0x68, 0xae, 0x16, 0x29, 0xaf, 0x44, 0x7a, 0x8d, 0x4a, 0x0b, 0x59, 0x56, 0xd9, 0xa6, + 0x72, 0x1d, 0xa7, 0x97, 0x30, 0x64, 0x7c, 0x69, 0x5e, 0x18, 0xa3, 0x44, 0x56, 0x1b, 0xd4, 0x74, + 0x04, 0x41, 0x85, 0xa8, 0xe6, 0xb5, 0x2a, 0x74, 0x48, 0xe2, 0xc1, 0x38, 0x60, 0x7e, 0x03, 0x5c, + 0xaa, 0x42, 0xd3, 0x47, 0x00, 0x42, 0xcf, 0x0b, 0xe4, 0xaa, 0x44, 0x15, 0x7a, 0x31, 0x19, 0xfb, + 0x2c, 0x10, 0xfa, 0x8d, 0x03, 0x9e, 0x1f, 0x7e, 0xf9, 0x11, 0x0e, 0x26, 0xc9, 0xd9, 0xe9, 0x6b, + 0x80, 0x1e, 0x25, 0x85, 0xfd, 0x92, 0xaf, 0x30, 0x24, 0x31, 0x19, 0x07, 0xcc, 0xd6, 0xf4, 0x31, + 0x1c, 0x5d, 0x15, 0x02, 0x4b, 0xe3, 0x16, 0x79, 0x76, 0x11, 0x38, 0xa8, 0x59, 0xd5, 0x71, 0x7d, + 0x27, 0x70, 0x70, 0x61, 0xbd, 0xd2, 0x21, 0x78, 0xb3, 0xa9, 0xa5, 0xd9, 0x67, 0xde, 0x6c, 0x4a, + 0xcf, 0xe1, 0xae, 0xe2, 0x4b, 0x33, 0xe7, 0xdb, 0x5d, 0x56, 0xd3, 0xd1, 0xd3, 0x87, 0x49, 0x3f, + 0x9d, 0x64, 0xd7, 0x22, 0x1b, 0xaa, 0x5d, 0xcb, 0xe7, 0x70, 0xcf, 0xb5, 0xf7, 0x89, 0x06, 0x96, + 0x28, 0xdc, 0x25, 0xea, 0x91, 0xb4, 0x2f, 0xd2, 0x21, 0x9d, 0xe2, 0x33, 0x08, 0x5f, 0x15, 0xb5, + 0x36, 0xa8, 0xde, 0xbb, 0xb0, 0xdf, 0xa1, 0x61, 0xf8, 0xa9, 0x46, 0x6d, 0xe8, 0x31, 0x0c, 0xae, + 0x51, 0xb5, 0x51, 0x34, 0x65, 0x37, 0xf6, 0x95, 0xc0, 0xa8, 0x9d, 0xbb, 0xd8, 0x72, 0xf7, 0x46, + 0x47, 0x10, 0xb4, 0x32, 0xb7, 0x21, 0xf8, 0x0e, 0xb0, 0x51, 0xfc, 0xc7, 0x83, 0x77, 0x7b, 0x0f, + 0x6f, 0xe1, 0xc1, 0x54, 0x7e, 0x2e, 0x73, 0xc5, 0x17, 0x38, 0x2b, 0x97, 0xb2, 0xa7, 0x23, 0x84, + 0x43, 0x2c, 0x79, 0x56, 0xe0, 0xc2, 0xaa, 0xf0, 0xd9, 0xe6, 0x73, 0x63, 0xce, 0xfb, 0xd7, 0xdc, + 0xcb, 0x67, 0x37, 0xbf, 0xa3, 0xbd, 0x9b, 0x75, 0x44, 0x7e, 0xae, 0x23, 0xf2, 0x6b, 0x1d, 0x91, + 0x6f, 0x7f, 0xa2, 0xbd, 0x0f, 0x4f, 0x72, 0x99, 0x34, 0x37, 0x9a, 0x08, 0x99, 0x76, 0xb7, 0x3a, + 0x49, 0xfb, 0x82, 0xb3, 0x03, 0x7b, 0xaa, 0x93, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xcf, 0x56, + 0x21, 0x97, 0x04, 0x03, 0x00, 0x00, } func (m *RaftAttributes) Marshal() (dAtA []byte, err error) { diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/membershippb/membership.proto b/etcd/vendor/go.etcd.io/etcd/api/v3/membershippb/membership.proto index e63e9ecc99..cbccfefccf 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/membershippb/membership.proto +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/membershippb/membership.proto @@ -2,6 +2,9 @@ syntax = "proto3"; package membershippb; import "gogoproto/gogo.proto"; +import "etcd/api/versionpb/version.proto"; + +option go_package = "go.etcd.io/etcd/api/v3/membershippb"; option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; @@ -10,6 +13,8 @@ option (gogoproto.goproto_getters_all) = false; // RaftAttributes represents the raft related attributes of an etcd member. message RaftAttributes { + option (versionpb.etcd_version_msg) = "3.5"; + // peerURLs is the list of peers in the raft cluster. repeated string peer_urls = 1; // isLearner indicates if the member is raft learner. @@ -18,26 +23,36 @@ message RaftAttributes { // Attributes represents all the non-raft related attributes of an etcd member. message Attributes { + option (versionpb.etcd_version_msg) = "3.5"; + string name = 1; repeated string client_urls = 2; } message Member { + option (versionpb.etcd_version_msg) = "3.5"; + uint64 ID = 1; RaftAttributes raft_attributes = 2; Attributes member_attributes = 3; } message ClusterVersionSetRequest { + option (versionpb.etcd_version_msg) = "3.5"; + string ver = 1; } message ClusterMemberAttrSetRequest { + option (versionpb.etcd_version_msg) = "3.5"; + uint64 member_ID = 1; Attributes member_attributes = 2; } message DowngradeInfoSetRequest { + option (versionpb.etcd_version_msg) = "3.5"; + bool enabled = 1; string ver = 2; } \ No newline at end of file diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/mvccpb/kv.pb.go b/etcd/vendor/go.etcd.io/etcd/api/v3/mvccpb/kv.pb.go index fc258d6c20..2fed4242cc 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/mvccpb/kv.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/mvccpb/kv.pb.go @@ -164,26 +164,28 @@ func init() { func init() { proto.RegisterFile("kv.proto", fileDescriptor_2216fe83c9c12408) } var fileDescriptor_2216fe83c9c12408 = []byte{ - // 303 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x90, 0x41, 0x4e, 0xc2, 0x40, - 0x14, 0x86, 0x3b, 0x14, 0x0a, 0x3e, 0x08, 0x36, 0x13, 0x12, 0x27, 0x2e, 0x26, 0x95, 0x8d, 0x18, - 0x13, 0x4c, 0xf0, 0x06, 0xc6, 0xae, 0x70, 0x61, 0x1a, 0x74, 0x4b, 0x4a, 0x79, 0x21, 0xa4, 0x94, - 0x69, 0x4a, 0x9d, 0xa4, 0x37, 0x71, 0xef, 0xde, 0x73, 0xb0, 0xe4, 0x08, 0x52, 0x2f, 0x62, 0xfa, - 0xc6, 0xe2, 0xc6, 0xcd, 0xe4, 0xfd, 0xff, 0xff, 0x65, 0xe6, 0x7f, 0x03, 0x9d, 0x58, 0x8f, 0xd3, - 0x4c, 0xe5, 0x8a, 0x3b, 0x89, 0x8e, 0xa2, 0x74, 0x71, 0x39, 0x58, 0xa9, 0x95, 0x22, 0xeb, 0xae, - 0x9a, 0x4c, 0x3a, 0xfc, 0x64, 0xd0, 0x99, 0x62, 0xf1, 0x1a, 0x6e, 0xde, 0x90, 0xbb, 0x60, 0xc7, - 0x58, 0x08, 0xe6, 0xb1, 0x51, 0x2f, 0xa8, 0x46, 0x7e, 0x0d, 0xe7, 0x51, 0x86, 0x61, 0x8e, 0xf3, - 0x0c, 0xf5, 0x7a, 0xb7, 0x56, 0x5b, 0xd1, 0xf0, 0xd8, 0xc8, 0x0e, 0xfa, 0xc6, 0x0e, 0x7e, 0x5d, - 0x7e, 0x05, 0xbd, 0x44, 0x2d, 0xff, 0x28, 0x9b, 0xa8, 0x6e, 0xa2, 0x96, 0x27, 0x44, 0x40, 0x5b, - 0x63, 0x46, 0x69, 0x93, 0xd2, 0x5a, 0xf2, 0x01, 0xb4, 0x74, 0x55, 0x40, 0xb4, 0xe8, 0x65, 0x23, - 0x2a, 0x77, 0x83, 0xe1, 0x0e, 0x85, 0x43, 0xb4, 0x11, 0xc3, 0x0f, 0x06, 0x2d, 0x5f, 0xe3, 0x36, - 0xe7, 0xb7, 0xd0, 0xcc, 0x8b, 0x14, 0xa9, 0x6e, 0x7f, 0x72, 0x31, 0x36, 0x7b, 0x8e, 0x29, 0x34, - 0xe7, 0xac, 0x48, 0x31, 0x20, 0x88, 0x7b, 0xd0, 0x88, 0x35, 0x75, 0xef, 0x4e, 0xdc, 0x1a, 0xad, - 0x17, 0x0f, 0x1a, 0xb1, 0xe6, 0x37, 0xd0, 0x4e, 0x33, 0xd4, 0xf3, 0x58, 0x53, 0xf9, 0xff, 0x30, - 0xa7, 0x02, 0xa6, 0x7a, 0xe8, 0xc1, 0xd9, 0xe9, 0x7e, 0xde, 0x06, 0xfb, 0xf9, 0x65, 0xe6, 0x5a, - 0x1c, 0xc0, 0x79, 0xf4, 0x9f, 0xfc, 0x99, 0xef, 0xb2, 0x07, 0xb1, 0x3f, 0x4a, 0xeb, 0x70, 0x94, - 0xd6, 0xbe, 0x94, 0xec, 0x50, 0x4a, 0xf6, 0x55, 0x4a, 0xf6, 0xfe, 0x2d, 0xad, 0x85, 0x43, 0xff, - 0x7e, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0xb5, 0x45, 0x92, 0x5d, 0xa1, 0x01, 0x00, 0x00, + // 327 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0xc1, 0x6a, 0xfa, 0x40, + 0x10, 0xc6, 0xb3, 0x46, 0xa3, 0xff, 0x51, 0xfc, 0x87, 0x45, 0x68, 0x28, 0x34, 0xa4, 0x5e, 0x6a, + 0x29, 0x24, 0xa0, 0x87, 0xde, 0x4b, 0x73, 0xb2, 0x87, 0x12, 0x6c, 0x0f, 0xbd, 0x48, 0x8c, 0x83, + 0x84, 0xa8, 0x1b, 0x62, 0xba, 0x90, 0x37, 0xe9, 0xbd, 0xf7, 0x3e, 0x87, 0x47, 0x1f, 0xa1, 0xda, + 0x17, 0x29, 0x3b, 0x5b, 0xed, 0xa5, 0x97, 0xdd, 0x99, 0xef, 0xfb, 0xb1, 0xf3, 0x0d, 0x0b, 0xad, + 0x4c, 0xfa, 0x79, 0x21, 0x4a, 0xc1, 0xad, 0x95, 0x4c, 0x92, 0x7c, 0x76, 0xde, 0x5b, 0x88, 0x85, + 0x20, 0x29, 0x50, 0x95, 0x76, 0xfb, 0x1f, 0x0c, 0x5a, 0x63, 0xac, 0x9e, 0xe3, 0xe5, 0x2b, 0x72, + 0x1b, 0xcc, 0x0c, 0x2b, 0x87, 0x79, 0x6c, 0xd0, 0x89, 0x54, 0xc9, 0xaf, 0xe0, 0x7f, 0x52, 0x60, + 0x5c, 0xe2, 0xb4, 0x40, 0x99, 0x6e, 0x52, 0xb1, 0x76, 0x6a, 0x1e, 0x1b, 0x98, 0x51, 0x57, 0xcb, + 0xd1, 0x8f, 0xca, 0x2f, 0xa1, 0xb3, 0x12, 0xf3, 0x5f, 0xca, 0x24, 0xaa, 0xbd, 0x12, 0xf3, 0x13, + 0xe2, 0x40, 0x53, 0x62, 0x41, 0x6e, 0x9d, 0xdc, 0x63, 0xcb, 0x7b, 0xd0, 0x90, 0x2a, 0x80, 0xd3, + 0xa0, 0xc9, 0xba, 0x51, 0xea, 0x12, 0xe3, 0x0d, 0x3a, 0x16, 0xd1, 0xba, 0xe9, 0xbf, 0x33, 0x68, + 0x84, 0x12, 0xd7, 0x25, 0xbf, 0x81, 0x7a, 0x59, 0xe5, 0x48, 0x71, 0xbb, 0xc3, 0x33, 0x5f, 0xef, + 0xe9, 0x93, 0xa9, 0xcf, 0x49, 0x95, 0x63, 0x44, 0x10, 0xf7, 0xa0, 0x96, 0x49, 0xca, 0xde, 0x1e, + 0xda, 0x47, 0xf4, 0xb8, 0x78, 0x54, 0xcb, 0x24, 0xbf, 0x86, 0x66, 0x5e, 0xa0, 0x9c, 0x66, 0x92, + 0xc2, 0xff, 0x85, 0x59, 0x0a, 0x18, 0xcb, 0xbe, 0x07, 0xff, 0x4e, 0xef, 0xf3, 0x26, 0x98, 0x8f, + 0x4f, 0x13, 0xdb, 0xe0, 0x00, 0xd6, 0x7d, 0xf8, 0x10, 0x4e, 0x42, 0x9b, 0xdd, 0xdd, 0x6e, 0xf7, + 0xae, 0xb1, 0xdb, 0xbb, 0xc6, 0xf6, 0xe0, 0xb2, 0xdd, 0xc1, 0x65, 0x9f, 0x07, 0x97, 0xbd, 0x7d, + 0xb9, 0xc6, 0xcb, 0xc5, 0x42, 0xf8, 0x58, 0x26, 0x73, 0x3f, 0x15, 0x81, 0xba, 0x83, 0x38, 0x4f, + 0x03, 0x39, 0x0a, 0xf4, 0xac, 0x99, 0x45, 0xdf, 0x32, 0xfa, 0x0e, 0x00, 0x00, 0xff, 0xff, 0x78, + 0x06, 0x46, 0xf5, 0xc0, 0x01, 0x00, 0x00, } func (m *KeyValue) Marshal() (dAtA []byte, err error) { diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/mvccpb/kv.proto b/etcd/vendor/go.etcd.io/etcd/api/v3/mvccpb/kv.proto index 23c911b7da..a93479c69f 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/mvccpb/kv.proto +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/mvccpb/kv.proto @@ -3,6 +3,8 @@ package mvccpb; import "gogoproto/gogo.proto"; +option go_package = "go.etcd.io/etcd/api/v3/mvccpb"; + option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; option (gogoproto.unmarshaler_all) = true; diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/error.go b/etcd/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/error.go index 23201302e8..781c73b7bf 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/error.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/error.go @@ -21,75 +21,81 @@ import ( // server-side error var ( - ErrGRPCEmptyKey = status.New(codes.InvalidArgument, "etcdserver: key is not provided").Err() - ErrGRPCKeyNotFound = status.New(codes.InvalidArgument, "etcdserver: key not found").Err() - ErrGRPCValueProvided = status.New(codes.InvalidArgument, "etcdserver: value is provided").Err() - ErrGRPCLeaseProvided = status.New(codes.InvalidArgument, "etcdserver: lease is provided").Err() - ErrGRPCTooManyOps = status.New(codes.InvalidArgument, "etcdserver: too many operations in txn request").Err() - ErrGRPCDuplicateKey = status.New(codes.InvalidArgument, "etcdserver: duplicate key given in txn request").Err() - ErrGRPCCompacted = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted").Err() - ErrGRPCFutureRev = status.New(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision").Err() - ErrGRPCNoSpace = status.New(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded").Err() + ErrGRPCEmptyKey = status.Error(codes.InvalidArgument, "etcdserver: key is not provided") + ErrGRPCKeyNotFound = status.Error(codes.InvalidArgument, "etcdserver: key not found") + ErrGRPCValueProvided = status.Error(codes.InvalidArgument, "etcdserver: value is provided") + ErrGRPCLeaseProvided = status.Error(codes.InvalidArgument, "etcdserver: lease is provided") + ErrGRPCTooManyOps = status.Error(codes.InvalidArgument, "etcdserver: too many operations in txn request") + ErrGRPCDuplicateKey = status.Error(codes.InvalidArgument, "etcdserver: duplicate key given in txn request") + ErrGRPCInvalidClientAPIVersion = status.Error(codes.InvalidArgument, "etcdserver: invalid client api version") + ErrGRPCInvalidSortOption = status.Error(codes.InvalidArgument, "etcdserver: invalid sort option") + ErrGRPCCompacted = status.Error(codes.OutOfRange, "etcdserver: mvcc: required revision has been compacted") + ErrGRPCFutureRev = status.Error(codes.OutOfRange, "etcdserver: mvcc: required revision is a future revision") + ErrGRPCNoSpace = status.Error(codes.ResourceExhausted, "etcdserver: mvcc: database space exceeded") - ErrGRPCLeaseNotFound = status.New(codes.NotFound, "etcdserver: requested lease not found").Err() - ErrGRPCLeaseExist = status.New(codes.FailedPrecondition, "etcdserver: lease already exists").Err() - ErrGRPCLeaseTTLTooLarge = status.New(codes.OutOfRange, "etcdserver: too large lease TTL").Err() + ErrGRPCLeaseNotFound = status.Error(codes.NotFound, "etcdserver: requested lease not found") + ErrGRPCLeaseExist = status.Error(codes.FailedPrecondition, "etcdserver: lease already exists") + ErrGRPCLeaseTTLTooLarge = status.Error(codes.OutOfRange, "etcdserver: too large lease TTL") - ErrGRPCWatchCanceled = status.New(codes.Canceled, "etcdserver: watch canceled").Err() + ErrGRPCWatchCanceled = status.Error(codes.Canceled, "etcdserver: watch canceled") - ErrGRPCMemberExist = status.New(codes.FailedPrecondition, "etcdserver: member ID already exist").Err() - ErrGRPCPeerURLExist = status.New(codes.FailedPrecondition, "etcdserver: Peer URLs already exists").Err() - ErrGRPCMemberNotEnoughStarted = status.New(codes.FailedPrecondition, "etcdserver: re-configuration failed due to not enough started members").Err() - ErrGRPCMemberBadURLs = status.New(codes.InvalidArgument, "etcdserver: given member URLs are invalid").Err() - ErrGRPCMemberNotFound = status.New(codes.NotFound, "etcdserver: member not found").Err() - ErrGRPCMemberNotLearner = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member").Err() - ErrGRPCLearnerNotReady = status.New(codes.FailedPrecondition, "etcdserver: can only promote a learner member which is in sync with leader").Err() - ErrGRPCTooManyLearners = status.New(codes.FailedPrecondition, "etcdserver: too many learner members in cluster").Err() - ErrGRPCClusterIdMismatch = status.New(codes.FailedPrecondition, "etcdserver: cluster ID mismatch").Err() + ErrGRPCMemberExist = status.Error(codes.FailedPrecondition, "etcdserver: member ID already exist") + ErrGRPCPeerURLExist = status.Error(codes.FailedPrecondition, "etcdserver: Peer URLs already exists") + ErrGRPCMemberNotEnoughStarted = status.Error(codes.FailedPrecondition, "etcdserver: re-configuration failed due to not enough started members") + ErrGRPCMemberBadURLs = status.Error(codes.InvalidArgument, "etcdserver: given member URLs are invalid") + ErrGRPCMemberNotFound = status.Error(codes.NotFound, "etcdserver: member not found") + ErrGRPCMemberNotLearner = status.Error(codes.FailedPrecondition, "etcdserver: can only promote a learner member") + ErrGRPCLearnerNotReady = status.Error(codes.FailedPrecondition, "etcdserver: can only promote a learner member which is in sync with leader") + ErrGRPCTooManyLearners = status.Error(codes.FailedPrecondition, "etcdserver: too many learner members in cluster") + ErrGRPCClusterIDMismatch = status.Error(codes.FailedPrecondition, "etcdserver: cluster ID mismatch") + //revive:disable:var-naming + // Deprecated: Please use ErrGRPCClusterIDMismatch. + ErrGRPCClusterIdMismatch = ErrGRPCClusterIDMismatch + //revive:enable:var-naming - ErrGRPCRequestTooLarge = status.New(codes.InvalidArgument, "etcdserver: request is too large").Err() - ErrGRPCRequestTooManyRequests = status.New(codes.ResourceExhausted, "etcdserver: too many requests").Err() + ErrGRPCRequestTooLarge = status.Error(codes.InvalidArgument, "etcdserver: request is too large") + ErrGRPCRequestTooManyRequests = status.Error(codes.ResourceExhausted, "etcdserver: too many requests") - ErrGRPCRootUserNotExist = status.New(codes.FailedPrecondition, "etcdserver: root user does not exist").Err() - ErrGRPCRootRoleNotExist = status.New(codes.FailedPrecondition, "etcdserver: root user does not have root role").Err() - ErrGRPCUserAlreadyExist = status.New(codes.FailedPrecondition, "etcdserver: user name already exists").Err() - ErrGRPCUserEmpty = status.New(codes.InvalidArgument, "etcdserver: user name is empty").Err() - ErrGRPCUserNotFound = status.New(codes.FailedPrecondition, "etcdserver: user name not found").Err() - ErrGRPCRoleAlreadyExist = status.New(codes.FailedPrecondition, "etcdserver: role name already exists").Err() - ErrGRPCRoleNotFound = status.New(codes.FailedPrecondition, "etcdserver: role name not found").Err() - ErrGRPCRoleEmpty = status.New(codes.InvalidArgument, "etcdserver: role name is empty").Err() - ErrGRPCAuthFailed = status.New(codes.InvalidArgument, "etcdserver: authentication failed, invalid user ID or password").Err() - ErrGRPCPermissionNotGiven = status.New(codes.InvalidArgument, "etcdserver: permission not given").Err() - ErrGRPCPermissionDenied = status.New(codes.PermissionDenied, "etcdserver: permission denied").Err() - ErrGRPCRoleNotGranted = status.New(codes.FailedPrecondition, "etcdserver: role is not granted to the user").Err() - ErrGRPCPermissionNotGranted = status.New(codes.FailedPrecondition, "etcdserver: permission is not granted to the role").Err() - ErrGRPCAuthNotEnabled = status.New(codes.FailedPrecondition, "etcdserver: authentication is not enabled").Err() - ErrGRPCInvalidAuthToken = status.New(codes.Unauthenticated, "etcdserver: invalid auth token").Err() - ErrGRPCInvalidAuthMgmt = status.New(codes.InvalidArgument, "etcdserver: invalid auth management").Err() - ErrGRPCAuthOldRevision = status.New(codes.InvalidArgument, "etcdserver: revision of auth store is old").Err() + ErrGRPCRootUserNotExist = status.Error(codes.FailedPrecondition, "etcdserver: root user does not exist") + ErrGRPCRootRoleNotExist = status.Error(codes.FailedPrecondition, "etcdserver: root user does not have root role") + ErrGRPCUserAlreadyExist = status.Error(codes.FailedPrecondition, "etcdserver: user name already exists") + ErrGRPCUserEmpty = status.Error(codes.InvalidArgument, "etcdserver: user name is empty") + ErrGRPCUserNotFound = status.Error(codes.FailedPrecondition, "etcdserver: user name not found") + ErrGRPCRoleAlreadyExist = status.Error(codes.FailedPrecondition, "etcdserver: role name already exists") + ErrGRPCRoleNotFound = status.Error(codes.FailedPrecondition, "etcdserver: role name not found") + ErrGRPCRoleEmpty = status.Error(codes.InvalidArgument, "etcdserver: role name is empty") + ErrGRPCAuthFailed = status.Error(codes.InvalidArgument, "etcdserver: authentication failed, invalid user ID or password") + ErrGRPCPermissionNotGiven = status.Error(codes.InvalidArgument, "etcdserver: permission not given") + ErrGRPCPermissionDenied = status.Error(codes.PermissionDenied, "etcdserver: permission denied") + ErrGRPCRoleNotGranted = status.Error(codes.FailedPrecondition, "etcdserver: role is not granted to the user") + ErrGRPCPermissionNotGranted = status.Error(codes.FailedPrecondition, "etcdserver: permission is not granted to the role") + ErrGRPCAuthNotEnabled = status.Error(codes.FailedPrecondition, "etcdserver: authentication is not enabled") + ErrGRPCInvalidAuthToken = status.Error(codes.Unauthenticated, "etcdserver: invalid auth token") + ErrGRPCInvalidAuthMgmt = status.Error(codes.InvalidArgument, "etcdserver: invalid auth management") + ErrGRPCAuthOldRevision = status.Error(codes.InvalidArgument, "etcdserver: revision of auth store is old") - ErrGRPCNoLeader = status.New(codes.Unavailable, "etcdserver: no leader").Err() - ErrGRPCNotLeader = status.New(codes.FailedPrecondition, "etcdserver: not leader").Err() - ErrGRPCLeaderChanged = status.New(codes.Unavailable, "etcdserver: leader changed").Err() - ErrGRPCNotCapable = status.New(codes.Unavailable, "etcdserver: not capable").Err() - ErrGRPCStopped = status.New(codes.Unavailable, "etcdserver: server stopped").Err() - ErrGRPCTimeout = status.New(codes.Unavailable, "etcdserver: request timed out").Err() - ErrGRPCTimeoutDueToLeaderFail = status.New(codes.Unavailable, "etcdserver: request timed out, possibly due to previous leader failure").Err() - ErrGRPCTimeoutDueToConnectionLost = status.New(codes.Unavailable, "etcdserver: request timed out, possibly due to connection lost").Err() - ErrGRPCTimeoutWaitAppliedIndex = status.New(codes.Unavailable, "etcdserver: request timed out, waiting for the applied index took too long").Err() - ErrGRPCUnhealthy = status.New(codes.Unavailable, "etcdserver: unhealthy cluster").Err() - ErrGRPCCorrupt = status.New(codes.DataLoss, "etcdserver: corrupt cluster").Err() - ErrGPRCNotSupportedForLearner = status.New(codes.Unavailable, "etcdserver: rpc not supported for learner").Err() - ErrGRPCBadLeaderTransferee = status.New(codes.FailedPrecondition, "etcdserver: bad leader transferee").Err() + ErrGRPCNoLeader = status.Error(codes.Unavailable, "etcdserver: no leader") + ErrGRPCNotLeader = status.Error(codes.FailedPrecondition, "etcdserver: not leader") + ErrGRPCLeaderChanged = status.Error(codes.Unavailable, "etcdserver: leader changed") + ErrGRPCNotCapable = status.Error(codes.FailedPrecondition, "etcdserver: not capable") + ErrGRPCStopped = status.Error(codes.Unavailable, "etcdserver: server stopped") + ErrGRPCTimeout = status.Error(codes.Unavailable, "etcdserver: request timed out") + ErrGRPCTimeoutDueToLeaderFail = status.Error(codes.Unavailable, "etcdserver: request timed out, possibly due to previous leader failure") + ErrGRPCTimeoutDueToConnectionLost = status.Error(codes.Unavailable, "etcdserver: request timed out, possibly due to connection lost") + ErrGRPCTimeoutWaitAppliedIndex = status.Error(codes.Unavailable, "etcdserver: request timed out, waiting for the applied index took too long") + ErrGRPCUnhealthy = status.Error(codes.Unavailable, "etcdserver: unhealthy cluster") + ErrGRPCCorrupt = status.Error(codes.DataLoss, "etcdserver: corrupt cluster") + ErrGRPCNotSupportedForLearner = status.Error(codes.FailedPrecondition, "etcdserver: rpc not supported for learner") + ErrGRPCBadLeaderTransferee = status.Error(codes.FailedPrecondition, "etcdserver: bad leader transferee") - ErrGRPCClusterVersionUnavailable = status.New(codes.Unavailable, "etcdserver: cluster version not found during downgrade").Err() - ErrGRPCWrongDowngradeVersionFormat = status.New(codes.InvalidArgument, "etcdserver: wrong downgrade target version format").Err() - ErrGRPCInvalidDowngradeTargetVersion = status.New(codes.InvalidArgument, "etcdserver: invalid downgrade target version").Err() - ErrGRPCDowngradeInProcess = status.New(codes.FailedPrecondition, "etcdserver: cluster has a downgrade job in progress").Err() - ErrGRPCNoInflightDowngrade = status.New(codes.FailedPrecondition, "etcdserver: no inflight downgrade job").Err() + ErrGRPCWrongDowngradeVersionFormat = status.Error(codes.InvalidArgument, "etcdserver: wrong downgrade target version format") + ErrGRPCInvalidDowngradeTargetVersion = status.Error(codes.InvalidArgument, "etcdserver: invalid downgrade target version") + ErrGRPCClusterVersionUnavailable = status.Error(codes.FailedPrecondition, "etcdserver: cluster version not found during downgrade") + ErrGRPCDowngradeInProcess = status.Error(codes.FailedPrecondition, "etcdserver: cluster has a downgrade job in progress") + ErrGRPCNoInflightDowngrade = status.Error(codes.FailedPrecondition, "etcdserver: no inflight downgrade job") - ErrGRPCCanceled = status.New(codes.Canceled, "etcdserver: request canceled").Err() - ErrGRPCDeadlineExceeded = status.New(codes.DeadlineExceeded, "etcdserver: context deadline exceeded").Err() + ErrGRPCCanceled = status.Error(codes.Canceled, "etcdserver: request canceled") + ErrGRPCDeadlineExceeded = status.Error(codes.DeadlineExceeded, "etcdserver: context deadline exceeded") errStringToError = map[string]error{ ErrorDesc(ErrGRPCEmptyKey): ErrGRPCEmptyKey, @@ -97,11 +103,12 @@ var ( ErrorDesc(ErrGRPCValueProvided): ErrGRPCValueProvided, ErrorDesc(ErrGRPCLeaseProvided): ErrGRPCLeaseProvided, - ErrorDesc(ErrGRPCTooManyOps): ErrGRPCTooManyOps, - ErrorDesc(ErrGRPCDuplicateKey): ErrGRPCDuplicateKey, - ErrorDesc(ErrGRPCCompacted): ErrGRPCCompacted, - ErrorDesc(ErrGRPCFutureRev): ErrGRPCFutureRev, - ErrorDesc(ErrGRPCNoSpace): ErrGRPCNoSpace, + ErrorDesc(ErrGRPCTooManyOps): ErrGRPCTooManyOps, + ErrorDesc(ErrGRPCDuplicateKey): ErrGRPCDuplicateKey, + ErrorDesc(ErrGRPCInvalidSortOption): ErrGRPCInvalidSortOption, + ErrorDesc(ErrGRPCCompacted): ErrGRPCCompacted, + ErrorDesc(ErrGRPCFutureRev): ErrGRPCFutureRev, + ErrorDesc(ErrGRPCNoSpace): ErrGRPCNoSpace, ErrorDesc(ErrGRPCLeaseNotFound): ErrGRPCLeaseNotFound, ErrorDesc(ErrGRPCLeaseExist): ErrGRPCLeaseExist, @@ -115,7 +122,7 @@ var ( ErrorDesc(ErrGRPCMemberNotLearner): ErrGRPCMemberNotLearner, ErrorDesc(ErrGRPCLearnerNotReady): ErrGRPCLearnerNotReady, ErrorDesc(ErrGRPCTooManyLearners): ErrGRPCTooManyLearners, - ErrorDesc(ErrGRPCClusterIdMismatch): ErrGRPCClusterIdMismatch, + ErrorDesc(ErrGRPCClusterIDMismatch): ErrGRPCClusterIDMismatch, ErrorDesc(ErrGRPCRequestTooLarge): ErrGRPCRequestTooLarge, ErrorDesc(ErrGRPCRequestTooManyRequests): ErrGRPCRequestTooManyRequests, @@ -147,7 +154,7 @@ var ( ErrorDesc(ErrGRPCTimeoutDueToConnectionLost): ErrGRPCTimeoutDueToConnectionLost, ErrorDesc(ErrGRPCUnhealthy): ErrGRPCUnhealthy, ErrorDesc(ErrGRPCCorrupt): ErrGRPCCorrupt, - ErrorDesc(ErrGPRCNotSupportedForLearner): ErrGPRCNotSupportedForLearner, + ErrorDesc(ErrGRPCNotSupportedForLearner): ErrGRPCNotSupportedForLearner, ErrorDesc(ErrGRPCBadLeaderTransferee): ErrGRPCBadLeaderTransferee, ErrorDesc(ErrGRPCClusterVersionUnavailable): ErrGRPCClusterVersionUnavailable, @@ -160,15 +167,16 @@ var ( // client-side error var ( - ErrEmptyKey = Error(ErrGRPCEmptyKey) - ErrKeyNotFound = Error(ErrGRPCKeyNotFound) - ErrValueProvided = Error(ErrGRPCValueProvided) - ErrLeaseProvided = Error(ErrGRPCLeaseProvided) - ErrTooManyOps = Error(ErrGRPCTooManyOps) - ErrDuplicateKey = Error(ErrGRPCDuplicateKey) - ErrCompacted = Error(ErrGRPCCompacted) - ErrFutureRev = Error(ErrGRPCFutureRev) - ErrNoSpace = Error(ErrGRPCNoSpace) + ErrEmptyKey = Error(ErrGRPCEmptyKey) + ErrKeyNotFound = Error(ErrGRPCKeyNotFound) + ErrValueProvided = Error(ErrGRPCValueProvided) + ErrLeaseProvided = Error(ErrGRPCLeaseProvided) + ErrTooManyOps = Error(ErrGRPCTooManyOps) + ErrDuplicateKey = Error(ErrGRPCDuplicateKey) + ErrInvalidSortOption = Error(ErrGRPCInvalidSortOption) + ErrCompacted = Error(ErrGRPCCompacted) + ErrFutureRev = Error(ErrGRPCFutureRev) + ErrNoSpace = Error(ErrGRPCNoSpace) ErrLeaseNotFound = Error(ErrGRPCLeaseNotFound) ErrLeaseExist = Error(ErrGRPCLeaseExist) @@ -202,7 +210,11 @@ var ( ErrInvalidAuthToken = Error(ErrGRPCInvalidAuthToken) ErrAuthOldRevision = Error(ErrGRPCAuthOldRevision) ErrInvalidAuthMgmt = Error(ErrGRPCInvalidAuthMgmt) - ErrClusterIdMismatch = Error(ErrGRPCClusterIdMismatch) + ErrClusterIDMismatch = Error(ErrGRPCClusterIDMismatch) + //revive:disable:var-naming + // Deprecated: Please use ErrClusterIDMismatch. + ErrClusterIdMismatch = ErrClusterIDMismatch + //revive:enable:var-naming ErrNoLeader = Error(ErrGRPCNoLeader) ErrNotLeader = Error(ErrGRPCNotLeader) diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/metadatafields.go b/etcd/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/metadatafields.go index 8f8ac60ff2..e5770afb2e 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/metadatafields.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/v3rpc/rpctypes/metadatafields.go @@ -18,3 +18,6 @@ var ( TokenFieldNameGRPC = "token" TokenFieldNameSwagger = "authorization" ) + +// TokenFieldNameGRPCKey is used as a key of context to store token. +type TokenFieldNameGRPCKey struct{} diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/version/version.go b/etcd/vendor/go.etcd.io/etcd/api/v3/version/version.go index 03449b523b..9e7bc64c17 100644 --- a/etcd/vendor/go.etcd.io/etcd/api/v3/version/version.go +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/version/version.go @@ -26,13 +26,29 @@ import ( var ( // MinClusterVersion is the min cluster version this etcd binary is compatible with. MinClusterVersion = "3.0.0" - Version = "3.5.21" + Version = "3.6.5" APIVersion = "unknown" // Git SHA Value will be set during build GitSHA = "Not provided (use ./build instead of go build)" ) +// Get all constant versions defined in a centralized place. +var ( + V3_0 = semver.Version{Major: 3, Minor: 0} + V3_1 = semver.Version{Major: 3, Minor: 1} + V3_2 = semver.Version{Major: 3, Minor: 2} + V3_3 = semver.Version{Major: 3, Minor: 3} + V3_4 = semver.Version{Major: 3, Minor: 4} + V3_5 = semver.Version{Major: 3, Minor: 5} + V3_6 = semver.Version{Major: 3, Minor: 6} + V3_7 = semver.Version{Major: 3, Minor: 7} + V4_0 = semver.Version{Major: 4, Minor: 0} + + // AllVersions keeps all the versions in ascending order. + AllVersions = []semver.Version{V3_0, V3_1, V3_2, V3_3, V3_4, V3_5, V3_6, V3_7, V4_0} +) + func init() { ver, err := semver.NewVersion(Version) if err == nil { @@ -43,6 +59,7 @@ func init() { type Versions struct { Server string `json:"etcdserver"` Cluster string `json:"etcdcluster"` + Storage string `json:"storage"` // TODO: raft state machine version } @@ -54,3 +71,15 @@ func Cluster(v string) string { } return fmt.Sprintf("%s.%s", vs[0], vs[1]) } + +func Compare(ver1, ver2 semver.Version) int { + return ver1.Compare(ver2) +} + +func LessThan(ver1, ver2 semver.Version) bool { + return ver1.LessThan(ver2) +} + +func Equal(ver1, ver2 semver.Version) bool { + return ver1.Equal(ver2) +} diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/versionpb/version.pb.go b/etcd/vendor/go.etcd.io/etcd/api/v3/versionpb/version.pb.go new file mode 100644 index 0000000000..71c74eb719 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/versionpb/version.pb.go @@ -0,0 +1,91 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: version.proto + +package versionpb + +import ( + fmt "fmt" + math "math" + + _ "github.com/gogo/protobuf/gogoproto" + descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor" + proto "github.com/golang/protobuf/proto" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +var E_EtcdVersionMsg = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.MessageOptions)(nil), + ExtensionType: (*string)(nil), + Field: 50000, + Name: "versionpb.etcd_version_msg", + Tag: "bytes,50000,opt,name=etcd_version_msg", + Filename: "version.proto", +} + +var E_EtcdVersionField = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.FieldOptions)(nil), + ExtensionType: (*string)(nil), + Field: 50001, + Name: "versionpb.etcd_version_field", + Tag: "bytes,50001,opt,name=etcd_version_field", + Filename: "version.proto", +} + +var E_EtcdVersionEnum = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.EnumOptions)(nil), + ExtensionType: (*string)(nil), + Field: 50002, + Name: "versionpb.etcd_version_enum", + Tag: "bytes,50002,opt,name=etcd_version_enum", + Filename: "version.proto", +} + +var E_EtcdVersionEnumValue = &proto.ExtensionDesc{ + ExtendedType: (*descriptor.EnumValueOptions)(nil), + ExtensionType: (*string)(nil), + Field: 50003, + Name: "versionpb.etcd_version_enum_value", + Tag: "bytes,50003,opt,name=etcd_version_enum_value", + Filename: "version.proto", +} + +func init() { + proto.RegisterExtension(E_EtcdVersionMsg) + proto.RegisterExtension(E_EtcdVersionField) + proto.RegisterExtension(E_EtcdVersionEnum) + proto.RegisterExtension(E_EtcdVersionEnumValue) +} + +func init() { proto.RegisterFile("version.proto", fileDescriptor_7d2c07d79758f814) } + +var fileDescriptor_7d2c07d79758f814 = []byte{ + // 284 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0xd1, 0xc1, 0x4a, 0xc3, 0x30, + 0x18, 0x07, 0x70, 0x83, 0x20, 0x2c, 0xa0, 0xce, 0x30, 0x50, 0x86, 0xd6, 0x7a, 0xf3, 0x94, 0x80, + 0xbb, 0xed, 0x28, 0xe8, 0xad, 0x2a, 0x1e, 0x76, 0x10, 0xa4, 0xb4, 0x6b, 0x16, 0x02, 0x6d, 0xbf, + 0xd0, 0xb4, 0x7d, 0x04, 0xd9, 0x23, 0xf8, 0x48, 0x1e, 0xa7, 0xbe, 0x80, 0xd4, 0x17, 0x91, 0xa4, + 0xa9, 0xac, 0xd6, 0x53, 0xfb, 0x7d, 0xdf, 0xff, 0xff, 0xeb, 0xa1, 0x78, 0xbf, 0xe6, 0x85, 0x96, + 0x90, 0x53, 0x55, 0x40, 0x09, 0x64, 0xe4, 0x46, 0x15, 0x4f, 0x27, 0x02, 0x04, 0xd8, 0x2d, 0x33, + 0x6f, 0x6d, 0x60, 0xea, 0x0b, 0x00, 0x91, 0x72, 0x66, 0xa7, 0xb8, 0x5a, 0xb1, 0x84, 0xeb, 0x65, + 0x21, 0x55, 0x09, 0x45, 0x9b, 0x98, 0xdf, 0xe1, 0x31, 0x2f, 0x97, 0x49, 0xe8, 0xa4, 0x30, 0xd3, + 0x82, 0x9c, 0xd3, 0xb6, 0x46, 0xbb, 0x1a, 0x0d, 0xb8, 0xd6, 0x91, 0xe0, 0xf7, 0xaa, 0x94, 0x90, + 0xeb, 0x93, 0xcd, 0xcb, 0xae, 0x8f, 0x2e, 0x47, 0x8f, 0x07, 0xa6, 0xba, 0x68, 0x9b, 0x81, 0x16, + 0x6b, 0x84, 0xe6, 0x0f, 0x98, 0xf4, 0xbc, 0x95, 0xe4, 0x69, 0x42, 0xce, 0x06, 0xe2, 0xad, 0xd9, + 0x77, 0xde, 0xbb, 0xf3, 0xc6, 0x5b, 0x9e, 0x0d, 0x18, 0x31, 0xc0, 0x47, 0x3d, 0x91, 0xe7, 0x55, + 0x46, 0x4e, 0x07, 0xe0, 0x4d, 0x5e, 0x65, 0x9d, 0xf7, 0xe1, 0xbc, 0xc3, 0x2d, 0xcf, 0xdc, 0x0d, + 0xf7, 0x8c, 0x8f, 0x07, 0x5c, 0x58, 0x47, 0x69, 0xc5, 0xc9, 0xc5, 0xbf, 0xe8, 0xc2, 0xdc, 0x3a, + 0xf9, 0xd3, 0xc9, 0x93, 0x3f, 0xb2, 0x0d, 0xad, 0x11, 0xba, 0xbe, 0x7a, 0x6b, 0x3c, 0xb4, 0x69, + 0x3c, 0xf4, 0xd5, 0x78, 0xe8, 0xf5, 0xdb, 0xdb, 0x79, 0xf2, 0x05, 0x50, 0x93, 0xa6, 0x12, 0x98, + 0x79, 0xb2, 0x48, 0x49, 0x56, 0xcf, 0xd8, 0xef, 0xbf, 0x8b, 0xf7, 0xec, 0xf7, 0x66, 0x3f, 0x01, + 0x00, 0x00, 0xff, 0xff, 0xe8, 0x02, 0x15, 0xc0, 0xde, 0x01, 0x00, 0x00, +} diff --git a/etcd/vendor/go.etcd.io/etcd/api/v3/versionpb/version.proto b/etcd/vendor/go.etcd.io/etcd/api/v3/versionpb/version.proto new file mode 100644 index 0000000000..c81b2f58a4 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/api/v3/versionpb/version.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; +package versionpb; + +import "gogoproto/gogo.proto"; +import "google/protobuf/descriptor.proto"; + +option go_package = "go.etcd.io/etcd/api/v3/versionpb"; + +option (gogoproto.marshaler_all) = true; +option (gogoproto.unmarshaler_all) = true; + +// Indicates etcd version that introduced the message, used to determine minimal etcd version required to interpret wal that includes this message. +extend google.protobuf.MessageOptions { + optional string etcd_version_msg = 50000; +} + +// Indicates etcd version that introduced the field, used to determine minimal etcd version required to interpret wal that sets this field. +extend google.protobuf.FieldOptions { + optional string etcd_version_field = 50001; +} + +// Indicates etcd version that introduced the enum, used to determine minimal etcd version required to interpret wal that uses this enum. +extend google.protobuf.EnumOptions { + optional string etcd_version_enum = 50002; +} + +// Indicates etcd version that introduced the enum value, used to determine minimal etcd version required to interpret wal that sets this enum value. +extend google.protobuf.EnumValueOptions { + optional string etcd_version_enum_value = 50003; +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/dir_unix.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/dir_unix.go index ca82f765c9..42221f4b90 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/dir_unix.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/dir_unix.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !windows -// +build !windows package fileutil @@ -21,7 +20,7 @@ import "os" const ( // PrivateDirMode grants owner to make/remove files inside the directory. - PrivateDirMode = 0700 + PrivateDirMode = 0o700 ) // OpenDir opens a directory for syncing. diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/dir_windows.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/dir_windows.go index 849c63c876..0cb2280cd8 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/dir_windows.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/dir_windows.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build windows -// +build windows package fileutil @@ -24,7 +23,7 @@ import ( const ( // PrivateDirMode grants owner to make/remove files inside the directory. - PrivateDirMode = 0777 + PrivateDirMode = 0o777 ) // OpenDir opens a directory in windows with write access for syncing. diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/fileutil.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/fileutil.go index d31ece3e24..36394a375a 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/fileutil.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/fileutil.go @@ -17,16 +17,18 @@ package fileutil import ( "fmt" "io" - "io/ioutil" + "io/fs" "os" "path/filepath" "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/verify" ) const ( // PrivateFileMode grants owner to read/write a file. - PrivateFileMode = 0600 + PrivateFileMode = 0o600 ) // IsDirWriteable checks if dir is writable by writing and removing a file @@ -36,7 +38,7 @@ func IsDirWriteable(dir string) error { if err != nil { return err } - if err := ioutil.WriteFile(f, []byte(""), PrivateFileMode); err != nil { + if err := os.WriteFile(f, []byte(""), PrivateFileMode); err != nil { return err } return os.Remove(f) @@ -45,8 +47,9 @@ func IsDirWriteable(dir string) error { // TouchDirAll is similar to os.MkdirAll. It creates directories with 0700 permission if any directory // does not exists. TouchDirAll also ensures the given directory is writable. func TouchDirAll(lg *zap.Logger, dir string) error { + verify.Assert(lg != nil, "nil log isn't allowed") // If path is already a directory, MkdirAll does nothing and returns nil, so, - // first check if dir exist with an expected permission mode. + // first check if dir exists with an expected permission mode. if Exist(dir) { err := CheckDirPermission(dir, PrivateDirMode) if err != nil { @@ -122,7 +125,7 @@ func CheckDirPermission(dir string, perm os.FileMode) error { if !Exist(dir) { return fmt.Errorf("directory %q empty, cannot check permission", dir) } - //check the existing permission on the directory + // check the existing permission on the directory dirInfo, err := os.Stat(dir) if err != nil { return err @@ -157,7 +160,6 @@ func RemoveMatchFile(lg *zap.Logger, dir string, matchFunc func(fileName string) lg.Error("remove file failed", zap.String("file", file), zap.Error(err)) - continue } } } @@ -166,3 +168,16 @@ func RemoveMatchFile(lg *zap.Logger, dir string, matchFunc func(fileName string) } return nil } + +// ListFiles lists files if matchFunc is true on an existing dir +// Returns error if the dir does not exist +func ListFiles(dir string, matchFunc func(fileName string) bool) ([]string, error) { + var files []string + err := filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { + if matchFunc(path) { + files = append(files, path) + } + return nil + }) + return files, err +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock.go index 338627f43c..dd2fa545d2 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock.go @@ -19,8 +19,6 @@ import ( "os" ) -var ( - ErrLocked = errors.New("fileutil: file already locked") -) +var ErrLocked = errors.New("fileutil: file already locked") type LockedFile struct{ *os.File } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_flock.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_flock.go index dcdf226cdb..178c987a4a 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_flock.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_flock.go @@ -13,11 +13,11 @@ // limitations under the License. //go:build !windows && !plan9 && !solaris -// +build !windows,!plan9,!solaris package fileutil import ( + "errors" "os" "syscall" ) @@ -29,7 +29,7 @@ func flockTryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, err } if err = syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); err != nil { f.Close() - if err == syscall.EWOULDBLOCK { + if errors.Is(err, syscall.EWOULDBLOCK) { err = ErrLocked } return nil, err diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_linux.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_linux.go index d8952cc481..609ac39784 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_linux.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_linux.go @@ -13,11 +13,11 @@ // limitations under the License. //go:build linux -// +build linux package fileutil import ( + "errors" "fmt" "io" "os" @@ -59,13 +59,13 @@ func TryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) { func ofdTryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) { f, err := os.OpenFile(path, flag, perm) if err != nil { - return nil, fmt.Errorf("ofdTryLockFile failed to open %q (%v)", path, err) + return nil, fmt.Errorf("ofdTryLockFile failed to open %q (%w)", path, err) } flock := wrlck if err = syscall.FcntlFlock(f.Fd(), unix.F_OFD_SETLK, &flock); err != nil { f.Close() - if err == syscall.EWOULDBLOCK { + if errors.Is(err, syscall.EWOULDBLOCK) { err = ErrLocked } return nil, err @@ -80,7 +80,7 @@ func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) { func ofdLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) { f, err := os.OpenFile(path, flag, perm) if err != nil { - return nil, fmt.Errorf("ofdLockFile failed to open %q (%v)", path, err) + return nil, fmt.Errorf("ofdLockFile failed to open %q (%w)", path, err) } flock := wrlck diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_solaris.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_solaris.go index 683cc1db9c..2e892fecc6 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_solaris.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_solaris.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build solaris -// +build solaris package fileutil diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_unix.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_unix.go index d89027e1fa..05db536741 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_unix.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_unix.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !windows && !plan9 && !solaris && !linux -// +build !windows,!plan9,!solaris,!linux package fileutil diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_windows.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_windows.go index 5cbf2bc3d5..51010bdf81 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_windows.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/lock_windows.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build windows -// +build windows package fileutil @@ -22,31 +21,18 @@ import ( "fmt" "os" "syscall" - "unsafe" -) - -var ( - modkernel32 = syscall.NewLazyDLL("kernel32.dll") - procLockFileEx = modkernel32.NewProc("LockFileEx") - errLocked = errors.New("the process cannot access the file because another process has locked a portion of the file") + "golang.org/x/sys/windows" ) -const ( - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365203(v=vs.85).aspx - LOCKFILE_EXCLUSIVE_LOCK = 2 - LOCKFILE_FAIL_IMMEDIATELY = 1 - - // see https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx - errLockViolation syscall.Errno = 0x21 -) +var errLocked = errors.New("the process cannot access the file because another process has locked a portion of the file") func TryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) { f, err := open(path, flag, perm) if err != nil { return nil, err } - if err := lockFile(syscall.Handle(f.Fd()), LOCKFILE_FAIL_IMMEDIATELY); err != nil { + if err := lockFile(windows.Handle(f.Fd()), windows.LOCKFILE_FAIL_IMMEDIATELY); err != nil { f.Close() return nil, err } @@ -58,7 +44,7 @@ func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) { if err != nil { return nil, err } - if err := lockFile(syscall.Handle(f.Fd()), 0); err != nil { + if err := lockFile(windows.Handle(f.Fd()), 0); err != nil { f.Close() return nil, err } @@ -67,7 +53,7 @@ func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) { func open(path string, flag int, perm os.FileMode) (*os.File, error) { if path == "" { - return nil, fmt.Errorf("cannot open empty filename") + return nil, errors.New("cannot open empty filename") } var access uint32 switch flag { @@ -95,32 +81,17 @@ func open(path string, flag int, perm os.FileMode) (*os.File, error) { return os.NewFile(uintptr(fd), path), nil } -func lockFile(fd syscall.Handle, flags uint32) error { - var flag uint32 = LOCKFILE_EXCLUSIVE_LOCK - flag |= flags - if fd == syscall.InvalidHandle { +func lockFile(fd windows.Handle, flags uint32) error { + if fd == windows.InvalidHandle { return nil } - err := lockFileEx(fd, flag, 1, 0, &syscall.Overlapped{}) + err := windows.LockFileEx(fd, flags|windows.LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &windows.Overlapped{}) if err == nil { return nil } else if err.Error() == errLocked.Error() { return ErrLocked - } else if err != errLockViolation { + } else if err != windows.ERROR_LOCK_VIOLATION { return err } return nil } - -func lockFileEx(h syscall.Handle, flags, locklow, lockhigh uint32, ol *syscall.Overlapped) (err error) { - var reserved uint32 = 0 - r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(h), uintptr(flags), uintptr(reserved), uintptr(locklow), uintptr(lockhigh), uintptr(unsafe.Pointer(ol))) - if r1 == 0 { - if e1 != 0 { - err = error(e1) - } else { - err = syscall.EINVAL - } - } - return err -} diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate.go index c747b7cf81..aadbff7131 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate.go @@ -19,9 +19,9 @@ import ( "os" ) -// Preallocate tries to allocate the space for given -// file. This operation is only supported on linux by a -// few filesystems (btrfs, ext4, etc.). +// Preallocate tries to allocate the space for given file. This +// operation is only supported on darwin and linux by a few +// filesystems (APFS, btrfs, ext4, etc.). // If the operation is unsupported, no error will be returned. // Otherwise, the error encountered will be returned. func Preallocate(f *os.File, sizeInBytes int64, extendFile bool) error { diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_darwin.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_darwin.go index caab143dd3..72430ec273 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_darwin.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_darwin.go @@ -13,11 +13,11 @@ // limitations under the License. //go:build darwin -// +build darwin package fileutil import ( + "errors" "os" "syscall" @@ -40,7 +40,7 @@ func preallocFixed(f *os.File, sizeInBytes int64) error { Length: sizeInBytes, } err := unix.FcntlFstore(f.Fd(), unix.F_PREALLOCATE, fstore) - if err == nil || err == unix.ENOTSUP { + if err == nil || errors.Is(err, unix.ENOTSUP) { return nil } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_unix.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_unix.go index ebb8207c34..b0a8166ae1 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_unix.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_unix.go @@ -13,11 +13,11 @@ // limitations under the License. //go:build linux -// +build linux package fileutil import ( + "errors" "os" "syscall" ) @@ -26,10 +26,10 @@ func preallocExtend(f *os.File, sizeInBytes int64) error { // use mode = 0 to change size err := syscall.Fallocate(int(f.Fd()), 0, 0, sizeInBytes) if err != nil { - errno, ok := err.(syscall.Errno) + var errno syscall.Errno // not supported; fallback // fallocate EINTRs frequently in some environments; fallback - if ok && (errno == syscall.ENOTSUP || errno == syscall.EINTR) { + if errors.As(err, &errno) && (errno == syscall.ENOTSUP || errno == syscall.EINTR) { return preallocExtendTrunc(f, sizeInBytes) } } @@ -40,9 +40,9 @@ func preallocFixed(f *os.File, sizeInBytes int64) error { // use mode = 1 to keep size; see FALLOC_FL_KEEP_SIZE err := syscall.Fallocate(int(f.Fd()), 1, 0, sizeInBytes) if err != nil { - errno, ok := err.(syscall.Errno) + var errno syscall.Errno // treat not supported as nil error - if ok && errno == syscall.ENOTSUP { + if errors.As(err, &errno) && errno == syscall.ENOTSUP { return nil } } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_unsupported.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_unsupported.go index 2c46dd4907..e7fd937a43 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_unsupported.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/preallocate_unsupported.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !linux && !darwin -// +build !linux,!darwin package fileutil diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/purge.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/purge.go index b314e068fe..026ea03230 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/purge.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/purge.go @@ -17,7 +17,6 @@ package fileutil import ( "os" "path/filepath" - "sort" "strings" "time" @@ -58,21 +57,14 @@ func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval defer close(donec) } for { - fnames, err := ReadDir(dirname) + fnamesWithSuffix, err := readDirWithSuffix(dirname, suffix) if err != nil { errC <- err return } - newfnames := make([]string, 0) - for _, fname := range fnames { - if strings.HasSuffix(fname, suffix) { - newfnames = append(newfnames, fname) - } - } - sort.Strings(newfnames) - fnames = newfnames - for len(newfnames) > int(max) { - f := filepath.Join(dirname, newfnames[0]) + nPurged := 0 + for nPurged < len(fnamesWithSuffix)-int(max) { + f := filepath.Join(dirname, fnamesWithSuffix[nPurged]) var l *LockedFile if flock { l, err = TryLockFile(f, os.O_WRONLY, PrivateFileMode) @@ -94,11 +86,12 @@ func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval } } lg.Info("purged", zap.String("path", f)) - newfnames = newfnames[1:] + nPurged++ } + if purgec != nil { - for i := 0; i < len(fnames)-len(newfnames); i++ { - purgec <- fnames[i] + for i := 0; i < nPurged; i++ { + purgec <- fnamesWithSuffix[i] } } select { @@ -110,3 +103,18 @@ func purgeFile(lg *zap.Logger, dirname string, suffix string, max uint, interval }() return errC } + +func readDirWithSuffix(dirname string, suffix string) ([]string, error) { + fnames, err := ReadDir(dirname) + if err != nil { + return nil, err + } + // filter in place (ref. https://go.dev/wiki/SliceTricks#filtering-without-allocating) + fnamesWithSuffix := fnames[:0] + for _, fname := range fnames { + if strings.HasSuffix(fname, suffix) { + fnamesWithSuffix = append(fnamesWithSuffix, fname) + } + } + return fnamesWithSuffix, nil +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync.go index 0a0855309e..670d01fadc 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !linux && !darwin -// +build !linux,!darwin package fileutil diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync_darwin.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync_darwin.go index 1923b276ea..7affa78ea6 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync_darwin.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync_darwin.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build darwin -// +build darwin package fileutil diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync_linux.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync_linux.go index b9398c23f9..a3172382e5 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync_linux.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/fileutil/sync_linux.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build linux -// +build linux package fileutil diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/log_format.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/log_format.go new file mode 100644 index 0000000000..286d385ba3 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/log_format.go @@ -0,0 +1,42 @@ +// Copyright 2019 The etcd 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 logutil + +import "fmt" + +const ( + JSONLogFormat = "json" + ConsoleLogFormat = "console" + //revive:disable:var-naming + // Deprecated: Please use JSONLogFormat. + JsonLogFormat = JSONLogFormat + //revive:enable:var-naming +) + +var DefaultLogFormat = JSONLogFormat + +// ConvertToZapFormat converts and validated log format string. +func ConvertToZapFormat(format string) (string, error) { + switch format { + case ConsoleLogFormat: + return ConsoleLogFormat, nil + case JSONLogFormat: + return JSONLogFormat, nil + case "": + return DefaultLogFormat, nil + default: + return "", fmt.Errorf("unknown log format: %s, supported values json, console", format) + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap.go index f0f3739aad..befa575847 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap.go @@ -15,7 +15,7 @@ package logutil import ( - "sort" + "slices" "time" "go.uber.org/zap" @@ -43,7 +43,7 @@ var DefaultZapLoggerConfig = zap.Config{ Thereafter: 100, }, - Encoding: "json", + Encoding: DefaultLogFormat, // copied from "zap.NewProductionEncoderConfig" with some updates EncoderConfig: zapcore.EncoderConfig{ @@ -72,37 +72,22 @@ var DefaultZapLoggerConfig = zap.Config{ // MergeOutputPaths merges logging output paths, resolving conflicts. func MergeOutputPaths(cfg zap.Config) zap.Config { - outputs := make(map[string]struct{}) - for _, v := range cfg.OutputPaths { - outputs[v] = struct{}{} - } - outputSlice := make([]string, 0) - if _, ok := outputs["/dev/null"]; ok { - // "/dev/null" to discard all - outputSlice = []string{"/dev/null"} - } else { - for k := range outputs { - outputSlice = append(outputSlice, k) - } - } - cfg.OutputPaths = outputSlice - sort.Strings(cfg.OutputPaths) + cfg.OutputPaths = mergePaths(cfg.OutputPaths) + cfg.ErrorOutputPaths = mergePaths(cfg.ErrorOutputPaths) + return cfg +} - errOutputs := make(map[string]struct{}) - for _, v := range cfg.ErrorOutputPaths { - errOutputs[v] = struct{}{} +func mergePaths(old []string) []string { + if len(old) == 0 { + // the original implementation ensures the result is non-nil + return []string{} } - errOutputSlice := make([]string, 0) - if _, ok := errOutputs["/dev/null"]; ok { - // "/dev/null" to discard all - errOutputSlice = []string{"/dev/null"} - } else { - for k := range errOutputs { - errOutputSlice = append(errOutputSlice, k) - } + // use "/dev/null" to discard all + if slices.Contains(old, "/dev/null") { + return []string{"/dev/null"} } - cfg.ErrorOutputPaths = errOutputSlice - sort.Strings(cfg.ErrorOutputPaths) - - return cfg + // clone a new one; don't modify the original, in case it matters. + dup := slices.Clone(old) + slices.Sort(dup) + return slices.Compact(dup) } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap_journal.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap_journal.go index 9daa3e0aab..06dc40dacd 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap_journal.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/logutil/zap_journal.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !windows -// +build !windows package logutil @@ -25,10 +24,10 @@ import ( "os" "path/filepath" - "go.etcd.io/etcd/client/pkg/v3/systemd" - "github.com/coreos/go-systemd/v22/journal" "go.uber.org/zap/zapcore" + + "go.etcd.io/etcd/client/pkg/v3/systemd" ) // NewJournalWriter wraps "io.Writer" to redirect log output diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/srv/srv.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/srv/srv.go index 948c683490..e0a1ccef35 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/srv/srv.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/srv/srv.go @@ -33,7 +33,6 @@ var ( // GetCluster gets the cluster information via DNS discovery. // Also sees each entry as a separate instance. func GetCluster(serviceScheme, service, name, dns string, apurls types.URLs) ([]string, error) { - tempName := int(0) tcp2ap := make(map[string]url.URL) // First, resolve the apurls @@ -45,7 +44,10 @@ func GetCluster(serviceScheme, service, name, dns string, apurls types.URLs) ([] tcp2ap[tcpAddr.String()] = url } - stringParts := []string{} + var ( + tempName int + stringParts []string + ) updateNodeMap := func(service, scheme string) error { _, addrs, err := lookupSRV(service, "tcp", dns) if err != nil { @@ -85,7 +87,7 @@ func GetCluster(serviceScheme, service, name, dns string, apurls types.URLs) ([] err := updateNodeMap(service, serviceScheme) if err != nil { - return nil, fmt.Errorf("error querying DNS SRV records for _%s %s", service, err) + return nil, fmt.Errorf("error querying DNS SRV records for _%s %w", service, err) } return stringParts, nil } @@ -97,8 +99,10 @@ type SRVClients struct { // GetClient looks up the client endpoints for a service and domain. func GetClient(service, domain string, serviceName string) (*SRVClients, error) { - var urls []*url.URL - var srvs []*net.SRV + var ( + urls []*url.URL + srvs []*net.SRV + ) updateURLs := func(service, scheme string) error { _, addrs, err := lookupSRV(service, "tcp", domain) @@ -119,7 +123,7 @@ func GetClient(service, domain string, serviceName string) (*SRVClients, error) errHTTP := updateURLs(GetSRVService(service, serviceName, "http"), "http") if errHTTPS != nil && errHTTP != nil { - return nil, fmt.Errorf("dns lookup errors: %s and %s", errHTTPS, errHTTP) + return nil, fmt.Errorf("dns lookup errors: %w and %w", errHTTPS, errHTTP) } endpoints := make([]string, len(urls)) diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/tlsutil/tlsutil.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/tlsutil/tlsutil.go index 3a5aef089a..0f79865e80 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/tlsutil/tlsutil.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/tlsutil/tlsutil.go @@ -18,7 +18,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/pem" - "io/ioutil" + "os" ) // NewCertPool creates x509 certPool with provided CA files. @@ -26,7 +26,7 @@ func NewCertPool(CAFiles []string) (*x509.CertPool, error) { certPool := x509.NewCertPool() for _, CAFile := range CAFiles { - pemByte, err := ioutil.ReadFile(CAFile) + pemByte, err := os.ReadFile(CAFile) if err != nil { return nil, err } @@ -51,12 +51,12 @@ func NewCertPool(CAFiles []string) (*x509.CertPool, error) { // NewCert generates TLS cert by using the given cert,key and parse function. func NewCert(certfile, keyfile string, parseFunc func([]byte, []byte) (tls.Certificate, error)) (*tls.Certificate, error) { - cert, err := ioutil.ReadFile(certfile) + cert, err := os.ReadFile(certfile) if err != nil { return nil, err } - key, err := ioutil.ReadFile(keyfile) + key, err := os.ReadFile(keyfile) if err != nil { return nil, err } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/keepalive_listener.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/keepalive_listener.go index d00a93dc19..d43ac4f078 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/keepalive_listener.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/keepalive_listener.go @@ -16,6 +16,7 @@ package transport import ( "crypto/tls" + "errors" "fmt" "net" "time" @@ -38,7 +39,7 @@ func NewKeepAliveListener(l net.Listener, scheme string, tlscfg *tls.Config) (ne if scheme == "https" { if tlscfg == nil { - return nil, fmt.Errorf("cannot listen on TLS for given listener: KeyFile and CertFile are not presented") + return nil, errors.New("cannot listen on TLS for given listener: KeyFile and CertFile are not presented") } return newTLSKeepaliveListener(kal, tlscfg), nil } @@ -95,16 +96,17 @@ type tlsKeepaliveListener struct { // Accept waits for and returns the next incoming TLS connection. // The returned connection c is a *tls.Conn. -func (l *tlsKeepaliveListener) Accept() (c net.Conn, err error) { - c, err = l.Listener.Accept() +func (l *tlsKeepaliveListener) Accept() (net.Conn, error) { + c, err := l.Listener.Accept() if err != nil { - return + return nil, err } + c = tls.Server(c, l.config) return c, nil } -// NewListener creates a Listener which accepts connections from an inner +// newTLSKeepaliveListener creates a Listener which accepts connections from an inner // Listener and wraps each connection with Server. // The configuration config must be non-nil and must have // at least one certificate. diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/limit_listen.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/limit_listen.go index 404722ba76..bf4c4e104a 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/limit_listen.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/limit_listen.go @@ -23,9 +23,7 @@ import ( "time" ) -var ( - ErrNotTCP = errors.New("only tcp connections have keepalive") -) +var ErrNotTCP = errors.New("only tcp connections have keepalive") // LimitListener returns a Listener that accepts at most n simultaneous // connections from the provided Listener. diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener.go index a7d37688d9..9c2d29ba99 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener.go @@ -32,10 +32,11 @@ import ( "strings" "time" + "go.uber.org/zap" + "go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/client/pkg/v3/tlsutil" - - "go.uber.org/zap" + "go.etcd.io/etcd/client/pkg/v3/verify" ) // NewListener creates a new listner. @@ -43,7 +44,7 @@ func NewListener(addr, scheme string, tlsinfo *TLSInfo) (l net.Listener, err err return newListener(addr, scheme, WithTLSInfo(tlsinfo)) } -// NewListenerWithOpts creates a new listener which accpets listener options. +// NewListenerWithOpts creates a new listener which accepts listener options. func NewListenerWithOpts(addr, scheme string, opts ...ListenerOption) (net.Listener, error) { return newListener(addr, scheme, opts...) } @@ -59,11 +60,7 @@ func newListener(addr, scheme string, opts ...ListenerOption) (net.Listener, err switch { case lnOpts.IsSocketOpts(): // new ListenConfig with socket options. - config, err := newListenConfig(lnOpts.socketOpts) - if err != nil { - return nil, err - } - lnOpts.ListenConfig = config + lnOpts.ListenConfig = newListenConfig(lnOpts.socketOpts) // check for timeout fallthrough case lnOpts.IsTimeout(), lnOpts.IsSocketOpts(): @@ -102,14 +99,17 @@ func newListener(addr, scheme string, opts ...ListenerOption) (net.Listener, err return wrapTLS(scheme, lnOpts.tlsInfo, lnOpts.Listener) } -func newKeepAliveListener(cfg *net.ListenConfig, addr string) (ln net.Listener, err error) { +func newKeepAliveListener(cfg *net.ListenConfig, addr string) (net.Listener, error) { + var ln net.Listener + var err error + if cfg != nil { ln, err = cfg.Listen(context.TODO(), "tcp", addr) } else { ln, err = net.Listen("tcp", addr) } if err != nil { - return + return nil, err } return NewKeepAliveListener(ln, "tcp", nil) @@ -125,7 +125,7 @@ func wrapTLS(scheme string, tlsinfo *TLSInfo, l net.Listener) (net.Listener, err return newTLSListener(l, tlsinfo, checkSAN) } -func newListenConfig(sopts *SocketOpts) (net.ListenConfig, error) { +func newListenConfig(sopts *SocketOpts) net.ListenConfig { lc := net.ListenConfig{} if sopts != nil { ctls := getControls(sopts) @@ -133,7 +133,7 @@ func newListenConfig(sopts *SocketOpts) (net.ListenConfig, error) { lc.Control = ctls.Control } } - return lc, nil + return lc } type TLSInfo struct { @@ -204,6 +204,9 @@ type TLSInfo struct { // EmptyCN indicates that the cert must have empty CN. // If true, ClientConfig() will return an error for a cert with non empty CN. EmptyCN bool + + // LocalAddr is the local IP address to use when communicating with a peer. + LocalAddr string } func (info TLSInfo) String() string { @@ -214,34 +217,35 @@ func (info TLSInfo) Empty() bool { return info.CertFile == "" && info.KeyFile == "" } -func SelfCert(lg *zap.Logger, dirpath string, hosts []string, selfSignedCertValidity uint, additionalUsages ...x509.ExtKeyUsage) (info TLSInfo, err error) { - info.Logger = lg +func SelfCert(lg *zap.Logger, dirpath string, hosts []string, selfSignedCertValidity uint, additionalUsages ...x509.ExtKeyUsage) (TLSInfo, error) { + verify.Assert(lg != nil, "nil log isn't allowed") + + var err error + info := TLSInfo{Logger: lg} if selfSignedCertValidity == 0 { - err = fmt.Errorf("selfSignedCertValidity is invalid,it should be greater than 0") + err = errors.New("selfSignedCertValidity is invalid,it should be greater than 0") info.Logger.Warn( "cannot generate cert", zap.Error(err), ) - return + return info, err } err = fileutil.TouchDirAll(lg, dirpath) if err != nil { - if info.Logger != nil { - info.Logger.Warn( - "cannot create cert directory", - zap.Error(err), - ) - } - return + info.Logger.Warn( + "cannot create cert directory", + zap.Error(err), + ) + return info, err } certPath, err := filepath.Abs(filepath.Join(dirpath, "cert.pem")) if err != nil { - return + return info, err } keyPath, err := filepath.Abs(filepath.Join(dirpath, "key.pem")) if err != nil { - return + return info, err } _, errcert := os.Stat(certPath) _, errkey := os.Stat(keyPath) @@ -251,19 +255,17 @@ func SelfCert(lg *zap.Logger, dirpath string, hosts []string, selfSignedCertVali info.ClientCertFile = certPath info.ClientKeyFile = keyPath info.selfCert = true - return + return info, err } serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) if err != nil { - if info.Logger != nil { - info.Logger.Warn( - "cannot generate random number", - zap.Error(err), - ) - } - return + info.Logger.Warn( + "cannot generate random number", + zap.Error(err), + ) + return info, err } tmpl := x509.Certificate{ @@ -272,17 +274,16 @@ func SelfCert(lg *zap.Logger, dirpath string, hosts []string, selfSignedCertVali NotBefore: time.Now(), NotAfter: time.Now().Add(time.Duration(selfSignedCertValidity) * 365 * (24 * time.Hour)), - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCRLSign, ExtKeyUsage: append([]x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, additionalUsages...), BasicConstraintsValid: true, + IsCA: true, } - if info.Logger != nil { - info.Logger.Warn( - "automatically generate certificates", - zap.Time("certificate-validity-bound-not-after", tmpl.NotAfter), - ) - } + info.Logger.Warn( + "automatically generate certificates", + zap.Time("certificate-validity-bound-not-after", tmpl.NotAfter), + ) for _, host := range hosts { h, _, _ := net.SplitHostPort(host) @@ -295,24 +296,20 @@ func SelfCert(lg *zap.Logger, dirpath string, hosts []string, selfSignedCertVali priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader) if err != nil { - if info.Logger != nil { - info.Logger.Warn( - "cannot generate ECDSA key", - zap.Error(err), - ) - } - return + info.Logger.Warn( + "cannot generate ECDSA key", + zap.Error(err), + ) + return info, err } derBytes, err := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, &priv.PublicKey, priv) if err != nil { - if info.Logger != nil { - info.Logger.Warn( - "cannot generate x509 certificate", - zap.Error(err), - ) - } - return + info.Logger.Warn( + "cannot generate x509 certificate", + zap.Error(err), + ) + return info, err } certOut, err := os.Create(certPath) @@ -322,34 +319,29 @@ func SelfCert(lg *zap.Logger, dirpath string, hosts []string, selfSignedCertVali zap.String("path", certPath), zap.Error(err), ) - return + return info, err } pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) certOut.Close() - if info.Logger != nil { - info.Logger.Info("created cert file", zap.String("path", certPath)) - } + + info.Logger.Info("created cert file", zap.String("path", certPath)) b, err := x509.MarshalECPrivateKey(priv) if err != nil { - return + return info, err } - keyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + keyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600) if err != nil { - if info.Logger != nil { - info.Logger.Warn( - "cannot key file", - zap.String("path", keyPath), - zap.Error(err), - ) - } - return + info.Logger.Warn( + "cannot key file", + zap.String("path", keyPath), + zap.Error(err), + ) + return info, err } pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}) keyOut.Close() - if info.Logger != nil { - info.Logger.Info("created key file", zap.String("path", keyPath)) - } + info.Logger.Info("created key file", zap.String("path", keyPath)) return SelfCert(lg, dirpath, hosts, selfSignedCertValidity) } @@ -482,23 +474,19 @@ func (info TLSInfo) baseConfig() (*tls.Config, error) { cfg.GetCertificate = func(clientHello *tls.ClientHelloInfo) (cert *tls.Certificate, err error) { cert, err = tlsutil.NewCert(info.CertFile, info.KeyFile, info.parseFunc) if os.IsNotExist(err) { - if info.Logger != nil { - info.Logger.Warn( - "failed to find peer cert files", - zap.String("cert-file", info.CertFile), - zap.String("key-file", info.KeyFile), - zap.Error(err), - ) - } + info.Logger.Warn( + "failed to find peer cert files", + zap.String("cert-file", info.CertFile), + zap.String("key-file", info.KeyFile), + zap.Error(err), + ) } else if err != nil { - if info.Logger != nil { - info.Logger.Warn( - "failed to create peer certificate", - zap.String("cert-file", info.CertFile), - zap.String("key-file", info.KeyFile), - zap.Error(err), - ) - } + info.Logger.Warn( + "failed to create peer certificate", + zap.String("cert-file", info.CertFile), + zap.String("key-file", info.KeyFile), + zap.Error(err), + ) } return cert, err } @@ -509,23 +497,19 @@ func (info TLSInfo) baseConfig() (*tls.Config, error) { } cert, err = tlsutil.NewCert(certfile, keyfile, info.parseFunc) if os.IsNotExist(err) { - if info.Logger != nil { - info.Logger.Warn( - "failed to find client cert files", - zap.String("cert-file", certfile), - zap.String("key-file", keyfile), - zap.Error(err), - ) - } + info.Logger.Warn( + "failed to find client cert files", + zap.String("cert-file", certfile), + zap.String("key-file", keyfile), + zap.Error(err), + ) } else if err != nil { - if info.Logger != nil { - info.Logger.Warn( - "failed to create client certificate", - zap.String("cert-file", certfile), - zap.String("key-file", keyfile), - zap.Error(err), - ) - } + info.Logger.Warn( + "failed to create client certificate", + zap.String("cert-file", certfile), + zap.String("key-file", keyfile), + zap.Error(err), + ) } return cert, err } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener_opts.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener_opts.go index ad4f6904da..7536f6aff4 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener_opts.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener_opts.go @@ -1,3 +1,17 @@ +// Copyright 2021 The etcd 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 transport import ( diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener_tls.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener_tls.go index 6f1600945c..2c94841625 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener_tls.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/listener_tls.go @@ -19,8 +19,8 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "io/ioutil" "net" + "os" "strings" "sync" ) @@ -168,16 +168,16 @@ func (l *tlsListener) acceptLoop() { func checkCRL(crlPath string, cert []*x509.Certificate) error { // TODO: cache - crlBytes, err := ioutil.ReadFile(crlPath) + crlBytes, err := os.ReadFile(crlPath) if err != nil { return err } - certList, err := x509.ParseCRL(crlBytes) + certList, err := x509.ParseRevocationList(crlBytes) if err != nil { return err } revokedSerials := make(map[string]struct{}) - for _, rc := range certList.TBSCertList.RevokedCertificates { + for _, rc := range certList.RevokedCertificateEntries { revokedSerials[string(rc.SerialNumber.Bytes())] = struct{}{} } for _, c := range cert { @@ -222,7 +222,8 @@ func checkCertSAN(ctx context.Context, cert *x509.Certificate, remoteAddr string func isHostInDNS(ctx context.Context, host string, dnsNames []string) (ok bool, err error) { // reverse lookup - wildcards, names := []string{}, []string{} + var names []string + var wildcards []string for _, dns := range dnsNames { if strings.HasPrefix(dns, "*.") { wildcards = append(wildcards, dns[1:]) diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt.go index fe028c6132..49b48dc876 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt.go @@ -1,3 +1,17 @@ +// Copyright 2021 The etcd 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 transport import ( diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_solaris.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_solaris.go index 495c736365..149ad51024 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_solaris.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_solaris.go @@ -13,19 +13,18 @@ // limitations under the License. //go:build solaris -// +build solaris package transport import ( - "fmt" + "errors" "syscall" "golang.org/x/sys/unix" ) func setReusePort(network, address string, c syscall.RawConn) error { - return fmt.Errorf("port reuse is not supported on Solaris") + return errors.New("port reuse is not supported on Solaris") } func setReuseAddress(network, address string, conn syscall.RawConn) error { diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_unix.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_unix.go index e2cc6f4828..385eadb007 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_unix.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_unix.go @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build !windows && !solaris -// +build !windows,!solaris +//go:build !windows && !solaris && !wasm && !js package transport diff --git a/etcd/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_wasm.go similarity index 54% rename from etcd/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go rename to etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_wasm.go index d10ad66533..c6590b1d46 100644 --- a/etcd/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_wasm.go @@ -1,10 +1,10 @@ -// Copyright 2020 Google LLC +// Copyright 2023 The etcd 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 +// 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, @@ -12,12 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package field_mask aliases all exported identifiers in -// package "google.golang.org/protobuf/types/known/fieldmaskpb". -package field_mask +//go:build wasm || js -import "google.golang.org/protobuf/types/known/fieldmaskpb" +package transport -type FieldMask = fieldmaskpb.FieldMask +import ( + "errors" + "syscall" +) -var File_google_protobuf_field_mask_proto = fieldmaskpb.File_google_protobuf_field_mask_proto +func setReusePort(network, address string, c syscall.RawConn) error { + return errors.New("port reuse is not supported on WASM") +} + +func setReuseAddress(network, addr string, conn syscall.RawConn) error { + return errors.New("address reuse is not supported on WASM") +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_windows.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_windows.go index 4e5af70b11..2670b4dc7b 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_windows.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/sockopt_windows.go @@ -1,19 +1,32 @@ +// Copyright 2021 The etcd 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. + //go:build windows -// +build windows package transport import ( - "fmt" + "errors" "syscall" ) func setReusePort(network, address string, c syscall.RawConn) error { - return fmt.Errorf("port reuse is not supported on Windows") + return errors.New("port reuse is not supported on Windows") } // Windows supports SO_REUSEADDR, but it may cause undefined behavior, as // there is no protection against port hijacking. func setReuseAddress(network, addr string, conn syscall.RawConn) error { - return fmt.Errorf("address reuse is not supported on Windows") + return errors.New("address reuse is not supported on Windows") } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/tls.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/tls.go index 8c3a35b140..d5375863fd 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/tls.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/tls.go @@ -16,6 +16,7 @@ package transport import ( "context" + "errors" "fmt" "strings" "time" @@ -46,7 +47,7 @@ func ValidateSecureEndpoints(tlsInfo TLSInfo, eps []string) ([]string, error) { endpoints = append(endpoints, ep) } if len(errs) != 0 { - err = fmt.Errorf("%s", strings.Join(errs, ",")) + err = errors.New(strings.Join(errs, ",")) } return endpoints, err } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/transport.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/transport.go index 648512772d..67170d7436 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/transport.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/transport/transport.go @@ -30,10 +30,19 @@ func NewTransport(info TLSInfo, dialtimeoutd time.Duration) (*http.Transport, er return nil, err } + var ipAddr net.Addr + if info.LocalAddr != "" { + ipAddr, err = net.ResolveTCPAddr("tcp", info.LocalAddr+":0") + if err != nil { + return nil, err + } + } + t := &http.Transport{ Proxy: http.ProxyFromEnvironment, DialContext: (&net.Dialer{ - Timeout: dialtimeoutd, + Timeout: dialtimeoutd, + LocalAddr: ipAddr, // value taken from http.DefaultTransport KeepAlive: 30 * time.Second, }).DialContext, @@ -57,7 +66,7 @@ func NewTransport(info TLSInfo, dialtimeoutd time.Duration) (*http.Transport, er TLSClientConfig: cfg, // Cost of reopening connection on sockets is low, and they are mostly used in testing. // Long living unix-transport connections were leading to 'leak' test flakes. - // Alternativly the returned Transport (t) should override CloseIdleConnections to + // Alternatively the returned Transport (t) should override CloseIdleConnections to // forward it to 'tu' as well. IdleConnTimeout: time.Microsecond, } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/types/id.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/types/id.go index ae00388dde..7a09647b5d 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/types/id.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/types/id.go @@ -14,7 +14,10 @@ package types -import "strconv" +import ( + "strconv" + "strings" +) // ID represents a generic identifier which is canonically // stored as a uint64 but is typically represented as a @@ -37,3 +40,17 @@ type IDSlice []ID func (p IDSlice) Len() int { return len(p) } func (p IDSlice) Less(i, j int) bool { return uint64(p[i]) < uint64(p[j]) } func (p IDSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +func (p IDSlice) String() string { + var b strings.Builder + if p.Len() > 0 { + b.WriteString(p[0].String()) + } + + for i := 1; i < p.Len(); i++ { + b.WriteString(",") + b.WriteString(p[i].String()) + } + + return b.String() +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/types/set.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/types/set.go index e7a3cdc9ab..3e69c8d8b9 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/types/set.go +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/types/set.go @@ -90,7 +90,7 @@ func (us *unsafeSet) Length() int { // Values returns the values of the Set in an unspecified order. func (us *unsafeSet) Values() (values []string) { - values = make([]string, 0) + values = make([]string, 0, len(us.d)) for val := range us.d { values = append(values, val) } diff --git a/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/verify/verify.go b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/verify/verify.go new file mode 100644 index 0000000000..a7b2097bed --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/client/pkg/v3/verify/verify.go @@ -0,0 +1,80 @@ +// Copyright 2022 The etcd 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 verify + +import ( + "fmt" + "os" + "strings" +) + +const envVerify = "ETCD_VERIFY" + +type VerificationType string + +const ( + envVerifyValueAll VerificationType = "all" + envVerifyValueAssert VerificationType = "assert" +) + +func getEnvVerify() string { + return strings.ToLower(os.Getenv(envVerify)) +} + +func IsVerificationEnabled(verification VerificationType) bool { + env := getEnvVerify() + return env == string(envVerifyValueAll) || env == strings.ToLower(string(verification)) +} + +// EnableVerifications sets `envVerify` and returns a function that +// can be used to bring the original settings. +func EnableVerifications(verification VerificationType) func() { + previousEnv := getEnvVerify() + os.Setenv(envVerify, string(verification)) + return func() { + os.Setenv(envVerify, previousEnv) + } +} + +// EnableAllVerifications enables verification and returns a function +// that can be used to bring the original settings. +func EnableAllVerifications() func() { + return EnableVerifications(envVerifyValueAll) +} + +// DisableVerifications unsets `envVerify` and returns a function that +// can be used to bring the original settings. +func DisableVerifications() func() { + previousEnv := getEnvVerify() + os.Unsetenv(envVerify) + return func() { + os.Setenv(envVerify, previousEnv) + } +} + +// Verify performs verification if the assertions are enabled. +// In the default setup running in tests and skipped in the production code. +func Verify(f func()) { + if IsVerificationEnabled(envVerifyValueAssert) { + f() + } +} + +// Assert will panic with a given formatted message if the given condition is false. +func Assert(condition bool, msg string, v ...any) { + if !condition { + panic(fmt.Sprintf("assertion failed: "+msg, v...)) + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/json.go b/etcd/vendor/go.etcd.io/etcd/client/v2/json.go deleted file mode 100644 index d5be690a17..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/json.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2019 The etcd 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 client - -import ( - "strconv" - "unsafe" - - "github.com/json-iterator/go" - "github.com/modern-go/reflect2" -) - -type customNumberExtension struct { - jsoniter.DummyExtension -} - -func (cne *customNumberExtension) CreateDecoder(typ reflect2.Type) jsoniter.ValDecoder { - if typ.String() == "interface {}" { - return customNumberDecoder{} - } - return nil -} - -type customNumberDecoder struct { -} - -func (customNumberDecoder) Decode(ptr unsafe.Pointer, iter *jsoniter.Iterator) { - switch iter.WhatIsNext() { - case jsoniter.NumberValue: - var number jsoniter.Number - iter.ReadVal(&number) - i64, err := strconv.ParseInt(string(number), 10, 64) - if err == nil { - *(*interface{})(ptr) = i64 - return - } - f64, err := strconv.ParseFloat(string(number), 64) - if err == nil { - *(*interface{})(ptr) = f64 - return - } - iter.ReportError("DecodeNumber", err.Error()) - default: - *(*interface{})(ptr) = iter.Read() - } -} - -// caseSensitiveJsonIterator returns a jsoniterator API that's configured to be -// case-sensitive when unmarshalling, and otherwise compatible with -// the encoding/json standard library. -func caseSensitiveJsonIterator() jsoniter.API { - config := jsoniter.Config{ - EscapeHTML: true, - SortMapKeys: true, - ValidateJsonRawMessage: true, - CaseSensitive: true, - }.Froze() - // Force jsoniter to decode number to interface{} via int64/float64, if possible. - config.RegisterExtension(&customNumberExtension{}) - return config -} diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/OWNERS b/etcd/vendor/go.etcd.io/etcd/client/v3/OWNERS new file mode 100644 index 0000000000..2b7f28b793 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/OWNERS @@ -0,0 +1,4 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +labels: + - area/clientv3 diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/README.md b/etcd/vendor/go.etcd.io/etcd/client/v3/README.md index 16c0fe888c..af0087ebcc 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/README.md +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/README.md @@ -1,7 +1,7 @@ -# etcd/clientv3 +# etcd/client/v3 [![Docs](https://img.shields.io/badge/docs-latest-green.svg)](https://etcd.io/docs) -[![Godoc](https://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/go.etcd.io/etcd/clientv3) +[![Godoc](https://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/go.etcd.io/etcd/client/v3) `etcd/clientv3` is the official Go etcd client for v3. @@ -16,14 +16,18 @@ go get go.etcd.io/etcd/client/v3 Create client using `clientv3.New`: ```go -cli, err := clientv3.New(clientv3.Config{ - Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"}, - DialTimeout: 5 * time.Second, -}) -if err != nil { - // handle error! +import clientv3 "go.etcd.io/etcd/client/v3" + +func main() { + cli, err := clientv3.New(clientv3.Config{ + Endpoints: []string{"localhost:2379", "localhost:22379", "localhost:32379"}, + DialTimeout: 5 * time.Second, + }) + if err != nil { + // handle error! + } + defer cli.Close() } -defer cli.Close() ``` etcd v3 uses [`gRPC`](https://www.grpc.io) for remote procedure calls. And `clientv3` uses diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/auth.go b/etcd/vendor/go.etcd.io/etcd/client/v3/auth.go index 110918a4c7..382172b21b 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/auth.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/auth.go @@ -19,9 +19,10 @@ import ( "fmt" "strings" + "google.golang.org/grpc" + "go.etcd.io/etcd/api/v3/authpb" pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "google.golang.org/grpc" ) type ( diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/client.go b/etcd/vendor/go.etcd.io/etcd/client/v3/client.go index f7aa65a0a7..24f5988986 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/client.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/client.go @@ -18,22 +18,26 @@ import ( "context" "errors" "fmt" - "strconv" "strings" "sync" "time" - "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" - "go.etcd.io/etcd/client/pkg/v3/logutil" - "go.etcd.io/etcd/client/v3/credentials" - "go.etcd.io/etcd/client/v3/internal/endpoint" - "go.etcd.io/etcd/client/v3/internal/resolver" + "github.com/coreos/go-semver/semver" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/codes" grpccredentials "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/keepalive" "google.golang.org/grpc/status" + + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" + "go.etcd.io/etcd/api/v3/version" + "go.etcd.io/etcd/client/pkg/v3/logutil" + "go.etcd.io/etcd/client/pkg/v3/verify" + "go.etcd.io/etcd/client/v3/credentials" + "go.etcd.io/etcd/client/v3/internal/endpoint" + "go.etcd.io/etcd/client/v3/internal/resolver" ) var ( @@ -55,7 +59,9 @@ type Client struct { cfg Config creds grpccredentials.TransportCredentials resolver *resolver.EtcdManualResolver - mu *sync.RWMutex + + epMu *sync.RWMutex + endpoints []string ctx context.Context cancel context.CancelFunc @@ -64,7 +70,7 @@ type Client struct { Username string // Password is a password for authentication. Password string - authTokenBundle credentials.Bundle + authTokenBundle credentials.PerRPCCredentialsBundle callOpts []grpc.CallOption @@ -86,7 +92,7 @@ func New(cfg Config) (*Client, error) { // service interface implementations and do not need connection management. func NewCtxClient(ctx context.Context, opts ...Option) *Client { cctx, cancel := context.WithCancel(ctx) - c := &Client{ctx: cctx, cancel: cancel, lgMu: new(sync.RWMutex), mu: new(sync.RWMutex)} + c := &Client{ctx: cctx, cancel: cancel, lgMu: new(sync.RWMutex), epMu: new(sync.RWMutex)} for _, opt := range opts { opt(c) } @@ -161,18 +167,18 @@ func (c *Client) Ctx() context.Context { return c.ctx } // Endpoints lists the registered endpoints for the client. func (c *Client) Endpoints() []string { // copy the slice; protect original endpoints from being changed - c.mu.RLock() - defer c.mu.RUnlock() - eps := make([]string, len(c.cfg.Endpoints)) - copy(eps, c.cfg.Endpoints) + c.epMu.RLock() + defer c.epMu.RUnlock() + eps := make([]string, len(c.endpoints)) + copy(eps, c.endpoints) return eps } // SetEndpoints updates client's endpoints. func (c *Client) SetEndpoints(eps ...string) { - c.mu.Lock() - defer c.mu.Unlock() - c.cfg.Endpoints = eps + c.epMu.Lock() + defer c.epMu.Unlock() + c.endpoints = eps c.resolver.SetEndpoints(eps) } @@ -189,7 +195,15 @@ func (c *Client) Sync(ctx context.Context) error { eps = append(eps, m.ClientURLs...) } } + // The linearizable `MemberList` returned successfully, so the + // endpoints shouldn't be empty. + verify.Verify(func() { + if len(eps) == 0 { + panic("empty endpoints returned from etcd cluster") + } + }) c.SetEndpoints(eps...) + c.lg.Debug("set etcd endpoints by autoSync", zap.Strings("endpoints", eps)) return nil } @@ -206,7 +220,7 @@ func (c *Client) autoSync() { ctx, cancel := context.WithTimeout(c.ctx, 5*time.Second) err := c.Sync(ctx) cancel() - if err != nil && err != c.ctx.Err() { + if err != nil && !errors.Is(err, c.ctx.Err()) { c.lg.Info("Auto sync endpoints failed.", zap.Error(err)) } } @@ -214,7 +228,9 @@ func (c *Client) autoSync() { } // dialSetupOpts gives the dial opts prior to any authentication. -func (c *Client) dialSetupOpts(creds grpccredentials.TransportCredentials, dopts ...grpc.DialOption) (opts []grpc.DialOption, err error) { +func (c *Client) dialSetupOpts(creds grpccredentials.TransportCredentials, dopts ...grpc.DialOption) []grpc.DialOption { + var opts []grpc.DialOption + if c.cfg.DialKeepAliveTime > 0 { params := keepalive.ClientParameters{ Time: c.cfg.DialKeepAliveTime, @@ -228,7 +244,7 @@ func (c *Client) dialSetupOpts(creds grpccredentials.TransportCredentials, dopts if creds != nil { opts = append(opts, grpc.WithTransportCredentials(creds)) } else { - opts = append(opts, grpc.WithInsecure()) + opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) } unaryMaxRetries := defaultUnaryMaxRetries @@ -257,7 +273,7 @@ func (c *Client) dialSetupOpts(creds grpccredentials.TransportCredentials, dopts grpc.WithUnaryInterceptor(c.unaryClientInterceptor(withMax(unaryMaxRetries), rrBackoff)), ) - return opts, nil + return opts } // Dial connects to a single endpoint using the client's config. @@ -278,7 +294,7 @@ func (c *Client) getToken(ctx context.Context) error { resp, err := c.Auth.Authenticate(ctx, c.Username, c.Password) if err != nil { - if err == rpctypes.ErrAuthNotEnabled { + if errors.Is(err, rpctypes.ErrAuthNotEnabled) { c.authTokenBundle.UpdateAuthToken("") return nil } @@ -298,10 +314,8 @@ func (c *Client) dialWithBalancer(dopts ...grpc.DialOption) (*grpc.ClientConn, e // dial configures and dials any grpc balancer target. func (c *Client) dial(creds grpccredentials.TransportCredentials, dopts ...grpc.DialOption) (*grpc.ClientConn, error) { - opts, err := c.dialSetupOpts(creds, dopts...) - if err != nil { - return nil, fmt.Errorf("failed to configure dialer: %v", err) - } + opts := c.dialSetupOpts(creds, dopts...) + if c.authTokenBundle != nil { opts = append(opts, grpc.WithPerRPCCredentials(c.authTokenBundle.PerRPCCredentials())) } @@ -314,7 +328,7 @@ func (c *Client) dial(creds grpccredentials.TransportCredentials, dopts ...grpc. dctx, cancel = context.WithTimeout(c.ctx, c.cfg.DialTimeout) defer cancel() // TODO: Is this right for cases where grpc.WithBlock() is not set on the dial options? } - target := fmt.Sprintf("%s://%p/%s", resolver.Schema, c, authority(c.Endpoints()[0])) + target := fmt.Sprintf("%s://%p/%s", resolver.Schema, c, authority(c.endpoints[0])) conn, err := grpc.DialContext(dctx, target, opts...) if err != nil { return nil, err @@ -339,15 +353,15 @@ func authority(endpoint string) string { func (c *Client) credentialsForEndpoint(ep string) grpccredentials.TransportCredentials { r := endpoint.RequiresCredentials(ep) switch r { - case endpoint.CREDS_DROP: + case endpoint.CredsDrop: return nil - case endpoint.CREDS_OPTIONAL: + case endpoint.CredsOptional: return c.creds - case endpoint.CREDS_REQUIRE: + case endpoint.CredsRequire: if c.creds != nil { return c.creds } - return credentials.NewBundle(credentials.Config{}).TransportCredentials() + return credentials.NewTransportCredential(nil) default: panic(fmt.Errorf("unsupported CredsRequirement: %v", r)) } @@ -359,7 +373,7 @@ func newClient(cfg *Config) (*Client, error) { } var creds grpccredentials.TransportCredentials if cfg.TLS != nil { - creds = credentials.NewBundle(credentials.Config{TLSConfig: cfg.TLS}).TransportCredentials() + creds = credentials.NewTransportCredential(cfg.TLS) } // use a temporary skeleton client to bootstrap first connection @@ -375,7 +389,7 @@ func newClient(cfg *Config) (*Client, error) { creds: creds, ctx: ctx, cancel: cancel, - mu: new(sync.RWMutex), + epMu: new(sync.RWMutex), callOpts: defaultCallOpts, lgMu: new(sync.RWMutex), } @@ -398,7 +412,7 @@ func newClient(cfg *Config) (*Client, error) { if cfg.Username != "" && cfg.Password != "" { client.Username = cfg.Username client.Password = cfg.Password - client.authTokenBundle = credentials.NewBundle(credentials.Config{}) + client.authTokenBundle = credentials.NewPerRPCCredentialBundle() } if cfg.MaxCallSendMsgSize > 0 || cfg.MaxCallRecvMsgSize > 0 { if cfg.MaxCallRecvMsgSize > 0 && cfg.MaxCallSendMsgSize > cfg.MaxCallRecvMsgSize { @@ -422,8 +436,10 @@ func newClient(cfg *Config) (*Client, error) { if len(cfg.Endpoints) < 1 { client.cancel() - return nil, fmt.Errorf("at least one Endpoint is required in client config") + return nil, errors.New("at least one Endpoint is required in client config") } + client.SetEndpoints(cfg.Endpoints...) + // Use a provided endpoint target so that for https:// without any tls config given, then // grpc will assume the certificate server name is the endpoint host. conn, err := client.dialWithBalancer() @@ -442,7 +458,7 @@ func newClient(cfg *Config) (*Client, error) { client.Auth = NewAuth(client) client.Maintenance = NewMaintenance(client) - //get token with established connection + // get token with established connection ctx, cancel = client.ctx, func() {} if client.cfg.DialTimeout > 0 { ctx, cancel = context.WithTimeout(ctx, client.cfg.DialTimeout) @@ -451,7 +467,7 @@ func newClient(cfg *Config) (*Client, error) { if err != nil { client.Close() cancel() - //TODO: Consider fmt.Errorf("communicating with [%s] failed: %v", strings.Join(cfg.Endpoints, ";"), err) + // TODO: Consider fmt.Errorf("communicating with [%s] failed: %v", strings.Join(cfg.Endpoints, ";"), err) return nil, err } cancel() @@ -483,6 +499,22 @@ func (c *Client) roundRobinQuorumBackoff(waitBetween time.Duration, jitterFracti } } +// minSupportedVersion returns the minimum version supported, which is the previous minor release. +func minSupportedVersion() *semver.Version { + ver := semver.Must(semver.NewVersion(version.Version)) + // consider only major and minor version + ver = &semver.Version{Major: ver.Major, Minor: ver.Minor} + for i := range version.AllVersions { + if version.AllVersions[i].Equal(*ver) { + if i == 0 { + return ver + } + return &version.AllVersions[i-1] + } + } + panic("current version is not in the version list") +} + func (c *Client) checkVersion() (err error) { var wg sync.WaitGroup @@ -504,20 +536,13 @@ func (c *Client) checkVersion() (err error) { errc <- rerr return } - vs := strings.Split(resp.Version, ".") - maj, min := 0, 0 - if len(vs) >= 2 { - var serr error - if maj, serr = strconv.Atoi(vs[0]); serr != nil { - errc <- serr - return - } - if min, serr = strconv.Atoi(vs[1]); serr != nil { - errc <- serr - return - } + vs, serr := semver.NewVersion(resp.Version) + if serr != nil { + errc <- serr + return } - if maj < 3 || (maj == 3 && min < 4) { + + if vs.LessThan(*minSupportedVersion()) { rerr = ErrOldCluster } errc <- rerr @@ -580,7 +605,8 @@ func ContextError(ctx context.Context, err error) error { return nil } err = rpctypes.Error(err) - if _, ok := err.(rpctypes.EtcdError); ok { + var serverErr rpctypes.EtcdError + if errors.As(err, &serverErr) { return err } if ev, ok := status.FromError(err); ok { @@ -602,7 +628,7 @@ func canceledByCaller(stopCtx context.Context, err error) bool { return false } - return err == context.Canceled || err == context.DeadlineExceeded + return errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) } // IsConnCanceled returns true, if error is from a closed gRPC connection. @@ -620,7 +646,7 @@ func IsConnCanceled(err error) bool { } // >= gRPC v1.10.x - if err == context.Canceled { + if errors.Is(err, context.Canceled) { return true } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/cluster.go b/etcd/vendor/go.etcd.io/etcd/client/v3/cluster.go index 1815c1c964..1b7e83375c 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/cluster.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/cluster.go @@ -17,10 +17,10 @@ package clientv3 import ( "context" + "google.golang.org/grpc" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/client/pkg/v3/types" - - "google.golang.org/grpc" ) type ( @@ -34,7 +34,7 @@ type ( type Cluster interface { // MemberList lists the current cluster membership. - MemberList(ctx context.Context) (*MemberListResponse, error) + MemberList(ctx context.Context, opts ...OpOption) (*MemberListResponse, error) // MemberAdd adds a new member into the cluster. MemberAdd(ctx context.Context, peerAddrs []string) (*MemberAddResponse, error) @@ -122,9 +122,9 @@ func (c *cluster) MemberUpdate(ctx context.Context, id uint64, peerAddrs []strin return nil, ContextError(ctx, err) } -func (c *cluster) MemberList(ctx context.Context) (*MemberListResponse, error) { - // it is safe to retry on list. - resp, err := c.remote.MemberList(ctx, &pb.MemberListRequest{Linearizable: true}, c.callOpts...) +func (c *cluster) MemberList(ctx context.Context, opts ...OpOption) (*MemberListResponse, error) { + opt := OpGet("", opts...) + resp, err := c.remote.MemberList(ctx, &pb.MemberListRequest{Linearizable: !opt.serializable}, c.callOpts...) if err == nil { return (*MemberListResponse)(resp), nil } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/compare.go b/etcd/vendor/go.etcd.io/etcd/client/v3/compare.go index e2967cf38e..663fdb4d20 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/compare.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/compare.go @@ -18,8 +18,10 @@ import ( pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) -type CompareTarget int -type CompareResult int +type ( + CompareTarget int + CompareResult int +) const ( CompareVersion CompareTarget = iota @@ -30,7 +32,7 @@ const ( type Cmp pb.Compare -func Compare(cmp Cmp, result string, v interface{}) Cmp { +func Compare(cmp Cmp, result string, v any) Cmp { var r pb.Compare_CompareResult switch result { @@ -120,7 +122,7 @@ func (cmp Cmp) WithPrefix() Cmp { } // mustInt64 panics if val isn't an int or int64. It returns an int64 otherwise. -func mustInt64(val interface{}) int64 { +func mustInt64(val any) int64 { if v, ok := val.(int64); ok { return v } @@ -132,7 +134,7 @@ func mustInt64(val interface{}) int64 { // mustInt64orLeaseID panics if val isn't a LeaseID, int or int64. It returns an // int64 otherwise. -func mustInt64orLeaseID(val interface{}) int64 { +func mustInt64orLeaseID(val any) int64 { if v, ok := val.(LeaseID); ok { return int64(v) } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/election.go b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/election.go index 31e93d2428..ac1303dd8b 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/election.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/election.go @@ -90,7 +90,7 @@ func (e *Election) Campaign(ctx context.Context, val string) error { } } - _, err = waitDeletes(ctx, client, e.keyPrefix, e.leaderRev-1) + err = waitDeletes(ctx, client, e.keyPrefix, e.leaderRev-1) if err != nil { // clean up in case of context cancel select { diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/key.go b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/key.go index 20825950f3..92e365c471 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/key.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/key.go @@ -16,9 +16,8 @@ package concurrency import ( "context" - "fmt" + "errors" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/mvccpb" v3 "go.etcd.io/etcd/client/v3" ) @@ -42,24 +41,24 @@ func waitDelete(ctx context.Context, client *v3.Client, key string, rev int64) e if err := ctx.Err(); err != nil { return err } - return fmt.Errorf("lost watcher waiting for delete") + return errors.New("lost watcher waiting for delete") } // waitDeletes efficiently waits until all keys matching the prefix and no greater -// than the create revision. -func waitDeletes(ctx context.Context, client *v3.Client, pfx string, maxCreateRev int64) (*pb.ResponseHeader, error) { +// than the create revision are deleted. +func waitDeletes(ctx context.Context, client *v3.Client, pfx string, maxCreateRev int64) error { getOpts := append(v3.WithLastCreate(), v3.WithMaxCreateRev(maxCreateRev)) for { resp, err := client.Get(ctx, pfx, getOpts...) if err != nil { - return nil, err + return err } if len(resp.Kvs) == 0 { - return resp.Header, nil + return nil } lastKey := string(resp.Kvs[0].Key) if err = waitDelete(ctx, client, lastKey, resp.Header.Revision); err != nil { - return nil, err + return err } } } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/mutex.go b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/mutex.go index c3800d6282..6898bbcec4 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/mutex.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/mutex.go @@ -18,6 +18,7 @@ import ( "context" "errors" "fmt" + "strings" "sync" pb "go.etcd.io/etcd/api/v3/etcdserverpb" @@ -25,8 +26,11 @@ import ( ) // ErrLocked is returned by TryLock when Mutex is already locked by another session. -var ErrLocked = errors.New("mutex: Locked by another session") -var ErrSessionExpired = errors.New("mutex: session is expired") +var ( + ErrLocked = errors.New("mutex: Locked by another session") + ErrSessionExpired = errors.New("mutex: session is expired") + ErrLockReleased = errors.New("mutex: lock has already been released") +) // Mutex implements the sync Locker interface with etcd type Mutex struct { @@ -82,7 +86,7 @@ func (m *Mutex) Lock(ctx context.Context) error { client := m.s.Client() // wait for deletion revisions prior to myKey // TODO: early termination if the session key is deleted before other session keys with smaller revisions. - _, werr := waitDeletes(ctx, client, m.pfx, m.myRev-1) + werr := waitDeletes(ctx, client, m.pfx, m.myRev-1) // release lock key if wait failed if werr != nil { m.Unlock(client.Ctx()) @@ -128,6 +132,14 @@ func (m *Mutex) tryAcquire(ctx context.Context) (*v3.TxnResponse, error) { } func (m *Mutex) Unlock(ctx context.Context) error { + if m.myKey == "" || m.myRev <= 0 || m.myKey == "\x00" { + return ErrLockReleased + } + + if !strings.HasPrefix(m.myKey, m.pfx) { + return fmt.Errorf("invalid key %q, it should have prefix %q", m.myKey, m.pfx) + } + client := m.s.Client() if _, err := client.Delete(ctx, m.myKey); err != nil { return err @@ -154,6 +166,7 @@ func (lm *lockerMutex) Lock() { panic(err) } } + func (lm *lockerMutex) Unlock() { client := lm.s.Client() if err := lm.Mutex.Unlock(client.Ctx()); err != nil { diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/session.go b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/session.go index 7143cc4747..2275e96c97 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/session.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/session.go @@ -18,6 +18,8 @@ import ( "context" "time" + "go.uber.org/zap" + v3 "go.etcd.io/etcd/client/v3" ) @@ -30,15 +32,17 @@ type Session struct { opts *sessionOptions id v3.LeaseID + ctx context.Context cancel context.CancelFunc donec <-chan struct{} } // NewSession gets the leased session for a client. func NewSession(client *v3.Client, opts ...SessionOption) (*Session, error) { + lg := client.GetLogger() ops := &sessionOptions{ttl: defaultSessionTTL, ctx: client.Ctx()} for _, opt := range opts { - opt(ops) + opt(ops, lg) } id := ops.leaseID @@ -58,11 +62,14 @@ func NewSession(client *v3.Client, opts ...SessionOption) (*Session, error) { } donec := make(chan struct{}) - s := &Session{client: client, opts: ops, id: id, cancel: cancel, donec: donec} + s := &Session{client: client, opts: ops, id: id, ctx: ctx, cancel: cancel, donec: donec} // keep the lease alive until client error or cancelled context go func() { - defer close(donec) + defer func() { + close(donec) + cancel() + }() for range keepAlive { // eat messages until keep alive channel closes } @@ -79,6 +86,12 @@ func (s *Session) Client() *v3.Client { // Lease is the lease ID for keys bound to the session. func (s *Session) Lease() v3.LeaseID { return s.id } +// Ctx is the context attached to the session, it is canceled when the lease is orphaned, expires, or +// is otherwise no longer being refreshed. +func (s *Session) Ctx() context.Context { + return s.ctx +} + // Done returns a channel that closes when the lease is orphaned, expires, or // is otherwise no longer being refreshed. func (s *Session) Done() <-chan struct{} { return s.donec } @@ -108,14 +121,16 @@ type sessionOptions struct { } // SessionOption configures Session. -type SessionOption func(*sessionOptions) +type SessionOption func(*sessionOptions, *zap.Logger) // WithTTL configures the session's TTL in seconds. // If TTL is <= 0, the default 60 seconds TTL will be used. func WithTTL(ttl int) SessionOption { - return func(so *sessionOptions) { + return func(so *sessionOptions, lg *zap.Logger) { if ttl > 0 { so.ttl = ttl + } else { + lg.Warn("WithTTL(): TTL should be > 0, preserving current TTL", zap.Int64("current-session-ttl", int64(so.ttl))) } } } @@ -124,7 +139,7 @@ func WithTTL(ttl int) SessionOption { // This is useful in process restart scenario, for example, to reclaim // leadership from an election prior to restart. func WithLease(leaseID v3.LeaseID) SessionOption { - return func(so *sessionOptions) { + return func(so *sessionOptions, _ *zap.Logger) { so.leaseID = leaseID } } @@ -135,7 +150,7 @@ func WithLease(leaseID v3.LeaseID) SessionOption { // context is canceled before Close() completes, the session's lease will be // abandoned and left to expire instead of being revoked. func WithContext(ctx context.Context) SessionOption { - return func(so *sessionOptions) { + return func(so *sessionOptions, _ *zap.Logger) { so.ctx = ctx } } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/stm.go b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/stm.go index ba7303d097..49a82181db 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/stm.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/concurrency/stm.go @@ -303,6 +303,10 @@ type stmSerializable struct { } func (s *stmSerializable) Get(keys ...string) string { + if len(keys) == 0 { + return "" + } + if wv := s.wset.get(keys...); wv != nil { return wv.val } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/config.go b/etcd/vendor/go.etcd.io/etcd/client/v3/config.go index 6f5b41978d..8351828d2f 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/config.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/config.go @@ -21,6 +21,8 @@ import ( "go.uber.org/zap" "google.golang.org/grpc" + + "go.etcd.io/etcd/client/pkg/v3/transport" ) type Config struct { @@ -52,7 +54,7 @@ type Config struct { // If 0, it defaults to "math.MaxInt32", because range response can // easily exceed request send limits. // Make sure that "MaxCallRecvMsgSize" >= server-side default send/recv limit. - // ("--max-request-bytes" flag to etcd or "embed.Config.MaxRequestBytes"). + // ("--max-recv-bytes" flag to etcd). MaxCallRecvMsgSize int // TLS holds the client secure credentials, if any. @@ -99,3 +101,128 @@ type Config struct { // TODO: support custom balancer picker } + +// ConfigSpec is the configuration from users, which comes from command-line flags, +// environment variables or config file. It is a fully declarative configuration, +// and can be serialized & deserialized to/from JSON. +type ConfigSpec struct { + Endpoints []string `json:"endpoints"` + RequestTimeout time.Duration `json:"request-timeout"` + DialTimeout time.Duration `json:"dial-timeout"` + KeepAliveTime time.Duration `json:"keepalive-time"` + KeepAliveTimeout time.Duration `json:"keepalive-timeout"` + MaxCallSendMsgSize int `json:"max-request-bytes"` + MaxCallRecvMsgSize int `json:"max-recv-bytes"` + Secure *SecureConfig `json:"secure"` + Auth *AuthConfig `json:"auth"` +} + +type SecureConfig struct { + Cert string `json:"cert"` + Key string `json:"key"` + Cacert string `json:"cacert"` + ServerName string `json:"server-name"` + + InsecureTransport bool `json:"insecure-transport"` + InsecureSkipVerify bool `json:"insecure-skip-tls-verify"` +} + +type AuthConfig struct { + Username string `json:"username"` + Password string `json:"password"` +} + +func (cs *ConfigSpec) Clone() *ConfigSpec { + if cs == nil { + return nil + } + + clone := *cs + + if len(cs.Endpoints) > 0 { + clone.Endpoints = make([]string, len(cs.Endpoints)) + copy(clone.Endpoints, cs.Endpoints) + } + + if cs.Secure != nil { + clone.Secure = &SecureConfig{} + *clone.Secure = *cs.Secure + } + if cs.Auth != nil { + clone.Auth = &AuthConfig{} + *clone.Auth = *cs.Auth + } + + return &clone +} + +func (cfg AuthConfig) Empty() bool { + return cfg.Username == "" && cfg.Password == "" +} + +// NewClientConfig creates a Config based on the provided ConfigSpec. +func NewClientConfig(confSpec *ConfigSpec, lg *zap.Logger) (*Config, error) { + tlsCfg, err := newTLSConfig(confSpec.Secure, lg) + if err != nil { + return nil, err + } + + cfg := &Config{ + Endpoints: confSpec.Endpoints, + DialTimeout: confSpec.DialTimeout, + DialKeepAliveTime: confSpec.KeepAliveTime, + DialKeepAliveTimeout: confSpec.KeepAliveTimeout, + MaxCallSendMsgSize: confSpec.MaxCallSendMsgSize, + MaxCallRecvMsgSize: confSpec.MaxCallRecvMsgSize, + TLS: tlsCfg, + } + + if confSpec.Auth != nil { + cfg.Username = confSpec.Auth.Username + cfg.Password = confSpec.Auth.Password + } + + return cfg, nil +} + +func newTLSConfig(scfg *SecureConfig, lg *zap.Logger) (*tls.Config, error) { + var ( + tlsCfg *tls.Config + err error + ) + + if scfg == nil { + return nil, nil + } + + if scfg.Cert != "" || scfg.Key != "" || scfg.Cacert != "" || scfg.ServerName != "" { + cfgtls := &transport.TLSInfo{ + CertFile: scfg.Cert, + KeyFile: scfg.Key, + TrustedCAFile: scfg.Cacert, + ServerName: scfg.ServerName, + Logger: lg, + } + if tlsCfg, err = cfgtls.ClientConfig(); err != nil { + return nil, err + } + } + + // If key/cert is not given but user wants secure connection, we + // should still setup an empty tls configuration for gRPC to setup + // secure connection. + if tlsCfg == nil && !scfg.InsecureTransport { + tlsCfg = &tls.Config{} + } + + // If the user wants to skip TLS verification then we should set + // the InsecureSkipVerify flag in tls configuration. + if scfg.InsecureSkipVerify { + if tlsCfg == nil { + tlsCfg = &tls.Config{} + } + tlsCfg.InsecureSkipVerify = scfg.InsecureSkipVerify + } + + return tlsCfg, nil +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/credentials/credentials.go b/etcd/vendor/go.etcd.io/etcd/client/v3/credentials/credentials.go index 42f688eb35..a2d8b45e86 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/credentials/credentials.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/credentials/credentials.go @@ -19,92 +19,51 @@ package credentials import ( "context" "crypto/tls" - "net" "sync" - "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" grpccredentials "google.golang.org/grpc/credentials" + + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" ) -// Config defines gRPC credential configuration. -type Config struct { - TLSConfig *tls.Config +func NewTransportCredential(cfg *tls.Config) grpccredentials.TransportCredentials { + return grpccredentials.NewTLS(cfg) } -// Bundle defines gRPC credential interface. -type Bundle interface { - grpccredentials.Bundle +// PerRPCCredentialsBundle defines gRPC credential interface. +type PerRPCCredentialsBundle interface { UpdateAuthToken(token string) + PerRPCCredentials() grpccredentials.PerRPCCredentials } -// NewBundle constructs a new gRPC credential bundle. -func NewBundle(cfg Config) Bundle { - return &bundle{ - tc: newTransportCredential(cfg.TLSConfig), - rc: newPerRPCCredential(), +func NewPerRPCCredentialBundle() PerRPCCredentialsBundle { + return &perRPCCredentialBundle{ + rc: &perRPCCredential{}, } } -// bundle implements "grpccredentials.Bundle" interface. -type bundle struct { - tc *transportCredential +// perRPCCredentialBundle implements `PerRPCCredentialsBundle` interface. +type perRPCCredentialBundle struct { rc *perRPCCredential } -func (b *bundle) TransportCredentials() grpccredentials.TransportCredentials { - return b.tc -} - -func (b *bundle) PerRPCCredentials() grpccredentials.PerRPCCredentials { - return b.rc -} - -func (b *bundle) NewWithMode(mode string) (grpccredentials.Bundle, error) { - // no-op - return nil, nil -} - -// transportCredential implements "grpccredentials.TransportCredentials" interface. -type transportCredential struct { - gtc grpccredentials.TransportCredentials -} - -func newTransportCredential(cfg *tls.Config) *transportCredential { - return &transportCredential{ - gtc: grpccredentials.NewTLS(cfg), - } -} - -func (tc *transportCredential) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (net.Conn, grpccredentials.AuthInfo, error) { - return tc.gtc.ClientHandshake(ctx, authority, rawConn) -} - -func (tc *transportCredential) ServerHandshake(rawConn net.Conn) (net.Conn, grpccredentials.AuthInfo, error) { - return tc.gtc.ServerHandshake(rawConn) -} - -func (tc *transportCredential) Info() grpccredentials.ProtocolInfo { - return tc.gtc.Info() -} - -func (tc *transportCredential) Clone() grpccredentials.TransportCredentials { - return &transportCredential{ - gtc: tc.gtc.Clone(), +func (b *perRPCCredentialBundle) UpdateAuthToken(token string) { + if b.rc == nil { + return } + b.rc.UpdateAuthToken(token) } -func (tc *transportCredential) OverrideServerName(serverNameOverride string) error { - return tc.gtc.OverrideServerName(serverNameOverride) +func (b *perRPCCredentialBundle) PerRPCCredentials() grpccredentials.PerRPCCredentials { + return b.rc } -// perRPCCredential implements "grpccredentials.PerRPCCredentials" interface. +// perRPCCredential implements `grpccredentials.PerRPCCredentials` interface. type perRPCCredential struct { authToken string authTokenMu sync.RWMutex } -func newPerRPCCredential() *perRPCCredential { return &perRPCCredential{} } - func (rc *perRPCCredential) RequireTransportSecurity() bool { return false } func (rc *perRPCCredential) GetRequestMetadata(ctx context.Context, s ...string) (map[string]string, error) { @@ -117,13 +76,6 @@ func (rc *perRPCCredential) GetRequestMetadata(ctx context.Context, s ...string) return map[string]string{rpctypes.TokenFieldNameGRPC: authToken}, nil } -func (b *bundle) UpdateAuthToken(token string) { - if b.rc == nil { - return - } - b.rc.UpdateAuthToken(token) -} - func (rc *perRPCCredential) UpdateAuthToken(token string) { rc.authTokenMu.Lock() rc.authToken = token diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/ctx.go b/etcd/vendor/go.etcd.io/etcd/client/v3/ctx.go index 56b69cf2ed..38cee6c27e 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/ctx.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/ctx.go @@ -17,9 +17,10 @@ package clientv3 import ( "context" + "google.golang.org/grpc/metadata" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/api/v3/version" - "google.golang.org/grpc/metadata" ) // WithRequireLeader requires client requests to only succeed diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/doc.go b/etcd/vendor/go.etcd.io/etcd/client/v3/doc.go index fd61aff117..bd820d3d79 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/doc.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/doc.go @@ -47,8 +47,8 @@ // To specify a client request timeout, wrap the context with context.WithTimeout: // // ctx, cancel := context.WithTimeout(context.Background(), timeout) +// defer cancel() // resp, err := kvc.Put(ctx, "sample_key", "sample_value") -// cancel() // if err != nil { // // handle error! // } @@ -61,8 +61,7 @@ // // 1. context error: canceled or deadline exceeded. // 2. gRPC error: e.g. when clock drifts in server-side before client's context deadline exceeded. -// -// See https://github.com/etcd-io/etcd/blob/main/api/v3rpc/rpctypes/error.go +// See https://github.com/etcd-io/etcd/blob/main/api/v3rpc/rpctypes/error.go // // Here is the example code to handle client errors: // diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/internal/endpoint/endpoint.go b/etcd/vendor/go.etcd.io/etcd/client/v3/internal/endpoint/endpoint.go index 35a3fe8c33..2c45b5e306 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/internal/endpoint/endpoint.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/internal/endpoint/endpoint.go @@ -25,12 +25,12 @@ import ( type CredsRequirement int const ( - // CREDS_REQUIRE - Credentials/certificate required for thi type of connection. - CREDS_REQUIRE CredsRequirement = iota - // CREDS_DROP - Credentials/certificate not needed and should get ignored. - CREDS_DROP - // CREDS_OPTIONAL - Credentials/certificate might be used if supplied - CREDS_OPTIONAL + // CredsRequire - Credentials/certificate required for thi type of connection. + CredsRequire CredsRequirement = iota + // CredsDrop - Credentials/certificate not needed and should get ignored. + CredsDrop + // CredsOptional - Credentials/certificate might be used if supplied + CredsOptional ) func extractHostFromHostPort(ep string) string { @@ -54,20 +54,20 @@ func mustSplit2(s, sep string) (string, string) { func schemeToCredsRequirement(schema string) CredsRequirement { switch schema { case "https", "unixs": - return CREDS_REQUIRE + return CredsRequire case "http": - return CREDS_DROP + return CredsDrop case "unix": // Preserving previous behavior from: // https://github.com/etcd-io/etcd/blob/dae29bb719dd69dc119146fc297a0628fcc1ccf8/client/v3/client.go#L212 // that likely was a bug due to missing 'fallthrough'. // At the same time it seems legit to let the users decide whether they // want credential control or not (and 'unixs' schema is not a standard thing). - return CREDS_OPTIONAL + return CredsOptional case "": - return CREDS_OPTIONAL + return CredsOptional default: - return CREDS_OPTIONAL + return CredsOptional } } @@ -106,7 +106,7 @@ func translateEndpoint(ep string) (addr string, serverName string, requireCreds if strings.Contains(ep, "://") { url, err := url.Parse(ep) if err != nil { - return ep, ep, CREDS_OPTIONAL + return ep, ep, CredsOptional } if url.Scheme == "http" || url.Scheme == "https" { return url.Host, url.Host, schemeToCredsRequirement(url.Scheme) @@ -114,7 +114,7 @@ func translateEndpoint(ep string) (addr string, serverName string, requireCreds return ep, url.Host, schemeToCredsRequirement(url.Scheme) } // Handles plain addresses like 10.0.0.44:437. - return ep, ep, CREDS_OPTIONAL + return ep, ep, CredsOptional } // RequiresCredentials returns whether given endpoint requires diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/internal/resolver/resolver.go b/etcd/vendor/go.etcd.io/etcd/client/v3/internal/resolver/resolver.go index 3ee3cb8e2b..403b745cb7 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/internal/resolver/resolver.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/internal/resolver/resolver.go @@ -15,10 +15,11 @@ package resolver import ( - "go.etcd.io/etcd/client/v3/internal/endpoint" "google.golang.org/grpc/resolver" "google.golang.org/grpc/resolver/manual" "google.golang.org/grpc/serviceconfig" + + "go.etcd.io/etcd/client/v3/internal/endpoint" ) const ( @@ -60,13 +61,15 @@ func (r *EtcdManualResolver) SetEndpoints(endpoints []string) { func (r EtcdManualResolver) updateState() { if r.CC != nil { - addresses := make([]resolver.Address, len(r.endpoints)) + eps := make([]resolver.Endpoint, len(r.endpoints)) for i, ep := range r.endpoints { addr, serverName := endpoint.Interpret(ep) - addresses[i] = resolver.Address{Addr: addr, ServerName: serverName} + eps[i] = resolver.Endpoint{Addresses: []resolver.Address{ + {Addr: addr, ServerName: serverName}, + }} } state := resolver.State{ - Addresses: addresses, + Endpoints: eps, ServiceConfig: r.serviceConfig, } r.UpdateState(state) diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/kv.go b/etcd/vendor/go.etcd.io/etcd/client/v3/kv.go index be5b508dd6..8d0c595d1e 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/kv.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/kv.go @@ -17,9 +17,10 @@ package clientv3 import ( "context" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "google.golang.org/grpc" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" ) type ( @@ -79,12 +80,15 @@ func (op OpResponse) Txn() *TxnResponse { return op.txn } func (resp *PutResponse) OpResponse() OpResponse { return OpResponse{put: resp} } + func (resp *GetResponse) OpResponse() OpResponse { return OpResponse{get: resp} } + func (resp *DeleteResponse) OpResponse() OpResponse { return OpResponse{del: resp} } + func (resp *TxnResponse) OpResponse() OpResponse { return OpResponse{txn: resp} } @@ -145,10 +149,14 @@ func (kv *kv) Do(ctx context.Context, op Op) (OpResponse, error) { var err error switch op.t { case tRange: - var resp *pb.RangeResponse - resp, err = kv.remote.Range(ctx, op.toRangeRequest(), kv.callOpts...) - if err == nil { - return OpResponse{get: (*GetResponse)(resp)}, nil + if op.IsSortOptionValid() { + var resp *pb.RangeResponse + resp, err = kv.remote.Range(ctx, op.toRangeRequest(), kv.callOpts...) + if err == nil { + return OpResponse{get: (*GetResponse)(resp)}, nil + } + } else { + err = rpctypes.ErrInvalidSortOption } case tPut: var resp *pb.PutResponse diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/lease.go b/etcd/vendor/go.etcd.io/etcd/client/v3/lease.go index 4877ee9496..11b5834828 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/lease.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/lease.go @@ -16,15 +16,16 @@ package clientv3 import ( "context" + "errors" "sync" "time" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" - "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/metadata" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" ) type ( @@ -198,12 +199,12 @@ func NewLeaseFromLeaseClient(remote pb.LeaseClient, c *Client, keepAliveTimeout keepAlives: make(map[LeaseID]*keepAlive), remote: remote, firstKeepAliveTimeout: keepAliveTimeout, - lg: c.lg, } if l.firstKeepAliveTimeout == time.Second { l.firstKeepAliveTimeout = defaultTTL } if c != nil { + l.lg = c.lg l.callOpts = c.callOpts } reqLeaderCtx := WithRequireLeader(context.Background()) @@ -419,9 +420,9 @@ func (l *lessor) keepAliveOnce(ctx context.Context, id LeaseID) (karesp *LeaseKe } defer func() { - if err := stream.CloseSend(); err != nil { + if cerr := stream.CloseSend(); cerr != nil { if ferr == nil { - ferr = ContextError(ctx, err) + ferr = ContextError(ctx, cerr) } return } @@ -460,6 +461,9 @@ func (l *lessor) recvKeepAliveLoop() (gerr error) { for { stream, err := l.resetRecv() if err != nil { + l.lg.Warn("error occurred during lease keep alive loop", + zap.Error(err), + ) if canceledByCaller(l.stopCtx, err) { return err } @@ -471,7 +475,7 @@ func (l *lessor) recvKeepAliveLoop() (gerr error) { return err } - if ContextError(l.stopCtx, err) == rpctypes.ErrNoLeader { + if errors.Is(ContextError(l.stopCtx, err), rpctypes.ErrNoLeader) { l.closeRequireLeader() } break @@ -556,9 +560,12 @@ func (l *lessor) recvKeepAlive(resp *pb.LeaseKeepAliveResponse) { // deadlineLoop reaps any keep alive channels that have not received a response // within the lease TTL func (l *lessor) deadlineLoop() { + timer := time.NewTimer(time.Second) + defer timer.Stop() for { + timer.Reset(time.Second) select { - case <-time.After(time.Second): + case <-timer.C: case <-l.donec: return } @@ -592,7 +599,9 @@ func (l *lessor) sendKeepAliveLoop(stream pb.Lease_LeaseKeepAliveClient) { for _, id := range tosend { r := &pb.LeaseKeepAliveRequest{ID: int64(id)} if err := stream.Send(r); err != nil { - // TODO do something with this error? + l.lg.Warn("error occurred during lease keep alive request sending", + zap.Error(err), + ) return } } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/logger.go b/etcd/vendor/go.etcd.io/etcd/client/v3/logger.go index eaa35f2d3a..300363cd25 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/logger.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/logger.go @@ -18,10 +18,11 @@ import ( "log" "os" - "go.etcd.io/etcd/client/pkg/v3/logutil" "go.uber.org/zap/zapcore" "go.uber.org/zap/zapgrpc" "google.golang.org/grpc/grpclog" + + "go.etcd.io/etcd/client/pkg/v3/logutil" ) func init() { @@ -52,7 +53,7 @@ func etcdClientDebugLevel() zapcore.Level { } var l zapcore.Level if err := l.Set(envLevel); err != nil { - log.Printf("Invalid value for environment variable 'ETCD_CLIENT_DEBUG'. Using default level: 'info'") + log.Print("Invalid value for environment variable 'ETCD_CLIENT_DEBUG'. Using default level: 'info'") return zapcore.InfoLevel } return l diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/maintenance.go b/etcd/vendor/go.etcd.io/etcd/client/v3/maintenance.go index 71b28e6dc3..00aaacd15f 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/maintenance.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/maintenance.go @@ -16,12 +16,14 @@ package clientv3 import ( "context" + "errors" "fmt" "io" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.uber.org/zap" "google.golang.org/grpc" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) type ( @@ -31,6 +33,15 @@ type ( StatusResponse pb.StatusResponse HashKVResponse pb.HashKVResponse MoveLeaderResponse pb.MoveLeaderResponse + DowngradeResponse pb.DowngradeResponse + + DowngradeAction pb.DowngradeRequest_DowngradeAction +) + +const ( + DowngradeValidate = DowngradeAction(pb.DowngradeRequest_VALIDATE) + DowngradeEnable = DowngradeAction(pb.DowngradeRequest_ENABLE) + DowngradeCancel = DowngradeAction(pb.DowngradeRequest_CANCEL) ) type Maintenance interface { @@ -57,14 +68,40 @@ type Maintenance interface { // is non-zero, the hash is computed on all keys at or below the given revision. HashKV(ctx context.Context, endpoint string, rev int64) (*HashKVResponse, error) + // SnapshotWithVersion returns a reader for a point-in-time snapshot and version of etcd that created it. + // If the context "ctx" is canceled or timed out, reading from returned + // "io.ReadCloser" would error out (e.g. context.Canceled, context.DeadlineExceeded). + SnapshotWithVersion(ctx context.Context) (*SnapshotResponse, error) + // Snapshot provides a reader for a point-in-time snapshot of etcd. // If the context "ctx" is canceled or timed out, reading from returned // "io.ReadCloser" would error out (e.g. context.Canceled, context.DeadlineExceeded). + // Deprecated: use SnapshotWithVersion instead. Snapshot(ctx context.Context) (io.ReadCloser, error) // MoveLeader requests current leader to transfer its leadership to the transferee. // Request must be made to the leader. MoveLeader(ctx context.Context, transfereeID uint64) (*MoveLeaderResponse, error) + + // Downgrade requests downgrades, verifies feasibility or cancels downgrade + // on the cluster version. + // Supported since etcd 3.5. + Downgrade(ctx context.Context, action DowngradeAction, version string) (*DowngradeResponse, error) +} + +// SnapshotResponse is aggregated response from the snapshot stream. +// Consumer is responsible for closing steam by calling .Snapshot.Close() +type SnapshotResponse struct { + // Header is the first header in the snapshot stream, has the current key-value store information + // and indicates the point in time of the snapshot. + Header *pb.ResponseHeader + // Snapshot exposes ReaderCloser interface for data stored in the Blob field in the snapshot stream. + Snapshot io.ReadCloser + // Version is the local version of server that created the snapshot. + // In cluster with binaries with different version, each cluster can return different result. + // Informs which etcd server version should be used when restoring the snapshot. + // Supported on etcd >= v3.6. + Version string } type maintenance struct { @@ -80,22 +117,10 @@ func NewMaintenance(c *Client) Maintenance { dial: func(endpoint string) (pb.MaintenanceClient, func(), error) { conn, err := c.Dial(endpoint) if err != nil { - return nil, nil, fmt.Errorf("failed to dial endpoint %s with maintenance client: %v", endpoint, err) + return nil, nil, fmt.Errorf("failed to dial endpoint %s with maintenance client: %w", endpoint, err) } - //get token with established connection - dctx := c.ctx - cancel := func() {} - if c.cfg.DialTimeout > 0 { - dctx, cancel = context.WithTimeout(c.ctx, c.cfg.DialTimeout) - } - err = c.getToken(dctx) - cancel() - if err != nil { - conn.Close() - return nil, nil, fmt.Errorf("failed to getToken from endpoint %s with maintenance client: %v", endpoint, err) - } - cancel = func() { conn.Close() } + cancel := func() { conn.Close() } return RetryMaintenanceClient(c, conn), cancel, nil }, remote: RetryMaintenanceClient(c, c.conn), @@ -108,7 +133,6 @@ func NewMaintenance(c *Client) Maintenance { func NewMaintenanceFromMaintenanceClient(remote pb.MaintenanceClient, c *Client) Maintenance { api := &maintenance{ - lg: c.lg, dial: func(string) (pb.MaintenanceClient, func(), error) { return remote, func() {}, nil }, @@ -116,6 +140,7 @@ func NewMaintenanceFromMaintenanceClient(remote pb.MaintenanceClient, c *Client) } if c != nil { api.callOpts = c.callOpts + api.lg = c.lg } return api } @@ -192,7 +217,6 @@ func (m *maintenance) Status(ctx context.Context, endpoint string) (*StatusRespo func (m *maintenance) HashKV(ctx context.Context, endpoint string, rev int64) (*HashKVResponse, error) { remote, cancel, err := m.dial(endpoint) if err != nil { - return nil, ContextError(ctx, err) } defer cancel() @@ -203,7 +227,7 @@ func (m *maintenance) HashKV(ctx context.Context, endpoint string, rev int64) (* return (*HashKVResponse)(resp), nil } -func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) { +func (m *maintenance) SnapshotWithVersion(ctx context.Context) (*SnapshotResponse, error) { ss, err := m.remote.Snapshot(ctx, &pb.SnapshotRequest{}, append(m.callOpts, withMax(defaultStreamMaxRetries))...) if err != nil { return nil, ContextError(ctx, err) @@ -211,27 +235,60 @@ func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) { m.lg.Info("opened snapshot stream; downloading") pr, pw := io.Pipe() + + resp, err := ss.Recv() + if err != nil { + m.logAndCloseWithError(err, pw) + return nil, err + } go func() { + // Saving response is blocking + err := m.save(resp, pw) + if err != nil { + m.logAndCloseWithError(err, pw) + return + } for { - resp, err := ss.Recv() + sresp, err := ss.Recv() if err != nil { - switch err { - case io.EOF: - m.lg.Info("completed snapshot read; closing") - default: - m.lg.Warn("failed to receive from snapshot stream; closing", zap.Error(err)) - } - pw.CloseWithError(err) + m.logAndCloseWithError(err, pw) return } - // can "resp == nil && err == nil" - // before we receive snapshot SHA digest? - // No, server sends EOF with an empty response - // after it sends SHA digest at the end + err = m.save(sresp, pw) + if err != nil { + m.logAndCloseWithError(err, pw) + return + } + } + }() - if _, werr := pw.Write(resp.Blob); werr != nil { - pw.CloseWithError(werr) + return &SnapshotResponse{ + Header: resp.GetHeader(), + Snapshot: &snapshotReadCloser{ctx: ctx, ReadCloser: pr}, + Version: resp.GetVersion(), + }, nil +} + +func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) { + ss, err := m.remote.Snapshot(ctx, &pb.SnapshotRequest{}, append(m.callOpts, withMax(defaultStreamMaxRetries))...) + if err != nil { + return nil, ContextError(ctx, err) + } + + m.lg.Info("opened snapshot stream; downloading") + pr, pw := io.Pipe() + + go func() { + for { + resp, err := ss.Recv() + if err != nil { + m.logAndCloseWithError(err, pw) + return + } + err = m.save(resp, pw) + if err != nil { + m.logAndCloseWithError(err, pw) return } } @@ -239,6 +296,28 @@ func (m *maintenance) Snapshot(ctx context.Context) (io.ReadCloser, error) { return &snapshotReadCloser{ctx: ctx, ReadCloser: pr}, nil } +func (m *maintenance) logAndCloseWithError(err error, pw *io.PipeWriter) { + switch { + case errors.Is(err, io.EOF): + m.lg.Info("completed snapshot read; closing") + default: + m.lg.Warn("failed to receive from snapshot stream; closing", zap.Error(err)) + } + pw.CloseWithError(err) +} + +func (m *maintenance) save(resp *pb.SnapshotResponse, pw *io.PipeWriter) error { + // can "resp == nil && err == nil" + // before we receive snapshot SHA digest? + // No, server sends EOF with an empty response + // after it sends SHA digest at the end + + if _, werr := pw.Write(resp.Blob); werr != nil { + return werr + } + return nil +} + type snapshotReadCloser struct { ctx context.Context io.ReadCloser @@ -253,3 +332,19 @@ func (m *maintenance) MoveLeader(ctx context.Context, transfereeID uint64) (*Mov resp, err := m.remote.MoveLeader(ctx, &pb.MoveLeaderRequest{TargetID: transfereeID}, m.callOpts...) return (*MoveLeaderResponse)(resp), ContextError(ctx, err) } + +func (m *maintenance) Downgrade(ctx context.Context, action DowngradeAction, version string) (*DowngradeResponse, error) { + var actionType pb.DowngradeRequest_DowngradeAction + switch action { + case DowngradeValidate: + actionType = pb.DowngradeRequest_VALIDATE + case DowngradeEnable: + actionType = pb.DowngradeRequest_ENABLE + case DowngradeCancel: + actionType = pb.DowngradeRequest_CANCEL + default: + return nil, errors.New("etcdclient: unknown downgrade action") + } + resp, err := m.remote.Downgrade(ctx, &pb.DowngradeRequest{Action: actionType, Version: version}, m.callOpts...) + return (*DowngradeResponse)(resp), ContextError(ctx, err) +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/op.go b/etcd/vendor/go.etcd.io/etcd/client/v3/op.go index 5251906322..20cb34f5c3 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/op.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/op.go @@ -106,6 +106,9 @@ func (op Op) RangeBytes() []byte { return op.end } // Rev returns the requested revision, if any. func (op Op) Rev() int64 { return op.rev } +// Limit returns limit of the result, if any. +func (op Op) Limit() int64 { return op.limit } + // IsPut returns true iff the operation is a Put. func (op Op) IsPut() bool { return op.t == tPut } @@ -124,6 +127,10 @@ func (op Op) IsKeysOnly() bool { return op.keysOnly } // IsCountOnly returns whether countOnly is set. func (op Op) IsCountOnly() bool { return op.countOnly } +func (op Op) IsOptsWithFromKey() bool { return op.isOptsWithFromKey } + +func (op Op) IsOptsWithPrefix() bool { return op.isOptsWithPrefix } + // MinModRev returns the operation's minimum modify revision. func (op Op) MinModRev() int64 { return op.minModRev } @@ -418,9 +425,15 @@ func WithFromKey() OpOption { } } -// WithSerializable makes 'Get' request serializable. By default, -// it's linearizable. Serializable requests are better for lower latency -// requirement. +// WithSerializable makes `Get` and `MemberList` requests serializable. +// By default, they are linearizable. Serializable requests are better +// for lower latency requirement, but users should be aware that they +// could get stale data with serializable requests. +// +// In some situations users may want to use serializable requests. For +// example, when adding a new member to a one-node cluster, it's reasonable +// and safe to use serializable request before the new added member gets +// started. func WithSerializable() OpOption { return func(op *Op) { op.serializable = true } } @@ -581,3 +594,19 @@ func IsOptsWithFromKey(opts []OpOption) bool { return ret.isOptsWithFromKey } + +func (op Op) IsSortOptionValid() bool { + if op.sort != nil { + sortOrder := int32(op.sort.Order) + sortTarget := int32(op.sort.Target) + + if _, ok := pb.RangeRequest_SortOrder_name[sortOrder]; !ok { + return false + } + + if _, ok := pb.RangeRequest_SortTarget_name[sortTarget]; !ok { + return false + } + } + return true +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/options.go b/etcd/vendor/go.etcd.io/etcd/client/v3/options.go index cdae1b16a2..cc10a03d76 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/options.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/options.go @@ -23,7 +23,7 @@ import ( var ( // client-side handling retrying of request failures where data was not written to the wire or - // where server indicates it did not process the data. gRPC default is default is "WaitForReady(false)" + // where server indicates it did not process the data. gRPC default is "WaitForReady(false)" // but for etcd we default to "WaitForReady(true)" to minimize client request error responses due to // transient failures. defaultWaitForReady = grpc.WaitForReady(true) diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/retry.go b/etcd/vendor/go.etcd.io/etcd/client/v3/retry.go index 69ecc63147..9152c53a7d 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/retry.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/retry.go @@ -16,13 +16,14 @@ package clientv3 import ( "context" - - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" + "errors" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" ) type retryPolicy uint8 @@ -52,7 +53,8 @@ func (rp retryPolicy) String() string { // handle itself even with retries. func isSafeRetryImmutableRPC(err error) bool { eErr := rpctypes.Error(err) - if serverErr, ok := eErr.(rpctypes.EtcdError); ok && serverErr.Code() != codes.Unavailable { + var serverErr rpctypes.EtcdError + if errors.As(eErr, &serverErr) && serverErr.Code() != codes.Unavailable { // interrupted by non-transient server-side or gRPC-side error // client cannot handle itself (e.g. rpctypes.ErrCompacted) return false @@ -101,8 +103,9 @@ func RetryKVClient(c *Client) pb.KVClient { kc: pb.NewKVClient(c.conn), } } + func (rkv *retryKVClient) Range(ctx context.Context, in *pb.RangeRequest, opts ...grpc.CallOption) (resp *pb.RangeResponse, err error) { - return rkv.kc.Range(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rkv.kc.Range(ctx, in, append(opts, withRepeatablePolicy())...) } func (rkv *retryKVClient) Put(ctx context.Context, in *pb.PutRequest, opts ...grpc.CallOption) (resp *pb.PutResponse, err error) { @@ -133,23 +136,23 @@ func RetryLeaseClient(c *Client) pb.LeaseClient { } func (rlc *retryLeaseClient) LeaseTimeToLive(ctx context.Context, in *pb.LeaseTimeToLiveRequest, opts ...grpc.CallOption) (resp *pb.LeaseTimeToLiveResponse, err error) { - return rlc.lc.LeaseTimeToLive(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rlc.lc.LeaseTimeToLive(ctx, in, append(opts, withRepeatablePolicy())...) } func (rlc *retryLeaseClient) LeaseLeases(ctx context.Context, in *pb.LeaseLeasesRequest, opts ...grpc.CallOption) (resp *pb.LeaseLeasesResponse, err error) { - return rlc.lc.LeaseLeases(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rlc.lc.LeaseLeases(ctx, in, append(opts, withRepeatablePolicy())...) } func (rlc *retryLeaseClient) LeaseGrant(ctx context.Context, in *pb.LeaseGrantRequest, opts ...grpc.CallOption) (resp *pb.LeaseGrantResponse, err error) { - return rlc.lc.LeaseGrant(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rlc.lc.LeaseGrant(ctx, in, append(opts, withRepeatablePolicy())...) } func (rlc *retryLeaseClient) LeaseRevoke(ctx context.Context, in *pb.LeaseRevokeRequest, opts ...grpc.CallOption) (resp *pb.LeaseRevokeResponse, err error) { - return rlc.lc.LeaseRevoke(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rlc.lc.LeaseRevoke(ctx, in, append(opts, withRepeatablePolicy())...) } func (rlc *retryLeaseClient) LeaseKeepAlive(ctx context.Context, opts ...grpc.CallOption) (stream pb.Lease_LeaseKeepAliveClient, err error) { - return rlc.lc.LeaseKeepAlive(ctx, append(opts, withRetryPolicy(repeatable))...) + return rlc.lc.LeaseKeepAlive(ctx, append(opts, withRepeatablePolicy())...) } type retryClusterClient struct { @@ -164,7 +167,7 @@ func RetryClusterClient(c *Client) pb.ClusterClient { } func (rcc *retryClusterClient) MemberList(ctx context.Context, in *pb.MemberListRequest, opts ...grpc.CallOption) (resp *pb.MemberListResponse, err error) { - return rcc.cc.MemberList(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rcc.cc.MemberList(ctx, in, append(opts, withRepeatablePolicy())...) } func (rcc *retryClusterClient) MemberAdd(ctx context.Context, in *pb.MemberAddRequest, opts ...grpc.CallOption) (resp *pb.MemberAddResponse, err error) { @@ -195,27 +198,27 @@ func RetryMaintenanceClient(c *Client, conn *grpc.ClientConn) pb.MaintenanceClie } func (rmc *retryMaintenanceClient) Alarm(ctx context.Context, in *pb.AlarmRequest, opts ...grpc.CallOption) (resp *pb.AlarmResponse, err error) { - return rmc.mc.Alarm(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rmc.mc.Alarm(ctx, in, append(opts, withRepeatablePolicy())...) } func (rmc *retryMaintenanceClient) Status(ctx context.Context, in *pb.StatusRequest, opts ...grpc.CallOption) (resp *pb.StatusResponse, err error) { - return rmc.mc.Status(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rmc.mc.Status(ctx, in, append(opts, withRepeatablePolicy())...) } func (rmc *retryMaintenanceClient) Hash(ctx context.Context, in *pb.HashRequest, opts ...grpc.CallOption) (resp *pb.HashResponse, err error) { - return rmc.mc.Hash(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rmc.mc.Hash(ctx, in, append(opts, withRepeatablePolicy())...) } func (rmc *retryMaintenanceClient) HashKV(ctx context.Context, in *pb.HashKVRequest, opts ...grpc.CallOption) (resp *pb.HashKVResponse, err error) { - return rmc.mc.HashKV(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rmc.mc.HashKV(ctx, in, append(opts, withRepeatablePolicy())...) } func (rmc *retryMaintenanceClient) Snapshot(ctx context.Context, in *pb.SnapshotRequest, opts ...grpc.CallOption) (stream pb.Maintenance_SnapshotClient, err error) { - return rmc.mc.Snapshot(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rmc.mc.Snapshot(ctx, in, append(opts, withRepeatablePolicy())...) } func (rmc *retryMaintenanceClient) MoveLeader(ctx context.Context, in *pb.MoveLeaderRequest, opts ...grpc.CallOption) (resp *pb.MoveLeaderResponse, err error) { - return rmc.mc.MoveLeader(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rmc.mc.MoveLeader(ctx, in, append(opts, withRepeatablePolicy())...) } func (rmc *retryMaintenanceClient) Defragment(ctx context.Context, in *pb.DefragmentRequest, opts ...grpc.CallOption) (resp *pb.DefragmentResponse, err error) { @@ -238,19 +241,19 @@ func RetryAuthClient(c *Client) pb.AuthClient { } func (rac *retryAuthClient) UserList(ctx context.Context, in *pb.AuthUserListRequest, opts ...grpc.CallOption) (resp *pb.AuthUserListResponse, err error) { - return rac.ac.UserList(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rac.ac.UserList(ctx, in, append(opts, withRepeatablePolicy())...) } func (rac *retryAuthClient) UserGet(ctx context.Context, in *pb.AuthUserGetRequest, opts ...grpc.CallOption) (resp *pb.AuthUserGetResponse, err error) { - return rac.ac.UserGet(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rac.ac.UserGet(ctx, in, append(opts, withRepeatablePolicy())...) } func (rac *retryAuthClient) RoleGet(ctx context.Context, in *pb.AuthRoleGetRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleGetResponse, err error) { - return rac.ac.RoleGet(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rac.ac.RoleGet(ctx, in, append(opts, withRepeatablePolicy())...) } func (rac *retryAuthClient) RoleList(ctx context.Context, in *pb.AuthRoleListRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleListResponse, err error) { - return rac.ac.RoleList(ctx, in, append(opts, withRetryPolicy(repeatable))...) + return rac.ac.RoleList(ctx, in, append(opts, withRepeatablePolicy())...) } func (rac *retryAuthClient) AuthEnable(ctx context.Context, in *pb.AuthEnableRequest, opts ...grpc.CallOption) (resp *pb.AuthEnableResponse, err error) { diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go b/etcd/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go index 8c50dcfa93..7703e673b0 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/retry_interceptor.go @@ -24,12 +24,13 @@ import ( "sync" "time" - "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" ) // unaryClientInterceptor returns a new retrying unary client interceptor. @@ -38,7 +39,7 @@ import ( // changed through options (e.g. WithMax) on creation of the interceptor or on call (through grpc.CallOptions). func (c *Client) unaryClientInterceptor(optFuncs ...retryOption) grpc.UnaryClientInterceptor { intOpts := reuseOrNewWithCallOptions(defaultOptions, optFuncs) - return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { ctx = withVersion(ctx) grpcOpts, retryOpts := filterCallOptions(opts) callOpts := reuseOrNewWithCallOptions(intOpts, retryOpts) @@ -54,6 +55,7 @@ func (c *Client) unaryClientInterceptor(optFuncs ...retryOption) grpc.UnaryClien c.GetLogger().Debug( "retrying of unary invoker", zap.String("target", cc.Target()), + zap.String("method", method), zap.Uint("attempt", attempt), ) lastErr = invoker(ctx, method, req, reply, cc, grpcOpts...) @@ -63,6 +65,7 @@ func (c *Client) unaryClientInterceptor(optFuncs ...retryOption) grpc.UnaryClien c.GetLogger().Warn( "retrying of unary invoker failed", zap.String("target", cc.Target()), + zap.String("method", method), zap.Uint("attempt", attempt), zap.Error(lastErr), ) @@ -75,14 +78,14 @@ func (c *Client) unaryClientInterceptor(optFuncs ...retryOption) grpc.UnaryClien continue } if c.shouldRefreshToken(lastErr, callOpts) { - gterr := c.refreshToken(ctx) - if gterr != nil { + gtErr := c.refreshToken(ctx) + if gtErr != nil { c.GetLogger().Warn( "retrying of unary invoker failed to fetch new auth token", zap.String("target", cc.Target()), - zap.Error(gterr), + zap.Error(gtErr), ) - return gterr // lastErr must be invalid auth token + return gtErr // lastErr must be invalid auth token } continue } @@ -106,15 +109,12 @@ func (c *Client) streamClientInterceptor(optFuncs ...retryOption) grpc.StreamCli intOpts := reuseOrNewWithCallOptions(defaultOptions, optFuncs) return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { ctx = withVersion(ctx) - // getToken automatically - // TODO(cfc4n): keep this code block, remove codes about getToken in client.go after pr #12165 merged. - if c.authTokenBundle != nil { - // equal to c.Username != "" && c.Password != "" - err := c.getToken(ctx) - if err != nil && rpctypes.Error(err) != rpctypes.ErrAuthNotEnabled { - c.GetLogger().Error("clientv3/retry_interceptor: getToken failed", zap.Error(err)) - return nil, err - } + // getToken automatically. Otherwise, auth token may be invalid after watch reconnection because the token has expired + // (see https://github.com/etcd-io/etcd/issues/11954 for more). + err := c.getToken(ctx) + if err != nil { + c.GetLogger().Error("clientv3/retry_interceptor: getToken failed", zap.Error(err)) + return nil, err } grpcOpts, retryOpts := filterCallOptions(opts) callOpts := reuseOrNewWithCallOptions(intOpts, retryOpts) @@ -146,14 +146,14 @@ func (c *Client) streamClientInterceptor(optFuncs ...retryOption) grpc.StreamCli // shouldRefreshToken checks whether there's a need to refresh the token based on the error and callOptions, // and returns a boolean value. func (c *Client) shouldRefreshToken(err error, callOpts *options) bool { - if rpctypes.Error(err) == rpctypes.ErrUserEmpty { + if errors.Is(rpctypes.Error(err), rpctypes.ErrUserEmpty) { // refresh the token when username, password is present but the server returns ErrUserEmpty // which is possible when the client token is cleared somehow return c.authTokenBundle != nil // equal to c.Username != "" && c.Password != "" } return callOpts.retryAuth && - (rpctypes.Error(err) == rpctypes.ErrInvalidAuthToken || rpctypes.Error(err) == rpctypes.ErrAuthOldRevision) + (errors.Is(rpctypes.Error(err), rpctypes.ErrInvalidAuthToken) || errors.Is(rpctypes.Error(err), rpctypes.ErrAuthOldRevision)) } func (c *Client) refreshToken(ctx context.Context) error { @@ -169,8 +169,7 @@ func (c *Client) refreshToken(ctx context.Context) error { // clients just need to retry the operations (e.g. Put, Delete etc). return nil } - // clear auth token before refreshing it. - c.authTokenBundle.UpdateAuthToken("") + return c.getToken(ctx) } @@ -180,9 +179,9 @@ func (c *Client) refreshToken(ctx context.Context) error { type serverStreamingRetryingStream struct { grpc.ClientStream client *Client - bufferedSends []interface{} // single message that the client can sen - receivedGood bool // indicates whether any prior receives were successful - wasClosedSend bool // indicates that CloseSend was closed + bufferedSends []any // single message that the client can sen + receivedGood bool // indicates whether any prior receives were successful + wasClosedSend bool // indicates that CloseSend was closed ctx context.Context callOpts *options streamerCall func(ctx context.Context) (grpc.ClientStream, error) @@ -201,7 +200,7 @@ func (s *serverStreamingRetryingStream) getStream() grpc.ClientStream { return s.ClientStream } -func (s *serverStreamingRetryingStream) SendMsg(m interface{}) error { +func (s *serverStreamingRetryingStream) SendMsg(m any) error { s.mu.Lock() s.bufferedSends = append(s.bufferedSends, m) s.mu.Unlock() @@ -223,7 +222,7 @@ func (s *serverStreamingRetryingStream) Trailer() metadata.MD { return s.getStream().Trailer() } -func (s *serverStreamingRetryingStream) RecvMsg(m interface{}) error { +func (s *serverStreamingRetryingStream) RecvMsg(m any) error { attemptRetry, lastErr := s.receiveMsgAndIndicateRetry(m) if !attemptRetry { return lastErr // success or hard failure @@ -250,12 +249,12 @@ func (s *serverStreamingRetryingStream) RecvMsg(m interface{}) error { return lastErr } -func (s *serverStreamingRetryingStream) receiveMsgAndIndicateRetry(m interface{}) (bool, error) { +func (s *serverStreamingRetryingStream) receiveMsgAndIndicateRetry(m any) (bool, error) { s.mu.RLock() wasGood := s.receivedGood s.mu.RUnlock() err := s.getStream().RecvMsg(m) - if err == nil || err == io.EOF { + if err == nil || errors.Is(err, io.EOF) { s.mu.Lock() s.receivedGood = true s.mu.Unlock() @@ -272,13 +271,12 @@ func (s *serverStreamingRetryingStream) receiveMsgAndIndicateRetry(m interface{} return true, err } if s.client.shouldRefreshToken(err, s.callOpts) { - gterr := s.client.refreshToken(s.ctx) - if gterr != nil { - s.client.lg.Warn("retry failed to fetch new auth token", zap.Error(gterr)) + gtErr := s.client.refreshToken(s.ctx) + if gtErr != nil { + s.client.lg.Warn("retry failed to fetch new auth token", zap.Error(gtErr)) return false, err // return the original error for simplicity } return true, err - } return isSafeRetry(s.client, err, s.callOpts), err } @@ -312,7 +310,7 @@ func waitRetryBackoff(ctx context.Context, attempt uint, callOpts *options) erro select { case <-ctx.Done(): timer.Stop() - return contextErrToGrpcErr(ctx.Err()) + return contextErrToGRPCErr(ctx.Err()) case <-timer.C: } } @@ -331,7 +329,7 @@ func isSafeRetry(c *Client, err error, callOpts *options) bool { // customer provides mix of learners (not yet voters) and voters with an // expectation to pick voter in the next attempt. // TODO: Ideally client should be 'aware' which endpoint represents: leader/voter/learner with high probability. - if errors.Is(err, rpctypes.ErrGPRCNotSupportedForLearner) && len(c.Endpoints()) > 1 { + if errors.Is(err, rpctypes.ErrGRPCNotSupportedForLearner) && len(c.Endpoints()) > 1 { return true } @@ -350,25 +348,23 @@ func isContextError(err error) bool { return status.Code(err) == codes.DeadlineExceeded || status.Code(err) == codes.Canceled } -func contextErrToGrpcErr(err error) error { - switch err { - case context.DeadlineExceeded: - return status.Errorf(codes.DeadlineExceeded, err.Error()) - case context.Canceled: - return status.Errorf(codes.Canceled, err.Error()) +func contextErrToGRPCErr(err error) error { + switch { + case errors.Is(err, context.DeadlineExceeded): + return status.Error(codes.DeadlineExceeded, err.Error()) + case errors.Is(err, context.Canceled): + return status.Error(codes.Canceled, err.Error()) default: - return status.Errorf(codes.Unknown, err.Error()) + return status.Error(codes.Unknown, err.Error()) } } -var ( - defaultOptions = &options{ - retryPolicy: nonRepeatable, - max: 0, // disable - backoffFunc: backoffLinearWithJitter(50*time.Millisecond /*jitter*/, 0.10), - retryAuth: true, - } -) +var defaultOptions = &options{ + retryPolicy: nonRepeatable, + max: 0, // disable + backoffFunc: backoffLinearWithJitter(50*time.Millisecond /*jitter*/, 0.10), + retryAuth: true, +} // backoffFunc denotes a family of functions that control the backoff duration between call retries. // @@ -378,10 +374,10 @@ var ( // with the next iteration. type backoffFunc func(attempt uint) time.Duration -// withRetryPolicy sets the retry policy of this call. -func withRetryPolicy(rp retryPolicy) retryOption { +// withRepeatablePolicy sets the repeatable policy of this call. +func withRepeatablePolicy() retryOption { return retryOption{applyFunc: func(o *options) { - o.retryPolicy = rp + o.retryPolicy = repeatable }} } @@ -392,7 +388,7 @@ func withMax(maxRetries uint) retryOption { }} } -// WithBackoff sets the `BackoffFunc `used to control time between retries. +// WithBackoff sets the `BackoffFunc` used to control time between retries. func withBackoff(bf backoffFunc) retryOption { return retryOption{applyFunc: func(o *options) { o.backoffFunc = bf diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/sort.go b/etcd/vendor/go.etcd.io/etcd/client/v3/sort.go index 2bb9d9a13b..9918ea927f 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/sort.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/sort.go @@ -14,8 +14,10 @@ package clientv3 -type SortTarget int -type SortOrder int +type ( + SortTarget int + SortOrder int +) const ( SortNone SortOrder = iota diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/txn.go b/etcd/vendor/go.etcd.io/etcd/client/v3/txn.go index e31bfe0b94..0a57332ac7 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/txn.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/txn.go @@ -18,9 +18,9 @@ import ( "context" "sync" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "google.golang.org/grpc" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) // Txn is the interface that wraps mini-transactions. diff --git a/etcd/vendor/go.etcd.io/etcd/client/v3/watch.go b/etcd/vendor/go.etcd.io/etcd/client/v3/watch.go index 725e8a869e..a46f98b8e2 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v3/watch.go +++ b/etcd/vendor/go.etcd.io/etcd/client/v3/watch.go @@ -21,15 +21,15 @@ import ( "sync" "time" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/api/v3/mvccpb" - v3rpc "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" - "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/mvccpb" + v3rpc "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" ) const ( @@ -149,12 +149,12 @@ type watcher struct { mu sync.Mutex // streams holds all the active grpc streams keyed by ctx value. - streams map[string]*watchGrpcStream + streams map[string]*watchGRPCStream lg *zap.Logger } -// watchGrpcStream tracks all watch resources attached to a single grpc stream. -type watchGrpcStream struct { +// watchGRPCStream tracks all watch resources attached to a single grpc stream. +type watchGRPCStream struct { owner *watcher remote pb.WatchClient callOpts []grpc.CallOption @@ -221,8 +221,7 @@ type watchRequest struct { } // progressRequest is issued by the subscriber to request watch progress -type progressRequest struct { -} +type progressRequest struct{} // watcherStream represents a registered watcher type watcherStream struct { @@ -251,7 +250,7 @@ func NewWatcher(c *Client) Watcher { func NewWatchFromWatchClient(wc pb.WatchClient, c *Client) Watcher { w := &watcher{ remote: wc, - streams: make(map[string]*watchGrpcStream), + streams: make(map[string]*watchGRPCStream), } if c != nil { w.callOpts = c.callOpts @@ -261,8 +260,10 @@ func NewWatchFromWatchClient(wc pb.WatchClient, c *Client) Watcher { } // never closes -var valCtxCh = make(chan struct{}) -var zeroTime = time.Unix(0, 0) +var ( + valCtxCh = make(chan struct{}) + zeroTime = time.Unix(0, 0) +) // ctx with only the values; never Done type valCtx struct{ context.Context } @@ -271,9 +272,9 @@ func (vc *valCtx) Deadline() (time.Time, bool) { return zeroTime, false } func (vc *valCtx) Done() <-chan struct{} { return valCtxCh } func (vc *valCtx) Err() error { return nil } -func (w *watcher) newWatcherGrpcStream(inctx context.Context) *watchGrpcStream { +func (w *watcher) newWatcherGRPCStream(inctx context.Context) *watchGRPCStream { ctx, cancel := context.WithCancel(&valCtx{inctx}) - wgs := &watchGrpcStream{ + wgs := &watchGRPCStream{ owner: w, remote: w.remote, callOpts: w.callOpts, @@ -334,7 +335,7 @@ func (w *watcher) Watch(ctx context.Context, key string, opts ...OpOption) Watch } wgs := w.streams[ctxKey] if wgs == nil { - wgs = w.newWatcherGrpcStream(ctx) + wgs = w.newWatcherGRPCStream(ctx) w.streams[ctxKey] = wgs } donec := wgs.donec @@ -395,7 +396,7 @@ func (w *watcher) Close() (err error) { } } // Consider context.Canceled as a successful close - if err == context.Canceled { + if errors.Is(err, context.Canceled) { err = nil } return err @@ -408,11 +409,11 @@ func (w *watcher) RequestProgress(ctx context.Context) (err error) { w.mu.Lock() if w.streams == nil { w.mu.Unlock() - return fmt.Errorf("no stream found for context") + return errors.New("no stream found for context") } wgs := w.streams[ctxKey] if wgs == nil { - wgs = w.newWatcherGrpcStream(ctx) + wgs = w.newWatcherGRPCStream(ctx) w.streams[ctxKey] = wgs } donec := wgs.donec @@ -435,7 +436,7 @@ func (w *watcher) RequestProgress(ctx context.Context) (err error) { } } -func (w *watchGrpcStream) close() (err error) { +func (w *watchGRPCStream) close() (err error) { w.cancel() <-w.donec select { @@ -445,7 +446,7 @@ func (w *watchGrpcStream) close() (err error) { return ContextError(w.ctx, err) } -func (w *watcher) closeStream(wgs *watchGrpcStream) { +func (w *watcher) closeStream(wgs *watchGRPCStream) { w.mu.Lock() close(wgs.donec) wgs.cancel() @@ -455,7 +456,7 @@ func (w *watcher) closeStream(wgs *watchGrpcStream) { w.mu.Unlock() } -func (w *watchGrpcStream) addSubstream(resp *pb.WatchResponse, ws *watcherStream) { +func (w *watchGRPCStream) addSubstream(resp *pb.WatchResponse, ws *watcherStream) { // check watch ID for backward compatibility (<= v3.3) if resp.WatchId == InvalidWatchID || (resp.Canceled && resp.CancelReason != "") { w.closeErr = v3rpc.Error(errors.New(resp.CancelReason)) @@ -467,7 +468,7 @@ func (w *watchGrpcStream) addSubstream(resp *pb.WatchResponse, ws *watcherStream w.substreams[ws.id] = ws } -func (w *watchGrpcStream) sendCloseSubstream(ws *watcherStream, resp *WatchResponse) { +func (w *watchGRPCStream) sendCloseSubstream(ws *watcherStream, resp *WatchResponse) { select { case ws.outc <- *resp: case <-ws.initReq.ctx.Done(): @@ -476,7 +477,7 @@ func (w *watchGrpcStream) sendCloseSubstream(ws *watcherStream, resp *WatchRespo close(ws.outc) } -func (w *watchGrpcStream) closeSubstream(ws *watcherStream) { +func (w *watchGRPCStream) closeSubstream(ws *watcherStream) { // send channel response in case stream was never established select { case ws.initReq.retc <- ws.outc: @@ -501,7 +502,7 @@ func (w *watchGrpcStream) closeSubstream(ws *watcherStream) { } // run is the root of the goroutines for managing a watcher client -func (w *watchGrpcStream) run() { +func (w *watchGRPCStream) run() { var wc pb.Watch_WatchClient var closeErr error @@ -653,7 +654,7 @@ func (w *watchGrpcStream) run() { // watch client failed on Recv; spawn another if possible case err := <-w.errc: - if isHaltErr(w.ctx, err) || ContextError(w.ctx, err) == v3rpc.ErrNoLeader { + if isHaltErr(w.ctx, err) || errors.Is(ContextError(w.ctx, err), v3rpc.ErrNoLeader) { closeErr = err return } @@ -699,7 +700,7 @@ func (w *watchGrpcStream) run() { // nextResume chooses the next resuming to register with the grpc stream. Abandoned // streams are marked as nil in the queue since the head must wait for its inflight registration. -func (w *watchGrpcStream) nextResume() *watcherStream { +func (w *watchGRPCStream) nextResume() *watcherStream { for len(w.resuming) != 0 { if w.resuming[0] != nil { return w.resuming[0] @@ -710,7 +711,7 @@ func (w *watchGrpcStream) nextResume() *watcherStream { } // dispatchEvent sends a WatchResponse to the appropriate watcher stream -func (w *watchGrpcStream) dispatchEvent(pbresp *pb.WatchResponse) bool { +func (w *watchGRPCStream) dispatchEvent(pbresp *pb.WatchResponse) bool { events := make([]*Event, len(pbresp.Events)) for i, ev := range pbresp.Events { events[i] = (*Event)(ev) @@ -732,11 +733,10 @@ func (w *watchGrpcStream) dispatchEvent(pbresp *pb.WatchResponse) bool { } return w.unicastResponse(wr, pbresp.WatchId) - } // broadcastResponse send a watch response to all watch substreams. -func (w *watchGrpcStream) broadcastResponse(wr *WatchResponse) bool { +func (w *watchGRPCStream) broadcastResponse(wr *WatchResponse) bool { for _, ws := range w.substreams { select { case ws.recvc <- wr: @@ -747,8 +747,8 @@ func (w *watchGrpcStream) broadcastResponse(wr *WatchResponse) bool { } // unicastResponse sends a watch response to a specific watch substream. -func (w *watchGrpcStream) unicastResponse(wr *WatchResponse, watchId int64) bool { - ws, ok := w.substreams[watchId] +func (w *watchGRPCStream) unicastResponse(wr *WatchResponse, watchID int64) bool { + ws, ok := w.substreams[watchID] if !ok { return false } @@ -761,7 +761,7 @@ func (w *watchGrpcStream) unicastResponse(wr *WatchResponse, watchId int64) bool } // serveWatchClient forwards messages from the grpc stream to run() -func (w *watchGrpcStream) serveWatchClient(wc pb.Watch_WatchClient) { +func (w *watchGRPCStream) serveWatchClient(wc pb.Watch_WatchClient) { for { resp, err := wc.Recv() if err != nil { @@ -780,7 +780,7 @@ func (w *watchGrpcStream) serveWatchClient(wc pb.Watch_WatchClient) { } // serveSubstream forwards watch responses from run() to the subscriber -func (w *watchGrpcStream) serveSubstream(ws *watcherStream, resumec chan struct{}) { +func (w *watchGRPCStream) serveSubstream(ws *watcherStream, resumec chan struct{}) { if ws.closing { panic("created substream goroutine but substream is closing") } @@ -854,6 +854,7 @@ func (w *watchGrpcStream) serveSubstream(ws *watcherStream, resumec chan struct{ if len(wr.Events) > 0 { nextRev = wr.Events[len(wr.Events)-1].Kv.ModRevision + 1 } + ws.initReq.rev = nextRev // created event is already sent above, @@ -876,7 +877,7 @@ func (w *watchGrpcStream) serveSubstream(ws *watcherStream, resumec chan struct{ // lazily send cancel message if events on missing id } -func (w *watchGrpcStream) newWatchClient() (pb.Watch_WatchClient, error) { +func (w *watchGRPCStream) newWatchClient() (pb.Watch_WatchClient, error) { // mark all substreams as resuming close(w.resumec) w.resumec = make(chan struct{}) @@ -922,7 +923,7 @@ func (w *watchGrpcStream) newWatchClient() (pb.Watch_WatchClient, error) { return wc, nil } -func (w *watchGrpcStream) waitCancelSubstreams(stopc <-chan struct{}) <-chan struct{} { +func (w *watchGRPCStream) waitCancelSubstreams(stopc <-chan struct{}) <-chan struct{} { var wg sync.WaitGroup wg.Add(len(w.resuming)) donec := make(chan struct{}) @@ -959,7 +960,7 @@ func (w *watchGrpcStream) waitCancelSubstreams(stopc <-chan struct{}) <-chan str } // joinSubstreams waits for all substream goroutines to complete. -func (w *watchGrpcStream) joinSubstreams() { +func (w *watchGRPCStream) joinSubstreams() { for _, ws := range w.substreams { <-ws.donec } @@ -972,7 +973,7 @@ func (w *watchGrpcStream) joinSubstreams() { var maxBackoff = 100 * time.Millisecond -func (w *watchGrpcStream) backoffIfUnavailable(backoff time.Duration, err error) time.Duration { +func (w *watchGRPCStream) backoffIfUnavailable(backoff time.Duration, err error) time.Duration { if isUnavailableErr(w.ctx, err) { // retry, but backoff if backoff < maxBackoff { @@ -990,7 +991,7 @@ func (w *watchGrpcStream) backoffIfUnavailable(backoff time.Duration, err error) // openWatchClient retries opening a watch client until success or halt. // manually retry in case "ws==nil && err==nil" // TODO: remove FailFast=false -func (w *watchGrpcStream) openWatchClient() (ws pb.Watch_WatchClient, err error) { +func (w *watchGRPCStream) openWatchClient() (ws pb.Watch_WatchClient, err error) { backoff := time.Millisecond for { select { diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/adt/interval_tree.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/adt/interval_tree.go index 271e3d3893..3c1c3ea832 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/adt/interval_tree.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/adt/interval_tree.go @@ -176,7 +176,7 @@ func (x *intervalNode) visit(iv *Interval, sentinel *intervalNode, nv nodeVisito // IntervalValue represents a range tree node that contains a range and a value. type IntervalValue struct { Ivl Interval - Val interface{} + Val any } // IntervalTree represents a (mostly) textbook implementation of the @@ -184,7 +184,7 @@ type IntervalValue struct { // and chapter 14.3 interval tree with search supporting "stabbing queries". type IntervalTree interface { // Insert adds a node with the given interval into the tree. - Insert(ivl Interval, val interface{}) + Insert(ivl Interval, val any) // Delete removes the node with the given interval from the tree, returning // true if a node is in fact removed. Delete(ivl Interval) bool @@ -241,34 +241,34 @@ type intervalTree struct { // // "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.4, p324 // -// RB-DELETE(T, z) -// -// y = z -// y-original-color = y.color -// -// if z.left == T.nil -// x = z.right -// RB-TRANSPLANT(T, z, z.right) -// else if z.right == T.nil -// x = z.left -// RB-TRANSPLANT(T, z, z.left) -// else -// y = TREE-MINIMUM(z.right) -// y-original-color = y.color -// x = y.right -// if y.p == z -// x.p = y -// else -// RB-TRANSPLANT(T, y, y.right) -// y.right = z.right -// y.right.p = y -// RB-TRANSPLANT(T, z, y) -// y.left = z.left -// y.left.p = y -// y.color = z.color -// -// if y-original-color == BLACK -// RB-DELETE-FIXUP(T, x) +// RB-DELETE(T, z) +// +// y = z +// y-original-color = y.color +// +// if z.left == T.nil +// x = z.right +// RB-TRANSPLANT(T, z, z.right) +// else if z.right == T.nil +// x = z.left +// RB-TRANSPLANT(T, z, z.left) +// else +// y = TREE-MINIMUM(z.right) +// y-original-color = y.color +// x = y.right +// if y.p == z +// x.p = y +// else +// RB-TRANSPLANT(T, y, y.right) +// y.right = z.right +// y.right.p = y +// RB-TRANSPLANT(T, z, y) +// y.left = z.left +// y.left.p = y +// y.color = z.color +// +// if y-original-color == BLACK +// RB-DELETE-FIXUP(T, x) // Delete removes the node with the given interval from the tree, returning // true if a node is in fact removed. @@ -423,7 +423,7 @@ func (ivt *intervalTree) deleteFixup(x *intervalNode) { } } -func (ivt *intervalTree) createIntervalNode(ivl Interval, val interface{}) *intervalNode { +func (ivt *intervalTree) createIntervalNode(ivl Interval, val any) *intervalNode { return &intervalNode{ iv: IntervalValue{ivl, val}, max: ivl.End, @@ -438,35 +438,35 @@ func (ivt *intervalTree) createIntervalNode(ivl Interval, val interface{}) *inte // // "Introduction to Algorithms" (Cormen et al, 3rd ed.), chapter 13.3, p315 // -// RB-INSERT(T, z) +// RB-INSERT(T, z) // -// y = T.nil -// x = T.root +// y = T.nil +// x = T.root // -// while x ≠ T.nil -// y = x -// if z.key < x.key -// x = x.left -// else -// x = x.right +// while x ≠ T.nil +// y = x +// if z.key < x.key +// x = x.left +// else +// x = x.right // -// z.p = y +// z.p = y // -// if y == T.nil -// T.root = z -// else if z.key < y.key -// y.left = z -// else -// y.right = z +// if y == T.nil +// T.root = z +// else if z.key < y.key +// y.left = z +// else +// y.right = z // -// z.left = T.nil -// z.right = T.nil -// z.color = RED +// z.left = T.nil +// z.right = T.nil +// z.color = RED // -// RB-INSERT-FIXUP(T, z) +// RB-INSERT-FIXUP(T, z) // Insert adds a node with the given interval into the tree. -func (ivt *intervalTree) Insert(ivl Interval, val interface{}) { +func (ivt *intervalTree) Insert(ivl Interval, val any) { y := ivt.sentinel z := ivt.createIntervalNode(ivl, val) x := ivt.root @@ -532,7 +532,6 @@ func (ivt *intervalTree) Insert(ivl Interval, val interface{}) { func (ivt *intervalTree) insertFixup(z *intervalNode) { for z.parent.color(ivt.sentinel) == red { if z.parent == z.parent.parent.left { // line 3-15 - y := z.parent.parent.right if y.color(ivt.sentinel) == red { y.c = black diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/contention/contention.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/contention/contention.go index 26ce9a2f34..d883eb3de9 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/contention/contention.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/contention/contention.go @@ -27,8 +27,7 @@ import ( type TimeoutDetector struct { mu sync.Mutex // protects all maxDuration time.Duration - // map from event to time - // time is the last seen time of the event. + // map from event to last seen time of event. records map[uint64]time.Time } @@ -40,7 +39,7 @@ func NewTimeoutDetector(maxDuration time.Duration) *TimeoutDetector { } } -// Reset resets the NewTimeoutDetector. +// Reset resets the TimeoutDetector. func (td *TimeoutDetector) Reset() { td.mu.Lock() defer td.mu.Unlock() @@ -48,9 +47,11 @@ func (td *TimeoutDetector) Reset() { td.records = make(map[uint64]time.Time) } -// Observe observes an event for given id. It returns false and exceeded duration -// if the interval is longer than the expectation. -func (td *TimeoutDetector) Observe(which uint64) (bool, time.Duration) { +// Observe observes an event of given id. It computes +// the time elapsed between successive events of given id. +// It returns whether this time elapsed exceeds the expectation, +// and the amount by which it exceeds the expectation. +func (td *TimeoutDetector) Observe(id uint64) (bool, time.Duration) { td.mu.Lock() defer td.mu.Unlock() @@ -58,12 +59,12 @@ func (td *TimeoutDetector) Observe(which uint64) (bool, time.Duration) { now := time.Now() exceed := time.Duration(0) - if pt, found := td.records[which]; found { + if pt, found := td.records[id]; found { exceed = now.Sub(pt) - td.maxDuration if exceed > 0 { ok = false } } - td.records[which] = now + td.records[id] = now return ok, exceed } diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/cpuutil/endian.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/cpuutil/endian.go index 06c06cd4a5..d654b74766 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/cpuutil/endian.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/cpuutil/endian.go @@ -19,7 +19,7 @@ import ( "unsafe" ) -const intWidth int = int(unsafe.Sizeof(0)) +const intWidth = int(unsafe.Sizeof(0)) var byteOrder binary.ByteOrder @@ -27,7 +27,7 @@ var byteOrder binary.ByteOrder func ByteOrder() binary.ByteOrder { return byteOrder } func init() { - i := int(0x1) + i := 0x1 if v := (*[intWidth]byte)(unsafe.Pointer(&i)); v[0] == 0 { byteOrder = binary.BigEndian } else { diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/featuregate/feature_gate.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/featuregate/feature_gate.go new file mode 100644 index 0000000000..2f3eaf5585 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/featuregate/feature_gate.go @@ -0,0 +1,400 @@ +// Copyright 2024 The etcd 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 featuregate is copied from k8s.io/component-base@v0.30.1 to avoid any potential circular dependency between k8s and etcd. +package featuregate + +import ( + "flag" + "fmt" + "maps" + "sort" + "strconv" + "strings" + "sync" + "sync/atomic" + + "github.com/spf13/pflag" + "go.uber.org/zap" +) + +type Feature string + +const ( + defaultFlagName = "feature-gates" + + // allAlphaGate is a global toggle for alpha features. Per-feature key + // values override the default set by allAlphaGate. Examples: + // AllAlpha=false,NewFeature=true will result in newFeature=true + // AllAlpha=true,NewFeature=false will result in newFeature=false + allAlphaGate Feature = "AllAlpha" + + // allBetaGate is a global toggle for beta features. Per-feature key + // values override the default set by allBetaGate. Examples: + // AllBeta=false,NewFeature=true will result in NewFeature=true + // AllBeta=true,NewFeature=false will result in NewFeature=false + allBetaGate Feature = "AllBeta" +) + +var ( + // The generic features. + defaultFeatures = map[Feature]FeatureSpec{ + allAlphaGate: {Default: false, PreRelease: Alpha}, + allBetaGate: {Default: false, PreRelease: Beta}, + } + + // Special handling for a few gates. + specialFeatures = map[Feature]func(known map[Feature]FeatureSpec, enabled map[Feature]bool, val bool){ + allAlphaGate: setUnsetAlphaGates, + allBetaGate: setUnsetBetaGates, + } +) + +type FeatureSpec struct { + // Default is the default enablement state for the feature + Default bool + // LockToDefault indicates that the feature is locked to its default and cannot be changed + LockToDefault bool + // PreRelease indicates the maturity level of the feature + PreRelease prerelease +} + +type prerelease string + +const ( + // Values for PreRelease. + Alpha = prerelease("ALPHA") + Beta = prerelease("BETA") + GA = prerelease("") + + // Deprecated + Deprecated = prerelease("DEPRECATED") +) + +// FeatureGate indicates whether a given feature is enabled or not +type FeatureGate interface { + // Enabled returns true if the key is enabled. + Enabled(key Feature) bool + // KnownFeatures returns a slice of strings describing the FeatureGate's known features. + KnownFeatures() []string + // DeepCopy returns a deep copy of the FeatureGate object, such that gates can be + // set on the copy without mutating the original. This is useful for validating + // config against potential feature gate changes before committing those changes. + DeepCopy() MutableFeatureGate + // String returns a string containing all enabled feature gates, formatted as "key1=value1,key2=value2,...". + String() string +} + +// MutableFeatureGate parses and stores flag gates for known features from +// a string like feature1=true,feature2=false,... +type MutableFeatureGate interface { + FeatureGate + + // AddFlag adds a flag for setting global feature gates to the specified FlagSet. + AddFlag(fs *flag.FlagSet, flagName string) + // Set parses and stores flag gates for known features + // from a string like feature1=true,feature2=false,... + Set(value string) error + // SetFromMap stores flag gates for known features from a map[string]bool or returns an error + SetFromMap(m map[string]bool) error + // Add adds features to the featureGate. + Add(features map[Feature]FeatureSpec) error + // GetAll returns a copy of the map of known feature names to feature specs. + GetAll() map[Feature]FeatureSpec + // OverrideDefault sets a local override for the registered default value of a named + // feature. If the feature has not been previously registered (e.g. by a call to Add), has a + // locked default, or if the gate has already registered itself with a FlagSet, a non-nil + // error is returned. + // + // When two or more components consume a common feature, one component can override its + // default at runtime in order to adopt new defaults before or after the other + // components. For example, a new feature can be evaluated with a limited blast radius by + // overriding its default to true for a limited number of components without simultaneously + // changing its default for all consuming components. + OverrideDefault(name Feature, override bool) error +} + +// featureGate implements FeatureGate as well as pflag.Value for flag parsing. +type featureGate struct { + lg *zap.Logger + + featureGateName string + + special map[Feature]func(map[Feature]FeatureSpec, map[Feature]bool, bool) + + // lock guards writes to known, enabled, and reads/writes of closed + lock sync.Mutex + // known holds a map[Feature]FeatureSpec + known atomic.Value + // enabled holds a map[Feature]bool + enabled atomic.Value + // closed is set to true when AddFlag is called, and prevents subsequent calls to Add + closed bool +} + +func setUnsetAlphaGates(known map[Feature]FeatureSpec, enabled map[Feature]bool, val bool) { + for k, v := range known { + if v.PreRelease == Alpha { + if _, found := enabled[k]; !found { + enabled[k] = val + } + } + } +} + +func setUnsetBetaGates(known map[Feature]FeatureSpec, enabled map[Feature]bool, val bool) { + for k, v := range known { + if v.PreRelease == Beta { + if _, found := enabled[k]; !found { + enabled[k] = val + } + } + } +} + +// Set, String, and Type implement pflag.Value +var _ pflag.Value = &featureGate{} + +func New(name string, lg *zap.Logger) MutableFeatureGate { + if lg == nil { + lg = zap.NewNop() + } + known := maps.Clone(defaultFeatures) + + f := &featureGate{ + lg: lg, + featureGateName: name, + special: specialFeatures, + } + f.known.Store(known) + f.enabled.Store(map[Feature]bool{}) + + return f +} + +// Set parses a string of the form "key1=value1,key2=value2,..." into a +// map[string]bool of known keys or returns an error. +func (f *featureGate) Set(value string) error { + m := make(map[string]bool) + for _, s := range strings.Split(value, ",") { + if len(s) == 0 { + continue + } + arr := strings.SplitN(s, "=", 2) + k := strings.TrimSpace(arr[0]) + if len(arr) != 2 { + return fmt.Errorf("missing bool value for %s", k) + } + v := strings.TrimSpace(arr[1]) + boolValue, err := strconv.ParseBool(v) + if err != nil { + return fmt.Errorf("invalid value of %s=%s, err: %w", k, v, err) + } + m[k] = boolValue + } + return f.SetFromMap(m) +} + +// SetFromMap stores flag gates for known features from a map[string]bool or returns an error +func (f *featureGate) SetFromMap(m map[string]bool) error { + f.lock.Lock() + defer f.lock.Unlock() + + // Copy existing state + known := map[Feature]FeatureSpec{} + maps.Copy(known, f.known.Load().(map[Feature]FeatureSpec)) + enabled := map[Feature]bool{} + maps.Copy(enabled, f.enabled.Load().(map[Feature]bool)) + + for k, v := range m { + k := Feature(k) + featureSpec, ok := known[k] + if !ok { + return fmt.Errorf("unrecognized feature gate: %s", k) + } + if featureSpec.LockToDefault && featureSpec.Default != v { + return fmt.Errorf("cannot set feature gate %v to %v, feature is locked to %v", k, v, featureSpec.Default) + } + enabled[k] = v + // Handle "special" features like "all alpha gates" + if fn, found := f.special[k]; found { + fn(known, enabled, v) + } + + if featureSpec.PreRelease == Deprecated { + f.lg.Warn(fmt.Sprintf("Setting deprecated feature gate %s=%t. It will be removed in a future release.", k, v)) + } else if featureSpec.PreRelease == GA { + f.lg.Warn(fmt.Sprintf("Setting GA feature gate %s=%t. It will be removed in a future release.", k, v)) + } + } + + // Persist changes + f.known.Store(known) + f.enabled.Store(enabled) + + f.lg.Info(fmt.Sprintf("feature gates: %v", f.enabled)) + return nil +} + +// String returns a string containing all enabled feature gates, formatted as "key1=value1,key2=value2,...". +func (f *featureGate) String() string { + pairs := []string{} + for k, v := range f.enabled.Load().(map[Feature]bool) { + pairs = append(pairs, fmt.Sprintf("%s=%t", k, v)) + } + sort.Strings(pairs) + return strings.Join(pairs, ",") +} + +func (f *featureGate) Type() string { + return "mapStringBool" +} + +// Add adds features to the featureGate. +func (f *featureGate) Add(features map[Feature]FeatureSpec) error { + f.lock.Lock() + defer f.lock.Unlock() + + if f.closed { + return fmt.Errorf("cannot add a feature gate after adding it to the flag set") + } + + // Copy existing state + known := map[Feature]FeatureSpec{} + maps.Copy(known, f.known.Load().(map[Feature]FeatureSpec)) + + for name, spec := range features { + if existingSpec, found := known[name]; found { + if existingSpec == spec { + continue + } + return fmt.Errorf("feature gate %q with different spec already exists: %v", name, existingSpec) + } + + known[name] = spec + } + + // Persist updated state + f.known.Store(known) + + return nil +} + +func (f *featureGate) OverrideDefault(name Feature, override bool) error { + f.lock.Lock() + defer f.lock.Unlock() + + if f.closed { + return fmt.Errorf("cannot override default for feature %q: gates already added to a flag set", name) + } + + known := map[Feature]FeatureSpec{} + for name, spec := range f.known.Load().(map[Feature]FeatureSpec) { + known[name] = spec + } + + spec, ok := known[name] + switch { + case !ok: + return fmt.Errorf("cannot override default: feature %q is not registered", name) + case spec.LockToDefault: + return fmt.Errorf("cannot override default: feature %q default is locked to %t", name, spec.Default) + case spec.PreRelease == Deprecated: + f.lg.Warn(fmt.Sprintf("Overriding default of deprecated feature gate %s=%t. It will be removed in a future release.", name, override)) + case spec.PreRelease == GA: + f.lg.Warn(fmt.Sprintf("Overriding default of GA feature gate %s=%t. It will be removed in a future release.", name, override)) + } + + spec.Default = override + known[name] = spec + f.known.Store(known) + + return nil +} + +// GetAll returns a copy of the map of known feature names to feature specs. +func (f *featureGate) GetAll() map[Feature]FeatureSpec { + retval := map[Feature]FeatureSpec{} + maps.Copy(retval, f.known.Load().(map[Feature]FeatureSpec)) + return retval +} + +// Enabled returns true if the key is enabled. If the key is not known, this call will panic. +func (f *featureGate) Enabled(key Feature) bool { + if v, ok := f.enabled.Load().(map[Feature]bool)[key]; ok { + return v + } + if v, ok := f.known.Load().(map[Feature]FeatureSpec)[key]; ok { + return v.Default + } + + panic(fmt.Errorf("feature %q is not registered in FeatureGate %q", key, f.featureGateName)) +} + +// AddFlag adds a flag for setting global feature gates to the specified FlagSet. +func (f *featureGate) AddFlag(fs *flag.FlagSet, flagName string) { + if flagName == "" { + flagName = defaultFlagName + } + f.lock.Lock() + // TODO(mtaufen): Shouldn't we just close it on the first Set/SetFromMap instead? + // Not all components expose a feature gates flag using this AddFlag method, and + // in the future, all components will completely stop exposing a feature gates flag, + // in favor of componentconfig. + f.closed = true + f.lock.Unlock() + + known := f.KnownFeatures() + fs.Var(f, flagName, ""+ + "A set of key=value pairs that describe feature gates for alpha/experimental features. "+ + "Options are:\n"+strings.Join(known, "\n")) +} + +// KnownFeatures returns a slice of strings describing the FeatureGate's known features. +// Deprecated and GA features are hidden from the list. +func (f *featureGate) KnownFeatures() []string { + var known []string + for k, v := range f.known.Load().(map[Feature]FeatureSpec) { + if v.PreRelease == GA || v.PreRelease == Deprecated { + continue + } + known = append(known, fmt.Sprintf("%s=true|false (%s - default=%t)", k, v.PreRelease, v.Default)) + } + sort.Strings(known) + return known +} + +// DeepCopy returns a deep copy of the FeatureGate object, such that gates can be +// set on the copy without mutating the original. This is useful for validating +// config against potential feature gate changes before committing those changes. +func (f *featureGate) DeepCopy() MutableFeatureGate { + // Copy existing state. + known := map[Feature]FeatureSpec{} + maps.Copy(known, f.known.Load().(map[Feature]FeatureSpec)) + enabled := map[Feature]bool{} + maps.Copy(enabled, f.enabled.Load().(map[Feature]bool)) + + // Construct a new featureGate around the copied state. + // Note that specialFeatures is treated as immutable by convention, + // and we maintain the value of f.closed across the copy. + fg := &featureGate{ + special: specialFeatures, + closed: f.closed, + } + + fg.known.Store(known) + fg.enabled.Store(enabled) + + return fg +} diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/flag.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/flag.go index 76a51a8901..b48921c6dc 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/flag.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/flag.go @@ -19,6 +19,7 @@ import ( "flag" "fmt" "os" + "strconv" "strings" "github.com/spf13/pflag" @@ -66,7 +67,7 @@ func SetPflagsFromEnv(lg *zap.Logger, prefix string, fs *pflag.FlagSet) error { // FlagToEnv converts flag string to upper-case environment variable key string. func FlagToEnv(prefix, name string) string { - return prefix + "_" + strings.ToUpper(strings.Replace(name, "-", "_", -1)) + return prefix + "_" + strings.ToUpper(strings.ReplaceAll(name, "-", "_")) } func verifyEnv(lg *zap.Logger, prefix string, usedEnvKey, alreadySet map[string]bool) { @@ -107,7 +108,7 @@ func setFlagFromEnv(lg *zap.Logger, fs flagSetter, prefix, fname string, usedEnv if val != "" { usedEnvKey[key] = true if serr := fs.Set(fname, val); serr != nil { - return fmt.Errorf("invalid value %q for %s: %v", val, key, serr) + return fmt.Errorf("invalid value %q for %s: %w", val, key, serr) } if log && lg != nil { lg.Info( @@ -130,3 +131,16 @@ func IsSet(fs *flag.FlagSet, name string) bool { }) return set } + +// GetBoolFlagVal returns the value of the a given bool flag if it is explicitly set +// in the cmd line arguments, otherwise returns nil. +func GetBoolFlagVal(fs *flag.FlagSet, flagName string) (*bool, error) { + if !IsSet(fs, flagName) { + return nil, nil + } + flagVal, parseErr := strconv.ParseBool(fs.Lookup(flagName).Value.String()) + if parseErr != nil { + return nil, parseErr + } + return &flagVal, nil +} diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/selective_string.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/selective_string.go index 4b90fbf4b4..c0e4794a3f 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/selective_string.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/selective_string.go @@ -59,7 +59,7 @@ func (ss *SelectiveStringValue) Valids() []string { // valids[0] will be default value. Caller must be sure // len(valids) != 0 or it will panic. func NewSelectiveStringValue(valids ...string) *SelectiveStringValue { - vm := make(map[string]struct{}) + vm := make(map[string]struct{}, len(valids)) for _, v := range valids { vm[v] = struct{}{} } @@ -77,11 +77,10 @@ type SelectiveStringsValue struct { func (ss *SelectiveStringsValue) Set(s string) error { vs := strings.Split(s, ",") for i := range vs { - if _, ok := ss.valids[vs[i]]; ok { - ss.vs = append(ss.vs, vs[i]) - } else { + if _, ok := ss.valids[vs[i]]; !ok { return fmt.Errorf("invalid value %q", vs[i]) } + ss.vs = append(ss.vs, vs[i]) } sort.Strings(ss.vs) return nil @@ -106,7 +105,7 @@ func (ss *SelectiveStringsValue) Valids() []string { // for which any one of the given strings is a valid value, // and any other value is an error. func NewSelectiveStringsValue(valids ...string) *SelectiveStringsValue { - vm := make(map[string]struct{}) + vm := make(map[string]struct{}, len(valids)) for _, v := range valids { vm[v] = struct{}{} } diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/strings.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/strings.go index a80190658e..e3d131f790 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/strings.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/strings.go @@ -49,5 +49,5 @@ func NewStringsValue(s string) (ss *StringsValue) { // StringsFromFlag returns a string slice from the flag. func StringsFromFlag(fs *flag.FlagSet, flagName string) []string { - return []string(*fs.Lookup(flagName).Value.(*StringsValue)) + return *fs.Lookup(flagName).Value.(*StringsValue) } diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_strings.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_strings.go index e67af1f9b5..575516cb7e 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_strings.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/unique_strings.go @@ -31,8 +31,9 @@ type UniqueStringsValue struct { // Implements "flag.Value" interface. // The values are set in order. func (us *UniqueStringsValue) Set(s string) error { - us.Values = make(map[string]struct{}) - for _, v := range strings.Split(s, ",") { + values := strings.Split(s, ",") + us.Values = make(map[string]struct{}, len(values)) + for _, v := range values { us.Values[v] = struct{}{} } return nil diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/urls.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/urls.go index 885d32f457..27db58743b 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/urls.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/flags/urls.go @@ -62,5 +62,5 @@ func NewURLsValue(s string) *URLsValue { // URLsFromFlag returns a slices from url got from the flag. func URLsFromFlag(fs *flag.FlagSet, urlsFlagName string) []url.URL { - return []url.URL(*fs.Lookup(urlsFlagName).Value.(*URLsValue)) + return *fs.Lookup(urlsFlagName).Value.(*URLsValue) } diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/httputil/httputil.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/httputil/httputil.go index 3bf58a3a1d..41758138a4 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/httputil/httputil.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/httputil/httputil.go @@ -21,7 +21,6 @@ package httputil import ( "io" - "io/ioutil" "net" "net/http" ) @@ -31,7 +30,7 @@ import ( // therefore available for reuse. // Borrowed from golang/net/context/ctxhttp/cancelreq.go. func GracefulClose(resp *http.Response) { - io.Copy(ioutil.Discard, resp.Body) + io.Copy(io.Discard, resp.Body) resp.Body.Close() } diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/ioutil/pagewriter.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/ioutil/pagewriter.go index 62eb5cd43e..ebab6487e0 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/ioutil/pagewriter.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/ioutil/pagewriter.go @@ -15,8 +15,9 @@ package ioutil import ( - "fmt" "io" + + "go.etcd.io/etcd/client/pkg/v3/verify" ) var defaultBufferBytes = 128 * 1024 @@ -42,9 +43,7 @@ type PageWriter struct { // NewPageWriter creates a new PageWriter. pageBytes is the number of bytes // to write per page. pageOffset is the starting offset of io.Writer. func NewPageWriter(w io.Writer, pageBytes, pageOffset int) *PageWriter { - if pageBytes <= 0 { - panic(fmt.Sprintf("assertion failed: invalid pageBytes (%d) value, it must be greater than 0", pageBytes)) - } + verify.Assert(pageBytes > 0, "invalid pageBytes (%d) value, it must be greater than 0", pageBytes) return &PageWriter{ w: w, pageOffset: pageOffset, @@ -105,11 +104,6 @@ func (pw *PageWriter) Flush() error { return err } -// FlushN flushes buffered data and returns the number of written bytes. -func (pw *PageWriter) FlushN() (int, error) { - return pw.flush() -} - func (pw *PageWriter) flush() (int, error) { if pw.bufferedBytes == 0 { return 0, nil diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/netutil.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/netutil.go index 689927b4c6..0f1a685855 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/netutil.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/netutil.go @@ -16,6 +16,7 @@ package netutil import ( "context" + "errors" "fmt" "net" "net/url" @@ -23,9 +24,9 @@ import ( "sort" "time" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/types" ) // indirection for testing @@ -70,14 +71,14 @@ func resolveTCPAddrs(ctx context.Context, lg *zap.Logger, urls [][]url.URL) ([][ for i, u := range us { nu, err := url.Parse(u.String()) if err != nil { - return nil, fmt.Errorf("failed to parse %q (%v)", u.String(), err) + return nil, fmt.Errorf("failed to parse %q (%w)", u.String(), err) } nus[i] = *nu } for i, u := range nus { h, err := resolveURL(ctx, lg, u) if err != nil { - return nil, fmt.Errorf("failed to resolve %q (%v)", u.String(), err) + return nil, fmt.Errorf("failed to resolve %q (%w)", u.String(), err) } if h != "" { nus[i].Host = h @@ -217,6 +218,6 @@ func stringsToURLs(us []string) ([]url.URL, error) { } func IsNetworkTimeoutError(err error) bool { - nerr, ok := err.(net.Error) - return ok && nerr.Timeout() + var nerr net.Error + return errors.As(err, &nerr) && nerr.Timeout() } diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes.go index f66719ea16..a7d67df3d4 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !linux -// +build !linux package netutil diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes_linux.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes_linux.go index 5f8bd0c488..b00ce457ec 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes_linux.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/netutil/routes_linux.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build linux -// +build linux package netutil @@ -22,15 +21,17 @@ import ( "encoding/binary" "fmt" "net" - "sort" + "slices" "syscall" "go.etcd.io/etcd/pkg/v3/cpuutil" ) -var errNoDefaultRoute = fmt.Errorf("could not find default route") -var errNoDefaultHost = fmt.Errorf("could not find default host") -var errNoDefaultInterface = fmt.Errorf("could not find default interface") +var ( + errNoDefaultRoute = fmt.Errorf("could not find default route") + errNoDefaultHost = fmt.Errorf("could not find default host") + errNoDefaultInterface = fmt.Errorf("could not find default interface") +) // GetDefaultHost obtains the first IP address of machine from the routing table and returns the IP address as string. // An IPv4 address is preferred to an IPv6 address for backward compatibility. @@ -49,14 +50,13 @@ func GetDefaultHost() (string, error) { } // sort so choice is deterministic - var families []int + var families []uint8 for family := range rmsgs { - families = append(families, int(family)) + families = append(families, family) } - sort.Ints(families) + slices.Sort(families) - for _, f := range families { - family := uint8(f) + for _, family := range families { if host, err := chooseHost(family, rmsgs[family]); host != "" || err != nil { return host, err } @@ -154,7 +154,6 @@ func getIfaceAddr(idx uint32, family uint8) (*syscall.NetlinkMessage, error) { } return nil, fmt.Errorf("could not find address for interface index %v", idx) - } // Used to get a name of interface. diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/notify/notify.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/notify/notify.go new file mode 100644 index 0000000000..8925a1ea21 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/notify/notify.go @@ -0,0 +1,52 @@ +// Copyright 2021 The etcd 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 notify + +import ( + "sync" +) + +// Notifier is a thread safe struct that can be used to send notification about +// some event to multiple consumers. +type Notifier struct { + mu sync.RWMutex + channel chan struct{} +} + +// NewNotifier returns new notifier +func NewNotifier() *Notifier { + return &Notifier{ + channel: make(chan struct{}), + } +} + +// Receive returns channel that can be used to wait for notification. +// Consumers will be informed by closing the channel. +func (n *Notifier) Receive() <-chan struct{} { + n.mu.RLock() + defer n.mu.RUnlock() + return n.channel +} + +// Notify closes the channel passed to consumers and creates new channel to used +// for next notification. +func (n *Notifier) Notify() { + newChannel := make(chan struct{}) + n.mu.Lock() + channelToClose := n.channel + n.channel = newChannel + n.mu.Unlock() + close(channelToClose) +} diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/runtime/fds_other.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/runtime/fds_other.go index 034f3d4264..2311bb1972 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/runtime/fds_other.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/runtime/fds_other.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !linux -// +build !linux package runtime diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/schedule/schedule.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/schedule/schedule.go index 234d01989d..06a243df91 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/schedule/schedule.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/schedule/schedule.go @@ -17,9 +17,36 @@ package schedule import ( "context" "sync" + + "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/verify" ) -type Job func(context.Context) +type Job interface { + Name() string + Do(context.Context) +} + +type job struct { + name string + do func(context.Context) +} + +func (j job) Name() string { + return j.name +} + +func (j job) Do(ctx context.Context) { + j.do(ctx) +} + +func NewJob(name string, do func(ctx context.Context)) Job { + return job{ + name: name, + do: do, + } +} // Scheduler can schedule jobs. type Scheduler interface { @@ -56,14 +83,18 @@ type fifo struct { finishCond *sync.Cond donec chan struct{} + lg *zap.Logger } // NewFIFOScheduler returns a Scheduler that schedules jobs in FIFO // order sequentially -func NewFIFOScheduler() Scheduler { +func NewFIFOScheduler(lg *zap.Logger) Scheduler { + verify.Assert(lg != nil, "the logger should not be nil") + f := &fifo{ resume: make(chan struct{}, 1), donec: make(chan struct{}, 1), + lg: lg, } f.finishCond = sync.NewCond(&f.mu) f.ctx, f.cancel = context.WithCancel(context.Background()) @@ -125,7 +156,6 @@ func (f *fifo) Stop() { } func (f *fifo) run() { - // TODO: recover from job panic? defer func() { close(f.donec) close(f.resume) @@ -149,17 +179,29 @@ func (f *fifo) run() { f.mu.Unlock() // clean up pending jobs for _, todo := range pendings { - todo(f.ctx) + f.executeJob(todo, true) } return } } else { - todo(f.ctx) + f.executeJob(todo, false) + } + } +} + +func (f *fifo) executeJob(todo Job, updatedFinishedStats bool) { + defer func() { + if !updatedFinishedStats { f.finishCond.L.Lock() f.finished++ f.pendings = f.pendings[1:] f.finishCond.Broadcast() f.finishCond.L.Unlock() } - } + if err := recover(); err != nil { + f.lg.Panic("execute job failed", zap.String("job", todo.Name()), zap.Any("panic", err)) + } + }() + + todo.Do(f.ctx) } diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/traceutil/trace.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/traceutil/trace.go index bdd8e9b66a..abf5cf1d22 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/traceutil/trace.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/traceutil/trace.go @@ -16,24 +16,25 @@ package traceutil import ( - "bytes" "context" "fmt" "math/rand" + "strings" "time" "go.uber.org/zap" ) -const ( - TraceKey = "trace" - StartTimeKey = "startTime" -) +// TraceKey is used as a key of context for Trace. +type TraceKey struct{} + +// StartTimeKey is used as a key of context for start time of operation. +type StartTimeKey struct{} // Field is a kv pair to record additional details of the trace. type Field struct { Key string - Value interface{} + Value any } func (f *Field) format() string { @@ -44,7 +45,7 @@ func writeFields(fields []Field) string { if len(fields) == 0 { return "" } - var buf bytes.Buffer + var buf strings.Builder buf.WriteString("{") for _, f := range fields { buf.WriteString(f.format()) @@ -81,7 +82,7 @@ func TODO() *Trace { } func Get(ctx context.Context) *Trace { - if trace, ok := ctx.Value(TraceKey).(*Trace); ok && trace != nil { + if trace, ok := ctx.Value(TraceKey{}).(*Trace); ok && trace != nil { return trace } return TODO() @@ -181,41 +182,43 @@ func (t *Trace) logInfo(threshold time.Duration) (string, []zap.Field) { var steps []string lastStepTime := t.startTime for i := 0; i < len(t.steps); i++ { - step := t.steps[i] + tstep := t.steps[i] // add subtrace common fields which defined at the beginning to each sub-steps - if step.isSubTraceStart { + if tstep.isSubTraceStart { for j := i + 1; j < len(t.steps) && !t.steps[j].isSubTraceEnd; j++ { - t.steps[j].fields = append(step.fields, t.steps[j].fields...) + t.steps[j].fields = append(tstep.fields, t.steps[j].fields...) } continue } // add subtrace common fields which defined at the end to each sub-steps - if step.isSubTraceEnd { + if tstep.isSubTraceEnd { for j := i - 1; j >= 0 && !t.steps[j].isSubTraceStart; j-- { - t.steps[j].fields = append(step.fields, t.steps[j].fields...) + t.steps[j].fields = append(tstep.fields, t.steps[j].fields...) } continue } } for i := 0; i < len(t.steps); i++ { - step := t.steps[i] - if step.isSubTraceStart || step.isSubTraceEnd { + tstep := t.steps[i] + if tstep.isSubTraceStart || tstep.isSubTraceEnd { continue } - stepDuration := step.time.Sub(lastStepTime) + stepDuration := tstep.time.Sub(lastStepTime) if stepDuration > threshold { steps = append(steps, fmt.Sprintf("trace[%d] '%v' %s (duration: %v)", - traceNum, step.msg, writeFields(step.fields), stepDuration)) + traceNum, tstep.msg, writeFields(tstep.fields), stepDuration)) } - lastStepTime = step.time + lastStepTime = tstep.time } - fs := []zap.Field{zap.String("detail", writeFields(t.fields)), + fs := []zap.Field{ + zap.String("detail", writeFields(t.fields)), zap.Duration("duration", totalDuration), zap.Time("start", t.startTime), zap.Time("end", endTime), zap.Strings("steps", steps), - zap.Int("step_count", len(steps))} + zap.Int("step_count", len(steps)), + } return msg, fs } diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/wait/wait.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/wait/wait.go index a3e2aec7cb..8989f32d57 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/wait/wait.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/wait/wait.go @@ -34,9 +34,9 @@ type Wait interface { // Register waits returns a chan that waits on the given ID. // The chan will be triggered when Trigger is called with // the same ID. - Register(id uint64) <-chan interface{} + Register(id uint64) <-chan any // Trigger triggers the waiting chans with the given ID. - Trigger(id uint64, x interface{}) + Trigger(id uint64, x any) IsRegistered(id uint64) bool } @@ -46,7 +46,7 @@ type list struct { type listElement struct { l sync.RWMutex - m map[uint64]chan interface{} + m map[uint64]chan any } // New creates a Wait. @@ -55,14 +55,14 @@ func New() Wait { e: make([]listElement, defaultListElementLength), } for i := 0; i < len(res.e); i++ { - res.e[i].m = make(map[uint64]chan interface{}) + res.e[i].m = make(map[uint64]chan any) } return &res } -func (w *list) Register(id uint64) <-chan interface{} { +func (w *list) Register(id uint64) <-chan any { idx := id % defaultListElementLength - newCh := make(chan interface{}, 1) + newCh := make(chan any, 1) w.e[idx].l.Lock() defer w.e[idx].l.Unlock() if _, ok := w.e[idx].m[id]; !ok { @@ -73,7 +73,7 @@ func (w *list) Register(id uint64) <-chan interface{} { return newCh } -func (w *list) Trigger(id uint64, x interface{}) { +func (w *list) Trigger(id uint64, x any) { idx := id % defaultListElementLength w.e[idx].l.Lock() ch := w.e[idx].m[id] @@ -94,17 +94,17 @@ func (w *list) IsRegistered(id uint64) bool { } type waitWithResponse struct { - ch <-chan interface{} + ch <-chan any } -func NewWithResponse(ch <-chan interface{}) Wait { +func NewWithResponse(ch <-chan any) Wait { return &waitWithResponse{ch: ch} } -func (w *waitWithResponse) Register(id uint64) <-chan interface{} { +func (w *waitWithResponse) Register(id uint64) <-chan any { return w.ch } -func (w *waitWithResponse) Trigger(id uint64, x interface{}) {} +func (w *waitWithResponse) Trigger(id uint64, x any) {} func (w *waitWithResponse) IsRegistered(id uint64) bool { panic("waitWithResponse.IsRegistered() shouldn't be called") } diff --git a/etcd/vendor/go.etcd.io/etcd/pkg/v3/wait/wait_time.go b/etcd/vendor/go.etcd.io/etcd/pkg/v3/wait/wait_time.go index 297e48a47d..131788959e 100644 --- a/etcd/vendor/go.etcd.io/etcd/pkg/v3/wait/wait_time.go +++ b/etcd/vendor/go.etcd.io/etcd/pkg/v3/wait/wait_time.go @@ -19,9 +19,9 @@ import "sync" type WaitTime interface { // Wait returns a chan that waits on the given logical deadline. // The chan will be triggered when Trigger is called with a - // deadline that is later than the one it is waiting for. + // deadline that is later than or equal to the one it is waiting for. Wait(deadline uint64) <-chan struct{} - // Trigger triggers all the waiting chans with an earlier logical deadline. + // Trigger triggers all the waiting chans with an equal or earlier logical deadline. Trigger(deadline uint64) } diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/LICENSE b/etcd/vendor/go.etcd.io/etcd/raft/v3/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/OWNERS b/etcd/vendor/go.etcd.io/etcd/raft/v3/OWNERS deleted file mode 100644 index 35fc8f6871..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/OWNERS +++ /dev/null @@ -1,5 +0,0 @@ -approvers: - - hexfusion - - smarterclayton -reviewers: - - hexfusion diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/log.go b/etcd/vendor/go.etcd.io/etcd/raft/v3/log.go deleted file mode 100644 index c94c41f778..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/log.go +++ /dev/null @@ -1,406 +0,0 @@ -// Copyright 2015 The etcd 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 raft - -import ( - "fmt" - "log" - - pb "go.etcd.io/etcd/raft/v3/raftpb" -) - -type raftLog struct { - // storage contains all stable entries since the last snapshot. - storage Storage - - // unstable contains all unstable entries and snapshot. - // they will be saved into storage. - unstable unstable - - // committed is the highest log position that is known to be in - // stable storage on a quorum of nodes. - committed uint64 - // applied is the highest log position that the application has - // been instructed to apply to its state machine. - // Invariant: applied <= committed - applied uint64 - - logger Logger - - // maxNextEntsSize is the maximum number aggregate byte size of the messages - // returned from calls to nextEnts. - maxNextEntsSize uint64 -} - -// newLog returns log using the given storage and default options. It -// recovers the log to the state that it just commits and applies the -// latest snapshot. -func newLog(storage Storage, logger Logger) *raftLog { - return newLogWithSize(storage, logger, noLimit) -} - -// newLogWithSize returns a log using the given storage and max -// message size. -func newLogWithSize(storage Storage, logger Logger, maxNextEntsSize uint64) *raftLog { - if storage == nil { - log.Panic("storage must not be nil") - } - log := &raftLog{ - storage: storage, - logger: logger, - maxNextEntsSize: maxNextEntsSize, - } - firstIndex, err := storage.FirstIndex() - if err != nil { - panic(err) // TODO(bdarnell) - } - lastIndex, err := storage.LastIndex() - if err != nil { - panic(err) // TODO(bdarnell) - } - log.unstable.offset = lastIndex + 1 - log.unstable.logger = logger - // Initialize our committed and applied pointers to the time of the last compaction. - log.committed = firstIndex - 1 - log.applied = firstIndex - 1 - - return log -} - -func (l *raftLog) String() string { - return fmt.Sprintf("committed=%d, applied=%d, unstable.offset=%d, len(unstable.Entries)=%d", l.committed, l.applied, l.unstable.offset, len(l.unstable.entries)) -} - -// maybeAppend returns (0, false) if the entries cannot be appended. Otherwise, -// it returns (last index of new entries, true). -func (l *raftLog) maybeAppend(index, logTerm, committed uint64, ents ...pb.Entry) (lastnewi uint64, ok bool) { - if l.matchTerm(index, logTerm) { - lastnewi = index + uint64(len(ents)) - ci := l.findConflict(ents) - switch { - case ci == 0: - case ci <= l.committed: - l.logger.Panicf("entry %d conflict with committed entry [committed(%d)]", ci, l.committed) - default: - offset := index + 1 - l.append(ents[ci-offset:]...) - } - l.commitTo(min(committed, lastnewi)) - return lastnewi, true - } - return 0, false -} - -func (l *raftLog) append(ents ...pb.Entry) uint64 { - if len(ents) == 0 { - return l.lastIndex() - } - if after := ents[0].Index - 1; after < l.committed { - l.logger.Panicf("after(%d) is out of range [committed(%d)]", after, l.committed) - } - l.unstable.truncateAndAppend(ents) - return l.lastIndex() -} - -// findConflict finds the index of the conflict. -// It returns the first pair of conflicting entries between the existing -// entries and the given entries, if there are any. -// If there is no conflicting entries, and the existing entries contains -// all the given entries, zero will be returned. -// If there is no conflicting entries, but the given entries contains new -// entries, the index of the first new entry will be returned. -// An entry is considered to be conflicting if it has the same index but -// a different term. -// The index of the given entries MUST be continuously increasing. -func (l *raftLog) findConflict(ents []pb.Entry) uint64 { - for _, ne := range ents { - if !l.matchTerm(ne.Index, ne.Term) { - if ne.Index <= l.lastIndex() { - l.logger.Infof("found conflict at index %d [existing term: %d, conflicting term: %d]", - ne.Index, l.zeroTermOnErrCompacted(l.term(ne.Index)), ne.Term) - } - return ne.Index - } - } - return 0 -} - -// findConflictByTerm takes an (index, term) pair (indicating a conflicting log -// entry on a leader/follower during an append) and finds the largest index in -// log l with a term <= `term` and an index <= `index`. If no such index exists -// in the log, the log's first index is returned. -// -// The index provided MUST be equal to or less than l.lastIndex(). Invalid -// inputs log a warning and the input index is returned. -func (l *raftLog) findConflictByTerm(index uint64, term uint64) uint64 { - if li := l.lastIndex(); index > li { - // NB: such calls should not exist, but since there is a straightfoward - // way to recover, do it. - // - // It is tempting to also check something about the first index, but - // there is odd behavior with peers that have no log, in which case - // lastIndex will return zero and firstIndex will return one, which - // leads to calls with an index of zero into this method. - l.logger.Warningf("index(%d) is out of range [0, lastIndex(%d)] in findConflictByTerm", - index, li) - return index - } - for { - logTerm, err := l.term(index) - if logTerm <= term || err != nil { - break - } - index-- - } - return index -} - -func (l *raftLog) unstableEntries() []pb.Entry { - if len(l.unstable.entries) == 0 { - return nil - } - return l.unstable.entries -} - -// nextEnts returns all the available entries for execution. -// If applied is smaller than the index of snapshot, it returns all committed -// entries after the index of snapshot. -func (l *raftLog) nextEnts() (ents []pb.Entry) { - off := max(l.applied+1, l.firstIndex()) - if l.committed+1 > off { - ents, err := l.slice(off, l.committed+1, l.maxNextEntsSize) - if err != nil { - l.logger.Panicf("unexpected error when getting unapplied entries (%v)", err) - } - return ents - } - return nil -} - -// hasNextEnts returns if there is any available entries for execution. This -// is a fast check without heavy raftLog.slice() in raftLog.nextEnts(). -func (l *raftLog) hasNextEnts() bool { - off := max(l.applied+1, l.firstIndex()) - return l.committed+1 > off -} - -// hasPendingSnapshot returns if there is pending snapshot waiting for applying. -func (l *raftLog) hasPendingSnapshot() bool { - return l.unstable.snapshot != nil && !IsEmptySnap(*l.unstable.snapshot) -} - -func (l *raftLog) snapshot() (pb.Snapshot, error) { - if l.unstable.snapshot != nil { - return *l.unstable.snapshot, nil - } - return l.storage.Snapshot() -} - -func (l *raftLog) firstIndex() uint64 { - if i, ok := l.unstable.maybeFirstIndex(); ok { - return i - } - index, err := l.storage.FirstIndex() - if err != nil { - panic(err) // TODO(bdarnell) - } - return index -} - -func (l *raftLog) lastIndex() uint64 { - if i, ok := l.unstable.maybeLastIndex(); ok { - return i - } - i, err := l.storage.LastIndex() - if err != nil { - panic(err) // TODO(bdarnell) - } - return i -} - -func (l *raftLog) commitTo(tocommit uint64) { - // never decrease commit - if l.committed < tocommit { - if l.lastIndex() < tocommit { - l.logger.Panicf("tocommit(%d) is out of range [lastIndex(%d)]. Was the raft log corrupted, truncated, or lost?", tocommit, l.lastIndex()) - } - l.committed = tocommit - } -} - -func (l *raftLog) appliedTo(i uint64) { - if i == 0 { - return - } - if l.committed < i || i < l.applied { - l.logger.Panicf("applied(%d) is out of range [prevApplied(%d), committed(%d)]", i, l.applied, l.committed) - } - l.applied = i -} - -func (l *raftLog) stableTo(i, t uint64) { l.unstable.stableTo(i, t) } - -func (l *raftLog) stableSnapTo(i uint64) { l.unstable.stableSnapTo(i) } - -func (l *raftLog) lastTerm() uint64 { - t, err := l.term(l.lastIndex()) - if err != nil { - l.logger.Panicf("unexpected error when getting the last term (%v)", err) - } - return t -} - -func (l *raftLog) term(i uint64) (uint64, error) { - // the valid term range is [index of dummy entry, last index] - dummyIndex := l.firstIndex() - 1 - if i < dummyIndex || i > l.lastIndex() { - // TODO: return an error instead? - return 0, nil - } - - if t, ok := l.unstable.maybeTerm(i); ok { - return t, nil - } - - t, err := l.storage.Term(i) - if err == nil { - return t, nil - } - if err == ErrCompacted || err == ErrUnavailable { - return 0, err - } - panic(err) // TODO(bdarnell) -} - -func (l *raftLog) entries(i, maxsize uint64) ([]pb.Entry, error) { - if i > l.lastIndex() { - return nil, nil - } - return l.slice(i, l.lastIndex()+1, maxsize) -} - -// allEntries returns all entries in the log. -func (l *raftLog) allEntries() []pb.Entry { - ents, err := l.entries(l.firstIndex(), noLimit) - if err == nil { - return ents - } - if err == ErrCompacted { // try again if there was a racing compaction - return l.allEntries() - } - // TODO (xiangli): handle error? - panic(err) -} - -// isUpToDate determines if the given (lastIndex,term) log is more up-to-date -// by comparing the index and term of the last entries in the existing logs. -// If the logs have last entries with different terms, then the log with the -// later term is more up-to-date. If the logs end with the same term, then -// whichever log has the larger lastIndex is more up-to-date. If the logs are -// the same, the given log is up-to-date. -func (l *raftLog) isUpToDate(lasti, term uint64) bool { - return term > l.lastTerm() || (term == l.lastTerm() && lasti >= l.lastIndex()) -} - -func (l *raftLog) matchTerm(i, term uint64) bool { - t, err := l.term(i) - if err != nil { - return false - } - return t == term -} - -func (l *raftLog) maybeCommit(maxIndex, term uint64) bool { - if maxIndex > l.committed && l.zeroTermOnErrCompacted(l.term(maxIndex)) == term { - l.commitTo(maxIndex) - return true - } - return false -} - -func (l *raftLog) restore(s pb.Snapshot) { - l.logger.Infof("log [%s] starts to restore snapshot [index: %d, term: %d]", l, s.Metadata.Index, s.Metadata.Term) - l.committed = s.Metadata.Index - l.unstable.restore(s) -} - -// slice returns a slice of log entries from lo through hi-1, inclusive. -func (l *raftLog) slice(lo, hi, maxSize uint64) ([]pb.Entry, error) { - err := l.mustCheckOutOfBounds(lo, hi) - if err != nil { - return nil, err - } - if lo == hi { - return nil, nil - } - var ents []pb.Entry - if lo < l.unstable.offset { - storedEnts, err := l.storage.Entries(lo, min(hi, l.unstable.offset), maxSize) - if err == ErrCompacted { - return nil, err - } else if err == ErrUnavailable { - l.logger.Panicf("entries[%d:%d) is unavailable from storage", lo, min(hi, l.unstable.offset)) - } else if err != nil { - panic(err) // TODO(bdarnell) - } - - // check if ents has reached the size limitation - if uint64(len(storedEnts)) < min(hi, l.unstable.offset)-lo { - return storedEnts, nil - } - - ents = storedEnts - } - if hi > l.unstable.offset { - unstable := l.unstable.slice(max(lo, l.unstable.offset), hi) - if len(ents) > 0 { - combined := make([]pb.Entry, len(ents)+len(unstable)) - n := copy(combined, ents) - copy(combined[n:], unstable) - ents = combined - } else { - ents = unstable - } - } - return limitSize(ents, maxSize), nil -} - -// l.firstIndex <= lo <= hi <= l.firstIndex + len(l.entries) -func (l *raftLog) mustCheckOutOfBounds(lo, hi uint64) error { - if lo > hi { - l.logger.Panicf("invalid slice %d > %d", lo, hi) - } - fi := l.firstIndex() - if lo < fi { - return ErrCompacted - } - - length := l.lastIndex() + 1 - fi - if hi > fi+length { - l.logger.Panicf("slice[%d,%d) out of bound [%d,%d]", lo, hi, fi, l.lastIndex()) - } - return nil -} - -func (l *raftLog) zeroTermOnErrCompacted(t uint64, err error) uint64 { - if err == nil { - return t - } - if err == ErrCompacted { - return 0 - } - l.logger.Panicf("unexpected error (%v)", err) - return 0 -} diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/log_unstable.go b/etcd/vendor/go.etcd.io/etcd/raft/v3/log_unstable.go deleted file mode 100644 index 230fd21f99..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/log_unstable.go +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2015 The etcd 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 raft - -import pb "go.etcd.io/etcd/raft/v3/raftpb" - -// unstable.entries[i] has raft log position i+unstable.offset. -// Note that unstable.offset may be less than the highest log -// position in storage; this means that the next write to storage -// might need to truncate the log before persisting unstable.entries. -type unstable struct { - // the incoming unstable snapshot, if any. - snapshot *pb.Snapshot - // all entries that have not yet been written to storage. - entries []pb.Entry - offset uint64 - - logger Logger -} - -// maybeFirstIndex returns the index of the first possible entry in entries -// if it has a snapshot. -func (u *unstable) maybeFirstIndex() (uint64, bool) { - if u.snapshot != nil { - return u.snapshot.Metadata.Index + 1, true - } - return 0, false -} - -// maybeLastIndex returns the last index if it has at least one -// unstable entry or snapshot. -func (u *unstable) maybeLastIndex() (uint64, bool) { - if l := len(u.entries); l != 0 { - return u.offset + uint64(l) - 1, true - } - if u.snapshot != nil { - return u.snapshot.Metadata.Index, true - } - return 0, false -} - -// maybeTerm returns the term of the entry at index i, if there -// is any. -func (u *unstable) maybeTerm(i uint64) (uint64, bool) { - if i < u.offset { - if u.snapshot != nil && u.snapshot.Metadata.Index == i { - return u.snapshot.Metadata.Term, true - } - return 0, false - } - - last, ok := u.maybeLastIndex() - if !ok { - return 0, false - } - if i > last { - return 0, false - } - - return u.entries[i-u.offset].Term, true -} - -func (u *unstable) stableTo(i, t uint64) { - gt, ok := u.maybeTerm(i) - if !ok { - return - } - // if i < offset, term is matched with the snapshot - // only update the unstable entries if term is matched with - // an unstable entry. - if gt == t && i >= u.offset { - u.entries = u.entries[i+1-u.offset:] - u.offset = i + 1 - u.shrinkEntriesArray() - } -} - -// shrinkEntriesArray discards the underlying array used by the entries slice -// if most of it isn't being used. This avoids holding references to a bunch of -// potentially large entries that aren't needed anymore. Simply clearing the -// entries wouldn't be safe because clients might still be using them. -func (u *unstable) shrinkEntriesArray() { - // We replace the array if we're using less than half of the space in - // it. This number is fairly arbitrary, chosen as an attempt to balance - // memory usage vs number of allocations. It could probably be improved - // with some focused tuning. - const lenMultiple = 2 - if len(u.entries) == 0 { - u.entries = nil - } else if len(u.entries)*lenMultiple < cap(u.entries) { - newEntries := make([]pb.Entry, len(u.entries)) - copy(newEntries, u.entries) - u.entries = newEntries - } -} - -func (u *unstable) stableSnapTo(i uint64) { - if u.snapshot != nil && u.snapshot.Metadata.Index == i { - u.snapshot = nil - } -} - -func (u *unstable) restore(s pb.Snapshot) { - u.offset = s.Metadata.Index + 1 - u.entries = nil - u.snapshot = &s -} - -func (u *unstable) truncateAndAppend(ents []pb.Entry) { - after := ents[0].Index - switch { - case after == u.offset+uint64(len(u.entries)): - // after is the next index in the u.entries - // directly append - u.entries = append(u.entries, ents...) - case after <= u.offset: - u.logger.Infof("replace the unstable entries from index %d", after) - // The log is being truncated to before our current offset - // portion, so set the offset and replace the entries - u.offset = after - u.entries = ents - default: - // truncate to after and copy to u.entries - // then append - u.logger.Infof("truncate the unstable entries before index %d", after) - u.entries = append([]pb.Entry{}, u.slice(u.offset, after)...) - u.entries = append(u.entries, ents...) - } -} - -func (u *unstable) slice(lo uint64, hi uint64) []pb.Entry { - u.mustCheckOutOfBounds(lo, hi) - return u.entries[lo-u.offset : hi-u.offset] -} - -// u.offset <= lo <= hi <= u.offset+len(u.entries) -func (u *unstable) mustCheckOutOfBounds(lo, hi uint64) { - if lo > hi { - u.logger.Panicf("invalid unstable.slice %d > %d", lo, hi) - } - upper := u.offset + uint64(len(u.entries)) - if lo < u.offset || hi > upper { - u.logger.Panicf("unstable.slice[%d,%d) out of bound [%d,%d]", lo, hi, u.offset, upper) - } -} diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/rawnode.go b/etcd/vendor/go.etcd.io/etcd/raft/v3/rawnode.go deleted file mode 100644 index 4111d029dd..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/rawnode.go +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright 2015 The etcd 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 raft - -import ( - "errors" - - pb "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/raft/v3/tracker" -) - -// ErrStepLocalMsg is returned when try to step a local raft message -var ErrStepLocalMsg = errors.New("raft: cannot step raft local message") - -// ErrStepPeerNotFound is returned when try to step a response message -// but there is no peer found in raft.prs for that node. -var ErrStepPeerNotFound = errors.New("raft: cannot step as peer not found") - -// RawNode is a thread-unsafe Node. -// The methods of this struct correspond to the methods of Node and are described -// more fully there. -type RawNode struct { - raft *raft - prevSoftSt *SoftState - prevHardSt pb.HardState -} - -// NewRawNode instantiates a RawNode from the given configuration. -// -// See Bootstrap() for bootstrapping an initial state; this replaces the former -// 'peers' argument to this method (with identical behavior). However, It is -// recommended that instead of calling Bootstrap, applications bootstrap their -// state manually by setting up a Storage that has a first index > 1 and which -// stores the desired ConfState as its InitialState. -func NewRawNode(config *Config) (*RawNode, error) { - r := newRaft(config) - rn := &RawNode{ - raft: r, - } - rn.prevSoftSt = r.softState() - rn.prevHardSt = r.hardState() - return rn, nil -} - -// Tick advances the internal logical clock by a single tick. -func (rn *RawNode) Tick() { - rn.raft.tick() -} - -// TickQuiesced advances the internal logical clock by a single tick without -// performing any other state machine processing. It allows the caller to avoid -// periodic heartbeats and elections when all of the peers in a Raft group are -// known to be at the same state. Expected usage is to periodically invoke Tick -// or TickQuiesced depending on whether the group is "active" or "quiesced". -// -// WARNING: Be very careful about using this method as it subverts the Raft -// state machine. You should probably be using Tick instead. -func (rn *RawNode) TickQuiesced() { - rn.raft.electionElapsed++ -} - -// Campaign causes this RawNode to transition to candidate state. -func (rn *RawNode) Campaign() error { - return rn.raft.Step(pb.Message{ - Type: pb.MsgHup, - }) -} - -// Propose proposes data be appended to the raft log. -func (rn *RawNode) Propose(data []byte) error { - return rn.raft.Step(pb.Message{ - Type: pb.MsgProp, - From: rn.raft.id, - Entries: []pb.Entry{ - {Data: data}, - }}) -} - -// ProposeConfChange proposes a config change. See (Node).ProposeConfChange for -// details. -func (rn *RawNode) ProposeConfChange(cc pb.ConfChangeI) error { - m, err := confChangeToMsg(cc) - if err != nil { - return err - } - return rn.raft.Step(m) -} - -// ApplyConfChange applies a config change to the local node. The app must call -// this when it applies a configuration change, except when it decides to reject -// the configuration change, in which case no call must take place. -func (rn *RawNode) ApplyConfChange(cc pb.ConfChangeI) *pb.ConfState { - cs := rn.raft.applyConfChange(cc.AsV2()) - return &cs -} - -// Step advances the state machine using the given message. -func (rn *RawNode) Step(m pb.Message) error { - // ignore unexpected local messages receiving over network - if IsLocalMsg(m.Type) { - return ErrStepLocalMsg - } - if pr := rn.raft.prs.Progress[m.From]; pr != nil || !IsResponseMsg(m.Type) { - return rn.raft.Step(m) - } - return ErrStepPeerNotFound -} - -// Ready returns the outstanding work that the application needs to handle. This -// includes appending and applying entries or a snapshot, updating the HardState, -// and sending messages. The returned Ready() *must* be handled and subsequently -// passed back via Advance(). -func (rn *RawNode) Ready() Ready { - rd := rn.readyWithoutAccept() - rn.acceptReady(rd) - return rd -} - -// readyWithoutAccept returns a Ready. This is a read-only operation, i.e. there -// is no obligation that the Ready must be handled. -func (rn *RawNode) readyWithoutAccept() Ready { - return newReady(rn.raft, rn.prevSoftSt, rn.prevHardSt) -} - -// acceptReady is called when the consumer of the RawNode has decided to go -// ahead and handle a Ready. Nothing must alter the state of the RawNode between -// this call and the prior call to Ready(). -func (rn *RawNode) acceptReady(rd Ready) { - if rd.SoftState != nil { - rn.prevSoftSt = rd.SoftState - } - if len(rd.ReadStates) != 0 { - rn.raft.readStates = nil - } - rn.raft.msgs = nil -} - -// HasReady called when RawNode user need to check if any Ready pending. -// Checking logic in this method should be consistent with Ready.containsUpdates(). -func (rn *RawNode) HasReady() bool { - r := rn.raft - if !r.softState().equal(rn.prevSoftSt) { - return true - } - if hardSt := r.hardState(); !IsEmptyHardState(hardSt) && !isHardStateEqual(hardSt, rn.prevHardSt) { - return true - } - if r.raftLog.hasPendingSnapshot() { - return true - } - if len(r.msgs) > 0 || len(r.raftLog.unstableEntries()) > 0 || r.raftLog.hasNextEnts() { - return true - } - if len(r.readStates) != 0 { - return true - } - return false -} - -// Advance notifies the RawNode that the application has applied and saved progress in the -// last Ready results. -func (rn *RawNode) Advance(rd Ready) { - if !IsEmptyHardState(rd.HardState) { - rn.prevHardSt = rd.HardState - } - rn.raft.advance(rd) -} - -// Status returns the current status of the given group. This allocates, see -// BasicStatus and WithProgress for allocation-friendlier choices. -func (rn *RawNode) Status() Status { - status := getStatus(rn.raft) - return status -} - -// BasicStatus returns a BasicStatus. Notably this does not contain the -// Progress map; see WithProgress for an allocation-free way to inspect it. -func (rn *RawNode) BasicStatus() BasicStatus { - return getBasicStatus(rn.raft) -} - -// ProgressType indicates the type of replica a Progress corresponds to. -type ProgressType byte - -const ( - // ProgressTypePeer accompanies a Progress for a regular peer replica. - ProgressTypePeer ProgressType = iota - // ProgressTypeLearner accompanies a Progress for a learner replica. - ProgressTypeLearner -) - -// WithProgress is a helper to introspect the Progress for this node and its -// peers. -func (rn *RawNode) WithProgress(visitor func(id uint64, typ ProgressType, pr tracker.Progress)) { - rn.raft.prs.Visit(func(id uint64, pr *tracker.Progress) { - typ := ProgressTypePeer - if pr.IsLearner { - typ = ProgressTypeLearner - } - p := *pr - p.Inflights = nil - visitor(id, typ, p) - }) -} - -// ReportUnreachable reports the given node is not reachable for the last send. -func (rn *RawNode) ReportUnreachable(id uint64) { - _ = rn.raft.Step(pb.Message{Type: pb.MsgUnreachable, From: id}) -} - -// ReportSnapshot reports the status of the sent snapshot. -func (rn *RawNode) ReportSnapshot(id uint64, status SnapshotStatus) { - rej := status == SnapshotFailure - - _ = rn.raft.Step(pb.Message{Type: pb.MsgSnapStatus, From: id, Reject: rej}) -} - -// TransferLeader tries to transfer leadership to the given transferee. -func (rn *RawNode) TransferLeader(transferee uint64) { - _ = rn.raft.Step(pb.Message{Type: pb.MsgTransferLeader, From: transferee}) -} - -// ReadIndex requests a read state. The read state will be set in ready. -// Read State has a read index. Once the application advances further than the read -// index, any linearizable read requests issued before the read request can be -// processed safely. The read state will have the same rctx attached. -func (rn *RawNode) ReadIndex(rctx []byte) { - _ = rn.raft.Step(pb.Message{Type: pb.MsgReadIndex, Entries: []pb.Entry{{Data: rctx}}}) -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/jwt.go b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/jwt.go index a797794494..e6aad1857d 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/jwt.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/jwt.go @@ -17,18 +17,19 @@ package auth import ( "context" "crypto/ecdsa" + "crypto/ed25519" "crypto/rsa" "errors" "time" - "github.com/golang-jwt/jwt/v4" + "github.com/golang-jwt/jwt/v5" "go.uber.org/zap" ) type tokenJWT struct { lg *zap.Logger signMethod jwt.SigningMethod - key interface{} + key any ttl time.Duration verifyOnly bool } @@ -45,7 +46,7 @@ func (t *tokenJWT) info(ctx context.Context, token string, rev uint64) (*AuthInf revision float64 ) - parsed, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) { + parsed, err := jwt.Parse(token, func(token *jwt.Token) (any, error) { if token.Method.Alg() != t.signMethod.Alg() { return nil, errors.New("invalid signing method") } @@ -54,15 +55,15 @@ func (t *tokenJWT) info(ctx context.Context, token string, rev uint64) (*AuthInf return &k.PublicKey, nil case *ecdsa.PrivateKey: return &k.PublicKey, nil + case ed25519.PrivateKey: + return k.Public(), nil default: return t.key, nil } }) - if err != nil { t.lg.Warn( "failed to parse a JWT token", - zap.String("token", token), zap.Error(err), ) return nil, false @@ -70,7 +71,7 @@ func (t *tokenJWT) info(ctx context.Context, token string, rev uint64) (*AuthInf claims, ok := parsed.Claims.(jwt.MapClaims) if !parsed.Valid || !ok { - t.lg.Warn("invalid JWT token", zap.String("token", token)) + t.lg.Warn("failed to obtain claims from a JWT token") return nil, false } @@ -135,7 +136,7 @@ func newTokenProviderJWT(lg *zap.Logger, optMap map[string]string) (*tokenJWT, e return nil, ErrInvalidAuthOpts } - var keys = make([]string, 0, len(optMap)) + keys := make([]string, 0, len(optMap)) for k := range optMap { if !knownOptions[k] { keys = append(keys, k) @@ -162,6 +163,10 @@ func newTokenProviderJWT(lg *zap.Logger, optMap map[string]string) (*tokenJWT, e if _, ok := t.key.(*ecdsa.PublicKey); ok { t.verifyOnly = true } + case *jwt.SigningMethodEd25519: + if _, ok := t.key.(ed25519.PublicKey); ok { + t.verifyOnly = true + } case *jwt.SigningMethodRSA, *jwt.SigningMethodRSAPSS: if _, ok := t.key.(*rsa.PublicKey); ok { t.verifyOnly = true diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/metrics.go index f7ce279202..8bf9470ae1 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/metrics.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/metrics.go @@ -21,12 +21,13 @@ import ( ) var ( - currentAuthRevision = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ - Namespace: "etcd_debugging", - Subsystem: "auth", - Name: "revision", - Help: "The current revision of auth store.", - }, + currentAuthRevision = prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: "etcd_debugging", + Subsystem: "auth", + Name: "revision", + Help: "The current revision of auth store.", + }, func() float64 { reportCurrentAuthRevMu.RLock() defer reportCurrentAuthRevMu.RUnlock() diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/nop.go b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/nop.go index d4378747bd..8ba3f8c893 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/nop.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/nop.go @@ -27,9 +27,11 @@ func (t *tokenNop) genTokenPrefix() (string, error) { return "", nil } func (t *tokenNop) info(ctx context.Context, token string, rev uint64) (*AuthInfo, bool) { return nil, false } + func (t *tokenNop) assign(ctx context.Context, username string, revision uint64) (string, error) { return "", ErrAuthFailed } + func newTokenProviderNop() (*tokenNop, error) { return &tokenNop{}, nil } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/options.go b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/options.go index 0b01d2c4a3..fa9db20c92 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/options.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/options.go @@ -15,13 +15,15 @@ package auth import ( + "crypto" "crypto/ecdsa" + "crypto/ed25519" "crypto/rsa" "fmt" - "io/ioutil" + "os" "time" - "github.com/golang-jwt/jwt/v4" + "github.com/golang-jwt/jwt/v5" ) const ( @@ -38,10 +40,8 @@ var knownOptions = map[string]bool{ optTTL: true, } -var ( - // DefaultTTL will be used when a 'ttl' is not specified - DefaultTTL = 5 * time.Minute -) +// DefaultTTL will be used when a 'ttl' is not specified +var DefaultTTL = 5 * time.Minute type jwtOptions struct { SignMethod jwt.SigningMethod @@ -70,14 +70,14 @@ func (opts *jwtOptions) Parse(optMap map[string]string) error { } if file := optMap[optPublicKey]; file != "" { - opts.PublicKey, err = ioutil.ReadFile(file) + opts.PublicKey, err = os.ReadFile(file) if err != nil { return err } } if file := optMap[optPrivateKey]; file != "" { - opts.PrivateKey, err = ioutil.ReadFile(file) + opts.PrivateKey, err = os.ReadFile(file) if err != nil { return err } @@ -94,12 +94,14 @@ func (opts *jwtOptions) Parse(optMap map[string]string) error { } // Key will parse and return the appropriately typed key for the selected signature method -func (opts *jwtOptions) Key() (interface{}, error) { +func (opts *jwtOptions) Key() (any, error) { switch opts.SignMethod.(type) { case *jwt.SigningMethodRSA, *jwt.SigningMethodRSAPSS: return opts.rsaKey() case *jwt.SigningMethodECDSA: return opts.ecKey() + case *jwt.SigningMethodEd25519: + return opts.edKey() case *jwt.SigningMethodHMAC: return opts.hmacKey() default: @@ -107,14 +109,14 @@ func (opts *jwtOptions) Key() (interface{}, error) { } } -func (opts *jwtOptions) hmacKey() (interface{}, error) { +func (opts *jwtOptions) hmacKey() (any, error) { if len(opts.PrivateKey) == 0 { return nil, ErrMissingKey } return opts.PrivateKey, nil } -func (opts *jwtOptions) rsaKey() (interface{}, error) { +func (opts *jwtOptions) rsaKey() (any, error) { var ( priv *rsa.PrivateKey pub *rsa.PublicKey @@ -145,14 +147,14 @@ func (opts *jwtOptions) rsaKey() (interface{}, error) { } // both keys provided, make sure they match - if pub != nil && pub.E != priv.E && pub.N.Cmp(priv.N) != 0 { + if pub != nil && !pub.Equal(priv.Public()) { return nil, ErrKeyMismatch } return priv, nil } -func (opts *jwtOptions) ecKey() (interface{}, error) { +func (opts *jwtOptions) ecKey() (any, error) { var ( priv *ecdsa.PrivateKey pub *ecdsa.PublicKey @@ -183,8 +185,49 @@ func (opts *jwtOptions) ecKey() (interface{}, error) { } // both keys provided, make sure they match - if pub != nil && pub.Curve != priv.Curve && - pub.X.Cmp(priv.X) != 0 && pub.Y.Cmp(priv.Y) != 0 { + if pub != nil && !pub.Equal(priv.Public()) { + return nil, ErrKeyMismatch + } + + return priv, nil +} + +func (opts *jwtOptions) edKey() (any, error) { + var ( + priv ed25519.PrivateKey + pub ed25519.PublicKey + err error + ) + + if len(opts.PrivateKey) > 0 { + var privKey crypto.PrivateKey + privKey, err = jwt.ParseEdPrivateKeyFromPEM(opts.PrivateKey) + if err != nil { + return nil, err + } + priv = privKey.(ed25519.PrivateKey) + } + + if len(opts.PublicKey) > 0 { + var pubKey crypto.PublicKey + pubKey, err = jwt.ParseEdPublicKeyFromPEM(opts.PublicKey) + if err != nil { + return nil, err + } + pub = pubKey.(ed25519.PublicKey) + } + + if priv == nil { + if pub == nil { + // Neither key given + return nil, ErrMissingKey + } + // Public key only, can verify tokens + return pub, nil + } + + // both keys provided, make sure they match + if pub != nil && !pub.Equal(priv.Public()) { return nil, ErrKeyMismatch } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/range_perm_cache.go b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/range_perm_cache.go index e096710c32..539ed290e6 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/range_perm_cache.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/range_perm_cache.go @@ -15,15 +15,14 @@ package auth import ( + "go.uber.org/zap" + "go.etcd.io/etcd/api/v3/authpb" "go.etcd.io/etcd/pkg/v3/adt" - "go.etcd.io/etcd/server/v3/mvcc/backend" - - "go.uber.org/zap" ) -func getMergedPerms(lg *zap.Logger, tx backend.ReadTx, userName string) *unifiedRangePermissions { - user := getUser(lg, tx, userName) +func getMergedPerms(tx UnsafeAuthReader, userName string) *unifiedRangePermissions { + user := tx.UnsafeGetUser(userName) if user == nil { return nil } @@ -32,7 +31,7 @@ func getMergedPerms(lg *zap.Logger, tx backend.ReadTx, userName string) *unified writePerms := adt.NewIntervalTree() for _, roleName := range user.Roles { - role := getRole(lg, tx, roleName) + role := tx.UnsafeGetRole(roleName) if role == nil { continue } @@ -75,7 +74,8 @@ func checkKeyInterval( lg *zap.Logger, cachedPerms *unifiedRangePermissions, key, rangeEnd []byte, - permtyp authpb.Permission_Type) bool { + permtyp authpb.Permission_Type, +) bool { if isOpenEnded(rangeEnd) { rangeEnd = nil // nil rangeEnd will be converetd to []byte{}, the largest element of BytesAffineComparable, @@ -108,6 +108,7 @@ func checkKeyPoint(lg *zap.Logger, cachedPerms *unifiedRangePermissions, key []b } func (as *authStore) isRangeOpPermitted(userName string, key, rangeEnd []byte, permtyp authpb.Permission_Type) bool { + // assumption: tx is Lock()ed as.rangePermCacheMu.RLock() defer as.rangePermCacheMu.RUnlock() @@ -127,19 +128,21 @@ func (as *authStore) isRangeOpPermitted(userName string, key, rangeEnd []byte, p return checkKeyInterval(as.lg, rangePerm, key, rangeEnd, permtyp) } -func (as *authStore) refreshRangePermCache(tx backend.ReadTx) { +func (as *authStore) refreshRangePermCache(tx UnsafeAuthReader) { // Note that every authentication configuration update calls this method and it invalidates the entire // rangePermCache and reconstruct it based on information of users and roles stored in the backend. // This can be a costly operation. as.rangePermCacheMu.Lock() defer as.rangePermCacheMu.Unlock() + as.lg.Debug("Refreshing rangePermCache") + as.rangePermCache = make(map[string]*unifiedRangePermissions) - users := getAllUsers(as.lg, tx) + users := tx.UnsafeGetAllUsers() for _, user := range users { userName := string(user.Name) - perms := getMergedPerms(as.lg, tx, userName) + perms := getMergedPerms(tx, userName) if perms == nil { as.lg.Error( "failed to create a merged permission", @@ -187,7 +190,7 @@ func isValidPermissionRange(key, rangeEnd []byte) bool { if len(key) == 0 { return false } - if rangeEnd == nil || len(rangeEnd) == 0 { // ensure rule b1 + if len(rangeEnd) == 0 { // ensure rule b1 return true } @@ -197,9 +200,5 @@ func isValidPermissionRange(key, rangeEnd []byte) bool { return true } - if isOpenEnded(rangeEnd) { - return true - } - - return false + return isOpenEnded(rangeEnd) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/simple_token.go b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/simple_token.go index a657d9daef..f8272b185d 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/simple_token.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/simple_token.go @@ -20,6 +20,7 @@ package auth import ( "context" "crypto/rand" + "errors" "fmt" "math/big" "strconv" @@ -212,7 +213,11 @@ func (t *tokenSimple) info(ctx context.Context, token string, revision uint64) ( func (t *tokenSimple) assign(ctx context.Context, username string, rev uint64) (string, error) { // rev isn't used in simple token, it is only used in JWT - index := ctx.Value(AuthenticateParamIndex{}).(uint64) + var index uint64 + var ok bool + if index, ok = ctx.Value(AuthenticateParamIndex{}).(uint64); !ok { + return "", errors.New("failed to assign") + } simpleTokenPrefix := ctx.Value(AuthenticateParamSimpleTokenPrefix{}).(string) token := fmt.Sprintf("%s.%d", simpleTokenPrefix, index) t.assignSimpleTokenToUser(username, token) @@ -231,7 +236,7 @@ func (t *tokenSimple) isValidSimpleToken(ctx context.Context, token string) bool } select { - case <-t.indexWaiter(uint64(index)): + case <-t.indexWaiter(index): return true case <-ctx.Done(): } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/store.go b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/store.go index 67c5694cde..cfacfb001c 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/auth/store.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/auth/store.go @@ -18,7 +18,6 @@ import ( "bytes" "context" "encoding/base64" - "encoding/binary" "errors" "sort" "strings" @@ -26,25 +25,21 @@ import ( "sync/atomic" "time" - "go.etcd.io/etcd/api/v3/authpb" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" - "go.uber.org/zap" "golang.org/x/crypto/bcrypt" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" + + "go.etcd.io/etcd/api/v3/authpb" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" ) -var ( - enableFlagKey = []byte("authEnabled") - authEnabled = []byte{1} - authDisabled = []byte{0} +var _ AuthStore = (*authStore)(nil) - revisionKey = []byte("authRevision") +var ( + rootPerm = authpb.Permission{PermType: authpb.READWRITE, Key: []byte{}, RangeEnd: []byte{0}} ErrRootUserNotExist = errors.New("auth: root user does not exist") ErrRootRoleNotExist = errors.New("auth: root user does not have root role") @@ -77,8 +72,6 @@ const ( tokenTypeSimple = "simple" tokenTypeJWT = "jwt" - - revBytesLen = 8 ) type AuthInfo struct { @@ -107,7 +100,7 @@ type AuthStore interface { Authenticate(ctx context.Context, username, password string) (*pb.AuthenticateResponse, error) // Recover recovers the state of auth store from the given backend - Recover(b backend.Backend) + Recover(be AuthBackend) // UserAdd adds a new user UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) @@ -199,12 +192,59 @@ type TokenProvider interface { genTokenPrefix() (string, error) } +type AuthBackend interface { + CreateAuthBuckets() + ForceCommit() + ReadTx() AuthReadTx + BatchTx() AuthBatchTx + + GetUser(string) *authpb.User + GetAllUsers() []*authpb.User + GetRole(string) *authpb.Role + GetAllRoles() []*authpb.Role +} + +type AuthReadTx interface { + RLock() + RUnlock() + UnsafeAuthReader +} + +type UnsafeAuthReader interface { + UnsafeReadAuthEnabled() bool + UnsafeReadAuthRevision() uint64 + UnsafeGetUser(string) *authpb.User + UnsafeGetRole(string) *authpb.Role + UnsafeGetAllUsers() []*authpb.User + UnsafeGetAllRoles() []*authpb.Role +} + +type AuthBatchTx interface { + Lock() + Unlock() + UnsafeAuthReadWriter +} + +type UnsafeAuthReadWriter interface { + UnsafeAuthReader + UnsafeAuthWriter +} + +type UnsafeAuthWriter interface { + UnsafeSaveAuthEnabled(enabled bool) + UnsafeSaveAuthRevision(rev uint64) + UnsafePutUser(*authpb.User) + UnsafeDeleteUser(string) + UnsafePutRole(*authpb.Role) + UnsafeDeleteRole(string) +} + type authStore struct { // atomic operations; need 64-bit align, or 32-bit tests will crash revision uint64 lg *zap.Logger - be backend.Backend + be AuthBackend enabled bool enabledMu sync.RWMutex @@ -228,15 +268,14 @@ func (as *authStore) AuthEnable() error { as.lg.Info("authentication is already enabled; ignored auth enable request") return nil } - b := as.be - tx := b.BatchTx() - tx.LockInsideApply() + tx := as.be.BatchTx() + tx.Lock() defer func() { tx.Unlock() - b.ForceCommit() + as.be.ForceCommit() }() - u := getUser(as.lg, tx, rootUser) + u := tx.UnsafeGetUser(rootUser) if u == nil { return ErrRootUserNotExist } @@ -245,14 +284,13 @@ func (as *authStore) AuthEnable() error { return ErrRootRoleNotExist } - tx.UnsafePut(buckets.Auth, enableFlagKey, authEnabled) - + tx.UnsafeSaveAuthEnabled(true) as.enabled = true as.tokenProvider.enable() as.refreshRangePermCache(tx) - as.setRevision(getRevision(tx)) + as.setRevision(tx.UnsafeReadAuthRevision()) as.lg.Info("enabled authentication") return nil @@ -265,11 +303,13 @@ func (as *authStore) AuthDisable() { return } b := as.be + tx := b.BatchTx() - tx.LockInsideApply() - tx.UnsafePut(buckets.Auth, enableFlagKey, authDisabled) + tx.Lock() + tx.UnsafeSaveAuthEnabled(false) as.commitRevision(tx) tx.Unlock() + b.ForceCommit() as.enabled = false @@ -292,12 +332,7 @@ func (as *authStore) Authenticate(ctx context.Context, username, password string if !as.IsAuthEnabled() { return nil, ErrAuthNotEnabled } - - tx := as.be.BatchTx() - tx.LockInsideApply() - defer tx.Unlock() - - user := getUser(as.lg, tx, username) + user := as.be.GetUser(username) if user == nil { return nil, ErrAuthFailed } @@ -332,10 +367,10 @@ func (as *authStore) CheckPassword(username, password string) (uint64, error) { // to avoid putting it in the critical section of the tx lock. revision, err := func() (uint64, error) { tx := as.be.ReadTx() - tx.Lock() - defer tx.Unlock() + tx.RLock() + defer tx.RUnlock() - user = getUser(as.lg, tx, username) + user = tx.UnsafeGetUser(username) if user == nil { return 0, ErrAuthFailed } @@ -344,7 +379,7 @@ func (as *authStore) CheckPassword(username, password string) (uint64, error) { return 0, ErrNoPasswordUser } - return getRevision(tx), nil + return tx.UnsafeReadAuthRevision(), nil }() if err != nil { return 0, err @@ -357,22 +392,16 @@ func (as *authStore) CheckPassword(username, password string) (uint64, error) { return revision, nil } -func (as *authStore) Recover(be backend.Backend) { - enabled := false +func (as *authStore) Recover(be AuthBackend) { as.be = be tx := be.ReadTx() - tx.Lock() - _, vs := tx.UnsafeRange(buckets.Auth, enableFlagKey, nil, 0) - if len(vs) == 1 { - if bytes.Equal(vs[0], authEnabled) { - enabled = true - } - } + tx.RLock() - as.setRevision(getRevision(tx)) + enabled := tx.UnsafeReadAuthEnabled() + as.setRevision(tx.UnsafeReadAuthRevision()) as.refreshRangePermCache(tx) - tx.Unlock() + tx.RUnlock() as.enabledMu.Lock() as.enabled = enabled @@ -396,10 +425,10 @@ func (as *authStore) UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, } tx := as.be.BatchTx() - tx.LockInsideApply() + tx.Lock() defer tx.Unlock() - user := getUser(as.lg, tx, r.Name) + user := tx.UnsafeGetUser(r.Name) if user != nil { return nil, ErrUserAlreadyExist } @@ -426,8 +455,7 @@ func (as *authStore) UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, Password: password, Options: options, } - - putUser(as.lg, tx, newUser) + tx.UnsafePutUser(newUser) as.commitRevision(tx) as.refreshRangePermCache(tx) @@ -443,15 +471,14 @@ func (as *authStore) UserDelete(r *pb.AuthUserDeleteRequest) (*pb.AuthUserDelete } tx := as.be.BatchTx() - tx.LockInsideApply() + tx.Lock() defer tx.Unlock() - user := getUser(as.lg, tx, r.Name) + user := tx.UnsafeGetUser(r.Name) if user == nil { return nil, ErrUserNotFound } - - delUser(tx, r.Name) + tx.UnsafeDeleteUser(r.Name) as.commitRevision(tx) as.refreshRangePermCache(tx) @@ -468,10 +495,10 @@ func (as *authStore) UserDelete(r *pb.AuthUserDeleteRequest) (*pb.AuthUserDelete func (as *authStore) UserChangePassword(r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) { tx := as.be.BatchTx() - tx.LockInsideApply() + tx.Lock() defer tx.Unlock() - user := getUser(as.lg, tx, r.Name) + user := tx.UnsafeGetUser(r.Name) if user == nil { return nil, ErrUserNotFound } @@ -493,8 +520,7 @@ func (as *authStore) UserChangePassword(r *pb.AuthUserChangePasswordRequest) (*p Password: password, Options: user.Options, } - - putUser(as.lg, tx, updatedUser) + tx.UnsafePutUser(updatedUser) as.commitRevision(tx) as.refreshRangePermCache(tx) @@ -511,16 +537,16 @@ func (as *authStore) UserChangePassword(r *pb.AuthUserChangePasswordRequest) (*p func (as *authStore) UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) { tx := as.be.BatchTx() - tx.LockInsideApply() + tx.Lock() defer tx.Unlock() - user := getUser(as.lg, tx, r.User) + user := tx.UnsafeGetUser(r.User) if user == nil { return nil, ErrUserNotFound } if r.Role != rootRole { - role := getRole(as.lg, tx, r.Role) + role := tx.UnsafeGetRole(r.Role) if role == nil { return nil, ErrRoleNotFound } @@ -540,7 +566,7 @@ func (as *authStore) UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUser user.Roles = append(user.Roles, r.Role) sort.Strings(user.Roles) - putUser(as.lg, tx, user) + tx.UnsafePutUser(user) as.commitRevision(tx) as.refreshRangePermCache(tx) @@ -555,10 +581,7 @@ func (as *authStore) UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUser } func (as *authStore) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) { - tx := as.be.BatchTx() - tx.LockInsideApply() - user := getUser(as.lg, tx, r.Name) - tx.Unlock() + user := as.be.GetUser(r.Name) if user == nil { return nil, ErrUserNotFound @@ -570,10 +593,7 @@ func (as *authStore) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, } func (as *authStore) UserList(r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) { - tx := as.be.BatchTx() - tx.LockInsideApply() - users := getAllUsers(as.lg, tx) - tx.Unlock() + users := as.be.GetAllUsers() resp := &pb.AuthUserListResponse{Users: make([]string, len(users))} for i := range users { @@ -593,10 +613,10 @@ func (as *authStore) UserRevokeRole(r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUs } tx := as.be.BatchTx() - tx.LockInsideApply() + tx.Lock() defer tx.Unlock() - user := getUser(as.lg, tx, r.Name) + user := tx.UnsafeGetUser(r.Name) if user == nil { return nil, ErrUserNotFound } @@ -617,7 +637,7 @@ func (as *authStore) UserRevokeRole(r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUs return nil, ErrRoleNotGranted } - putUser(as.lg, tx, updatedUser) + tx.UnsafePutUser(updatedUser) as.commitRevision(tx) as.refreshRangePermCache(tx) @@ -633,25 +653,22 @@ func (as *authStore) UserRevokeRole(r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUs } func (as *authStore) RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) { - tx := as.be.BatchTx() - tx.LockInsideApply() - defer tx.Unlock() - var resp pb.AuthRoleGetResponse - role := getRole(as.lg, tx, r.Role) + role := as.be.GetRole(r.Role) if role == nil { return nil, ErrRoleNotFound } - resp.Perm = append(resp.Perm, role.KeyPermission...) + if rootRole == string(role.Name) { + resp.Perm = append(resp.Perm, &rootPerm) + } else { + resp.Perm = append(resp.Perm, role.KeyPermission...) + } return &resp, nil } func (as *authStore) RoleList(r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) { - tx := as.be.BatchTx() - tx.LockInsideApply() - roles := getAllRoles(as.lg, tx) - tx.Unlock() + roles := as.be.GetAllRoles() resp := &pb.AuthRoleListResponse{Roles: make([]string, len(roles))} for i := range roles { @@ -662,10 +679,10 @@ func (as *authStore) RoleList(r *pb.AuthRoleListRequest) (*pb.AuthRoleListRespon func (as *authStore) RoleRevokePermission(r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) { tx := as.be.BatchTx() - tx.LockInsideApply() + tx.Lock() defer tx.Unlock() - role := getRole(as.lg, tx, r.Role) + role := tx.UnsafeGetRole(r.Role) if role == nil { return nil, ErrRoleNotFound } @@ -684,7 +701,7 @@ func (as *authStore) RoleRevokePermission(r *pb.AuthRoleRevokePermissionRequest) return nil, ErrPermissionNotGranted } - putRole(as.lg, tx, updatedRole) + tx.UnsafePutRole(updatedRole) as.commitRevision(tx) as.refreshRangePermCache(tx) @@ -705,17 +722,17 @@ func (as *authStore) RoleDelete(r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDelete } tx := as.be.BatchTx() - tx.LockInsideApply() + tx.Lock() defer tx.Unlock() - role := getRole(as.lg, tx, r.Role) + role := tx.UnsafeGetRole(r.Role) if role == nil { return nil, ErrRoleNotFound } - delRole(tx, r.Role) + tx.UnsafeDeleteRole(r.Role) - users := getAllUsers(as.lg, tx) + users := tx.UnsafeGetAllUsers() for _, user := range users { updatedUser := &authpb.User{ Name: user.Name, @@ -733,8 +750,7 @@ func (as *authStore) RoleDelete(r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDelete continue } - putUser(as.lg, tx, updatedUser) - + tx.UnsafePutUser(updatedUser) } as.commitRevision(tx) @@ -750,10 +766,10 @@ func (as *authStore) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, } tx := as.be.BatchTx() - tx.LockInsideApply() + tx.Lock() defer tx.Unlock() - role := getRole(as.lg, tx, r.Name) + role := tx.UnsafeGetRole(r.Name) if role != nil { return nil, ErrRoleAlreadyExist } @@ -762,7 +778,7 @@ func (as *authStore) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, Name: []byte(r.Name), } - putRole(as.lg, tx, newRole) + tx.UnsafePutRole(newRole) as.commitRevision(tx) @@ -797,10 +813,10 @@ func (as *authStore) RoleGrantPermission(r *pb.AuthRoleGrantPermissionRequest) ( } tx := as.be.BatchTx() - tx.LockInsideApply() + tx.Lock() defer tx.Unlock() - role := getRole(as.lg, tx, r.Name) + role := tx.UnsafeGetRole(r.Name) if role == nil { return nil, ErrRoleNotFound } @@ -824,7 +840,7 @@ func (as *authStore) RoleGrantPermission(r *pb.AuthRoleGrantPermissionRequest) ( sort.Sort(permSlice(role.KeyPermission)) } - putRole(as.lg, tx, role) + tx.UnsafePutRole(role) as.commitRevision(tx) as.refreshRangePermCache(tx) @@ -833,6 +849,8 @@ func (as *authStore) RoleGrantPermission(r *pb.AuthRoleGrantPermissionRequest) ( "granted/updated a permission to a user", zap.String("user-name", r.Name), zap.String("permission-name", authpb.Permission_Type_name[int32(r.Perm.PermType)]), + zap.ByteString("key", r.Perm.Key), + zap.ByteString("range-end", r.Perm.RangeEnd), ) return &pb.AuthRoleGrantPermissionResponse{}, nil } @@ -858,10 +876,10 @@ func (as *authStore) isOpPermitted(userName string, revision uint64, key, rangeE } tx := as.be.ReadTx() - tx.Lock() - defer tx.Unlock() + tx.RLock() + defer tx.RUnlock() - user := getUser(as.lg, tx, userName) + user := tx.UnsafeGetUser(userName) if user == nil { as.lg.Error("cannot find a user for permission check", zap.String("user-name", userName)) return ErrPermissionDenied @@ -900,9 +918,9 @@ func (as *authStore) IsAdminPermitted(authInfo *AuthInfo) error { } tx := as.be.ReadTx() - tx.Lock() - u := getUser(as.lg, tx, authInfo.Username) - tx.Unlock() + tx.RLock() + defer tx.RUnlock() + u := tx.UnsafeGetUser(authInfo.Username) if u == nil { return ErrUserNotFound @@ -915,111 +933,6 @@ func (as *authStore) IsAdminPermitted(authInfo *AuthInfo) error { return nil } -func getUser(lg *zap.Logger, tx backend.ReadTx, username string) *authpb.User { - _, vs := tx.UnsafeRange(buckets.AuthUsers, []byte(username), nil, 0) - if len(vs) == 0 { - return nil - } - - user := &authpb.User{} - err := user.Unmarshal(vs[0]) - if err != nil { - lg.Panic( - "failed to unmarshal 'authpb.User'", - zap.String("user-name", username), - zap.Error(err), - ) - } - return user -} - -func getAllUsers(lg *zap.Logger, tx backend.ReadTx) []*authpb.User { - var vs [][]byte - err := tx.UnsafeForEach(buckets.AuthUsers, func(k []byte, v []byte) error { - vs = append(vs, v) - return nil - }) - if err != nil { - lg.Panic("failed to get users", - zap.Error(err)) - } - if len(vs) == 0 { - return nil - } - - users := make([]*authpb.User, len(vs)) - for i := range vs { - user := &authpb.User{} - err := user.Unmarshal(vs[i]) - if err != nil { - lg.Panic("failed to unmarshal 'authpb.User'", zap.Error(err)) - } - users[i] = user - } - return users -} - -func putUser(lg *zap.Logger, tx backend.BatchTx, user *authpb.User) { - b, err := user.Marshal() - if err != nil { - lg.Panic("failed to unmarshal 'authpb.User'", zap.Error(err)) - } - tx.UnsafePut(buckets.AuthUsers, user.Name, b) -} - -func delUser(tx backend.BatchTx, username string) { - tx.UnsafeDelete(buckets.AuthUsers, []byte(username)) -} - -func getRole(lg *zap.Logger, tx backend.ReadTx, rolename string) *authpb.Role { - _, vs := tx.UnsafeRange(buckets.AuthRoles, []byte(rolename), nil, 0) - if len(vs) == 0 { - return nil - } - - role := &authpb.Role{} - err := role.Unmarshal(vs[0]) - if err != nil { - lg.Panic("failed to unmarshal 'authpb.Role'", zap.Error(err)) - } - return role -} - -func getAllRoles(lg *zap.Logger, tx backend.ReadTx) []*authpb.Role { - _, vs := tx.UnsafeRange(buckets.AuthRoles, []byte{0}, []byte{0xff}, -1) - if len(vs) == 0 { - return nil - } - - roles := make([]*authpb.Role, len(vs)) - for i := range vs { - role := &authpb.Role{} - err := role.Unmarshal(vs[i]) - if err != nil { - lg.Panic("failed to unmarshal 'authpb.Role'", zap.Error(err)) - } - roles[i] = role - } - return roles -} - -func putRole(lg *zap.Logger, tx backend.BatchTx, role *authpb.Role) { - b, err := role.Marshal() - if err != nil { - lg.Panic( - "failed to marshal 'authpb.Role'", - zap.String("role-name", string(role.Name)), - zap.Error(err), - ) - } - - tx.UnsafePut(buckets.AuthRoles, role.Name, b) -} - -func delRole(tx backend.BatchTx, rolename string) { - tx.UnsafeDelete(buckets.AuthRoles, []byte(rolename)) -} - func (as *authStore) IsAuthEnabled() bool { as.enabledMu.RLock() defer as.enabledMu.RUnlock() @@ -1027,7 +940,7 @@ func (as *authStore) IsAuthEnabled() bool { } // NewAuthStore creates a new AuthStore. -func NewAuthStore(lg *zap.Logger, be backend.Backend, tp TokenProvider, bcryptCost int) *authStore { +func NewAuthStore(lg *zap.Logger, be AuthBackend, tp TokenProvider, bcryptCost int) AuthStore { if lg == nil { lg = zap.NewNop() } @@ -1043,23 +956,14 @@ func NewAuthStore(lg *zap.Logger, be backend.Backend, tp TokenProvider, bcryptCo bcryptCost = bcrypt.DefaultCost } + be.CreateAuthBuckets() tx := be.BatchTx() - tx.LockOutsideApply() - - tx.UnsafeCreateBucket(buckets.Auth) - tx.UnsafeCreateBucket(buckets.AuthUsers) - tx.UnsafeCreateBucket(buckets.AuthRoles) - - enabled := false - _, vs := tx.UnsafeRange(buckets.Auth, enableFlagKey, nil, 0) - if len(vs) == 1 { - if bytes.Equal(vs[0], authEnabled) { - enabled = true - } - } - + // We should call LockOutsideApply here, but the txPostLockHoos isn't set + // to EtcdServer yet, so it's OK. + tx.Lock() + enabled := tx.UnsafeReadAuthEnabled() as := &authStore{ - revision: getRevision(tx), + revision: tx.UnsafeReadAuthRevision(), lg: lg, be: be, enabled: enabled, @@ -1092,20 +996,9 @@ func hasRootRole(u *authpb.User) bool { return idx != len(u.Roles) && u.Roles[idx] == rootRole } -func (as *authStore) commitRevision(tx backend.BatchTx) { +func (as *authStore) commitRevision(tx UnsafeAuthWriter) { atomic.AddUint64(&as.revision, 1) - revBytes := make([]byte, revBytesLen) - binary.BigEndian.PutUint64(revBytes, as.Revision()) - tx.UnsafePut(buckets.Auth, revisionKey, revBytes) -} - -func getRevision(tx backend.ReadTx) uint64 { - _, vs := tx.UnsafeRange(buckets.Auth, revisionKey, nil, 0) - if len(vs) != 1 { - // this can happen in the initialization phase - return 0 - } - return binary.BigEndian.Uint64(vs[0]) + tx.UnsafeSaveAuthRevision(as.Revision()) } func (as *authStore) setRevision(rev uint64) { @@ -1163,12 +1056,13 @@ func (as *authStore) AuthInfoFromCtx(ctx context.Context) (*AuthInfo, error) { if !as.IsAuthEnabled() { return nil, nil } + md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, nil } - //TODO(mitake|hexfusion) review unifying key names + // TODO(mitake|hexfusion) review unifying key names ts, ok := md[rpctypes.TokenFieldNameGRPC] if !ok { ts, ok = md[rpctypes.TokenFieldNameSwagger] @@ -1221,7 +1115,6 @@ func decomposeOpts(lg *zap.Logger, optstr string) (string, map[string]string, er } return tokenType, typeSpecificOpts, nil - } // NewTokenProvider creates a new token provider. @@ -1229,7 +1122,8 @@ func NewTokenProvider( lg *zap.Logger, tokenOpts string, indexWaiter func(uint64) <-chan struct{}, - TokenTTL time.Duration) (TokenProvider, error) { + TokenTTL time.Duration, +) (TokenProvider, error) { tokenType, typeSpecificOpts, err := decomposeOpts(lg, tokenOpts) if err != nil { return nil, ErrInvalidAuthOpts @@ -1302,8 +1196,8 @@ func (as *authStore) WithRoot(ctx context.Context) context.Context { func (as *authStore) HasRole(user, role string) bool { tx := as.be.BatchTx() - tx.LockInsideApply() - u := getUser(as.lg, tx, user) + tx.Lock() + u := tx.UnsafeGetUser(user) tx.Unlock() if u == nil { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/config/config.go b/etcd/vendor/go.etcd.io/etcd/server/v3/config/config.go index 1203f7a0df..182dec2ae4 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/config/config.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/config/config.go @@ -24,24 +24,33 @@ import ( "strings" "time" + "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.uber.org/zap" + + bolt "go.etcd.io/bbolt" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/pkg/v3/featuregate" "go.etcd.io/etcd/pkg/v3/netutil" - "go.etcd.io/etcd/server/v3/datadir" - "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery" + "go.etcd.io/etcd/server/v3/storage/datadir" +) - bolt "go.etcd.io/bbolt" - "go.uber.org/zap" +const ( + grpcOverheadBytes = 512 * 1024 ) // ServerConfig holds the configuration of etcd as taken from the command line or discovery. type ServerConfig struct { - Name string + Name string + DiscoveryURL string DiscoveryProxy string - ClientURLs types.URLs - PeerURLs types.URLs - DataDir string + DiscoveryCfg v3discovery.DiscoveryConfig + + ClientURLs types.URLs + PeerURLs types.URLs + DataDir string // DedicatedWALDir config will make the etcd to write the WAL to the WALDir // rather than the dataDir/member/wal. DedicatedWALDir string @@ -53,7 +62,6 @@ type ServerConfig struct { // We expect the follower has a millisecond level latency with the leader. // The max throughput is around 10K. Keep a 5K entries is enough for helping // follower to catch up. - // WARNING: only change this for tests. Always use "DefaultSnapshotCatchUpEntries" SnapshotCatchUpEntries uint64 MaxSnapFiles uint @@ -127,7 +135,8 @@ type ServerConfig struct { // streams that each client can open at a time. MaxConcurrentStreams uint32 - WarningApplyDuration time.Duration + WarningApplyDuration time.Duration + WarningUnaryRequestDuration time.Duration StrictReconfigCheck bool @@ -140,10 +149,9 @@ type ServerConfig struct { // InitialCorruptCheck is true to check data corruption on boot // before serving any peer/client traffic. - InitialCorruptCheck bool - CorruptCheckTime time.Duration - CompactHashCheckEnabled bool - CompactHashCheckTime time.Duration + InitialCorruptCheck bool + CorruptCheckTime time.Duration + CompactHashCheckTime time.Duration // PreVote is true to enable Raft Pre-Vote. PreVote bool @@ -157,19 +165,15 @@ type ServerConfig struct { ForceNewCluster bool ForceNewClusterBumpAmount uint64 - // EnableLeaseCheckpoint enables leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change. - EnableLeaseCheckpoint bool // LeaseCheckpointInterval time.Duration is the wait duration between lease checkpoints. LeaseCheckpointInterval time.Duration - // LeaseCheckpointPersist enables persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled. - LeaseCheckpointPersist bool EnableGRPCGateway bool - // ExperimentalEnableDistributedTracing enables distributed tracing using OpenTelemetry protocol. - ExperimentalEnableDistributedTracing bool - // ExperimentalTracerOptions are options for OpenTelemetry gRPC interceptor. - ExperimentalTracerOptions []otelgrpc.Option + // EnableDistributedTracing enables distributed tracing using OpenTelemetry protocol. + EnableDistributedTracing bool + // TracerOptions are options for OpenTelemetry gRPC interceptor. + TracerOptions []otelgrpc.Option WatchProgressNotifyInterval time.Duration @@ -179,24 +183,26 @@ type ServerConfig struct { DowngradeCheckTime time.Duration - // ExperimentalMemoryMlock enables mlocking of etcd owned memory pages. + // MemoryMlock enables mlocking of etcd owned memory pages. // The setting improves etcd tail latency in environments were: // - memory pressure might lead to swapping pages to disk // - disk latency might be unstable // Currently all etcd memory gets mlocked, but in future the flag can // be refined to mlock in-use area of bbolt only. - ExperimentalMemoryMlock bool `json:"experimental-memory-mlock"` + MemoryMlock bool `json:"memory-mlock"` // ExperimentalTxnModeWriteWithSharedBuffer enable write transaction to use // a shared buffer in its readonly check operations. + // TODO: Delete in v3.7 + // Deprecated: Use TxnModeWriteWithSharedBuffer Feature Gate instead. Will be decommissioned in v3.7. ExperimentalTxnModeWriteWithSharedBuffer bool `json:"experimental-txn-mode-write-with-shared-buffer"` - // ExperimentalStopGRPCServiceOnDefrag enables etcd gRPC service to stop serving client requests on defragmentation. - ExperimentalStopGRPCServiceOnDefrag bool `json:"experimental-stop-grpc-service-on-defrag"` - - // ExperimentalBootstrapDefragThresholdMegabytes is the minimum number of megabytes needed to be freed for etcd server to + // BootstrapDefragThresholdMegabytes is the minimum number of megabytes needed to be freed for etcd server to // consider running defrag during bootstrap. Needs to be set to non-zero value to take effect. - ExperimentalBootstrapDefragThresholdMegabytes uint `json:"experimental-bootstrap-defrag-threshold-megabytes"` + BootstrapDefragThresholdMegabytes uint `json:"bootstrap-defrag-threshold-megabytes"` + + // MaxLearners sets a limit to the number of learner members that can exist in the cluster membership. + MaxLearners int `json:"max-learners"` // ExperimentalMaxLearners sets a limit to the number of learner members that can exist in the cluster membership. ExperimentalMaxLearners int `json:"experimental-max-learners"` @@ -204,6 +210,15 @@ type ServerConfig struct { // V2Deprecation defines a phase of v2store deprecation process. V2Deprecation V2DeprecationEnum `json:"v2-deprecation"` + // ExperimentalLocalAddress is the local IP address to use when communicating with a peer. + ExperimentalLocalAddress string `json:"experimental-local-address"` + + // ServerFeatureGate is a server level feature gate + ServerFeatureGate featuregate.FeatureGate + + // Metrics types of metrics - should be either 'basic' or 'extensive' + Metrics string + // openshiftHardwareDelaySeconds sets the duration, in seconds, to extend the standard etcd // request timeout by based on hardware speed. OpenShift currently has a notion of differentiating // between standard and slower hardware: https://github.com/openshift/cluster-etcd-operator/blob/5bbe49442101475febb89bba3be808aa121f5c0c/pkg/hwspeedhelpers/hwhelper.go#L21-L33 @@ -273,7 +288,7 @@ func (c *ServerConfig) advertiseMatchesCluster() error { initMap[url.String()] = struct{}{} } - missing := []string{} + var missing []string for url := range initMap { if _, ok := apMap[url]; !ok { missing = append(missing, url) @@ -285,7 +300,7 @@ func (c *ServerConfig) advertiseMatchesCluster() error { } mstr := strings.Join(missing, ",") apStr := strings.Join(apurls, ",") - return fmt.Errorf("--initial-cluster has %s but missing from --initial-advertise-peer-urls=%s (%v)", mstr, apStr, err) + return fmt.Errorf("--initial-cluster has %s but missing from --initial-advertise-peer-urls=%s (%w)", mstr, apStr, err) } for url := range apMap { @@ -302,7 +317,7 @@ func (c *ServerConfig) advertiseMatchesCluster() error { // resolved URLs from "--initial-advertise-peer-urls" and "--initial-cluster" did not match or failed apStr := strings.Join(apurls, ",") umap := types.URLsMap(map[string]types.URLs{c.Name: c.PeerURLs}) - return fmt.Errorf("failed to resolve %s to match --initial-cluster=%s (%v)", apStr, umap.String(), err) + return fmt.Errorf("failed to resolve %s to match --initial-cluster=%s (%w)", apStr, umap.String(), err) } func (c *ServerConfig) MemberDir() string { return datadir.ToMemberDir(c.DataDir) } @@ -311,12 +326,14 @@ func (c *ServerConfig) WALDir() string { if c.DedicatedWALDir != "" { return c.DedicatedWALDir } - return datadir.ToWalDir(c.DataDir) + return datadir.ToWALDir(c.DataDir) } func (c *ServerConfig) SnapDir() string { return filepath.Join(c.MemberDir(), "snap") } -func (c *ServerConfig) ShouldDiscover() bool { return c.DiscoveryURL != "" } +func (c *ServerConfig) ShouldDiscover() bool { + return c.DiscoveryURL != "" || len(c.DiscoveryCfg.Endpoints) > 0 +} // ReqTimeout returns timeout for request to finish. func (c *ServerConfig) ReqTimeout() time.Duration { @@ -380,3 +397,7 @@ func (c *ServerConfig) BootstrapTimeoutEffective() time.Duration { } func (c *ServerConfig) BackendPath() string { return datadir.ToBackendFileName(c.DataDir) } + +func (c *ServerConfig) MaxRequestBytesWithOverhead() uint { + return c.MaxRequestBytes + grpcOverheadBytes +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/config/v2_deprecation.go b/etcd/vendor/go.etcd.io/etcd/server/v3/config/v2_deprecation.go index 828bd9a8f4..c50401cc93 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/config/v2_deprecation.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/config/v2_deprecation.go @@ -17,18 +17,52 @@ package config type V2DeprecationEnum string const ( - // Default in v3.5. Issues a warning if v2store have meaningful content. - V2_DEPR_0_NOT_YET = V2DeprecationEnum("not-yet") + // V2Depr0NotYet means v2store isn't deprecated yet. + // Default in v3.5, and no longer supported in v3.6. + V2Depr0NotYet = V2DeprecationEnum("not-yet") + + // Deprecated: to be decommissioned in 3.7. Please use V2Depr0NotYet. + // TODO: remove in 3.7 + //revive:disable-next-line:var-naming + V2_DEPR_0_NOT_YET = V2Depr0NotYet + + // V2Depr1WriteOnly means only writing v2store is allowed. // Default in v3.6. Meaningful v2 state is not allowed. // The V2 files are maintained for v3.5 rollback. - V2_DEPR_1_WRITE_ONLY = V2DeprecationEnum("write-only") - // V2store is WIPED if found !!! - V2_DEPR_1_WRITE_ONLY_DROP = V2DeprecationEnum("write-only-drop-data") - // V2store is neither written nor read. Usage of this configuration is blocking + V2Depr1WriteOnly = V2DeprecationEnum("write-only") + + // Deprecated: to be decommissioned in 3.7. Please use V2Depr1WriteOnly. + // TODO: remove in 3.7 + //revive:disable-next-line:var-naming + V2_DEPR_1_WRITE_ONLY = V2Depr1WriteOnly + + // V2Depr1WriteOnlyDrop means v2store is WIPED if found !!! + // Will be default in 3.7. + V2Depr1WriteOnlyDrop = V2DeprecationEnum("write-only-drop-data") + + // Deprecated: to be decommissioned in 3.7. Pleae use V2Depr1WriteOnlyDrop. + // TODO: remove in 3.7 + //revive:disable-next-line:var-naming + V2_DEPR_1_WRITE_ONLY_DROP = V2Depr1WriteOnlyDrop + + // V2Depr2Gone means v2store is completely gone. The v2store is + // neither written nor read. Anything related to v2store will be + // cleaned up in v3.8. Usage of this configuration is blocking // ability to rollback to etcd v3.5. - V2_DEPR_2_GONE = V2DeprecationEnum("gone") + V2Depr2Gone = V2DeprecationEnum("gone") + + // Deprecated: to be decommissioned in 3.7. Please use V2Depr2Gone. + // TODO: remove in 3.7 + //revive:disable-next-line:var-naming + V2_DEPR_2_GONE = V2Depr2Gone + + // V2DeprDefault is the default deprecation level. + V2DeprDefault = V2Depr1WriteOnly - V2_DEPR_DEFAULT = V2_DEPR_0_NOT_YET + // Deprecated: to be decommissioned in 3.7. Please use V2DeprDefault. + // TODO: remove in 3.7 + //revive:disable-next-line:var-naming + V2_DEPR_DEFAULT = V2DeprDefault ) func (e V2DeprecationEnum) IsAtLeast(v2d V2DeprecationEnum) bool { @@ -37,13 +71,13 @@ func (e V2DeprecationEnum) IsAtLeast(v2d V2DeprecationEnum) bool { func (e V2DeprecationEnum) level() int { switch e { - case V2_DEPR_0_NOT_YET: + case V2Depr0NotYet: return 0 - case V2_DEPR_1_WRITE_ONLY: + case V2Depr1WriteOnly: return 1 - case V2_DEPR_1_WRITE_ONLY_DROP: + case V2Depr1WriteOnlyDrop: return 2 - case V2_DEPR_2_GONE: + case V2Depr2Gone: return 3 } panic("Unknown V2DeprecationEnum: " + e) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config.go b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config.go index 5e0fe25290..a344edc3d0 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config.go @@ -16,11 +16,13 @@ package embed import ( "crypto/tls" + "errors" + "flag" "fmt" - "io/ioutil" "math" "net" "net/http" + "net/netip" "net/url" "os" "path/filepath" @@ -28,41 +30,59 @@ import ( "sync" "time" + "go.uber.org/zap" + "golang.org/x/crypto/bcrypt" + "google.golang.org/grpc" + "sigs.k8s.io/yaml" + + bolt "go.etcd.io/bbolt" "go.etcd.io/etcd/client/pkg/v3/logutil" "go.etcd.io/etcd/client/pkg/v3/srv" "go.etcd.io/etcd/client/pkg/v3/tlsutil" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" + clientv3 "go.etcd.io/etcd/client/v3" + "go.etcd.io/etcd/pkg/v3/featuregate" "go.etcd.io/etcd/pkg/v3/flags" "go.etcd.io/etcd/pkg/v3/netutil" "go.etcd.io/etcd/server/v3/config" "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" "go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor" - - bolt "go.etcd.io/bbolt" - "go.uber.org/multierr" - "go.uber.org/zap" - "golang.org/x/crypto/bcrypt" - "google.golang.org/grpc" - "sigs.k8s.io/yaml" + "go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery" + "go.etcd.io/etcd/server/v3/features" ) const ( ClusterStateFlagNew = "new" ClusterStateFlagExisting = "existing" - DefaultName = "default" - DefaultMaxSnapshots = 5 - DefaultMaxWALs = 5 - DefaultMaxTxnOps = uint(128) - DefaultWarningApplyDuration = 100 * time.Millisecond - DefaultMaxRequestBytes = 1.5 * 1024 * 1024 - DefaultMaxConcurrentStreams = math.MaxUint32 - DefaultGRPCKeepAliveMinTime = 5 * time.Second - DefaultGRPCKeepAliveInterval = 2 * time.Hour - DefaultGRPCKeepAliveTimeout = 20 * time.Second - DefaultDowngradeCheckTime = 5 * time.Second + DefaultName = "default" + DefaultMaxSnapshots = 5 + DefaultMaxWALs = 5 + DefaultMaxTxnOps = uint(128) + DefaultWarningApplyDuration = 100 * time.Millisecond + DefaultWarningUnaryRequestDuration = 300 * time.Millisecond + DefaultMaxRequestBytes = 1.5 * 1024 * 1024 + DefaultMaxConcurrentStreams = math.MaxUint32 + DefaultGRPCKeepAliveMinTime = 5 * time.Second + DefaultGRPCKeepAliveInterval = 2 * time.Hour + DefaultGRPCKeepAliveTimeout = 20 * time.Second + DefaultDowngradeCheckTime = 5 * time.Second + DefaultAutoCompactionMode = "periodic" + DefaultAutoCompactionRetention = "0" + DefaultAuthToken = "simple" + DefaultCompactHashCheckTime = time.Minute + DefaultLoggingFormat = "json" + + DefaultDiscoveryDialTimeout = 2 * time.Second + DefaultDiscoveryRequestTimeOut = 5 * time.Second + DefaultDiscoveryKeepAliveTime = 2 * time.Second + DefaultDiscoveryKeepAliveTimeOut = 6 * time.Second + DefaultDiscoveryInsecureTransport = true + DefaultSelfSignedCertValidity = 1 + DefaultTLSMinVersion = string(tlsutil.TLSVersion12) DefaultListenPeerURLs = "http://localhost:2380" DefaultListenClientURLs = "http://localhost:2379" @@ -82,27 +102,36 @@ const ( DefaultLogRotationConfig = `{"maxsize": 100, "maxage": 0, "maxbackups": 0, "localtime": false, "compress": false}` // ExperimentalDistributedTracingAddress is the default collector address. + // TODO: delete in v3.7 + // Deprecated: Use DefaultDistributedTracingAddress instead. Will be decommissioned in v3.7. ExperimentalDistributedTracingAddress = "localhost:4317" + // DefaultDistributedTracingAddress is the default collector address. + DefaultDistributedTracingAddress = "localhost:4317" // ExperimentalDistributedTracingServiceName is the default etcd service name. + // TODO: delete in v3.7 + // Deprecated: Use DefaultDistributedTracingServiceName instead. Will be decommissioned in v3.7. ExperimentalDistributedTracingServiceName = "etcd" + // DefaultDistributedTracingServiceName is the default etcd service name. + DefaultDistributedTracingServiceName = "etcd" + + DefaultExperimentalTxnModeWriteWithSharedBuffer = true // DefaultStrictReconfigCheck is the default value for "--strict-reconfig-check" flag. // It's enabled by default. DefaultStrictReconfigCheck = true - // DefaultEnableV2 is the default value for "--enable-v2" flag. - // v2 API is disabled by default. - DefaultEnableV2 = false // maxElectionMs specifies the maximum value of election timeout. - // More details are listed in ../Documentation/tuning.md#time-parameters. + // More details are listed on etcd.io/docs > version > tuning/#time-parameters maxElectionMs = 50000 // backend freelist map type freelistArrayType = "array" + + ServerFeatureGateFlagName = "feature-gates" ) var ( ErrConflictBootstrapFlags = fmt.Errorf("multiple discovery or bootstrap flags are set. " + - "Choose one of \"initial-cluster\", \"discovery\" or \"discovery-srv\"") + "Choose one of \"initial-cluster\", \"discovery\", \"discovery-endpoints\" or \"discovery-srv\"") ErrUnsetAdvertiseClientURLsFlag = fmt.Errorf("--advertise-client-urls is required when --listen-client-urls is set explicitly") ErrLogRotationInvalidLogOutput = fmt.Errorf("--log-outputs requires a single file path when --log-rotate-config-json is defined") @@ -114,6 +143,28 @@ var ( // indirection for testing getCluster = srv.GetCluster + + // in 3.6, we are migration all the --experimental flags to feature gate and flags without the prefix. + // This is the mapping from the non boolean `experimental-` to the new flags. + // TODO: delete in v3.7 + experimentalFlagMigrationMap = map[string]string{ + "experimental-compact-hash-check-time": "compact-hash-check-time", + "experimental-corrupt-check-time": "corrupt-check-time", + "experimental-compaction-batch-limit": "compaction-batch-limit", + "experimental-watch-progress-notify-interval": "watch-progress-notify-interval", + "experimental-warning-apply-duration": "warning-apply-duration", + "experimental-bootstrap-defrag-threshold-megabytes": "bootstrap-defrag-threshold-megabytes", + "experimental-memory-mlock": "memory-mlock", + "experimental-snapshot-catchup-entries": "snapshot-catchup-entries", + "experimental-compaction-sleep-interval": "compaction-sleep-interval", + "experimental-downgrade-check-time": "downgrade-check-time", + "experimental-peer-skip-client-san-verification": "peer-skip-client-san-verification", + "experimental-enable-distributed-tracing": "enable-distributed-tracing", + "experimental-distributed-tracing-address": "distributed-tracing-address", + "experimental-distributed-tracing-service-name": "distributed-tracing-service-name", + "experimental-distributed-tracing-instance-id": "distributed-tracing-instance-id", + "experimental-distributed-tracing-sampling-rate": "distributed-tracing-sampling-rate", + } ) var ( @@ -139,23 +190,40 @@ func init() { // Config holds the arguments for configuring an etcd server. type Config struct { - Name string `json:"name"` - Dir string `json:"data-dir"` + Name string `json:"name"` + Dir string `json:"data-dir"` + //revive:disable-next-line:var-naming WalDir string `json:"wal-dir"` + // SnapshotCount is the number of committed transactions that trigger a snapshot to disk. + // TODO: remove it in 3.7. + // Deprecated: Will be decommissioned in v3.7. SnapshotCount uint64 `json:"snapshot-count"` - // SnapshotCatchUpEntries is the number of entries for a slow follower + // ExperimentalSnapshotCatchUpEntries is the number of entries for a slow follower + // to catch-up after compacting the raft storage entries. + // We expect the follower has a millisecond level latency with the leader. + // The max throughput is around 10K. Keep a 5K entries is enough for helping + // follower to catch up. + // TODO: remove in v3.7. + // Note we made a mistake in https://github.com/etcd-io/etcd/pull/15033. The json tag + // `*-catch-up-*` isn't consistent with the command line flag `*-catchup-*`. + // Deprecated: Use SnapshotCatchUpEntries instead. Will be removed in v3.7. + ExperimentalSnapshotCatchUpEntries uint64 `json:"experimental-snapshot-catch-up-entries"` + + // SnapshotCatchUpEntries is the number of entires for a slow follower // to catch-up after compacting the raft storage entries. // We expect the follower has a millisecond level latency with the leader. // The max throughput is around 10K. Keep a 5K entries is enough for helping // follower to catch up. - // WARNING: only change this for tests. - // Always use "DefaultSnapshotCatchUpEntries" - SnapshotCatchUpEntries uint64 `json:"experimental-snapshot-catch-up-entries"` + SnapshotCatchUpEntries uint64 `json:"snapshot-catchup-entries"` + // MaxSnapFiles is the maximum number of snapshot files. + // TODO: remove it in 3.7. + // Deprecated: Will be removed in v3.7. MaxSnapFiles uint `json:"max-snapshots"` - MaxWalFiles uint `json:"max-wals"` + //revive:disable-next-line:var-naming + MaxWalFiles uint `json:"max-wals"` // TickMs is the number of milliseconds between heartbeat ticks. // TODO: decouple tickMs and heartbeat tick (current heartbeat tick = 1). @@ -206,12 +274,16 @@ type Config struct { // streams that each client can open at a time. MaxConcurrentStreams uint32 `json:"max-concurrent-streams"` + //revive:disable:var-naming ListenPeerUrls, ListenClientUrls, ListenClientHttpUrls []url.URL AdvertisePeerUrls, AdvertiseClientUrls []url.URL - ClientTLSInfo transport.TLSInfo - ClientAutoTLS bool - PeerTLSInfo transport.TLSInfo - PeerAutoTLS bool + //revive:enable:var-naming + + ClientTLSInfo transport.TLSInfo + ClientAutoTLS bool + PeerTLSInfo transport.TLSInfo + PeerAutoTLS bool + // SelfSignedCertValidity specifies the validity period of the client and peer certificates // that are automatically generated by etcd when you specify ClientAutoTLS and PeerAutoTLS, // the unit is year, and the default is 1 @@ -223,23 +295,24 @@ type Config struct { CipherSuites []string `json:"cipher-suites"` // TlsMinVersion is the minimum accepted TLS version between client/server and peers. + //revive:disable-next-line:var-naming TlsMinVersion string `json:"tls-min-version"` + // TlsMaxVersion is the maximum accepted TLS version between client/server and peers. + //revive:disable-next-line:var-naming TlsMaxVersion string `json:"tls-max-version"` ClusterState string `json:"initial-cluster-state"` DNSCluster string `json:"discovery-srv"` DNSClusterServiceName string `json:"discovery-srv-name"` Dproxy string `json:"discovery-proxy"` - Durl string `json:"discovery"` - InitialCluster string `json:"initial-cluster"` - InitialClusterToken string `json:"initial-cluster-token"` - StrictReconfigCheck bool `json:"strict-reconfig-check"` - // EnableV2 exposes the deprecated V2 API surface. - // TODO: Delete in 3.6 (https://github.com/etcd-io/etcd/issues/12913) - // Deprecated in 3.5. - EnableV2 bool `json:"enable-v2"` + Durl string `json:"discovery"` + DiscoveryCfg v3discovery.DiscoveryConfig `json:"discovery-config"` + + InitialCluster string `json:"initial-cluster"` + InitialClusterToken string `json:"initial-cluster-token"` + StrictReconfigCheck bool `json:"strict-reconfig-check"` // AutoCompactionMode is either 'periodic' or 'revision'. AutoCompactionMode string `json:"auto-compaction-mode"` @@ -264,6 +337,13 @@ type Config struct { // before closing a non-responsive connection. 0 to disable. GRPCKeepAliveTimeout time.Duration `json:"grpc-keepalive-timeout"` + // GRPCAdditionalServerOptions is the additional server option hook + // for changing the default internal gRPC configuration. Note these + // additional configurations take precedence over the existing individual + // configurations if present. Please refer to + // https://github.com/etcd-io/etcd/pull/14066#issuecomment-1248682996 + GRPCAdditionalServerOptions []grpc.ServerOption `json:"grpc-additional-server-options"` + // SocketOpts are socket options passed to listener config. SocketOpts transport.SocketOpts `json:"socket-options"` @@ -308,7 +388,7 @@ type Config struct { UserHandlers map[string]http.Handler `json:"-"` // ServiceRegister is for registering users' gRPC services. A simple usage example: // cfg := embed.NewConfig() - // cfg.ServerRegister = func(s *grpc.Server) { + // cfg.ServiceRegister = func(s *grpc.Server) { // pb.RegisterFooServer(s, &fooServer{}) // pb.RegisterBarServer(s, &barServer{}) // } @@ -318,36 +398,78 @@ type Config struct { AuthToken string `json:"auth-token"` BcryptCost uint `json:"bcrypt-cost"` - // AuthTokenTTL specifies the TTL in seconds of the simple token + // AuthTokenTTL in seconds of the simple token AuthTokenTTL uint `json:"auth-token-ttl"` - ExperimentalInitialCorruptCheck bool `json:"experimental-initial-corrupt-check"` - ExperimentalCorruptCheckTime time.Duration `json:"experimental-corrupt-check-time"` - ExperimentalCompactHashCheckEnabled bool `json:"experimental-compact-hash-check-enabled"` - ExperimentalCompactHashCheckTime time.Duration `json:"experimental-compact-hash-check-time"` - // ExperimentalEnableV2V3 configures URLs that expose deprecated V2 API working on V3 store. - // Deprecated in v3.5. - // TODO: Delete in v3.6 (https://github.com/etcd-io/etcd/issues/12913) - ExperimentalEnableV2V3 string `json:"experimental-enable-v2v3"` + // ExperimentalInitialCorruptCheck defines to check data corrution on boot. + // TODO: delete in v3.7 + // Deprecated: Use InitialCorruptCheck Feature Gate instead. Will be decommissioned in v3.7. + ExperimentalInitialCorruptCheck bool `json:"experimental-initial-corrupt-check"` + // ExperimentalCorruptCheckTime is the duration of time between cluster corruption check passes. + // TODO: delete in v3.7 + // Deprecated: Use CorruptCheckTime instead. Will be decommissioned in v3.7. + ExperimentalCorruptCheckTime time.Duration `json:"experimental-corrupt-check-time"` + // CorruptCheckTime is the duration of time between cluster corruption check passes. + CorruptCheckTime time.Duration `json:"corrupt-check-time"` + // ExperimentalCompactHashCheckEnabled enables leader to periodically check followers compaction hashes. + // TODO: delete in v3.7 + // Deprecated: Use CompactHashCheck Feature Gate. Will be decommissioned in v3.7. + ExperimentalCompactHashCheckEnabled bool `json:"experimental-compact-hash-check-enabled"` + // ExperimentalCompactHashCheckTime is the duration of time between leader checks followers compaction hashes. + // TODO: delete in v3.7 + // Deprecated: Use CompactHashCheckTime instead. Will be decommissioned in v3.7. + ExperimentalCompactHashCheckTime time.Duration `json:"experimental-compact-hash-check-time"` + // CompactHashCheckTime is the duration of time between leader checks followers compaction hashes. + CompactHashCheckTime time.Duration `json:"compact-hash-check-time"` + // ExperimentalEnableLeaseCheckpoint enables leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change. ExperimentalEnableLeaseCheckpoint bool `json:"experimental-enable-lease-checkpoint"` // ExperimentalEnableLeaseCheckpointPersist enables persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled. // Requires experimental-enable-lease-checkpoint to be enabled. - // Deprecated in v3.6. // TODO: Delete in v3.7 + // Deprecated: To be decommissioned in v3.7. ExperimentalEnableLeaseCheckpointPersist bool `json:"experimental-enable-lease-checkpoint-persist"` - ExperimentalCompactionBatchLimit int `json:"experimental-compaction-batch-limit"` + // ExperimentalCompactionBatchLimit Sets the maximum revisions deleted in each compaction batch. + // TODO: Delete in v3.7 + // Deprecated: Use CompactionBatchLimit instead. Will be decommissioned in v3.7. + ExperimentalCompactionBatchLimit int `json:"experimental-compaction-batch-limit"` + // CompactionBatchLimit Sets the maximum revisions deleted in each compaction batch. + CompactionBatchLimit int `json:"compaction-batch-limit"` // ExperimentalCompactionSleepInterval is the sleep interval between every etcd compaction loop. - ExperimentalCompactionSleepInterval time.Duration `json:"experimental-compaction-sleep-interval"` + // TODO: Delete in v3.7 + // Deprecated: Use CompactionSleepInterval instead. Will be decommissioned in v3.7. + ExperimentalCompactionSleepInterval time.Duration `json:"experimental-compaction-sleep-interval"` + // CompactionSleepInterval is the sleep interval between every etcd compaction loop. + CompactionSleepInterval time.Duration `json:"compaction-sleep-interval"` + // ExperimentalWatchProgressNotifyInterval is the time duration of periodic watch progress notifications. + // TODO: Delete in v3.7 + // Deprecated: Use WatchProgressNotifyInterval instead. Will be decommissioned in v3.7. ExperimentalWatchProgressNotifyInterval time.Duration `json:"experimental-watch-progress-notify-interval"` + // WatchProgressNotifyInterval is the time duration of periodic watch progress notifications. + WatchProgressNotifyInterval time.Duration `json:"watch-progress-notify-interval"` // ExperimentalWarningApplyDuration is the time duration after which a warning is generated if applying request // takes more time than this value. + // TODO: Delete in v3.7 + // Deprecated: Use WarningApplyDuration instead. Will be decommissioned in v3.7. ExperimentalWarningApplyDuration time.Duration `json:"experimental-warning-apply-duration"` + // WarningApplyDuration is the time duration after which a warning is generated if applying request + WarningApplyDuration time.Duration `json:"warning-apply-duration"` // ExperimentalBootstrapDefragThresholdMegabytes is the minimum number of megabytes needed to be freed for etcd server to // consider running defrag during bootstrap. Needs to be set to non-zero value to take effect. + // TODO: Delete in v3.7 + // Deprecated: Use BootstrapDefragThresholdMegabytes instead. Will be decommissioned in v3.7. ExperimentalBootstrapDefragThresholdMegabytes uint `json:"experimental-bootstrap-defrag-threshold-megabytes"` - // ExperimentalMaxLearners sets a limit to the number of learner members that can exist in the cluster membership. - ExperimentalMaxLearners int `json:"experimental-max-learners"` + // BootstrapDefragThresholdMegabytes is the minimum number of megabytes needed to be freed for etcd server to + BootstrapDefragThresholdMegabytes uint `json:"bootstrap-defrag-threshold-megabytes"` + // WarningUnaryRequestDuration is the time duration after which a warning is generated if applying + // unary request takes more time than this value. + WarningUnaryRequestDuration time.Duration `json:"warning-unary-request-duration"` + // ExperimentalWarningUnaryRequestDuration is the time duration after which a warning is generated if applying + // TODO: Delete in v3.7 + // Deprecated: Use WarningUnaryRequestDuration. Will be decommissioned in v3.7. + ExperimentalWarningUnaryRequestDuration time.Duration `json:"experimental-warning-unary-request-duration"` + // MaxLearners sets a limit to the number of learner members that can exist in the cluster membership. + MaxLearners int `json:"max-learners"` // ForceNewCluster starts a new cluster even if previously started; unsafe. ForceNewCluster bool `json:"force-new-cluster"` @@ -359,27 +481,61 @@ type Config struct { ListenMetricsUrlsJSON string `json:"listen-metrics-urls"` // ExperimentalEnableDistributedTracing indicates if experimental tracing using OpenTelemetry is enabled. + // TODO: delete in v3.7 + // Deprecated: Use EnableDistributedTracing instead. Will be decommissioned in v3.7. ExperimentalEnableDistributedTracing bool `json:"experimental-enable-distributed-tracing"` + // EnableDistributedTracing indicates if tracing using OpenTelemetry is enabled. + EnableDistributedTracing bool `json:"enable-distributed-tracing"` // ExperimentalDistributedTracingAddress is the address of the OpenTelemetry Collector. // Can only be set if ExperimentalEnableDistributedTracing is true. + // TODO: delete in v3.7 + // Deprecated: Use DistributedTracingAddress instead. Will be decommissioned in v3.7. ExperimentalDistributedTracingAddress string `json:"experimental-distributed-tracing-address"` + // DistributedTracingAddress is the address of the OpenTelemetry Collector. + // Can only be set if EnableDistributedTracing is true. + DistributedTracingAddress string `json:"distributed-tracing-address"` // ExperimentalDistributedTracingServiceName is the name of the service. // Can only be used if ExperimentalEnableDistributedTracing is true. + // TODO: delete in v3.7 + // Deprecated: Use DistributedTracingServiceName instead. Will be decommissioned in v3.7. ExperimentalDistributedTracingServiceName string `json:"experimental-distributed-tracing-service-name"` + // DistributedTracingServiceName is the name of the service. + // Can only be used if EnableDistributedTracing is true. + DistributedTracingServiceName string `json:"distributed-tracing-service-name"` // ExperimentalDistributedTracingServiceInstanceID is the ID key of the service. // This ID must be unique, as helps to distinguish instances of the same service // that exist at the same time. // Can only be used if ExperimentalEnableDistributedTracing is true. + // TODO: delete in v3.7 + // Deprecated: Use DistributedTracingServiceInstanceID instead. Will be decommissioned in v3.7. ExperimentalDistributedTracingServiceInstanceID string `json:"experimental-distributed-tracing-instance-id"` + // DistributedTracingServiceInstanceID is the ID key of the service. + // This ID must be unique, as helps to distinguish instances of the same service + // that exist at the same time. + // Can only be used if EnableDistributedTracing is true. + DistributedTracingServiceInstanceID string `json:"distributed-tracing-instance-id"` // ExperimentalDistributedTracingSamplingRatePerMillion is the number of samples to collect per million spans. // Defaults to 0. + // TODO: delete in v3.7 + // Deprecated: Use DistributedTracingSamplingRatePerMillion instead. Will be decommissioned in v3.7. ExperimentalDistributedTracingSamplingRatePerMillion int `json:"experimental-distributed-tracing-sampling-rate"` + // DistributedTracingSamplingRatePerMillion is the number of samples to collect per million spans. + // Defaults to 0. + DistributedTracingSamplingRatePerMillion int `json:"distributed-tracing-sampling-rate"` + + // ExperimentalPeerSkipClientSanVerification determines whether to skip verification of SAN field + // in client certificate for peer connections. + // TODO: Delete in v3.7 + // Deprecated: Use `peer-skip-client-san-verification` instead. Will be decommissioned in v3.7. + ExperimentalPeerSkipClientSanVerification bool `json:"experimental-peer-skip-client-san-verification"` // Logger is logger options: currently only supports "zap". // "capnslog" is removed in v3.5. Logger string `json:"logger"` // LogLevel configures log level. Only supports debug, info, warn, error, panic, or fatal. Default 'info'. LogLevel string `json:"log-level"` + // LogFormat set log encoding. Only supports json, console. Default is 'json'. + LogFormat string `json:"log-format"` // LogOutputs is either: // - "default" as os.Stderr, // - "stderr" as os.Stderr, @@ -407,24 +563,46 @@ type Config struct { // Setting this is unsafe and will cause data loss. UnsafeNoFsync bool `json:"unsafe-no-fsync"` + // ExperimentalDowngradeCheckTime is the duration between two downgrade status checks (in seconds). + // TODO: Delete `ExperimentalDowngradeCheckTime` in v3.7. + // Deprecated: Use DowngradeCheckTime instead. Will be decommissioned in v3.7. ExperimentalDowngradeCheckTime time.Duration `json:"experimental-downgrade-check-time"` + // DowngradeCheckTime is the duration between two downgrade status checks (in seconds). + DowngradeCheckTime time.Duration `json:"downgrade-check-time"` - // ExperimentalMemoryMlock enables mlocking of etcd owned memory pages. + // MemoryMlock enables mlocking of etcd owned memory pages. // The setting improves etcd tail latency in environments were: // - memory pressure might lead to swapping pages to disk // - disk latency might be unstable // Currently all etcd memory gets mlocked, but in future the flag can // be refined to mlock in-use area of bbolt only. + MemoryMlock bool `json:"memory-mlock"` + + // ExperimentalMemoryMlock enables mlocking of etcd owned memory pages. + // TODO: Delete in v3.7 + // Deprecated: Use MemoryMlock instad. To be decommissioned in v3.7. ExperimentalMemoryMlock bool `json:"experimental-memory-mlock"` // ExperimentalTxnModeWriteWithSharedBuffer enables write transaction to use a shared buffer in its readonly check operations. + // TODO: Delete in v3.7 + // Deprecated: Use TxnModeWriteWithSharedBuffer Feature Flag. Will be decommissioned in v3.7. ExperimentalTxnModeWriteWithSharedBuffer bool `json:"experimental-txn-mode-write-with-shared-buffer"` // ExperimentalStopGRPCServiceOnDefrag enables etcd gRPC service to stop serving client requests on defragmentation. + // TODO: Delete in v3.7 + // Deprecated: Use StopGRPCServiceOnDefrag Feature Flag. Will be decommissioned in v3.7. ExperimentalStopGRPCServiceOnDefrag bool `json:"experimental-stop-grpc-service-on-defrag"` - // V2Deprecation describes phase of API & Storage V2 support + // V2Deprecation describes phase of API & Storage V2 support. + // Do not set this field for embedded use cases, as it has no effect. However, setting it will not cause any harm. + // TODO: Delete in v3.8 + // Deprecated: The default value is enforced, to be removed in v3.8. V2Deprecation config.V2DeprecationEnum `json:"v2-deprecation"` + + // ServerFeatureGate is a server level feature gate + ServerFeatureGate featuregate.FeatureGate + // FlagsExplicitlySet stores if a flag is explicitly set from the cmd line or config file. + FlagsExplicitlySet map[string]bool } // configYAML holds the config suitable for yaml parsing @@ -435,29 +613,32 @@ type configYAML struct { // configJSON has file options that are translated into Config options type configJSON struct { - ListenPeerUrls string `json:"listen-peer-urls"` - ListenClientUrls string `json:"listen-client-urls"` - ListenClientHttpUrls string `json:"listen-client-http-urls"` - AdvertisePeerUrls string `json:"initial-advertise-peer-urls"` - AdvertiseClientUrls string `json:"advertise-client-urls"` + ListenPeerURLs string `json:"listen-peer-urls"` + ListenClientURLs string `json:"listen-client-urls"` + ListenClientHTTPURLs string `json:"listen-client-http-urls"` + AdvertisePeerURLs string `json:"initial-advertise-peer-urls"` + AdvertiseClientURLs string `json:"advertise-client-urls"` CORSJSON string `json:"cors"` HostWhitelistJSON string `json:"host-whitelist"` ClientSecurityJSON securityConfig `json:"client-transport-security"` PeerSecurityJSON securityConfig `json:"peer-transport-security"` + + ServerFeatureGatesJSON string `json:"feature-gates"` } type securityConfig struct { - CertFile string `json:"cert-file"` - KeyFile string `json:"key-file"` - ClientCertFile string `json:"client-cert-file"` - ClientKeyFile string `json:"client-key-file"` - CertAuth bool `json:"client-cert-auth"` - TrustedCAFile string `json:"trusted-ca-file"` - AutoTLS bool `json:"auto-tls"` - AllowedCNs []string `json:"allowed-cn"` - AllowedHostnames []string `json:"allowed-hostname"` + CertFile string `json:"cert-file"` + KeyFile string `json:"key-file"` + ClientCertFile string `json:"client-cert-file"` + ClientKeyFile string `json:"client-key-file"` + CertAuth bool `json:"client-cert-auth"` + TrustedCAFile string `json:"trusted-ca-file"` + AutoTLS bool `json:"auto-tls"` + AllowedCNs []string `json:"allowed-cn"` + AllowedHostnames []string `json:"allowed-hostname"` + SkipClientSANVerify bool `json:"skip-client-san-verification,omitempty"` } // NewConfig creates a new Config populated with default values. @@ -472,13 +653,14 @@ func NewConfig() *Config { Name: DefaultName, - SnapshotCount: etcdserver.DefaultSnapshotCount, - SnapshotCatchUpEntries: etcdserver.DefaultSnapshotCatchUpEntries, + SnapshotCount: etcdserver.DefaultSnapshotCount, + ExperimentalSnapshotCatchUpEntries: etcdserver.DefaultSnapshotCatchUpEntries, + SnapshotCatchUpEntries: etcdserver.DefaultSnapshotCatchUpEntries, - MaxTxnOps: DefaultMaxTxnOps, - MaxRequestBytes: DefaultMaxRequestBytes, - MaxConcurrentStreams: DefaultMaxConcurrentStreams, - ExperimentalWarningApplyDuration: DefaultWarningApplyDuration, + MaxTxnOps: DefaultMaxTxnOps, + MaxRequestBytes: DefaultMaxRequestBytes, + MaxConcurrentStreams: DefaultMaxConcurrentStreams, + WarningApplyDuration: DefaultWarningApplyDuration, GRPCKeepAliveMinTime: DefaultGRPCKeepAliveMinTime, GRPCKeepAliveInterval: DefaultGRPCKeepAliveInterval, @@ -503,41 +685,287 @@ func NewConfig() *Config { StrictReconfigCheck: DefaultStrictReconfigCheck, Metrics: "basic", - EnableV2: DefaultEnableV2, CORS: map[string]struct{}{"*": {}}, HostWhitelist: map[string]struct{}{"*": {}}, - AuthToken: "simple", - BcryptCost: uint(bcrypt.DefaultCost), - AuthTokenTTL: 300, + AuthToken: DefaultAuthToken, + BcryptCost: uint(bcrypt.DefaultCost), + AuthTokenTTL: 300, + SelfSignedCertValidity: DefaultSelfSignedCertValidity, + TlsMinVersion: DefaultTLSMinVersion, PreVote: true, loggerMu: new(sync.RWMutex), logger: nil, Logger: "zap", + LogFormat: DefaultLoggingFormat, LogOutputs: []string{DefaultLogOutput}, LogLevel: logutil.DefaultLogLevel, EnableLogRotation: false, LogRotationConfigJSON: DefaultLogRotationConfig, EnableGRPCGateway: true, - ExperimentalDowngradeCheckTime: DefaultDowngradeCheckTime, - ExperimentalMemoryMlock: false, - ExperimentalTxnModeWriteWithSharedBuffer: true, - ExperimentalStopGRPCServiceOnDefrag: false, - ExperimentalMaxLearners: membership.DefaultMaxLearners, - - ExperimentalCompactHashCheckEnabled: false, - ExperimentalCompactHashCheckTime: time.Minute, + ExperimentalDowngradeCheckTime: DefaultDowngradeCheckTime, + DowngradeCheckTime: DefaultDowngradeCheckTime, + MemoryMlock: false, + // TODO: delete in v3.7 + ExperimentalMemoryMlock: false, + ExperimentalStopGRPCServiceOnDefrag: false, + MaxLearners: membership.DefaultMaxLearners, + + ExperimentalTxnModeWriteWithSharedBuffer: DefaultExperimentalTxnModeWriteWithSharedBuffer, + ExperimentalDistributedTracingAddress: DefaultDistributedTracingAddress, + DistributedTracingAddress: DefaultDistributedTracingAddress, + ExperimentalDistributedTracingServiceName: DefaultDistributedTracingServiceName, + DistributedTracingServiceName: DefaultDistributedTracingServiceName, + + CompactHashCheckTime: DefaultCompactHashCheckTime, + // TODO: delete in v3.7 + ExperimentalCompactHashCheckTime: DefaultCompactHashCheckTime, + + V2Deprecation: config.V2DeprDefault, + + DiscoveryCfg: v3discovery.DiscoveryConfig{ + ConfigSpec: clientv3.ConfigSpec{ + DialTimeout: DefaultDiscoveryDialTimeout, + RequestTimeout: DefaultDiscoveryRequestTimeOut, + KeepAliveTime: DefaultDiscoveryKeepAliveTime, + KeepAliveTimeout: DefaultDiscoveryKeepAliveTimeOut, + + Secure: &clientv3.SecureConfig{ + InsecureTransport: true, + }, + Auth: &clientv3.AuthConfig{}, + }, + }, - V2Deprecation: config.V2_DEPR_DEFAULT, + AutoCompactionMode: DefaultAutoCompactionMode, + AutoCompactionRetention: DefaultAutoCompactionRetention, + ServerFeatureGate: features.NewDefaultServerFeatureGate(DefaultName, nil), + FlagsExplicitlySet: map[string]bool{}, } cfg.InitialCluster = cfg.InitialClusterFromName(cfg.Name) return cfg } +func (cfg *Config) AddFlags(fs *flag.FlagSet) { + // member + fs.StringVar(&cfg.Dir, "data-dir", cfg.Dir, "Path to the data directory.") + fs.StringVar(&cfg.WalDir, "wal-dir", cfg.WalDir, "Path to the dedicated wal directory.") + fs.Var( + flags.NewUniqueURLsWithExceptions(DefaultListenPeerURLs, ""), + "listen-peer-urls", + "List of URLs to listen on for peer traffic.", + ) + fs.Var( + flags.NewUniqueURLsWithExceptions(DefaultListenClientURLs, ""), "listen-client-urls", + "List of URLs to listen on for client grpc traffic and http as long as --listen-client-http-urls is not specified.", + ) + fs.Var( + flags.NewUniqueURLsWithExceptions("", ""), "listen-client-http-urls", + "List of URLs to listen on for http only client traffic. Enabling this flag removes http services from --listen-client-urls.", + ) + fs.Var( + flags.NewUniqueURLsWithExceptions("", ""), + "listen-metrics-urls", + "List of URLs to listen on for the metrics and health endpoints.", + ) + fs.UintVar(&cfg.MaxSnapFiles, "max-snapshots", cfg.MaxSnapFiles, "Maximum number of snapshot files to retain (0 is unlimited). Deprecated in v3.6 and will be decommissioned in v3.7.") + fs.UintVar(&cfg.MaxWalFiles, "max-wals", cfg.MaxWalFiles, "Maximum number of wal files to retain (0 is unlimited).") + fs.StringVar(&cfg.Name, "name", cfg.Name, "Human-readable name for this member.") + fs.Uint64Var(&cfg.SnapshotCount, "snapshot-count", cfg.SnapshotCount, "Number of committed transactions to trigger a snapshot to disk. Deprecated in v3.6 and will be decommissioned in v3.7.") + fs.UintVar(&cfg.TickMs, "heartbeat-interval", cfg.TickMs, "Time (in milliseconds) of a heartbeat interval.") + fs.UintVar(&cfg.ElectionMs, "election-timeout", cfg.ElectionMs, "Time (in milliseconds) for an election to timeout.") + fs.BoolVar(&cfg.InitialElectionTickAdvance, "initial-election-tick-advance", cfg.InitialElectionTickAdvance, "Whether to fast-forward initial election ticks on boot for faster election.") + fs.Int64Var(&cfg.QuotaBackendBytes, "quota-backend-bytes", cfg.QuotaBackendBytes, "Sets the maximum size (in bytes) that the etcd backend database may consume. Exceeding this triggers an alarm and puts etcd in read-only mode. Set to 0 to use the default 2GiB limit.") + fs.StringVar(&cfg.BackendFreelistType, "backend-bbolt-freelist-type", cfg.BackendFreelistType, "BackendFreelistType specifies the type of freelist that boltdb backend uses(array and map are supported types)") + fs.DurationVar(&cfg.BackendBatchInterval, "backend-batch-interval", cfg.BackendBatchInterval, "BackendBatchInterval is the maximum time before commit the backend transaction.") + fs.IntVar(&cfg.BackendBatchLimit, "backend-batch-limit", cfg.BackendBatchLimit, "BackendBatchLimit is the maximum operations before commit the backend transaction.") + fs.UintVar(&cfg.MaxTxnOps, "max-txn-ops", cfg.MaxTxnOps, "Maximum number of operations permitted in a transaction.") + fs.UintVar(&cfg.MaxRequestBytes, "max-request-bytes", cfg.MaxRequestBytes, "Maximum client request size in bytes the server will accept.") + fs.DurationVar(&cfg.GRPCKeepAliveMinTime, "grpc-keepalive-min-time", cfg.GRPCKeepAliveMinTime, "Minimum interval duration that a client should wait before pinging server.") + fs.DurationVar(&cfg.GRPCKeepAliveInterval, "grpc-keepalive-interval", cfg.GRPCKeepAliveInterval, "Frequency duration of server-to-client ping to check if a connection is alive (0 to disable).") + fs.DurationVar(&cfg.GRPCKeepAliveTimeout, "grpc-keepalive-timeout", cfg.GRPCKeepAliveTimeout, "Additional duration of wait before closing a non-responsive connection (0 to disable).") + fs.BoolVar(&cfg.SocketOpts.ReusePort, "socket-reuse-port", cfg.SocketOpts.ReusePort, "Enable to set socket option SO_REUSEPORT on listeners allowing rebinding of a port already in use.") + fs.BoolVar(&cfg.SocketOpts.ReuseAddress, "socket-reuse-address", cfg.SocketOpts.ReuseAddress, "Enable to set socket option SO_REUSEADDR on listeners allowing binding to an address in `TIME_WAIT` state.") + + fs.Var(flags.NewUint32Value(cfg.MaxConcurrentStreams), "max-concurrent-streams", "Maximum concurrent streams that each client can open at a time.") + + // raft connection timeouts + fs.DurationVar(&rafthttp.ConnReadTimeout, "raft-read-timeout", rafthttp.DefaultConnReadTimeout, "Read timeout set on each rafthttp connection") + fs.DurationVar(&rafthttp.ConnWriteTimeout, "raft-write-timeout", rafthttp.DefaultConnWriteTimeout, "Write timeout set on each rafthttp connection") + + // clustering + fs.Var( + flags.NewUniqueURLsWithExceptions(DefaultInitialAdvertisePeerURLs, ""), + "initial-advertise-peer-urls", + "List of this member's peer URLs to advertise to the rest of the cluster.", + ) + + fs.Var( + flags.NewUniqueURLsWithExceptions(DefaultAdvertiseClientURLs, ""), + "advertise-client-urls", + "List of this member's client URLs to advertise to the public.", + ) + + fs.StringVar(&cfg.Durl, "discovery", cfg.Durl, "Discovery URL used to bootstrap the cluster for v2 discovery. Will be deprecated in v3.7, and be decommissioned in v3.8.") + + fs.Var( + flags.NewUniqueStringsValue(""), + "discovery-endpoints", + "V3 discovery: List of gRPC endpoints of the discovery service.", + ) + fs.StringVar(&cfg.DiscoveryCfg.Token, "discovery-token", "", "V3 discovery: discovery token for the etcd cluster to be bootstrapped.") + fs.DurationVar(&cfg.DiscoveryCfg.DialTimeout, "discovery-dial-timeout", cfg.DiscoveryCfg.DialTimeout, "V3 discovery: dial timeout for client connections.") + fs.DurationVar(&cfg.DiscoveryCfg.RequestTimeout, "discovery-request-timeout", cfg.DiscoveryCfg.RequestTimeout, "V3 discovery: timeout for discovery requests (excluding dial timeout).") + fs.DurationVar(&cfg.DiscoveryCfg.KeepAliveTime, "discovery-keepalive-time", cfg.DiscoveryCfg.KeepAliveTime, "V3 discovery: keepalive time for client connections.") + fs.DurationVar(&cfg.DiscoveryCfg.KeepAliveTimeout, "discovery-keepalive-timeout", cfg.DiscoveryCfg.KeepAliveTimeout, "V3 discovery: keepalive timeout for client connections.") + fs.BoolVar(&cfg.DiscoveryCfg.Secure.InsecureTransport, "discovery-insecure-transport", true, "V3 discovery: disable transport security for client connections.") + fs.BoolVar(&cfg.DiscoveryCfg.Secure.InsecureSkipVerify, "discovery-insecure-skip-tls-verify", false, "V3 discovery: skip server certificate verification (CAUTION: this option should be enabled only for testing purposes).") + fs.StringVar(&cfg.DiscoveryCfg.Secure.Cert, "discovery-cert", "", "V3 discovery: identify secure client using this TLS certificate file.") + fs.StringVar(&cfg.DiscoveryCfg.Secure.Key, "discovery-key", "", "V3 discovery: identify secure client using this TLS key file.") + fs.StringVar(&cfg.DiscoveryCfg.Secure.Cacert, "discovery-cacert", "", "V3 discovery: verify certificates of TLS-enabled secure servers using this CA bundle.") + fs.StringVar(&cfg.DiscoveryCfg.Auth.Username, "discovery-user", "", "V3 discovery: username[:password] for authentication (prompt if password is not supplied).") + fs.StringVar(&cfg.DiscoveryCfg.Auth.Password, "discovery-password", "", "V3 discovery: password for authentication (if this option is used, --user option shouldn't include password).") + + fs.StringVar(&cfg.Dproxy, "discovery-proxy", cfg.Dproxy, "HTTP proxy to use for traffic to discovery service. Will be deprecated in v3.7, and be decommissioned in v3.8.") + fs.StringVar(&cfg.DNSCluster, "discovery-srv", cfg.DNSCluster, "DNS domain used to bootstrap initial cluster.") + fs.StringVar(&cfg.DNSClusterServiceName, "discovery-srv-name", cfg.DNSClusterServiceName, "Service name to query when using DNS discovery.") + fs.StringVar(&cfg.InitialCluster, "initial-cluster", cfg.InitialCluster, "Initial cluster configuration for bootstrapping.") + fs.StringVar(&cfg.InitialClusterToken, "initial-cluster-token", cfg.InitialClusterToken, "Initial cluster token for the etcd cluster during bootstrap.") + fs.BoolVar(&cfg.StrictReconfigCheck, "strict-reconfig-check", cfg.StrictReconfigCheck, "Reject reconfiguration requests that would cause quorum loss.") + + fs.BoolVar(&cfg.PreVote, "pre-vote", cfg.PreVote, "Enable the raft Pre-Vote algorithm to prevent disruption when a node that has been partitioned away rejoins the cluster.") + + // security + fs.StringVar(&cfg.ClientTLSInfo.CertFile, "cert-file", "", "Path to the client server TLS cert file.") + fs.StringVar(&cfg.ClientTLSInfo.KeyFile, "key-file", "", "Path to the client server TLS key file.") + fs.StringVar(&cfg.ClientTLSInfo.ClientCertFile, "client-cert-file", "", "Path to an explicit peer client TLS cert file otherwise cert file will be used when client auth is required.") + fs.StringVar(&cfg.ClientTLSInfo.ClientKeyFile, "client-key-file", "", "Path to an explicit peer client TLS key file otherwise key file will be used when client auth is required.") + fs.BoolVar(&cfg.ClientTLSInfo.ClientCertAuth, "client-cert-auth", false, "Enable client cert authentication.") + fs.StringVar(&cfg.ClientTLSInfo.CRLFile, "client-crl-file", "", "Path to the client certificate revocation list file.") + fs.Var(flags.NewStringsValue(""), "client-cert-allowed-hostname", "Comma-separated list of allowed SAN hostnames for client cert authentication.") + fs.StringVar(&cfg.ClientTLSInfo.TrustedCAFile, "trusted-ca-file", "", "Path to the client server TLS trusted CA cert file.") + fs.BoolVar(&cfg.ClientAutoTLS, "auto-tls", false, "Client TLS using generated certificates") + fs.StringVar(&cfg.PeerTLSInfo.CertFile, "peer-cert-file", "", "Path to the peer server TLS cert file.") + fs.StringVar(&cfg.PeerTLSInfo.KeyFile, "peer-key-file", "", "Path to the peer server TLS key file.") + fs.StringVar(&cfg.PeerTLSInfo.ClientCertFile, "peer-client-cert-file", "", "Path to an explicit peer client TLS cert file otherwise peer cert file will be used when client auth is required.") + fs.StringVar(&cfg.PeerTLSInfo.ClientKeyFile, "peer-client-key-file", "", "Path to an explicit peer client TLS key file otherwise peer key file will be used when client auth is required.") + fs.BoolVar(&cfg.PeerTLSInfo.ClientCertAuth, "peer-client-cert-auth", false, "Enable peer client cert authentication.") + fs.StringVar(&cfg.PeerTLSInfo.TrustedCAFile, "peer-trusted-ca-file", "", "Path to the peer server TLS trusted CA file.") + fs.BoolVar(&cfg.PeerAutoTLS, "peer-auto-tls", false, "Peer TLS using generated certificates") + fs.UintVar(&cfg.SelfSignedCertValidity, "self-signed-cert-validity", 1, "The validity period of the client and peer certificates, unit is year") + fs.StringVar(&cfg.PeerTLSInfo.CRLFile, "peer-crl-file", "", "Path to the peer certificate revocation list file.") + fs.Var(flags.NewStringsValue(""), "peer-cert-allowed-cn", "Comma-separated list of allowed CNs for inter-peer TLS authentication.") + fs.Var(flags.NewStringsValue(""), "peer-cert-allowed-hostname", "Comma-separated list of allowed SAN hostnames for inter-peer TLS authentication.") + fs.Var(flags.NewStringsValue(""), "cipher-suites", "Comma-separated list of supported TLS cipher suites between client/server and peers (empty will be auto-populated by Go).") + fs.BoolVar(&cfg.ExperimentalPeerSkipClientSanVerification, "experimental-peer-skip-client-san-verification", false, "Skip verification of SAN field in client certificate for peer connections.Deprecated in v3.6 and will be decommissioned in v3.7. Use peer-skip-client-san-verification instead") + fs.BoolVar(&cfg.PeerTLSInfo.SkipClientSANVerify, "peer-skip-client-san-verification", false, "Skip verification of SAN field in client certificate for peer connections.") + fs.StringVar(&cfg.TlsMinVersion, "tls-min-version", string(tlsutil.TLSVersion12), "Minimum TLS version supported by etcd. Possible values: TLS1.2, TLS1.3.") + fs.StringVar(&cfg.TlsMaxVersion, "tls-max-version", string(tlsutil.TLSVersionDefault), "Maximum TLS version supported by etcd. Possible values: TLS1.2, TLS1.3 (empty defers to Go).") + + fs.Var( + flags.NewUniqueURLsWithExceptions("*", "*"), + "cors", + "Comma-separated white list of origins for CORS, or cross-origin resource sharing, (empty or * means allow all)", + ) + fs.Var(flags.NewUniqueStringsValue("*"), "host-whitelist", "Comma-separated acceptable hostnames from HTTP client requests, if server is not secure (empty means allow all).") + + // logging + fs.StringVar(&cfg.Logger, "logger", "zap", "Currently only supports 'zap' for structured logging.") + fs.Var(flags.NewUniqueStringsValue(DefaultLogOutput), "log-outputs", "Specify 'stdout' or 'stderr' to skip journald logging even when running under systemd, or list of comma separated output targets.") + fs.StringVar(&cfg.LogLevel, "log-level", logutil.DefaultLogLevel, "Configures log level. Only supports debug, info, warn, error, panic, or fatal. Default 'info'.") + fs.StringVar(&cfg.LogFormat, "log-format", logutil.DefaultLogFormat, "Configures log format. Only supports json, console. Default is 'json'.") + fs.BoolVar(&cfg.EnableLogRotation, "enable-log-rotation", false, "Enable log rotation of a single log-outputs file target.") + fs.StringVar(&cfg.LogRotationConfigJSON, "log-rotation-config-json", DefaultLogRotationConfig, "Configures log rotation if enabled with a JSON logger config. Default: MaxSize=100(MB), MaxAge=0(days,no limit), MaxBackups=0(no limit), LocalTime=false(UTC), Compress=false(gzip)") + + fs.StringVar(&cfg.AutoCompactionRetention, "auto-compaction-retention", "0", "Auto compaction retention for mvcc key value store. 0 means disable auto compaction.") + fs.StringVar(&cfg.AutoCompactionMode, "auto-compaction-mode", "periodic", "interpret 'auto-compaction-retention' one of: periodic|revision. 'periodic' for duration based retention, defaulting to hours if no time unit is provided (e.g. '5m'). 'revision' for revision number based retention.") + + // pprof profiler via HTTP + fs.BoolVar(&cfg.EnablePprof, "enable-pprof", false, "Enable runtime profiling data via HTTP server. Address is at client URL + \"/debug/pprof/\"") + + // additional metrics + fs.StringVar(&cfg.Metrics, "metrics", cfg.Metrics, "Set level of detail for exported metrics, specify 'extensive' to include server side grpc histogram metrics") + + // experimental distributed tracing + fs.BoolVar(&cfg.ExperimentalEnableDistributedTracing, "experimental-enable-distributed-tracing", false, "Enable experimental distributed tracing using OpenTelemetry Tracing. Deprecated in v3.6 and will be decommissioned in v3.7. Use --enable-distributed-tracing instead.") + fs.BoolVar(&cfg.EnableDistributedTracing, "enable-distributed-tracing", false, "Enable distributed tracing using OpenTelemetry Tracing.") + + fs.StringVar(&cfg.ExperimentalDistributedTracingAddress, "experimental-distributed-tracing-address", cfg.ExperimentalDistributedTracingAddress, "Address for distributed tracing used for OpenTelemetry Tracing (if enabled with experimental-enable-distributed-tracing flag). Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-address instead.") + fs.StringVar(&cfg.DistributedTracingAddress, "distributed-tracing-address", cfg.DistributedTracingAddress, "Address for distributed tracing used for OpenTelemetry Tracing (if enabled with enable-distributed-tracing flag).") + + fs.StringVar(&cfg.ExperimentalDistributedTracingServiceName, "experimental-distributed-tracing-service-name", cfg.ExperimentalDistributedTracingServiceName, "Configures service name for distributed tracing to be used to define service name for OpenTelemetry Tracing (if enabled with experimental-enable-distributed-tracing flag). 'etcd' is the default service name. Use the same service name for all instances of etcd. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-service-name instead.") + fs.StringVar(&cfg.DistributedTracingServiceName, "distributed-tracing-service-name", cfg.DistributedTracingServiceName, "Configures service name for distributed tracing to be used to define service name for OpenTelemetry Tracing (if enabled with enable-distributed-tracing flag). 'etcd' is the default service name. Use the same service name for all instances of etcd.") + + fs.StringVar(&cfg.ExperimentalDistributedTracingServiceInstanceID, "experimental-distributed-tracing-instance-id", "", "Configures service instance ID for distributed tracing to be used to define service instance ID key for OpenTelemetry Tracing (if enabled with experimental-enable-distributed-tracing flag). There is no default value set. This ID must be unique per etcd instance. Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-instance-id instead.") + fs.StringVar(&cfg.DistributedTracingServiceInstanceID, "distributed-tracing-instance-id", "", "Configures service instance ID for distributed tracing to be used to define service instance ID key for OpenTelemetry Tracing (if enabled with enable-distributed-tracing flag). There is no default value set. This ID must be unique per etcd instance.") + + fs.IntVar(&cfg.ExperimentalDistributedTracingSamplingRatePerMillion, "experimental-distributed-tracing-sampling-rate", 0, "Number of samples to collect per million spans for OpenTelemetry Tracing (if enabled with experimental-enable-distributed-tracing flag). Deprecated in v3.6 and will be decommissioned in v3.7. Use --distributed-tracing-sampling-rate instead.") + fs.IntVar(&cfg.DistributedTracingSamplingRatePerMillion, "distributed-tracing-sampling-rate", 0, "Number of samples to collect per million spans for OpenTelemetry Tracing (if enabled with enable-distributed-tracing flag).") + + // auth + fs.StringVar(&cfg.AuthToken, "auth-token", cfg.AuthToken, "Specify auth token specific options.") + fs.UintVar(&cfg.BcryptCost, "bcrypt-cost", cfg.BcryptCost, "Specify bcrypt algorithm cost factor for auth password hashing.") + fs.UintVar(&cfg.AuthTokenTTL, "auth-token-ttl", cfg.AuthTokenTTL, "The lifetime in seconds of the auth token.") + + // gateway + fs.BoolVar(&cfg.EnableGRPCGateway, "enable-grpc-gateway", cfg.EnableGRPCGateway, "Enable GRPC gateway.") + + // experimental + fs.BoolVar(&cfg.ExperimentalInitialCorruptCheck, "experimental-initial-corrupt-check", cfg.ExperimentalInitialCorruptCheck, "Enable to check data corruption before serving any client/peer traffic.") + // TODO: delete in v3.7 + fs.DurationVar(&cfg.ExperimentalCorruptCheckTime, "experimental-corrupt-check-time", cfg.ExperimentalCorruptCheckTime, "Duration of time between cluster corruption check passes. Deprecated in v3.6 and will be decommissioned in v3.7. Use --corrupt-check-time instead") + fs.DurationVar(&cfg.CorruptCheckTime, "corrupt-check-time", cfg.CorruptCheckTime, "Duration of time between cluster corruption check passes.") + // TODO: delete in v3.7 + fs.BoolVar(&cfg.ExperimentalCompactHashCheckEnabled, "experimental-compact-hash-check-enabled", cfg.ExperimentalCompactHashCheckEnabled, "Enable leader to periodically check followers compaction hashes. Deprecated in v3.6 and will be decommissioned in v3.7. Use '--feature-gates=CompactHashCheck=true' instead") + fs.DurationVar(&cfg.ExperimentalCompactHashCheckTime, "experimental-compact-hash-check-time", cfg.ExperimentalCompactHashCheckTime, "Duration of time between leader checks followers compaction hashes. Deprecated in v3.6 and will be decommissioned in v3.7. Use --compact-hash-check-time instead.") + + fs.DurationVar(&cfg.CompactHashCheckTime, "compact-hash-check-time", cfg.CompactHashCheckTime, "Duration of time between leader checks followers compaction hashes.") + + fs.BoolVar(&cfg.ExperimentalEnableLeaseCheckpoint, "experimental-enable-lease-checkpoint", false, "Enable leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change.") + // TODO: delete in v3.7 + fs.BoolVar(&cfg.ExperimentalEnableLeaseCheckpointPersist, "experimental-enable-lease-checkpoint-persist", false, "Enable persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled. Requires experimental-enable-lease-checkpoint to be enabled.") + // TODO: delete in v3.7 + fs.IntVar(&cfg.ExperimentalCompactionBatchLimit, "experimental-compaction-batch-limit", cfg.ExperimentalCompactionBatchLimit, "Sets the maximum revisions deleted in each compaction batch. Deprecated in v3.6 and will be decommissioned in v3.7. Use --compaction-batch-limit instead.") + fs.IntVar(&cfg.CompactionBatchLimit, "compaction-batch-limit", cfg.CompactionBatchLimit, "Sets the maximum revisions deleted in each compaction batch.") + fs.DurationVar(&cfg.ExperimentalCompactionSleepInterval, "experimental-compaction-sleep-interval", cfg.ExperimentalCompactionSleepInterval, "Sets the sleep interval between each compaction batch. Deprecated in v3.6 and will be decommissioned in v3.7. Use --compaction-sleep-interval instead.") + fs.DurationVar(&cfg.CompactionSleepInterval, "compaction-sleep-interval", cfg.CompactionSleepInterval, "Sets the sleep interval between each compaction batch.") + // TODO: delete in v3.7 + fs.DurationVar(&cfg.ExperimentalWatchProgressNotifyInterval, "experimental-watch-progress-notify-interval", cfg.ExperimentalWatchProgressNotifyInterval, "Duration of periodic watch progress notifications. Deprecated in v3.6 and will be decommissioned in v3.7. Use --watch-progress-notify-interval instead.") + fs.DurationVar(&cfg.WatchProgressNotifyInterval, "watch-progress-notify-interval", cfg.WatchProgressNotifyInterval, "Duration of periodic watch progress notifications.") + fs.DurationVar(&cfg.DowngradeCheckTime, "downgrade-check-time", cfg.DowngradeCheckTime, "Duration of time between two downgrade status checks.") + // TODO: delete in v3.7 + fs.DurationVar(&cfg.ExperimentalDowngradeCheckTime, "experimental-downgrade-check-time", cfg.ExperimentalDowngradeCheckTime, "Duration of time between two downgrade status checks. Deprecated in v3.6 and will be decommissioned in v3.7. Use --downgrade-check-time instead.") + // TODO: delete in v3.7 + fs.DurationVar(&cfg.ExperimentalWarningApplyDuration, "experimental-warning-apply-duration", cfg.ExperimentalWarningApplyDuration, "Time duration after which a warning is generated if request takes more time. Deprecated in v3.6 and will be decommissioned in v3.7. Use --warning-watch-progress-duration instead.") + fs.DurationVar(&cfg.WarningApplyDuration, "warning-apply-duration", cfg.WarningApplyDuration, "Time duration after which a warning is generated if watch progress takes more time.") + fs.DurationVar(&cfg.WarningUnaryRequestDuration, "warning-unary-request-duration", cfg.WarningUnaryRequestDuration, "Time duration after which a warning is generated if a unary request takes more time.") + fs.DurationVar(&cfg.ExperimentalWarningUnaryRequestDuration, "experimental-warning-unary-request-duration", cfg.ExperimentalWarningUnaryRequestDuration, "Time duration after which a warning is generated if a unary request takes more time. It's deprecated, and will be decommissioned in v3.7. Use --warning-unary-request-duration instead.") + // TODO: delete in v3.7 + fs.BoolVar(&cfg.ExperimentalMemoryMlock, "experimental-memory-mlock", cfg.ExperimentalMemoryMlock, "Enable to enforce etcd pages (in particular bbolt) to stay in RAM.") + fs.BoolVar(&cfg.MemoryMlock, "memory-mlock", cfg.MemoryMlock, "Enable to enforce etcd pages (in particular bbolt) to stay in RAM.") + fs.BoolVar(&cfg.ExperimentalTxnModeWriteWithSharedBuffer, "experimental-txn-mode-write-with-shared-buffer", true, "Enable the write transaction to use a shared buffer in its readonly check operations.") + fs.BoolVar(&cfg.ExperimentalStopGRPCServiceOnDefrag, "experimental-stop-grpc-service-on-defrag", cfg.ExperimentalStopGRPCServiceOnDefrag, "Enable etcd gRPC service to stop serving client requests on defragmentation.") + // TODO: delete in v3.7 + fs.UintVar(&cfg.ExperimentalBootstrapDefragThresholdMegabytes, "experimental-bootstrap-defrag-threshold-megabytes", 0, "Enable the defrag during etcd server bootstrap on condition that it will free at least the provided threshold of disk space. Needs to be set to non-zero value to take effect. It's deprecated, and will be decommissioned in v3.7. Use --bootstrap-defrag-threshold-megabytes instead.") + fs.UintVar(&cfg.BootstrapDefragThresholdMegabytes, "bootstrap-defrag-threshold-megabytes", 0, "Enable the defrag during etcd server bootstrap on condition that it will free at least the provided threshold of disk space. Needs to be set to non-zero value to take effect.") + // TODO: delete in v3.7 + fs.IntVar(&cfg.MaxLearners, "max-learners", membership.DefaultMaxLearners, "Sets the maximum number of learners that can be available in the cluster membership.") + fs.Uint64Var(&cfg.ExperimentalSnapshotCatchUpEntries, "experimental-snapshot-catchup-entries", cfg.ExperimentalSnapshotCatchUpEntries, "Number of entries for a slow follower to catch up after compacting the raft storage entries. Deprecated in v3.6 and will be decommissioned in v3.7. Use --snapshot-catchup-entries instead.") + fs.Uint64Var(&cfg.SnapshotCatchUpEntries, "snapshot-catchup-entries", cfg.SnapshotCatchUpEntries, "Number of entries for a slow follower to catch up after compacting the raft storage entries.") + + // unsafe + fs.BoolVar(&cfg.UnsafeNoFsync, "unsafe-no-fsync", false, "Disables fsync, unsafe, will cause data loss.") + fs.BoolVar(&cfg.ForceNewCluster, "force-new-cluster", false, "Force to create a new one member cluster.") + fs.Uint64Var(&cfg.ForceNewClusterBumpAmount, "force-new-cluster-bump-amount", 0, "How much to increase the latest revision after --force-new-cluster.") + + // featuregate + cfg.ServerFeatureGate.(featuregate.MutableFeatureGate).AddFlag(fs, ServerFeatureGateFlagName) +} + func ConfigFromFile(path string) (*Config, error) { cfg := &configYAML{Config: *NewConfig()} if err := cfg.configFromFile(path); err != nil { @@ -547,7 +975,7 @@ func ConfigFromFile(path string) (*Config, error) { } func (cfg *configYAML) configFromFile(path string) error { - b, err := ioutil.ReadFile(path) + b, err := os.ReadFile(path) if err != nil { return err } @@ -559,8 +987,58 @@ func (cfg *configYAML) configFromFile(path string) error { return err } - if cfg.configJSON.ListenPeerUrls != "" { - u, err := types.NewURLs(strings.Split(cfg.configJSON.ListenPeerUrls, ",")) + if cfg.configJSON.ServerFeatureGatesJSON != "" { + err = cfg.Config.ServerFeatureGate.(featuregate.MutableFeatureGate).Set(cfg.configJSON.ServerFeatureGatesJSON) + if err != nil { + return err + } + } + + // parses the yaml bytes to raw map first, then getBoolFlagVal can get the top level bool flag value. + var cfgMap map[string]any + err = yaml.Unmarshal(b, &cfgMap) + if err != nil { + return err + } + + for flg := range cfgMap { + cfg.FlagsExplicitlySet[flg] = true + } + + if peerTransportSecurity, ok := cfgMap["peer-transport-security"]; ok { + peerTransportSecurityMap, isMap := peerTransportSecurity.(map[string]any) + if !isMap { + return fmt.Errorf("invalid peer-transport-security") + } + for k := range peerTransportSecurityMap { + cfg.FlagsExplicitlySet[fmt.Sprintf("peer-%s", k)] = true + } + } + + // attempt to fix a bug introduced in https://github.com/etcd-io/etcd/pull/15033 + // both `experimental-snapshot-catch-up-entries` and `experimental-snapshot-catchup-entries` refer to the same field, + // map the YAML field "experimental-snapshot-catch-up-entries" to the flag "experimental-snapshot-catchup-entries". + if val, ok := cfgMap["experimental-snapshot-catch-up-entries"]; ok { + cfgMap["experimental-snapshot-catchup-entries"] = val + cfg.ExperimentalSnapshotCatchUpEntries = uint64(val.(float64)) + cfg.FlagsExplicitlySet["experimental-snapshot-catchup-entries"] = true + } + + getBoolFlagVal := func(flagName string) *bool { + flagVal, ok := cfgMap[flagName] + if !ok { + return nil + } + boolVal := flagVal.(bool) + return &boolVal + } + err = SetFeatureGatesFromExperimentalFlags(cfg.ServerFeatureGate, getBoolFlagVal, cfg.configJSON.ServerFeatureGatesJSON) + if err != nil { + return err + } + + if cfg.configJSON.ListenPeerURLs != "" { + u, err := types.NewURLs(strings.Split(cfg.configJSON.ListenPeerURLs, ",")) if err != nil { fmt.Fprintf(os.Stderr, "unexpected error setting up listen-peer-urls: %v\n", err) os.Exit(1) @@ -568,8 +1046,8 @@ func (cfg *configYAML) configFromFile(path string) error { cfg.Config.ListenPeerUrls = u } - if cfg.configJSON.ListenClientUrls != "" { - u, err := types.NewURLs(strings.Split(cfg.configJSON.ListenClientUrls, ",")) + if cfg.configJSON.ListenClientURLs != "" { + u, err := types.NewURLs(strings.Split(cfg.configJSON.ListenClientURLs, ",")) if err != nil { fmt.Fprintf(os.Stderr, "unexpected error setting up listen-client-urls: %v\n", err) os.Exit(1) @@ -577,8 +1055,8 @@ func (cfg *configYAML) configFromFile(path string) error { cfg.Config.ListenClientUrls = u } - if cfg.configJSON.ListenClientHttpUrls != "" { - u, err := types.NewURLs(strings.Split(cfg.configJSON.ListenClientHttpUrls, ",")) + if cfg.configJSON.ListenClientHTTPURLs != "" { + u, err := types.NewURLs(strings.Split(cfg.configJSON.ListenClientHTTPURLs, ",")) if err != nil { fmt.Fprintf(os.Stderr, "unexpected error setting up listen-client-http-urls: %v\n", err) os.Exit(1) @@ -586,8 +1064,8 @@ func (cfg *configYAML) configFromFile(path string) error { cfg.Config.ListenClientHttpUrls = u } - if cfg.configJSON.AdvertisePeerUrls != "" { - u, err := types.NewURLs(strings.Split(cfg.configJSON.AdvertisePeerUrls, ",")) + if cfg.configJSON.AdvertisePeerURLs != "" { + u, err := types.NewURLs(strings.Split(cfg.configJSON.AdvertisePeerURLs, ",")) if err != nil { fmt.Fprintf(os.Stderr, "unexpected error setting up initial-advertise-peer-urls: %v\n", err) os.Exit(1) @@ -595,8 +1073,8 @@ func (cfg *configYAML) configFromFile(path string) error { cfg.Config.AdvertisePeerUrls = u } - if cfg.configJSON.AdvertiseClientUrls != "" { - u, err := types.NewURLs(strings.Split(cfg.configJSON.AdvertiseClientUrls, ",")) + if cfg.configJSON.AdvertiseClientURLs != "" { + u, err := types.NewURLs(strings.Split(cfg.configJSON.AdvertiseClientURLs, ",")) if err != nil { fmt.Fprintf(os.Stderr, "unexpected error setting up advertise-peer-urls: %v\n", err) os.Exit(1) @@ -610,7 +1088,7 @@ func (cfg *configYAML) configFromFile(path string) error { fmt.Fprintf(os.Stderr, "unexpected error setting up listen-metrics-urls: %v\n", err) os.Exit(1) } - cfg.ListenMetricsUrls = []url.URL(u) + cfg.ListenMetricsUrls = u } if cfg.CORSJSON != "" { @@ -623,8 +1101,8 @@ func (cfg *configYAML) configFromFile(path string) error { cfg.HostWhitelist = uv.Values } - // If a discovery flag is set, clear default initial cluster set by InitialClusterFromName - if (cfg.Durl != "" || cfg.DNSCluster != "") && cfg.InitialCluster == defaultInitialCluster { + // If a discovery or discovery-endpoints flag is set, clear default initial cluster set by InitialClusterFromName + if (cfg.Durl != "" || cfg.DNSCluster != "" || len(cfg.DiscoveryCfg.Endpoints) > 0) && cfg.InitialCluster == defaultInitialCluster { cfg.InitialCluster = "" } if cfg.ClusterState == "" { @@ -640,6 +1118,7 @@ func (cfg *configYAML) configFromFile(path string) error { tls.TrustedCAFile = ysc.TrustedCAFile tls.AllowedCNs = ysc.AllowedCNs tls.AllowedHostnames = ysc.AllowedHostnames + tls.SkipClientSANVerify = ysc.SkipClientSANVerify } copySecurityDetails(&cfg.ClientTLSInfo, &cfg.ClientSecurityJSON) copySecurityDetails(&cfg.PeerTLSInfo, &cfg.PeerSecurityJSON) @@ -651,6 +1130,36 @@ func (cfg *configYAML) configFromFile(path string) error { return cfg.Validate() } +// SetFeatureGatesFromExperimentalFlags sets the feature gate values if the feature gate is not explicitly set +// while their corresponding experimental flags are explicitly set, for all the features in ExperimentalFlagToFeatureMap. +// TODO: remove after all experimental flags are deprecated. +func SetFeatureGatesFromExperimentalFlags(fg featuregate.FeatureGate, getExperimentalFlagVal func(string) *bool, featureGatesVal string) error { + m := make(map[featuregate.Feature]bool) + // verify that the feature gate and its experimental flag are not both set at the same time. + for expFlagName, featureName := range features.ExperimentalFlagToFeatureMap { + flagVal := getExperimentalFlagVal(expFlagName) + if flagVal == nil { + continue + } + if strings.Contains(featureGatesVal, string(featureName)) { + return fmt.Errorf("cannot specify both flags: --%s=%v and --%s=%s=%v at the same time, please just use --%s=%s=%v", + expFlagName, *flagVal, ServerFeatureGateFlagName, featureName, fg.Enabled(featureName), ServerFeatureGateFlagName, featureName, fg.Enabled(featureName)) + } + m[featureName] = *flagVal + } + + // filter out unknown features for fg, because we could use SetFeatureGatesFromExperimentalFlags both for + // server and cluster level feature gates. + allFeatures := fg.(featuregate.MutableFeatureGate).GetAll() + mFiltered := make(map[string]bool) + for k, v := range m { + if _, ok := allFeatures[k]; ok { + mFiltered[string(k)] = v + } + } + return fg.(featuregate.MutableFeatureGate).SetFromMap(mFiltered) +} + func updateCipherSuites(tls *transport.TLSInfo, ss []string) error { if len(tls.CipherSuites) > 0 && len(ss) > 0 { return fmt.Errorf("TLSInfo.CipherSuites is already specified (given %v)", ss) @@ -678,6 +1187,14 @@ func updateMinMaxVersions(info *transport.TLSInfo, min, max string) { // Validate ensures that '*embed.Config' fields are properly configured. func (cfg *Config) Validate() error { + // make sure there is no conflict in the flag settings in the ExperimentalNonBoolFlagMigrationMap + // TODO: delete in v3.7 + for oldFlag, newFlag := range experimentalFlagMigrationMap { + if cfg.FlagsExplicitlySet[oldFlag] && cfg.FlagsExplicitlySet[newFlag] { + return fmt.Errorf("cannot set --%s and --%s at the same time, please use --%s only", oldFlag, newFlag, newFlag) + } + } + if err := cfg.setupLogging(); err != nil { return err } @@ -697,16 +1214,16 @@ func (cfg *Config) Validate() error { return err } if err := checkHostURLs(cfg.AdvertisePeerUrls); err != nil { - addrs := cfg.getAdvertisePeerUrls() - return fmt.Errorf(`--initial-advertise-peer-urls %q must be "host:port" (%v)`, strings.Join(addrs, ","), err) + addrs := cfg.getAdvertisePeerURLs() + return fmt.Errorf(`--initial-advertise-peer-urls %q must be "host:port" (%w)`, strings.Join(addrs, ","), err) } if err := checkHostURLs(cfg.AdvertiseClientUrls); err != nil { - addrs := cfg.getAdvertiseClientUrls() - return fmt.Errorf(`--advertise-client-urls %q must be "host:port" (%v)`, strings.Join(addrs, ","), err) + addrs := cfg.getAdvertiseClientURLs() + return fmt.Errorf(`--advertise-client-urls %q must be "host:port" (%w)`, strings.Join(addrs, ","), err) } // Check if conflicting flags are passed. nSet := 0 - for _, v := range []bool{cfg.Durl != "", cfg.InitialCluster != "", cfg.DNSCluster != ""} { + for _, v := range []bool{cfg.Durl != "", cfg.InitialCluster != "", cfg.DNSCluster != "", len(cfg.DiscoveryCfg.Endpoints) > 0} { if v { nSet++ } @@ -720,6 +1237,34 @@ func (cfg *Config) Validate() error { return ErrConflictBootstrapFlags } + // Check if both v2 discovery and v3 discovery flags are passed. + v2discoveryFlagsExist := cfg.Dproxy != "" + v3discoveryFlagsExist := len(cfg.DiscoveryCfg.Endpoints) > 0 || + cfg.DiscoveryCfg.Token != "" || + cfg.DiscoveryCfg.Secure.Cert != "" || + cfg.DiscoveryCfg.Secure.Key != "" || + cfg.DiscoveryCfg.Secure.Cacert != "" || + cfg.DiscoveryCfg.Auth.Username != "" || + cfg.DiscoveryCfg.Auth.Password != "" + + if v2discoveryFlagsExist && v3discoveryFlagsExist { + return errors.New("both v2 discovery settings (discovery, discovery-proxy) " + + "and v3 discovery settings (discovery-token, discovery-endpoints, discovery-cert, " + + "discovery-key, discovery-cacert, discovery-user, discovery-password) are set") + } + + // If one of `discovery-token` and `discovery-endpoints` is provided, + // then the other one must be provided as well. + if (cfg.DiscoveryCfg.Token != "") != (len(cfg.DiscoveryCfg.Endpoints) > 0) { + return errors.New("both --discovery-token and --discovery-endpoints must be set") + } + + for _, ep := range cfg.DiscoveryCfg.Endpoints { + if strings.TrimSpace(ep) == "" { + return errors.New("--discovery-endpoints must not contain empty endpoints") + } + } + if cfg.TickMs == 0 { return fmt.Errorf("--heartbeat-interval must be >0 (set to %dms)", cfg.TickMs) } @@ -739,23 +1284,46 @@ func (cfg *Config) Validate() error { } switch cfg.AutoCompactionMode { - case "": case CompactorModeRevision, CompactorModePeriodic: + case "": + return errors.New("undefined auto-compaction-mode") default: return fmt.Errorf("unknown auto-compaction-mode %q", cfg.AutoCompactionMode) } - if !cfg.ExperimentalEnableLeaseCheckpointPersist && cfg.ExperimentalEnableLeaseCheckpoint { - cfg.logger.Warn("Detected that checkpointing is enabled without persistence. Consider enabling experimental-enable-lease-checkpoint-persist") + // Validate distributed tracing configuration but only if enabled. + if cfg.EnableDistributedTracing { + if err := validateTracingConfig(cfg.DistributedTracingSamplingRatePerMillion); err != nil { + return fmt.Errorf("distributed tracing configurition is not valid: (%w)", err) + } } - if cfg.ExperimentalEnableLeaseCheckpointPersist && !cfg.ExperimentalEnableLeaseCheckpoint { - return fmt.Errorf("setting experimental-enable-lease-checkpoint-persist requires experimental-enable-lease-checkpoint") + if !cfg.ServerFeatureGate.Enabled(features.LeaseCheckpointPersist) && cfg.ServerFeatureGate.Enabled(features.LeaseCheckpoint) { + cfg.logger.Warn("Detected that checkpointing is enabled without persistence. Consider enabling feature gate LeaseCheckpointPersist") } + if cfg.ServerFeatureGate.Enabled(features.LeaseCheckpointPersist) && !cfg.ServerFeatureGate.Enabled(features.LeaseCheckpoint) { + return fmt.Errorf("enabling feature gate LeaseCheckpointPersist requires enabling feature gate LeaseCheckpoint") + } + // TODO: delete in v3.7 if cfg.ExperimentalCompactHashCheckTime <= 0 { return fmt.Errorf("--experimental-compact-hash-check-time must be >0 (set to %v)", cfg.ExperimentalCompactHashCheckTime) } + if cfg.CompactHashCheckTime <= 0 { + return fmt.Errorf("--compact-hash-check-time must be >0 (set to %v)", cfg.CompactHashCheckTime) + } + + // If `--name` isn't configured, then multiple members may have the same "default" name. + // When adding a new member with the "default" name as well, etcd may regards its peerURL + // as one additional peerURL of the existing member which has the same "default" name, + // because each member can have multiple client or peer URLs. + // Please refer to https://github.com/etcd-io/etcd/issues/13757 + if cfg.Name == DefaultName { + cfg.logger.Warn( + "it isn't recommended to use default name, please set a value for --name. "+ + "Note that etcd might run into issue when multiple members have the same default name", + zap.String("name", cfg.Name)) + } minVersion, err := tlsutil.GetTLSVersion(cfg.TlsMinVersion) if err != nil { @@ -776,13 +1344,6 @@ func (cfg *Config) Validate() error { return fmt.Errorf("cipher suites cannot be configured when only TLS1.3 is enabled") } - // Validate distributed tracing configuration but only if enabled. - if cfg.ExperimentalEnableDistributedTracing { - if err := validateTracingConfig(cfg.ExperimentalDistributedTracingSamplingRatePerMillion); err != nil { - return fmt.Errorf("distributed tracing configurition is not valid: (%v)", err) - } - } - return nil } @@ -792,11 +1353,18 @@ func (cfg *Config) PeerURLsMapAndToken(which string) (urlsmap types.URLsMap, tok switch { case cfg.Durl != "": urlsmap = types.URLsMap{} - // If using discovery, generate a temporary cluster based on + // If using v2 discovery, generate a temporary cluster based on // self's advertised peer URLs urlsmap[cfg.Name] = cfg.AdvertisePeerUrls token = cfg.Durl + case len(cfg.DiscoveryCfg.Endpoints) > 0: + urlsmap = types.URLsMap{} + // If using v3 discovery, generate a temporary cluster based on + // self's advertised peer URLs + urlsmap[cfg.Name] = cfg.AdvertisePeerUrls + token = cfg.DiscoveryCfg.Token + case cfg.DNSCluster != "": clusterStrs, cerr := cfg.GetDNSClusterNames() lg := cfg.logger @@ -858,7 +1426,7 @@ func (cfg *Config) GetDNSClusterNames() ([]string, error) { zap.String("service-name", "etcd-server-ssl"+serviceNameSuffix), zap.String("server-name", cfg.Name), zap.String("discovery-srv", cfg.DNSCluster), - zap.Strings("advertise-peer-urls", cfg.getAdvertisePeerUrls()), + zap.Strings("advertise-peer-urls", cfg.getAdvertisePeerURLs()), zap.Strings("found-cluster", clusterStrs), zap.Error(cerr), ) @@ -873,15 +1441,15 @@ func (cfg *Config) GetDNSClusterNames() ([]string, error) { zap.String("service-name", "etcd-server"+serviceNameSuffix), zap.String("server-name", cfg.Name), zap.String("discovery-srv", cfg.DNSCluster), - zap.Strings("advertise-peer-urls", cfg.getAdvertisePeerUrls()), + zap.Strings("advertise-peer-urls", cfg.getAdvertisePeerURLs()), zap.Strings("found-cluster", clusterStrs), zap.Error(httpCerr), ) - return clusterStrs, multierr.Combine(cerr, httpCerr) + return clusterStrs, errors.Join(cerr, httpCerr) } -func (cfg Config) InitialClusterFromName(name string) (ret string) { +func (cfg *Config) InitialClusterFromName(name string) (ret string) { if len(cfg.AdvertisePeerUrls) == 0 { return "" } @@ -895,21 +1463,55 @@ func (cfg Config) InitialClusterFromName(name string) (ret string) { return ret[1:] } -func (cfg Config) IsNewCluster() bool { return cfg.ClusterState == ClusterStateFlagNew } -func (cfg Config) ElectionTicks() int { return int(cfg.ElectionMs / cfg.TickMs) } +// InferLocalAddr tries to determine the LocalAddr used when communicating with +// an etcd peer. If SetMemberLocalAddr is true, then it will try to get the host +// from AdvertisePeerUrls by searching for the first URL with a specified +// non-loopback address. Otherwise, it defaults to empty string and the +// LocalAddr used will be the default for the Golang HTTP client. +func (cfg *Config) InferLocalAddr() string { + if !cfg.ServerFeatureGate.Enabled(features.SetMemberLocalAddr) { + return "" + } -func (cfg Config) V2DeprecationEffective() config.V2DeprecationEnum { + lg := cfg.GetLogger() + lg.Info( + "searching for a suitable member local address in AdvertisePeerURLs", + zap.Strings("advertise-peer-urls", cfg.getAdvertisePeerURLs()), + ) + for _, peerURL := range cfg.AdvertisePeerUrls { + if addr, err := netip.ParseAddr(peerURL.Hostname()); err == nil { + if addr.IsLoopback() || addr.IsUnspecified() { + continue + } + lg.Info( + "setting member local address", + zap.String("LocalAddr", addr.String()), + ) + return addr.String() + } + } + lg.Warn( + "unable to set a member local address due to lack of suitable local addresses", + zap.Strings("advertise-peer-urls", cfg.getAdvertisePeerURLs()), + ) + return "" +} + +func (cfg *Config) IsNewCluster() bool { return cfg.ClusterState == ClusterStateFlagNew } +func (cfg *Config) ElectionTicks() int { return int(cfg.ElectionMs / cfg.TickMs) } + +func (cfg *Config) V2DeprecationEffective() config.V2DeprecationEnum { if cfg.V2Deprecation == "" { - return config.V2_DEPR_DEFAULT + return config.V2DeprDefault } return cfg.V2Deprecation } -func (cfg Config) defaultPeerHost() bool { +func (cfg *Config) defaultPeerHost() bool { return len(cfg.AdvertisePeerUrls) == 1 && cfg.AdvertisePeerUrls[0].String() == DefaultInitialAdvertisePeerURLs } -func (cfg Config) defaultClientHost() bool { +func (cfg *Config) defaultClientHost() bool { return len(cfg.AdvertiseClientUrls) == 1 && cfg.AdvertiseClientUrls[0].String() == DefaultAdvertiseClientURLs } @@ -1029,7 +1631,7 @@ func checkHostURLs(urls []url.URL) error { return nil } -func (cfg *Config) getAdvertisePeerUrls() (ss []string) { +func (cfg *Config) getAdvertisePeerURLs() (ss []string) { ss = make([]string, len(cfg.AdvertisePeerUrls)) for i := range cfg.AdvertisePeerUrls { ss[i] = cfg.AdvertisePeerUrls[i].String() @@ -1037,7 +1639,7 @@ func (cfg *Config) getAdvertisePeerUrls() (ss []string) { return ss } -func (cfg *Config) getListenPeerUrls() (ss []string) { +func (cfg *Config) getListenPeerURLs() (ss []string) { ss = make([]string, len(cfg.ListenPeerUrls)) for i := range cfg.ListenPeerUrls { ss[i] = cfg.ListenPeerUrls[i].String() @@ -1045,7 +1647,7 @@ func (cfg *Config) getListenPeerUrls() (ss []string) { return ss } -func (cfg *Config) getAdvertiseClientUrls() (ss []string) { +func (cfg *Config) getAdvertiseClientURLs() (ss []string) { ss = make([]string, len(cfg.AdvertiseClientUrls)) for i := range cfg.AdvertiseClientUrls { ss[i] = cfg.AdvertiseClientUrls[i].String() @@ -1053,7 +1655,7 @@ func (cfg *Config) getAdvertiseClientUrls() (ss []string) { return ss } -func (cfg *Config) getListenClientUrls() (ss []string) { +func (cfg *Config) getListenClientURLs() (ss []string) { ss = make([]string, len(cfg.ListenClientUrls)) for i := range cfg.ListenClientUrls { ss[i] = cfg.ListenClientUrls[i].String() @@ -1061,14 +1663,6 @@ func (cfg *Config) getListenClientUrls() (ss []string) { return ss } -func (cfg *Config) getListenClientHttpUrls() (ss []string) { - ss = make([]string, len(cfg.ListenClientHttpUrls)) - for i := range cfg.ListenClientHttpUrls { - ss[i] = cfg.ListenClientHttpUrls[i].String() - } - return ss -} - func (cfg *Config) getMetricsURLs() (ss []string) { ss = make([]string, len(cfg.ListenMetricsUrls)) for i := range cfg.ListenMetricsUrls { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging.go b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging.go index 1b363897b5..c9da6260d5 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging.go @@ -19,21 +19,22 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/url" "os" - "go.etcd.io/etcd/client/pkg/v3/logutil" "go.uber.org/zap" "go.uber.org/zap/zapcore" "go.uber.org/zap/zapgrpc" "google.golang.org/grpc" "google.golang.org/grpc/grpclog" "gopkg.in/natefinch/lumberjack.v2" + + "go.etcd.io/etcd/client/pkg/v3/logutil" ) // GetLogger returns the logger. -func (cfg Config) GetLogger() *zap.Logger { +func (cfg *Config) GetLogger() *zap.Logger { cfg.loggerMu.RLock() l := cfg.logger cfg.loggerMu.RUnlock() @@ -106,6 +107,11 @@ func (cfg *Config) setupLogging() error { copied.ErrorOutputPaths = errOutputPaths copied = logutil.MergeOutputPaths(copied) copied.Level = zap.NewAtomicLevelAt(logutil.ConvertToZapLevel(cfg.LogLevel)) + encoding, err := logutil.ConvertToZapFormat(cfg.LogFormat) + if err != nil { + return err + } + copied.Encoding = encoding if cfg.ZapLoggerBuilder == nil { lg, err := copied.Build() if err != nil { @@ -130,10 +136,22 @@ func (cfg *Config) setupLogging() error { lvl := zap.NewAtomicLevelAt(logutil.ConvertToZapLevel(cfg.LogLevel)) + var encoder zapcore.Encoder + encoding, err := logutil.ConvertToZapFormat(cfg.LogFormat) + if err != nil { + return err + } + + if encoding == logutil.ConsoleLogFormat { + encoder = zapcore.NewConsoleEncoder(logutil.DefaultZapLoggerConfig.EncoderConfig) + } else { + encoder = zapcore.NewJSONEncoder(logutil.DefaultZapLoggerConfig.EncoderConfig) + } + // WARN: do not change field names in encoder config // journald logging writer assumes field names of "level" and "caller" cr := zapcore.NewCore( - zapcore.NewJSONEncoder(logutil.DefaultZapLoggerConfig.EncoderConfig), + encoder, syncer, lvl, ) @@ -187,7 +205,7 @@ func (cfg *Config) setupLogging() error { return nil } -// NewZapLoggerBuilder generates a zap logger builder that sets given loger +// NewZapLoggerBuilder generates a zap logger builder that sets given logger // for embedded etcd. func NewZapLoggerBuilder(lg *zap.Logger) func(*Config) error { return func(cfg *Config) error { @@ -198,12 +216,6 @@ func NewZapLoggerBuilder(lg *zap.Logger) func(*Config) error { } } -// NewZapCoreLoggerBuilder - is a deprecated setter for the logger. -// Deprecated: Use simpler NewZapLoggerBuilder. To be removed in etcd-3.6. -func NewZapCoreLoggerBuilder(lg *zap.Logger, _ zapcore.Core, _ zapcore.WriteSyncer) func(*Config) error { - return NewZapLoggerBuilder(lg) -} - // SetupGlobalLoggers configures 'global' loggers (grpc, zapGlobal) based on the cfg. // // The method is not executed by embed server by default (since 3.5) to @@ -216,7 +228,7 @@ func (cfg *Config) SetupGlobalLoggers() { grpc.EnableTracing = true grpclog.SetLoggerV2(zapgrpc.NewLogger(lg)) } else { - grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, os.Stderr, os.Stderr)) + grpclog.SetLoggerV2(grpclog.NewLoggerV2(io.Discard, os.Stderr, os.Stderr)) } zap.ReplaceGlobals(lg) } @@ -231,7 +243,7 @@ func (logRotationConfig) Sync() error { return nil } // setupLogRotation initializes log rotation for a single file path target. func setupLogRotation(logOutputs []string, logRotateConfigJSON string) error { - var logRotationConfig logRotationConfig + var logRotationCfg logRotationConfig outputFilePaths := 0 for _, v := range logOutputs { switch v { @@ -250,7 +262,7 @@ func setupLogRotation(logOutputs []string, logRotateConfigJSON string) error { return ErrLogRotationInvalidLogOutput } - if err := json.Unmarshal([]byte(logRotateConfigJSON), &logRotationConfig); err != nil { + if err := json.Unmarshal([]byte(logRotateConfigJSON), &logRotationCfg); err != nil { var unmarshalTypeError *json.UnmarshalTypeError var syntaxError *json.SyntaxError switch { @@ -258,11 +270,13 @@ func setupLogRotation(logOutputs []string, logRotateConfigJSON string) error { return fmt.Errorf("improperly formatted log rotation config: %w", err) case errors.As(err, &unmarshalTypeError): return fmt.Errorf("invalid log rotation config: %w", err) + default: + return fmt.Errorf("fail to unmarshal log rotation config: %w", err) } } zap.RegisterSink("rotate", func(u *url.URL) (zap.Sink, error) { - logRotationConfig.Filename = u.Path[1:] - return &logRotationConfig, nil + logRotationCfg.Filename = u.Path[1:] + return &logRotationCfg, nil }) return nil } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_unix.go b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_unix.go index 76bb73265f..478dc65d60 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_unix.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_unix.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !windows -// +build !windows package embed @@ -21,16 +20,16 @@ import ( "fmt" "os" - "go.etcd.io/etcd/client/pkg/v3/logutil" - "go.uber.org/zap/zapcore" + + "go.etcd.io/etcd/client/pkg/v3/logutil" ) // use stderr as fallback func getJournalWriteSyncer() (zapcore.WriteSyncer, error) { jw, err := logutil.NewJournalWriter(os.Stderr) if err != nil { - return nil, fmt.Errorf("can't find journal (%v)", err) + return nil, fmt.Errorf("can't find journal (%w)", err) } return zapcore.AddSync(jw), nil } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_windows.go b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_windows.go index 58ed08631b..90dfad944e 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_windows.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_logging_journal_windows.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build windows -// +build windows package embed diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_tracing.go b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_tracing.go index 382bc00e76..0ca90fdc52 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_tracing.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/config_tracing.go @@ -1,4 +1,4 @@ -// Copyright 2022 The etcd Authors +// Copyright 2021 The etcd Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import ( "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" tracesdk "go.opentelemetry.io/otel/sdk/trace" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + semconv "go.opentelemetry.io/otel/semconv/v1.17.0" "go.uber.org/zap" ) @@ -49,7 +49,7 @@ type tracingExporter struct { func newTracingExporter(ctx context.Context, cfg *Config) (*tracingExporter, error) { exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure(), - otlptracegrpc.WithEndpoint(cfg.ExperimentalDistributedTracingAddress), + otlptracegrpc.WithEndpoint(cfg.DistributedTracingAddress), ) if err != nil { return nil, err @@ -57,14 +57,14 @@ func newTracingExporter(ctx context.Context, cfg *Config) (*tracingExporter, err res, err := resource.New(ctx, resource.WithAttributes( - semconv.ServiceNameKey.String(cfg.ExperimentalDistributedTracingServiceName), + semconv.ServiceNameKey.String(cfg.DistributedTracingServiceName), ), ) if err != nil { return nil, err } - if resWithIDKey := determineResourceWithIDKey(cfg.ExperimentalDistributedTracingServiceInstanceID); resWithIDKey != nil { + if resWithIDKey := determineResourceWithIDKey(cfg.DistributedTracingServiceInstanceID); resWithIDKey != nil { // Merge resources into a new // resource in case of duplicates. res, err = resource.Merge(res, resWithIDKey) @@ -77,7 +77,7 @@ func newTracingExporter(ctx context.Context, cfg *Config) (*tracingExporter, err tracesdk.WithBatcher(exporter), tracesdk.WithResource(res), tracesdk.WithSampler( - tracesdk.ParentBased(determineSampler(cfg.ExperimentalDistributedTracingSamplingRatePerMillion)), + tracesdk.ParentBased(determineSampler(cfg.DistributedTracingSamplingRatePerMillion)), ), ) @@ -95,9 +95,10 @@ func newTracingExporter(ctx context.Context, cfg *Config) (*tracingExporter, err cfg.logger.Debug( "distributed tracing enabled", - zap.String("address", cfg.ExperimentalDistributedTracingAddress), - zap.String("service-name", cfg.ExperimentalDistributedTracingServiceName), - zap.String("service-instance-id", cfg.ExperimentalDistributedTracingServiceInstanceID), + zap.String("address", cfg.DistributedTracingAddress), + zap.String("service-name", cfg.DistributedTracingServiceName), + zap.String("service-instance-id", cfg.DistributedTracingServiceInstanceID), + zap.Int("sampling-rate", cfg.DistributedTracingSamplingRatePerMillion), ) return &tracingExporter{ @@ -111,7 +112,6 @@ func (te *tracingExporter) Close(ctx context.Context) { if te.provider != nil { te.provider.Shutdown(ctx) } - if te.exporter != nil { te.exporter.Shutdown(ctx) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/etcd.go b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/etcd.go index 30cbff3d22..ef25652022 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/etcd.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/etcd.go @@ -16,10 +16,9 @@ package embed import ( "context" - "crypto/tls" "errors" "fmt" - "io/ioutil" + "io" defaultLog "log" "math" "net" @@ -28,9 +27,16 @@ import ( "runtime" "sort" "strconv" + "strings" "sync" "time" + "github.com/soheilhy/cmux" + "go.uber.org/zap" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/keepalive" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" @@ -41,18 +47,9 @@ import ( "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2v3" - "go.etcd.io/etcd/server/v3/etcdserver/api/v3client" - "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc" + "go.etcd.io/etcd/server/v3/features" + "go.etcd.io/etcd/server/v3/storage" "go.etcd.io/etcd/server/v3/verify" - - grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" - "github.com/soheilhy/cmux" - "go.uber.org/zap" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/keepalive" ) const ( @@ -96,7 +93,8 @@ type Etcd struct { // reading from `stopc`. errc chan error - // wg is used to track the lifecycle of all sub goroutines created by `StartEtcd`. + // wg is used to track the lifecycle of all sub goroutines which + // need to send error back to the `errc`. wg sync.WaitGroup } @@ -139,7 +137,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { } e.cfg.logger.Info( "configuring peer listeners", - zap.Strings("listen-peer-urls", e.cfg.getListenPeerUrls()), + zap.Strings("listen-peer-urls", e.cfg.getListenPeerURLs()), ) if e.Peers, err = configurePeerListeners(cfg); err != nil { return e, err @@ -147,7 +145,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { e.cfg.logger.Info( "configuring client listeners", - zap.Strings("listen-client-urls", e.cfg.getListenClientUrls()), + zap.Strings("listen-client-urls", e.cfg.getListenClientURLs()), ) if e.sctxs, err = configureClientListeners(cfg); err != nil { return e, err @@ -166,7 +164,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { memberInitialized = false urlsmap, token, err = cfg.PeerURLsMapAndToken("etcd") if err != nil { - return e, fmt.Errorf("error setting up initial cluster: %v", err) + return e, fmt.Errorf("error setting up initial cluster: %w", err) } } @@ -182,81 +180,84 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { backendFreelistType := parseBackendFreelistType(cfg.BackendFreelistType) srvcfg := config.ServerConfig{ - Name: cfg.Name, - ClientURLs: cfg.AdvertiseClientUrls, - PeerURLs: cfg.AdvertisePeerUrls, - DataDir: cfg.Dir, - DedicatedWALDir: cfg.WalDir, - SnapshotCount: cfg.SnapshotCount, - SnapshotCatchUpEntries: cfg.SnapshotCatchUpEntries, - MaxSnapFiles: cfg.MaxSnapFiles, - MaxWALFiles: cfg.MaxWalFiles, - InitialPeerURLsMap: urlsmap, - InitialClusterToken: token, - DiscoveryURL: cfg.Durl, - DiscoveryProxy: cfg.Dproxy, - NewCluster: cfg.IsNewCluster(), - PeerTLSInfo: cfg.PeerTLSInfo, - TickMs: cfg.TickMs, - ElectionTicks: cfg.ElectionTicks(), - InitialElectionTickAdvance: cfg.InitialElectionTickAdvance, - AutoCompactionRetention: autoCompactionRetention, - AutoCompactionMode: cfg.AutoCompactionMode, - QuotaBackendBytes: cfg.QuotaBackendBytes, - BackendBatchLimit: cfg.BackendBatchLimit, - BackendFreelistType: backendFreelistType, - BackendBatchInterval: cfg.BackendBatchInterval, - MaxTxnOps: cfg.MaxTxnOps, - MaxRequestBytes: cfg.MaxRequestBytes, - MaxConcurrentStreams: cfg.MaxConcurrentStreams, - SocketOpts: cfg.SocketOpts, - StrictReconfigCheck: cfg.StrictReconfigCheck, - ClientCertAuthEnabled: cfg.ClientTLSInfo.ClientCertAuth, - AuthToken: cfg.AuthToken, - BcryptCost: cfg.BcryptCost, - TokenTTL: cfg.AuthTokenTTL, - CORS: cfg.CORS, - HostWhitelist: cfg.HostWhitelist, - InitialCorruptCheck: cfg.ExperimentalInitialCorruptCheck, - CorruptCheckTime: cfg.ExperimentalCorruptCheckTime, - CompactHashCheckEnabled: cfg.ExperimentalCompactHashCheckEnabled, - CompactHashCheckTime: cfg.ExperimentalCompactHashCheckTime, - PreVote: cfg.PreVote, - Logger: cfg.logger, - ForceNewCluster: cfg.ForceNewCluster, - ForceNewClusterBumpAmount: cfg.ForceNewClusterBumpAmount, - EnableGRPCGateway: cfg.EnableGRPCGateway, - ExperimentalEnableDistributedTracing: cfg.ExperimentalEnableDistributedTracing, - UnsafeNoFsync: cfg.UnsafeNoFsync, - EnableLeaseCheckpoint: cfg.ExperimentalEnableLeaseCheckpoint, - LeaseCheckpointPersist: cfg.ExperimentalEnableLeaseCheckpointPersist, - CompactionBatchLimit: cfg.ExperimentalCompactionBatchLimit, - CompactionSleepInterval: cfg.ExperimentalCompactionSleepInterval, - WatchProgressNotifyInterval: cfg.ExperimentalWatchProgressNotifyInterval, - DowngradeCheckTime: cfg.ExperimentalDowngradeCheckTime, - WarningApplyDuration: cfg.ExperimentalWarningApplyDuration, - ExperimentalMemoryMlock: cfg.ExperimentalMemoryMlock, - ExperimentalTxnModeWriteWithSharedBuffer: cfg.ExperimentalTxnModeWriteWithSharedBuffer, - ExperimentalStopGRPCServiceOnDefrag: cfg.ExperimentalStopGRPCServiceOnDefrag, - ExperimentalBootstrapDefragThresholdMegabytes: cfg.ExperimentalBootstrapDefragThresholdMegabytes, - ExperimentalMaxLearners: cfg.ExperimentalMaxLearners, - V2Deprecation: cfg.V2DeprecationEffective(), - } - - if srvcfg.ExperimentalEnableDistributedTracing { + Name: cfg.Name, + ClientURLs: cfg.AdvertiseClientUrls, + PeerURLs: cfg.AdvertisePeerUrls, + DataDir: cfg.Dir, + DedicatedWALDir: cfg.WalDir, + SnapshotCount: cfg.SnapshotCount, + SnapshotCatchUpEntries: cfg.SnapshotCatchUpEntries, + MaxSnapFiles: cfg.MaxSnapFiles, + MaxWALFiles: cfg.MaxWalFiles, + InitialPeerURLsMap: urlsmap, + InitialClusterToken: token, + DiscoveryURL: cfg.Durl, + DiscoveryProxy: cfg.Dproxy, + DiscoveryCfg: cfg.DiscoveryCfg, + NewCluster: cfg.IsNewCluster(), + PeerTLSInfo: cfg.PeerTLSInfo, + TickMs: cfg.TickMs, + ElectionTicks: cfg.ElectionTicks(), + InitialElectionTickAdvance: cfg.InitialElectionTickAdvance, + AutoCompactionRetention: autoCompactionRetention, + AutoCompactionMode: cfg.AutoCompactionMode, + QuotaBackendBytes: cfg.QuotaBackendBytes, + BackendBatchLimit: cfg.BackendBatchLimit, + BackendFreelistType: backendFreelistType, + BackendBatchInterval: cfg.BackendBatchInterval, + MaxTxnOps: cfg.MaxTxnOps, + MaxRequestBytes: cfg.MaxRequestBytes, + MaxConcurrentStreams: cfg.MaxConcurrentStreams, + SocketOpts: cfg.SocketOpts, + StrictReconfigCheck: cfg.StrictReconfigCheck, + ClientCertAuthEnabled: cfg.ClientTLSInfo.ClientCertAuth, + AuthToken: cfg.AuthToken, + BcryptCost: cfg.BcryptCost, + TokenTTL: cfg.AuthTokenTTL, + CORS: cfg.CORS, + HostWhitelist: cfg.HostWhitelist, + CorruptCheckTime: cfg.CorruptCheckTime, + CompactHashCheckTime: cfg.CompactHashCheckTime, + PreVote: cfg.PreVote, + Logger: cfg.logger, + ForceNewCluster: cfg.ForceNewCluster, + ForceNewClusterBumpAmount: cfg.ForceNewClusterBumpAmount, + EnableGRPCGateway: cfg.EnableGRPCGateway, + EnableDistributedTracing: cfg.EnableDistributedTracing, + UnsafeNoFsync: cfg.UnsafeNoFsync, + CompactionBatchLimit: cfg.CompactionBatchLimit, + CompactionSleepInterval: cfg.CompactionSleepInterval, + WatchProgressNotifyInterval: cfg.WatchProgressNotifyInterval, + DowngradeCheckTime: cfg.DowngradeCheckTime, + WarningApplyDuration: cfg.WarningApplyDuration, + WarningUnaryRequestDuration: cfg.WarningUnaryRequestDuration, + MemoryMlock: cfg.MemoryMlock, + BootstrapDefragThresholdMegabytes: cfg.BootstrapDefragThresholdMegabytes, + MaxLearners: cfg.MaxLearners, + V2Deprecation: cfg.V2DeprecationEffective(), + ExperimentalLocalAddress: cfg.InferLocalAddr(), + ServerFeatureGate: cfg.ServerFeatureGate, + Metrics: cfg.Metrics, + } + + if srvcfg.EnableDistributedTracing { tctx := context.Background() - tracingExporter, err := newTracingExporter(tctx, cfg) - if err != nil { - return e, err + tracingExporter, terr := newTracingExporter(tctx, cfg) + if terr != nil { + return e, terr } e.tracingExporterShutdown = func() { tracingExporter.Close(tctx) } - srvcfg.ExperimentalTracerOptions = tracingExporter.opts + srvcfg.TracerOptions = tracingExporter.opts - e.cfg.logger.Info("distributed tracing setup enabled") + e.cfg.logger.Info( + "distributed tracing setup enabled", + ) } + srvcfg.PeerTLSInfo.LocalAddr = srvcfg.ExperimentalLocalAddress + print(e.cfg.logger, *cfg, srvcfg, memberInitialized) if e.Server, err = etcdserver.NewServer(srvcfg); err != nil { @@ -268,7 +269,7 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { // newly started member ("memberInitialized==false") // does not need corruption check - if memberInitialized && srvcfg.InitialCorruptCheck { + if memberInitialized && srvcfg.ServerFeatureGate.Enabled(features.InitialCorruptCheck) { if err = e.Server.CorruptionChecker().InitialCheck(); err != nil { // set "EtcdServer" to nil, so that it does not block on "EtcdServer.Close()" // (nothing to close since rafthttp transports have not been started) @@ -281,23 +282,21 @@ func StartEtcd(inCfg *Config) (e *Etcd, err error) { } e.Server.Start() - if err = e.servePeers(); err != nil { - return e, err - } - if err = e.serveClients(); err != nil { - return e, err - } + e.servePeers() + + e.serveClients() + if err = e.serveMetrics(); err != nil { return e, err } e.cfg.logger.Info( "now serving peer/client/metrics", - zap.String("local-member-id", e.Server.ID().String()), - zap.Strings("initial-advertise-peer-urls", e.cfg.getAdvertisePeerUrls()), - zap.Strings("listen-peer-urls", e.cfg.getListenPeerUrls()), - zap.Strings("advertise-client-urls", e.cfg.getAdvertiseClientUrls()), - zap.Strings("listen-client-urls", e.cfg.getListenClientUrls()), + zap.String("local-member-id", e.Server.MemberID().String()), + zap.Strings("initial-advertise-peer-urls", e.cfg.getAdvertisePeerURLs()), + zap.Strings("listen-peer-urls", e.cfg.getListenPeerURLs()), + zap.Strings("advertise-client-urls", e.cfg.getAdvertiseClientURLs()), + zap.Strings("listen-client-urls", e.cfg.getListenClientURLs()), zap.Strings("listen-metrics-urls", e.cfg.getMetricsURLs()), ) serving = true @@ -319,7 +318,7 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized quota := ec.QuotaBackendBytes if quota == 0 { - quota = etcdserver.DefaultQuotaBytes + quota = storage.DefaultQuotaBytes } lg.Info( @@ -345,11 +344,12 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized zap.Uint("max-wals", sc.MaxWALFiles), zap.Uint("max-snapshots", sc.MaxSnapFiles), zap.Uint64("snapshot-catchup-entries", sc.SnapshotCatchUpEntries), - zap.Strings("initial-advertise-peer-urls", ec.getAdvertisePeerUrls()), - zap.Strings("listen-peer-urls", ec.getListenPeerUrls()), - zap.Strings("advertise-client-urls", ec.getAdvertiseClientUrls()), - zap.Strings("listen-client-urls", ec.getListenClientUrls()), + zap.Strings("initial-advertise-peer-urls", ec.getAdvertisePeerURLs()), + zap.Strings("listen-peer-urls", ec.getListenPeerURLs()), + zap.Strings("advertise-client-urls", ec.getAdvertiseClientURLs()), + zap.Strings("listen-client-urls", ec.getListenClientURLs()), zap.Strings("listen-metrics-urls", ec.getMetricsURLs()), + zap.String("experimental-local-address", sc.ExperimentalLocalAddress), zap.Strings("cors", cors), zap.Strings("host-whitelist", hss), zap.String("initial-cluster", sc.InitialPeerURLsMap.String()), @@ -360,17 +360,33 @@ func print(lg *zap.Logger, ec Config, sc config.ServerConfig, memberInitialized zap.Uint32("max-concurrent-streams", sc.MaxConcurrentStreams), zap.Bool("pre-vote", sc.PreVote), + zap.String(ServerFeatureGateFlagName, sc.ServerFeatureGate.String()), zap.Bool("initial-corrupt-check", sc.InitialCorruptCheck), zap.String("corrupt-check-time-interval", sc.CorruptCheckTime.String()), - zap.Bool("compact-check-time-enabled", sc.CompactHashCheckEnabled), zap.Duration("compact-check-time-interval", sc.CompactHashCheckTime), zap.String("auto-compaction-mode", sc.AutoCompactionMode), zap.Duration("auto-compaction-retention", sc.AutoCompactionRetention), zap.String("auto-compaction-interval", sc.AutoCompactionRetention.String()), zap.String("discovery-url", sc.DiscoveryURL), zap.String("discovery-proxy", sc.DiscoveryProxy), + + zap.String("discovery-token", sc.DiscoveryCfg.Token), + zap.String("discovery-endpoints", strings.Join(sc.DiscoveryCfg.Endpoints, ",")), + zap.String("discovery-dial-timeout", sc.DiscoveryCfg.DialTimeout.String()), + zap.String("discovery-request-timeout", sc.DiscoveryCfg.RequestTimeout.String()), + zap.String("discovery-keepalive-time", sc.DiscoveryCfg.KeepAliveTime.String()), + zap.String("discovery-keepalive-timeout", sc.DiscoveryCfg.KeepAliveTimeout.String()), + zap.Bool("discovery-insecure-transport", sc.DiscoveryCfg.Secure.InsecureTransport), + zap.Bool("discovery-insecure-skip-tls-verify", sc.DiscoveryCfg.Secure.InsecureSkipVerify), + zap.String("discovery-cert", sc.DiscoveryCfg.Secure.Cert), + zap.String("discovery-key", sc.DiscoveryCfg.Secure.Key), + zap.String("discovery-cacert", sc.DiscoveryCfg.Secure.Cacert), + zap.String("discovery-user", sc.DiscoveryCfg.Auth.Username), + zap.String("downgrade-check-interval", sc.DowngradeCheckTime.String()), - zap.Int("max-learners", sc.ExperimentalMaxLearners), + zap.Int("max-learners", sc.MaxLearners), + + zap.String("v2-deprecation", string(ec.V2Deprecation)), ) } @@ -404,8 +420,8 @@ func (e *Etcd) Close() { fields := []zap.Field{ zap.String("name", e.cfg.Name), zap.String("data-dir", e.cfg.Dir), - zap.Strings("advertise-peer-urls", e.cfg.getAdvertisePeerUrls()), - zap.Strings("advertise-client-urls", e.cfg.getAdvertiseClientUrls()), + zap.Strings("advertise-peer-urls", e.cfg.getAdvertisePeerURLs()), + zap.Strings("advertise-client-urls", e.cfg.getAdvertiseClientURLs()), } lg := e.GetLogger() lg.Info("closing etcd server", fields...) @@ -524,9 +540,7 @@ func configurePeerListeners(cfg *Config) (peers []*peerListener, err error) { if err = cfg.PeerSelfCert(); err != nil { cfg.logger.Fatal("failed to get peer self-signed certs", zap.Error(err)) } - updateMinMaxVersions(&cfg.PeerTLSInfo, cfg.TlsMinVersion, cfg.TlsMaxVersion) - if !cfg.PeerTLSInfo.Empty() { cfg.logger.Info( "starting with peer TLS", @@ -582,24 +596,16 @@ func configurePeerListeners(cfg *Config) (peers []*peerListener, err error) { } // configure peer handlers after rafthttp.Transport started -func (e *Etcd) servePeers() (err error) { +func (e *Etcd) servePeers() { ph := etcdhttp.NewPeerHandler(e.GetLogger(), e.Server) - var peerTLScfg *tls.Config - if !e.cfg.PeerTLSInfo.Empty() { - if peerTLScfg, err = e.cfg.PeerTLSInfo.ServerConfig(); err != nil { - return err - } - } for _, p := range e.Peers { u := p.Listener.Addr().String() - gs := v3rpc.Server(e.Server, peerTLScfg, nil) m := cmux.New(p.Listener) - go gs.Serve(m.Match(cmux.HTTP2())) srv := &http.Server{ - Handler: grpcHandlerFunc(gs, ph), + Handler: ph, ReadTimeout: 5 * time.Minute, - ErrorLog: defaultLog.New(ioutil.Discard, "", 0), // do not log user error + ErrorLog: defaultLog.New(io.Discard, "", 0), // do not log user error } go srv.Serve(m.Match(cmux.Any())) p.serve = func() error { @@ -617,7 +623,7 @@ func (e *Etcd) servePeers() (err error) { "stopping serving peer traffic", zap.String("address", u), ) - stopServers(ctx, &servers{secure: peerTLScfg != nil, grpc: gs, http: srv}) + srv.Shutdown(ctx) e.cfg.logger.Info( "stopped serving peer traffic", zap.String("address", u), @@ -629,18 +635,16 @@ func (e *Etcd) servePeers() (err error) { // start peer servers in a goroutine for _, pl := range e.Peers { - e.wg.Add(1) - go func(l *peerListener) { - defer e.wg.Done() + l := pl + e.startHandler(func() error { u := l.Addr().String() e.cfg.logger.Info( "serving peer traffic", zap.String("address", u), ) - e.errHandler(l.serve()) - }(pl) + return l.serve() + }) } - return nil } func configureClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err error) { @@ -650,9 +654,7 @@ func configureClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err erro if err = cfg.ClientSelfCert(); err != nil { cfg.logger.Fatal("failed to get client self-signed certs", zap.Error(err)) } - updateMinMaxVersions(&cfg.ClientTLSInfo, cfg.TlsMinVersion, cfg.TlsMaxVersion) - if cfg.EnablePprof { cfg.logger.Info("pprof is enabled", zap.String("path", debugutil.HTTPPrefixPProf)) } @@ -673,7 +675,7 @@ func configureClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err erro } for _, u := range cfg.ListenClientUrls { - addr, secure, network := resolveUrl(u) + addr, secure, network := resolveURL(u) sctx := sctxs[addr] if sctx == nil { sctx = newServeCtx(cfg.logger) @@ -686,14 +688,14 @@ func configureClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err erro sctx.network = network } for _, u := range cfg.ListenClientHttpUrls { - addr, secure, network := resolveUrl(u) + addr, secure, network := resolveURL(u) sctx := sctxs[addr] if sctx == nil { sctx = newServeCtx(cfg.logger) sctxs[addr] = sctx } else if !sctx.httpOnly { - return nil, fmt.Errorf("cannot bind both --client-listen-urls and --client-listen-http-urls on the same url %s", u.String()) + return nil, fmt.Errorf("cannot bind both --listen-client-urls and --listen-client-http-urls on the same url %s", u.String()) } sctx.secure = sctx.secure || secure sctx.insecure = sctx.insecure || !secure @@ -749,7 +751,7 @@ func configureClientListeners(cfg *Config) (sctxs map[string]*serveCtx, err erro return sctxs, nil } -func resolveUrl(u url.URL) (addr string, secure bool, network string) { +func resolveURL(u url.URL) (addr string, secure bool, network string) { addr = u.Host network = "tcp" if u.Scheme == "unix" || u.Scheme == "unixs" { @@ -760,7 +762,7 @@ func resolveUrl(u url.URL) (addr string, secure bool, network string) { return addr, secure, network } -func (e *Etcd) serveClients() (err error) { +func (e *Etcd) serveClients() { if !e.cfg.ClientTLSInfo.Empty() { e.cfg.logger.Info( "starting with client TLS", @@ -770,28 +772,13 @@ func (e *Etcd) serveClients() (err error) { } // Start a client server goroutine for each listen address - var h http.Handler - if e.Config().EnableV2 { - if e.Config().V2DeprecationEffective().IsAtLeast(config.V2_DEPR_1_WRITE_ONLY) { - return fmt.Errorf("--enable-v2 and --v2-deprecation=%s are mutually exclusive", e.Config().V2DeprecationEffective()) - } - e.cfg.logger.Warn("Flag `enable-v2` is deprecated and will get removed in etcd 3.6.") - if len(e.Config().ExperimentalEnableV2V3) > 0 { - e.cfg.logger.Warn("Flag `experimental-enable-v2v3` is deprecated and will get removed in etcd 3.6.") - srv := v2v3.NewServer(e.cfg.logger, v3client.New(e.Server), e.cfg.ExperimentalEnableV2V3) - h = v2http.NewClientHandler(e.GetLogger(), srv, e.Server.Cfg.ReqTimeout()) - } else { - h = v2http.NewClientHandler(e.GetLogger(), e.Server, e.Server.Cfg.ReqTimeout()) - } - } else { - mux := http.NewServeMux() - etcdhttp.HandleBasic(e.cfg.logger, mux, e.Server) - etcdhttp.HandleMetrics(mux) - etcdhttp.HandleHealth(e.cfg.logger, mux, e.Server) - h = mux - } + mux := http.NewServeMux() + etcdhttp.HandleDebug(mux) + etcdhttp.HandleVersion(mux, e.Server) + etcdhttp.HandleMetrics(mux) + etcdhttp.HandleHealth(e.cfg.logger, mux, e.Server) - gopts := []grpc.ServerOption{} + var gopts []grpc.ServerOption if e.cfg.GRPCKeepAliveMinTime > time.Duration(0) { gopts = append(gopts, grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{ MinTime: e.cfg.GRPCKeepAliveMinTime, @@ -805,36 +792,34 @@ func (e *Etcd) serveClients() (err error) { Timeout: e.cfg.GRPCKeepAliveTimeout, })) } + gopts = append(gopts, e.cfg.GRPCAdditionalServerOptions...) - splitHttp := false + splitHTTP := false for _, sctx := range e.sctxs { if sctx.httpOnly { - splitHttp = true + splitHTTP = true } } // start client servers in each goroutine for _, sctx := range e.sctxs { - e.wg.Add(1) - go func(s *serveCtx) { - defer e.wg.Done() - e.errHandler(s.serve(e.Server, &e.cfg.ClientTLSInfo, h, e.errHandler, e.grpcGatewayDial(splitHttp), splitHttp, gopts...)) - }(sctx) + s := sctx + e.startHandler(func() error { + return s.serve(e.Server, &e.cfg.ClientTLSInfo, mux, e.errHandler, e.grpcGatewayDial(splitHTTP), splitHTTP, gopts...) + }) } - return nil } -func (e *Etcd) grpcGatewayDial(splitHttp bool) (grpcDial func(ctx context.Context) (*grpc.ClientConn, error)) { +func (e *Etcd) grpcGatewayDial(splitHTTP bool) (grpcDial func(ctx context.Context) (*grpc.ClientConn, error)) { if !e.cfg.EnableGRPCGateway { return nil } - sctx := e.pickGrpcGatewayServeContext(splitHttp) + sctx := e.pickGRPCGatewayServeContext(splitHTTP) addr := sctx.addr if network := sctx.network; network == "unix" { // explicitly define unix network for gRPC socket support addr = fmt.Sprintf("%s:%s", network, addr) } - opts := []grpc.DialOption{grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32))} if sctx.secure { tlscfg, tlsErr := e.cfg.ClientTLSInfo.ServerConfig() @@ -846,8 +831,7 @@ func (e *Etcd) grpcGatewayDial(splitHttp bool) (grpcDial func(ctx context.Contex dtls := tlscfg.Clone() // trust local server dtls.InsecureSkipVerify = true - bundle := credentials.NewBundle(credentials.Config{TLSConfig: dtls}) - opts = append(opts, grpc.WithTransportCredentials(bundle.TransportCredentials())) + opts = append(opts, grpc.WithTransportCredentials(credentials.NewTransportCredential(dtls))) } else { opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) } @@ -862,9 +846,9 @@ func (e *Etcd) grpcGatewayDial(splitHttp bool) (grpcDial func(ctx context.Contex } } -func (e *Etcd) pickGrpcGatewayServeContext(splitHttp bool) *serveCtx { +func (e *Etcd) pickGRPCGatewayServeContext(splitHTTP bool) *serveCtx { for _, sctx := range e.sctxs { - if !splitHttp || !sctx.httpOnly { + if !splitHTTP || !sctx.httpOnly { return sctx } } @@ -890,36 +874,44 @@ func (e *Etcd) createMetricsListener(murl url.URL) (net.Listener, error) { } func (e *Etcd) serveMetrics() (err error) { - if e.cfg.Metrics == "extensive" { - grpc_prometheus.EnableHandlingTimeHistogram() - } - if len(e.cfg.ListenMetricsUrls) > 0 { metricsMux := http.NewServeMux() etcdhttp.HandleMetrics(metricsMux) etcdhttp.HandleHealth(e.cfg.logger, metricsMux, e.Server) for _, murl := range e.cfg.ListenMetricsUrls { + u := murl ml, err := e.createMetricsListener(murl) if err != nil { return err } e.metricsListeners = append(e.metricsListeners, ml) - e.wg.Add(1) - go func(u url.URL, ln net.Listener) { - defer e.wg.Done() + + e.startHandler(func() error { e.cfg.logger.Info( "serving metrics", zap.String("address", u.String()), ) - e.errHandler(http.Serve(ln, metricsMux)) - }(murl, ml) + return http.Serve(ml, metricsMux) + }) } } return nil } +func (e *Etcd) startHandler(handler func() error) { + // start each handler in a separate goroutine + e.wg.Add(1) + go func() { + defer e.wg.Done() + e.errHandler(handler()) + }() +} + func (e *Etcd) errHandler(err error) { + if err != nil { + e.GetLogger().Error("setting up serving from embedded etcd failed.", zap.Error(err)) + } select { case <-e.stopc: return @@ -947,12 +939,14 @@ func parseCompactionRetention(mode, retention string) (ret time.Duration, err er ret = time.Duration(int64(h)) case CompactorModePeriodic: ret = time.Duration(int64(h)) * time.Hour + case "": + return 0, errors.New("--auto-compaction-mode is undefined") } } else { // periodic compaction ret, err = time.ParseDuration(retention) if err != nil { - return 0, fmt.Errorf("error parsing CompactionRetention: %v", err) + return 0, fmt.Errorf("error parsing CompactionRetention: %w", err) } } return ret, nil diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/serve.go b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/serve.go index 55ffe3743f..e50529dfe4 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/serve.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/serve.go @@ -18,13 +18,22 @@ import ( "context" "errors" "fmt" - "io/ioutil" + "io" defaultLog "log" "net" "net/http" "strings" "sync" + gw "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/soheilhy/cmux" + "github.com/tmc/grpc-websocket-proxy/wsproxy" + "go.uber.org/zap" + "golang.org/x/net/http2" + "golang.org/x/net/trace" + "google.golang.org/grpc" + "google.golang.org/protobuf/encoding/protojson" + etcdservergw "go.etcd.io/etcd/api/v3/etcdserverpb/gw" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/pkg/v3/debugutil" @@ -39,14 +48,6 @@ import ( "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb" v3lockgw "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw" "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc" - - gw "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/soheilhy/cmux" - "github.com/tmc/grpc-websocket-proxy/wsproxy" - "go.uber.org/zap" - "golang.org/x/net/http2" - "golang.org/x/net/trace" - "google.golang.org/grpc" ) type serveCtx struct { @@ -79,6 +80,18 @@ type serveCtx struct { wg sync.WaitGroup } +func (sctx *serveCtx) startHandler(errHandler func(error), handler func() error) { + // start each handler in a separate goroutine + sctx.wg.Add(1) + go func() { + defer sctx.wg.Done() + err := handler() + if errHandler != nil { + errHandler(err) + } + }() +} + type servers struct { secure bool grpc *grpc.Server @@ -108,9 +121,10 @@ func (sctx *serveCtx) serve( handler http.Handler, errHandler func(error), grpcDialForRestGatewayBackends func(ctx context.Context) (*grpc.ClientConn, error), - splitHttp bool, - gopts ...grpc.ServerOption) (err error) { - logger := defaultLog.New(ioutil.Discard, "etcdhttp", 0) + splitHTTP bool, + gopts ...grpc.ServerOption, +) (err error) { + logger := defaultLog.New(io.Discard, "etcdhttp", 0) // Make sure serversC is closed even if we prematurely exit the function. defer sctx.close() @@ -125,9 +139,9 @@ func (sctx *serveCtx) serve( m := cmux.New(sctx.l) var server func() error - onlyGRPC := splitHttp && !sctx.httpOnly - onlyHttp := splitHttp && sctx.httpOnly - grpcEnabled := !onlyHttp + onlyGRPC := splitHTTP && !sctx.httpOnly + onlyHTTP := splitHTTP && sctx.httpOnly + grpcEnabled := !onlyHTTP httpEnabled := !onlyGRPC v3c := v3client.New(s) @@ -147,7 +161,7 @@ func (sctx *serveCtx) serve( switch { case onlyGRPC: traffic = "grpc" - case onlyHttp: + case onlyHTTP: traffic = "http" default: traffic = "grpc+http" @@ -162,7 +176,7 @@ func (sctx *serveCtx) serve( Handler: createAccessController(sctx.lg, s, httpmux), ErrorLog: logger, // do not log user error } - if err := configureHttpServer(srv, s.Cfg); err != nil { + if err = configureHTTPServer(srv, s.Cfg); err != nil { sctx.lg.Error("Configure http server failed", zap.Error(err)) return err } @@ -190,19 +204,15 @@ func (sctx *serveCtx) serve( server = m.Serve httpl := m.Match(cmux.HTTP1()) - sctx.wg.Add(1) - go func(srvhttp *http.Server, tlsLis net.Listener) { - defer sctx.wg.Done() - errHandler(srvhttp.Serve(tlsLis)) - }(srv, httpl) + sctx.startHandler(errHandler, func() error { + return srv.Serve(httpl) + }) if grpcEnabled { grpcl := m.Match(cmux.HTTP2()) - sctx.wg.Add(1) - go func(gs *grpc.Server, l net.Listener) { - defer sctx.wg.Done() - errHandler(gs.Serve(l)) - }(gs, grpcl) + sctx.startHandler(errHandler, func() error { + return gs.Serve(grpcl) + }) } } @@ -249,7 +259,7 @@ func (sctx *serveCtx) serve( TLSConfig: tlscfg, ErrorLog: logger, // do not log user error } - if err := configureHttpServer(srv, s.Cfg); err != nil { + if err = configureHTTPServer(srv, s.Cfg); err != nil { sctx.lg.Error("Configure https server failed", zap.Error(err)) return err } @@ -264,11 +274,9 @@ func (sctx *serveCtx) serve( if tlsErr != nil { return tlsErr } - sctx.wg.Add(1) - go func(srvhttp *http.Server, tlsl net.Listener) { - defer sctx.wg.Done() - errHandler(srvhttp.Serve(tlsl)) - }(srv, tlsl) + sctx.startHandler(errHandler, func() error { + return srv.Serve(tlsl) + }) } sctx.serversC <- &servers{secure: true, grpc: gs, http: srv} @@ -281,12 +289,11 @@ func (sctx *serveCtx) serve( err = server() sctx.close() - // ensure all goroutines, which are created by this method, to complete before this method returns. sctx.wg.Wait() return err } -func configureHttpServer(srv *http.Server, cfg config.ServerConfig) error { +func configureHTTPServer(srv *http.Server, cfg config.ServerConfig) error { // todo (ahrtr): should we support configuring other parameters in the future as well? return http2.ConfigureServer(srv, &http2.Server{ MaxConcurrentStreams: cfg.MaxConcurrentStreams, @@ -319,7 +326,23 @@ func (sctx *serveCtx) registerGateway(dial func(ctx context.Context) (*grpc.Clie if err != nil { return nil, err } - gwmux := gw.NewServeMux() + + // Refer to https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/customizing_your_gateway/ + gwmux := gw.NewServeMux( + gw.WithMarshalerOption(gw.MIMEWildcard, + &gw.HTTPBodyMarshaler{ + Marshaler: &gw.JSONPb{ + MarshalOptions: protojson.MarshalOptions{ + UseProtoNames: true, + EmitUnpopulated: false, + }, + UnmarshalOptions: protojson.UnmarshalOptions{ + DiscardUnknown: true, + }, + }, + }, + ), + ) handlers := []registerHandlerFunc{ etcdservergw.RegisterKVHandler, @@ -336,9 +359,7 @@ func (sctx *serveCtx) registerGateway(dial func(ctx context.Context) (*grpc.Clie return nil, err } } - sctx.wg.Add(1) - go func() { - defer sctx.wg.Done() + sctx.startHandler(nil, func() error { <-ctx.Done() if cerr := conn.Close(); cerr != nil { sctx.lg.Warn( @@ -347,7 +368,8 @@ func (sctx *serveCtx) registerGateway(dial func(ctx context.Context) (*grpc.Clie zap.Error(cerr), ) } - }() + return nil + }) return gwmux, nil } @@ -356,11 +378,11 @@ type wsProxyZapLogger struct { *zap.Logger } -func (w wsProxyZapLogger) Warnln(i ...interface{}) { +func (w wsProxyZapLogger) Warnln(i ...any) { w.Warn(fmt.Sprint(i...)) } -func (w wsProxyZapLogger) Debugln(i ...interface{}) { +func (w wsProxyZapLogger) Debugln(i ...any) { w.Debug(fmt.Sprint(i...)) } @@ -450,7 +472,7 @@ func (ac *accessController) ServeHTTP(rw http.ResponseWriter, req *http.Request) addCORSHeader(rw, origin) } - if req.Method == "OPTIONS" { + if req.Method == http.MethodOptions { rw.WriteHeader(http.StatusOK) return } @@ -500,7 +522,7 @@ func (ch *corsHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { addCORSHeader(rw, origin) } - if req.Method == "OPTIONS" { + if req.Method == http.MethodOptions { rw.WriteHeader(http.StatusOK) return } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/util.go index ad46153455..32efbe67a4 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/embed/util.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/embed/util.go @@ -17,13 +17,13 @@ package embed import ( "path/filepath" - "go.etcd.io/etcd/server/v3/wal" + "go.etcd.io/etcd/server/v3/storage/wal" ) func isMemberInitialized(cfg *Config) bool { - waldir := cfg.WalDir - if waldir == "" { - waldir = filepath.Join(cfg.Dir, "member", "wal") + walDir := cfg.WalDir + if walDir == "" { + walDir = filepath.Join(cfg.Dir, "member", "wal") } - return wal.Exist(waldir) + return wal.Exist(walDir) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/adapters.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/adapters.go new file mode 100644 index 0000000000..bc9790bc2e --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/adapters.go @@ -0,0 +1,89 @@ +// Copyright 2021 The etcd 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 etcdserver + +import ( + "context" + + "github.com/coreos/go-semver/semver" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/membershippb" + "go.etcd.io/etcd/api/v3/version" + serverversion "go.etcd.io/etcd/server/v3/etcdserver/version" + "go.etcd.io/etcd/server/v3/storage/schema" +) + +// serverVersionAdapter implements the interface Server defined in package +// go.etcd.io/etcd/server/v3/etcdserver/version, and it's needed by Monitor +// in the same package. +type serverVersionAdapter struct { + *EtcdServer +} + +func NewServerVersionAdapter(s *EtcdServer) serverversion.Server { + return &serverVersionAdapter{ + EtcdServer: s, + } +} + +var _ serverversion.Server = (*serverVersionAdapter)(nil) + +func (s *serverVersionAdapter) UpdateClusterVersion(version string) { + s.GoAttach(func() { s.updateClusterVersionV3(version) }) +} + +func (s *serverVersionAdapter) LinearizableReadNotify(ctx context.Context) error { + return s.linearizableReadNotify(ctx) +} + +func (s *serverVersionAdapter) DowngradeEnable(ctx context.Context, targetVersion *semver.Version) error { + raftRequest := membershippb.DowngradeInfoSetRequest{Enabled: true, Ver: targetVersion.String()} + _, err := s.raftRequest(ctx, pb.InternalRaftRequest{DowngradeInfoSet: &raftRequest}) + return err +} + +func (s *serverVersionAdapter) DowngradeCancel(ctx context.Context) error { + raftRequest := membershippb.DowngradeInfoSetRequest{Enabled: false} + _, err := s.raftRequest(ctx, pb.InternalRaftRequest{DowngradeInfoSet: &raftRequest}) + return err +} + +func (s *serverVersionAdapter) GetClusterVersion() *semver.Version { + return s.cluster.Version() +} + +func (s *serverVersionAdapter) GetDowngradeInfo() *serverversion.DowngradeInfo { + return s.cluster.DowngradeInfo() +} + +func (s *serverVersionAdapter) GetMembersVersions() map[string]*version.Versions { + return getMembersVersions(s.lg, s.cluster, s.MemberID(), s.peerRt, s.Cfg.ReqTimeout()) +} + +func (s *serverVersionAdapter) GetStorageVersion() *semver.Version { + return s.StorageVersion() +} + +func (s *serverVersionAdapter) UpdateStorageVersion(target semver.Version) error { + // `applySnapshot` sets a new backend instance, so we need to acquire the bemu lock. + s.bemu.RLock() + defer s.bemu.RUnlock() + + tx := s.be.BatchTx() + tx.LockOutsideApply() + defer tx.Unlock() + return schema.UnsafeMigrate(s.lg, tx, s.r.storage, target) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/capability.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/capability.go index ea2f0e97e4..cf535ec4ef 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/capability.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/capability.go @@ -17,11 +17,11 @@ package api import ( "sync" - "go.etcd.io/etcd/api/v3/version" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "github.com/coreos/go-semver/semver" "go.uber.org/zap" - "github.com/coreos/go-semver/semver" + "go.etcd.io/etcd/api/v3/version" + serverversion "go.etcd.io/etcd/server/v3/etcdserver/version" ) type Capability string @@ -40,6 +40,7 @@ var ( "3.3.0": {AuthCapability: true, V3rpcCapability: true}, "3.4.0": {AuthCapability: true, V3rpcCapability: true}, "3.5.0": {AuthCapability: true, V3rpcCapability: true}, + "3.6.0": {AuthCapability: true, V3rpcCapability: true}, } enableMapMu sync.RWMutex @@ -63,7 +64,7 @@ func UpdateCapability(lg *zap.Logger, v *semver.Version) { return } enableMapMu.Lock() - if curVersion != nil && !membership.IsValidVersionChange(v, curVersion) { + if curVersion != nil && !serverversion.IsValidClusterVersionChange(curVersion, v) { enableMapMu.Unlock() return } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/base.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/base.go deleted file mode 100644 index dcfa3f0695..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/base.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2015 The etcd 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 etcdhttp - -import ( - "encoding/json" - "expvar" - "fmt" - "net/http" - - "go.etcd.io/etcd/api/v3/version" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - "go.uber.org/zap" -) - -const ( - configPath = "/config" - varsPath = "/debug/vars" - versionPath = "/version" -) - -// HandleBasic adds handlers to a mux for serving JSON etcd client requests -// that do not access the v2 store. -func HandleBasic(lg *zap.Logger, mux *http.ServeMux, server etcdserver.ServerPeer) { - mux.HandleFunc(varsPath, serveVars) - mux.HandleFunc(versionPath, versionHandler(server.Cluster(), serveVersion)) -} - -func versionHandler(c api.Cluster, fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - v := c.Version() - if v != nil { - fn(w, r, v.String()) - } else { - fn(w, r, "not_decided") - } - } -} - -func serveVersion(w http.ResponseWriter, r *http.Request, clusterV string) { - if !allowMethod(w, r, "GET") { - return - } - vs := version.Versions{ - Server: version.Version, - Cluster: clusterV, - } - - w.Header().Set("Content-Type", "application/json") - b, err := json.Marshal(&vs) - if err != nil { - panic(fmt.Sprintf("cannot marshal versions to json (%v)", err)) - } - w.Write(b) -} - -func serveVars(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r, "GET") { - return - } - - w.Header().Set("Content-Type", "application/json; charset=utf-8") - fmt.Fprintf(w, "{\n") - first := true - expvar.Do(func(kv expvar.KeyValue) { - if !first { - fmt.Fprintf(w, ",\n") - } - first = false - fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) - }) - fmt.Fprintf(w, "\n}\n") -} - -func allowMethod(w http.ResponseWriter, r *http.Request, m string) bool { - if m == r.Method { - return true - } - w.Header().Set("Allow", m) - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - return false -} - -// WriteError logs and writes the given Error to the ResponseWriter -// If Error is an etcdErr, it is rendered to the ResponseWriter -// Otherwise, it is assumed to be a StatusInternalServerError -func WriteError(lg *zap.Logger, w http.ResponseWriter, r *http.Request, err error) { - if err == nil { - return - } - switch e := err.(type) { - case *v2error.Error: - e.WriteTo(w) - - case *httptypes.HTTPError: - if et := e.WriteTo(w); et != nil { - if lg != nil { - lg.Debug( - "failed to write v2 HTTP error", - zap.String("remote-addr", r.RemoteAddr), - zap.String("internal-server-error", e.Error()), - zap.Error(et), - ) - } - } - - default: - switch err { - case etcdserver.ErrTimeoutDueToLeaderFail, etcdserver.ErrTimeoutDueToConnectionLost, etcdserver.ErrNotEnoughStartedMembers, - etcdserver.ErrUnhealthy: - if lg != nil { - lg.Warn( - "v2 response error", - zap.String("remote-addr", r.RemoteAddr), - zap.String("internal-server-error", err.Error()), - ) - } - - default: - if lg != nil { - lg.Warn( - "unexpected v2 response error", - zap.String("remote-addr", r.RemoteAddr), - zap.String("internal-server-error", err.Error()), - ) - } - } - - herr := httptypes.NewHTTPError(http.StatusInternalServerError, "Internal Server Error") - if et := herr.WriteTo(w); et != nil { - if lg != nil { - lg.Debug( - "failed to write v2 HTTP error", - zap.String("remote-addr", r.RemoteAddr), - zap.String("internal-server-error", err.Error()), - zap.Error(et), - ) - } - } - } -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/debug.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/debug.go new file mode 100644 index 0000000000..ab7feee97f --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/debug.go @@ -0,0 +1,47 @@ +// Copyright 2015 The etcd 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 etcdhttp + +import ( + "expvar" + "fmt" + "net/http" +) + +const ( + varsPath = "/debug/vars" +) + +func HandleDebug(mux *http.ServeMux) { + mux.HandleFunc(varsPath, serveVars) +} + +func serveVars(w http.ResponseWriter, r *http.Request) { + if !allowMethod(w, r, "GET") { + return + } + + w.Header().Set("Content-Type", "application/json; charset=utf-8") + fmt.Fprint(w, "{\n") + first := true + expvar.Do(func(kv expvar.KeyValue) { + if !first { + fmt.Fprint(w, ",\n") + } + first = false + fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value) + }) + fmt.Fprint(w, "\n}\n") +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/health.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/health.go index fe22fb42c8..26ed4cab16 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/health.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/health.go @@ -25,17 +25,15 @@ import ( "net/http" "path" "strings" - "time" + "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" - "github.com/prometheus/client_golang/prometheus" pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/raft/v3" "go.etcd.io/etcd/server/v3/auth" "go.etcd.io/etcd/server/v3/config" - "go.etcd.io/etcd/server/v3/etcdserver" + "go.etcd.io/raft/v3" ) const ( @@ -49,31 +47,14 @@ const ( ) type ServerHealth interface { - serverHealthV2V3 + Alarms() []*pb.AlarmMember + Leader() types.ID Range(context.Context, *pb.RangeRequest) (*pb.RangeResponse, error) Config() config.ServerConfig AuthStore() auth.AuthStore IsLearner() bool } -type serverHealthV2V3 interface { - Alarms() []*pb.AlarmMember - Leader() types.ID -} - -// HandleHealthForV2 registers metrics and health handlers for v2. -func HandleHealthForV2(lg *zap.Logger, mux *http.ServeMux, srv etcdserver.ServerV2) { - mux.Handle(PathHealth, NewHealthHandler(lg, func(ctx context.Context, excludedAlarms StringSet, serializable bool) Health { - if h := checkAlarms(lg, srv, excludedAlarms); h.Health != "true" { - return h - } - if h := checkLeader(lg, srv, serializable); h.Health != "true" { - return h - } - return checkV2API(ctx, lg, srv) - })) -} - // HandleHealth registers metrics and health handlers. it checks health by using v3 range request // and its corresponding timeout. func HandleHealth(lg *zap.Logger, mux *http.ServeMux, srv ServerHealth) { @@ -139,20 +120,22 @@ var ( Name: "health_failures", Help: "The total number of failed health checks", }) - healthCheckGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "healthcheck", - Help: "The result of each kind of healthcheck.", - }, + healthCheckGauge = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "healthcheck", + Help: "The result of each kind of healthcheck.", + }, []string{"type", "name"}, ) - healthCheckCounter = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "healthchecks_total", - Help: "The total number of each kind of healthcheck.", - }, + healthCheckCounter = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "healthchecks_total", + Help: "The total number of each kind of healthcheck.", + }, []string{"type", "name", "status"}, ) ) @@ -197,35 +180,33 @@ func getSerializableFlag(r *http.Request) bool { // TODO: etcdserver.ErrNoLeader in health API -func checkAlarms(lg *zap.Logger, srv serverHealthV2V3, excludedAlarms StringSet) Health { +func checkAlarms(lg *zap.Logger, srv ServerHealth, excludedAlarms StringSet) Health { h := Health{Health: "true"} - as := srv.Alarms() - if len(as) > 0 { - for _, v := range as { - alarmName := v.Alarm.String() - if _, found := excludedAlarms[alarmName]; found { - lg.Debug("/health excluded alarm", zap.String("alarm", v.String())) - continue - } - h.Health = "false" - switch v.Alarm { - case pb.AlarmType_NOSPACE: - h.Reason = "ALARM NOSPACE" - case pb.AlarmType_CORRUPT: - h.Reason = "ALARM CORRUPT" - default: - h.Reason = "ALARM UNKNOWN" - } - lg.Warn("serving /health false due to an alarm", zap.String("alarm", v.String())) - return h + for _, v := range srv.Alarms() { + alarmName := v.Alarm.String() + if _, found := excludedAlarms[alarmName]; found { + lg.Debug("/health excluded alarm", zap.String("alarm", v.String())) + continue + } + + h.Health = "false" + switch v.Alarm { + case pb.AlarmType_NOSPACE: + h.Reason = "ALARM NOSPACE" + case pb.AlarmType_CORRUPT: + h.Reason = "ALARM CORRUPT" + default: + h.Reason = "ALARM UNKNOWN" } + lg.Warn("serving /health false due to an alarm", zap.String("alarm", v.String())) + return h } return h } -func checkLeader(lg *zap.Logger, srv serverHealthV2V3, serializable bool) Health { +func checkLeader(lg *zap.Logger, srv ServerHealth, serializable bool) Health { h := Health{Health: "true"} if !serializable && (uint64(srv.Leader()) == raft.None) { h.Health = "false" @@ -235,21 +216,6 @@ func checkLeader(lg *zap.Logger, srv serverHealthV2V3, serializable bool) Health return h } -func checkV2API(ctx context.Context, lg *zap.Logger, srv etcdserver.ServerV2) Health { - h := Health{Health: "true"} - ctx, cancel := context.WithTimeout(ctx, time.Second) - _, err := srv.Do(ctx, pb.Request{Method: "QGET"}) - cancel() - if err != nil { - h.Health = "false" - h.Reason = fmt.Sprintf("QGET ERROR:%s", err) - lg.Warn("serving /health false; QGET fails", zap.Error(err)) - return h - } - lg.Debug("serving /health true") - return h -} - func checkAPI(ctx context.Context, lg *zap.Logger, srv ServerHealth, serializable bool) Health { h := Health{Health: "true"} cfg := srv.Config() @@ -277,7 +243,7 @@ type CheckRegistry struct { func installLivezEndpoints(lg *zap.Logger, mux *http.ServeMux, server ServerHealth) { reg := CheckRegistry{checkType: checkTypeLivez, checks: make(map[string]HealthCheck)} reg.Register("serializable_read", readCheck(server, true /* serializable */)) - reg.InstallHttpEndpoints(lg, mux) + reg.InstallHTTPEndpoints(lg, mux) } func installReadyzEndpoints(lg *zap.Logger, mux *http.ServeMux, server ServerHealth) { @@ -291,7 +257,7 @@ func installReadyzEndpoints(lg *zap.Logger, mux *http.ServeMux, server ServerHea reg.Register("linearizable_read", readCheck(server, false)) // check if local is learner reg.Register("non_learner", learnerCheck(server)) - reg.InstallHttpEndpoints(lg, mux) + reg.InstallHTTPEndpoints(lg, mux) } func (reg *CheckRegistry) Register(name string, check HealthCheck) { @@ -302,14 +268,23 @@ func (reg *CheckRegistry) RootPath() string { return "/" + reg.checkType } +// InstallHttpEndpoints installs the http handlers for the health checks. +// +// Deprecated: Please use (*CheckRegistry) InstallHTTPEndpoints instead. +// +//revive:disable-next-line:var-naming func (reg *CheckRegistry) InstallHttpEndpoints(lg *zap.Logger, mux *http.ServeMux) { + reg.InstallHTTPEndpoints(lg, mux) +} + +func (reg *CheckRegistry) InstallHTTPEndpoints(lg *zap.Logger, mux *http.ServeMux) { checkNames := make([]string, 0, len(reg.checks)) for k := range reg.checks { checkNames = append(checkNames, k) } // installs the http handler for the root path. - reg.installRootHttpEndpoint(lg, mux, checkNames...) + reg.installRootHTTPEndpoint(lg, mux, checkNames...) for _, checkName := range checkNames { // installs the http handler for the individual check sub path. subpath := path.Join(reg.RootPath(), checkName) @@ -341,8 +316,8 @@ func (reg *CheckRegistry) runHealthChecks(ctx context.Context, checkNames ...str return h } -// installRootHttpEndpoint installs the http handler for the root path. -func (reg *CheckRegistry) installRootHttpEndpoint(lg *zap.Logger, mux *http.ServeMux, checks ...string) { +// installRootHTTPEndpoint installs the http handler for the root path. +func (reg *CheckRegistry) installRootHTTPEndpoint(lg *zap.Logger, mux *http.ServeMux, checks ...string) { hfunc := func(r *http.Request) HealthStatus { // extracts the health check names to be excludeList from the query param excluded := getQuerySet(r, "exclude") diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/peer.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/peer.go index badc98634b..de5948d30f 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/peer.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/peer.go @@ -16,19 +16,21 @@ package etcdhttp import ( "encoding/json" + errorspkg "errors" "fmt" "net/http" "strconv" "strings" + "go.uber.org/zap" + "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api" "go.etcd.io/etcd/server/v3/etcdserver/api/membership" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" + "go.etcd.io/etcd/server/v3/etcdserver/errors" "go.etcd.io/etcd/server/v3/lease/leasehttp" - - "go.uber.org/zap" ) const ( @@ -71,7 +73,7 @@ func newPeerHandler( if hashKVHandler != nil { mux.Handle(etcdserver.PeerHashKVPath, hashKVHandler) } - mux.HandleFunc(versionPath, versionHandler(s.Cluster(), serveVersion)) + mux.HandleFunc(versionPath, versionHandler(s, serveVersion)) return mux } @@ -137,15 +139,15 @@ func (h *peerMemberPromoteHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ resp, err := h.server.PromoteMember(r.Context(), id) if err != nil { - switch err { - case membership.ErrIDNotFound: + switch { + case errorspkg.Is(err, membership.ErrIDNotFound): http.Error(w, err.Error(), http.StatusNotFound) - case membership.ErrMemberNotLearner: + case errorspkg.Is(err, membership.ErrMemberNotLearner): http.Error(w, err.Error(), http.StatusPreconditionFailed) - case etcdserver.ErrLearnerNotReady: + case errorspkg.Is(err, errors.ErrLearnerNotReady): http.Error(w, err.Error(), http.StatusPreconditionFailed) default: - WriteError(h.lg, w, r, err) + writeError(h.lg, w, r, err) } h.lg.Warn( "failed to promote a member", diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/errors.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/types/errors.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/errors.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/types/errors.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/utils.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/utils.go new file mode 100644 index 0000000000..082fa5a9b2 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/utils.go @@ -0,0 +1,99 @@ +// Copyright 2022 The etcd 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 etcdhttp + +import ( + errorspkg "errors" + "net/http" + + "go.uber.org/zap" + + httptypes "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/types" + "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" + "go.etcd.io/etcd/server/v3/etcdserver/errors" +) + +func allowMethod(w http.ResponseWriter, r *http.Request, m string) bool { + if m == r.Method { + return true + } + w.Header().Set("Allow", m) + http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) + return false +} + +// writeError logs and writes the given Error to the ResponseWriter +// If Error is an etcdErr, it is rendered to the ResponseWriter +// Otherwise, it is assumed to be a StatusInternalServerError +func writeError(lg *zap.Logger, w http.ResponseWriter, r *http.Request, err error) { + if err == nil { + return + } + var v2Err *v2error.Error + var httpErr *httptypes.HTTPError + switch { + case errorspkg.As(err, &v2Err): + v2Err.WriteTo(w) + + case errorspkg.As(err, &httpErr): + if et := httpErr.WriteTo(w); et != nil { + if lg != nil { + lg.Debug( + "failed to write v2 HTTP error", + zap.String("remote-addr", r.RemoteAddr), + zap.String("internal-server-error", httpErr.Error()), + zap.Error(et), + ) + } + } + + default: + switch { + case + errorspkg.Is(err, errors.ErrTimeoutDueToLeaderFail), + errorspkg.Is(err, errors.ErrTimeoutDueToConnectionLost), + errorspkg.Is(err, errors.ErrNotEnoughStartedMembers), + errorspkg.Is(err, errors.ErrUnhealthy): + if lg != nil { + lg.Warn( + "v2 response error", + zap.String("remote-addr", r.RemoteAddr), + zap.String("internal-server-error", err.Error()), + ) + } + + default: + if lg != nil { + lg.Warn( + "unexpected v2 response error", + zap.String("remote-addr", r.RemoteAddr), + zap.String("internal-server-error", err.Error()), + ) + } + } + + herr := httptypes.NewHTTPError(http.StatusInternalServerError, "Internal Server Error") + if et := herr.WriteTo(w); et != nil { + if lg != nil { + lg.Debug( + "failed to write v2 HTTP error", + zap.String("remote-addr", r.RemoteAddr), + zap.String("internal-server-error", err.Error()), + zap.Error(et), + ) + } + } + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/version.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/version.go new file mode 100644 index 0000000000..8090703a0e --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/version.go @@ -0,0 +1,65 @@ +// Copyright 2015 The etcd 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 etcdhttp + +import ( + "encoding/json" + "fmt" + "net/http" + + "go.etcd.io/etcd/api/v3/version" + "go.etcd.io/etcd/server/v3/etcdserver" +) + +const ( + versionPath = "/version" +) + +func HandleVersion(mux *http.ServeMux, server etcdserver.Server) { + mux.HandleFunc(versionPath, versionHandler(server, serveVersion)) +} + +func versionHandler(server etcdserver.Server, fn func(http.ResponseWriter, *http.Request, string, string)) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + clusterVersion := server.ClusterVersion() + storageVersion := server.StorageVersion() + clusterVersionStr, storageVersionStr := "not_decided", "unknown" + if clusterVersion != nil { + clusterVersionStr = clusterVersion.String() + } + if storageVersion != nil { + storageVersionStr = storageVersion.String() + } + fn(w, r, clusterVersionStr, storageVersionStr) + } +} + +func serveVersion(w http.ResponseWriter, r *http.Request, clusterV, storageV string) { + if !allowMethod(w, r, "GET") { + return + } + vs := version.Versions{ + Server: version.Version, + Cluster: clusterV, + Storage: storageV, + } + + w.Header().Set("Content-Type", "application/json") + b, err := json.Marshal(&vs) + if err != nil { + panic(fmt.Sprintf("cannot marshal versions to json (%v)", err)) + } + w.Write(b) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/cluster.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/cluster.go index 38e0c1630e..299e61374c 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/cluster.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/cluster.go @@ -15,32 +15,28 @@ package membership import ( - "bytes" "context" "crypto/sha1" "encoding/binary" "encoding/json" - "errors" "fmt" - "path" "sort" "strings" "sync" "time" + "github.com/coreos/go-semver/semver" + "github.com/prometheus/client_golang/prometheus" + "go.uber.org/zap" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/pkg/v3/netutil" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" + "go.etcd.io/etcd/pkg/v3/notify" "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" - - "github.com/coreos/go-semver/semver" - "github.com/prometheus/client_golang/prometheus" - "go.uber.org/zap" + serverversion "go.etcd.io/etcd/server/v3/etcdserver/version" + "go.etcd.io/raft/v3" + "go.etcd.io/raft/v3/raftpb" ) // RaftCluster is a list of Members that belong to the same raft cluster @@ -51,7 +47,7 @@ type RaftCluster struct { cid types.ID v2store v2store.Store - be backend.Backend + be MembershipBackend sync.Mutex // guards the fields below version *semver.Version @@ -60,8 +56,9 @@ type RaftCluster struct { // removed id cannot be reused. removed map[types.ID]bool - downgradeInfo *DowngradeInfo - maxLearners int + downgradeInfo *serverversion.DowngradeInfo + maxLearners int + versionChanged *notify.Notifier } // ConfigChangeContext represents a context for confChange. @@ -117,7 +114,7 @@ func NewCluster(lg *zap.Logger, opts ...ClusterOption) *RaftCluster { lg: lg, members: make(map[types.ID]*Member), removed: make(map[types.ID]bool), - downgradeInfo: &DowngradeInfo{Enabled: false}, + downgradeInfo: &serverversion.DowngradeInfo{Enabled: false}, maxLearners: clOpts.maxLearners, } } @@ -132,7 +129,7 @@ func (c *RaftCluster) Members() []*Member { ms = append(ms, m.Clone()) } sort.Sort(ms) - return []*Member(ms) + return ms } func (c *RaftCluster) Member(id types.ID) *Member { @@ -151,7 +148,7 @@ func (c *RaftCluster) VotingMembers() []*Member { } } sort.Sort(ms) - return []*Member(ms) + return ms } // MemberByName returns a Member with the given name if exists. @@ -217,7 +214,7 @@ func (c *RaftCluster) ClientURLs() []string { func (c *RaftCluster) String() string { c.Lock() defer c.Unlock() - b := &bytes.Buffer{} + b := &strings.Builder{} fmt.Fprintf(b, "{ClusterID:%s ", c.cid) var ms []string for _, m := range c.members { @@ -245,38 +242,58 @@ func (c *RaftCluster) genID() { func (c *RaftCluster) SetID(localID, cid types.ID) { c.localID = localID c.cid = cid + c.buildMembershipMetric() } func (c *RaftCluster) SetStore(st v2store.Store) { c.v2store = st } -func (c *RaftCluster) SetBackend(be backend.Backend) { +func (c *RaftCluster) SetBackend(be MembershipBackend) { c.be = be - mustCreateBackendBuckets(c.be) + c.be.MustCreateBackendBuckets() } -func (c *RaftCluster) Recover(onSet func(*zap.Logger, *semver.Version)) { - c.Lock() - defer c.Unlock() +func (c *RaftCluster) SetVersionChangedNotifier(n *notify.Notifier) { + c.versionChanged = n +} - if c.v2store != nil { +func (c *RaftCluster) UnsafeLoad() { + if c.be != nil { + c.version = c.be.ClusterVersionFromBackend() + c.members, c.removed = c.be.MustReadMembersFromBackend() + } else { c.version = clusterVersionFromStore(c.lg, c.v2store) c.members, c.removed = membersFromStore(c.lg, c.v2store) - } else { - c.version = clusterVersionFromBackend(c.lg, c.be) - c.members, c.removed = membersFromBackend(c.lg, c.be) } if c.be != nil { - c.downgradeInfo = downgradeInfoFromBackend(c.lg, c.be) + c.downgradeInfo = c.be.DowngradeInfoFromBackend() } - d := &DowngradeInfo{Enabled: false} - if c.downgradeInfo != nil { - d = &DowngradeInfo{Enabled: c.downgradeInfo.Enabled, TargetVersion: c.downgradeInfo.TargetVersion} +} + +func (c *RaftCluster) Recover(onSet func(*zap.Logger, *semver.Version)) { + c.Lock() + defer c.Unlock() + + c.UnsafeLoad() + + c.buildMembershipMetric() + + sv := semver.Must(semver.NewVersion(version.Version)) + if c.downgradeInfo != nil && c.downgradeInfo.Enabled { + c.lg.Info( + "cluster is downgrading to target version", + zap.String("target-cluster-version", c.downgradeInfo.TargetVersion), + zap.String("current-server-version", sv.String()), + ) } - mustDetectDowngrade(c.lg, c.version, d) + serverversion.MustDetectDowngrade(c.lg, sv, c.version) onSet(c.lg, c.version) for _, m := range c.members { + if c.localID == m.ID { + setIsLearnerMetric(m) + } + c.lg.Info( "recovered/added member from store", zap.String("cluster-id", c.cid.String()), @@ -296,9 +313,16 @@ func (c *RaftCluster) Recover(onSet func(*zap.Logger, *semver.Version)) { // ValidateConfigurationChange takes a proposed ConfChange and // ensures that it is still valid. -func (c *RaftCluster) ValidateConfigurationChange(cc raftpb.ConfChange) error { - // TODO: this must be switched to backend as well. - membersMap, removedMap := membersFromStore(c.lg, c.v2store) +func (c *RaftCluster) ValidateConfigurationChange(cc raftpb.ConfChange, shouldApplyV3 ShouldApplyV3) error { + var membersMap map[types.ID]*Member + var removedMap map[types.ID]bool + + if shouldApplyV3 { + membersMap, removedMap = c.be.MustReadMembersFromBackend() + } else { + membersMap, removedMap = membersFromStore(c.lg, c.v2store) + } + id := types.ID(cc.NodeID) if removedMap[id] { return ErrIDRemoved @@ -383,49 +407,37 @@ func (c *RaftCluster) ValidateConfigurationChange(cc raftpb.ConfChange) error { func (c *RaftCluster) AddMember(m *Member, shouldApplyV3 ShouldApplyV3) { c.Lock() defer c.Unlock() - - var v2Err, beErr error if c.v2store != nil { - v2Err = unsafeSaveMemberToStore(c.lg, c.v2store, m) - if v2Err != nil { - if e, ok := v2Err.(*v2error.Error); !ok || e.ErrorCode != v2error.EcodeNodeExist { - c.lg.Panic( - "failed to save member to store", - zap.String("member-id", m.ID.String()), - zap.Error(v2Err), - ) - } - } - } - if c.be != nil && shouldApplyV3 { - beErr = unsafeSaveMemberToBackend(c.lg, c.be, m) - if beErr != nil && !errors.Is(beErr, errMemberAlreadyExist) { - c.lg.Panic( - "failed to save member to backend", - zap.String("member-id", m.ID.String()), - zap.Error(beErr), - ) - } + mustSaveMemberToStore(c.lg, c.v2store, m) } - // Panic if both storeV2 and backend report member already exist. - if v2Err != nil && (beErr != nil || c.be == nil) { - c.lg.Panic( - "failed to save member to store", - zap.String("member-id", m.ID.String()), - zap.Error(v2Err), - ) + + if m.ID == c.localID { + setIsLearnerMetric(m) } - c.members[m.ID] = m + if c.be != nil && shouldApplyV3 { + c.be.MustSaveMemberToBackend(m) - c.lg.Info( - "added member", - zap.String("cluster-id", c.cid.String()), - zap.String("local-member-id", c.localID.String()), - zap.String("added-peer-id", m.ID.String()), - zap.Strings("added-peer-peer-urls", m.PeerURLs), - zap.Bool("added-peer-is-learner", m.IsLearner), - ) + c.members[m.ID] = m + c.updateMembershipMetric(m.ID, true) + + c.lg.Info( + "added member", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("added-peer-id", m.ID.String()), + zap.Strings("added-peer-peer-urls", m.PeerURLs), + zap.Bool("added-peer-is-learner", m.IsLearner), + ) + } else { + c.lg.Info( + "ignore already added member", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("added-peer-id", m.ID.String()), + zap.Strings("added-peer-peer-urls", m.PeerURLs), + zap.Bool("added-peer-is-learner", m.IsLearner)) + } } // RemoveMember removes a member from the store. @@ -433,54 +445,37 @@ func (c *RaftCluster) AddMember(m *Member, shouldApplyV3 ShouldApplyV3) { func (c *RaftCluster) RemoveMember(id types.ID, shouldApplyV3 ShouldApplyV3) { c.Lock() defer c.Unlock() - var v2Err, beErr error if c.v2store != nil { - v2Err = unsafeDeleteMemberFromStore(c.v2store, id) - if v2Err != nil { - if e, ok := v2Err.(*v2error.Error); !ok || e.ErrorCode != v2error.EcodeKeyNotFound { - c.lg.Panic( - "failed to delete member from store", - zap.String("member-id", id.String()), - zap.Error(v2Err), - ) - } - } + mustDeleteMemberFromStore(c.lg, c.v2store, id) } if c.be != nil && shouldApplyV3 { - beErr = unsafeDeleteMemberFromBackend(c.be, id) - if beErr != nil && !errors.Is(beErr, errMemberNotFound) { - c.lg.Panic( - "failed to delete member from backend", - zap.String("member-id", id.String()), - zap.Error(beErr), + c.be.MustDeleteMemberFromBackend(id) + + m, ok := c.members[id] + delete(c.members, id) + c.removed[id] = true + c.updateMembershipMetric(id, false) + + if ok { + c.lg.Info( + "removed member", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("removed-remote-peer-id", id.String()), + zap.Strings("removed-remote-peer-urls", m.PeerURLs), + zap.Bool("removed-remote-peer-is-learner", m.IsLearner), + ) + } else { + c.lg.Warn( + "skipped removing already removed member", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("removed-remote-peer-id", id.String()), ) } - } - // Panic if both storeV2 and backend report member not found. - if v2Err != nil && (beErr != nil || c.be == nil) { - c.lg.Panic( - "failed to delete member from store", - zap.String("member-id", id.String()), - zap.Error(v2Err), - ) - } - - m, ok := c.members[id] - delete(c.members, id) - c.removed[id] = true - - if ok { - c.lg.Info( - "removed member", - zap.String("cluster-id", c.cid.String()), - zap.String("local-member-id", c.localID.String()), - zap.String("removed-remote-peer-id", id.String()), - zap.Strings("removed-remote-peer-urls", m.PeerURLs), - zap.Bool("removed-remote-peer-is-learner", m.IsLearner), - ) } else { - c.lg.Warn( - "skipped removing already removed member", + c.lg.Info( + "ignore already removed member", zap.String("cluster-id", c.cid.String()), zap.String("local-member-id", c.localID.String()), zap.String("removed-remote-peer-id", id.String()), @@ -498,7 +493,7 @@ func (c *RaftCluster) UpdateAttributes(id types.ID, attr Attributes, shouldApply mustUpdateMemberAttrInStore(c.lg, c.v2store, m) } if c.be != nil && shouldApplyV3 { - unsafeSaveMemberToBackend(c.lg, c.be, m) + c.be.MustSaveMemberToBackend(m) } return } @@ -526,42 +521,141 @@ func (c *RaftCluster) PromoteMember(id types.ID, shouldApplyV3 ShouldApplyV3) { c.Lock() defer c.Unlock() - c.members[id].RaftAttributes.IsLearner = false if c.v2store != nil { - mustUpdateMemberInStore(c.lg, c.v2store, c.members[id]) + membersMap, _ := membersFromStore(c.lg, c.v2store) + if _, ok := membersMap[id]; ok { + m := *(membersMap[id]) + m.RaftAttributes.IsLearner = false + mustUpdateMemberInStore(c.lg, c.v2store, &m) + } else { + c.lg.Info("Skipped promoting non-existent member in v2store", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("promoted-member-id", id.String()), + ) + } } - if c.be != nil && shouldApplyV3 { - unsafeSaveMemberToBackend(c.lg, c.be, c.members[id]) + + if id == c.localID { + isLearner.Set(0) } - c.lg.Info( - "promote member", - zap.String("cluster-id", c.cid.String()), - zap.String("local-member-id", c.localID.String()), - zap.String("promoted-member-id", id.String()), - ) + if c.be != nil { + m := c.members[id] + if shouldApplyV3 { + m.RaftAttributes.IsLearner = false + c.updateMembershipMetric(id, true) + c.be.MustSaveMemberToBackend(m) + + c.lg.Info( + "promote member", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("promoted-member-id", id.String()), + ) + } else { + // Workaround the issues which have already been affected by + // https://github.com/etcd-io/etcd/issues/19557. The learner + // promotion request had been applied to v3store, but not saved + // to v2snapshot yet when in 3.5. Once upgrading to 3.6, the + // patch here ensure the issue can be automatically fixed. + if m == nil { + c.lg.Info( + "Skipped forcibly promoting non-existent member in v3store", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("promoted-member-id", id.String()), + ) + } else if m.IsLearner { + m.RaftAttributes.IsLearner = false + c.lg.Info("Forcibly apply member promotion request in v3store", zap.String("member", fmt.Sprintf("%+v", *m))) + c.be.MustHackySaveMemberToBackend(m) + } else { + c.lg.Info( + "ignore already promoted member in v3store", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("promoted-member-id", id.String()), + ) + } + } + } else { + c.lg.Info( + "ignore already promoted member due to backend being nil", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("promoted-member-id", id.String()), + ) + } +} + +// SyncLearnerPromotionIfNeeded provides a workaround solution to fix the issues +// which have already been affected by https://github.com/etcd-io/etcd/issues/19557. +func (c *RaftCluster) SyncLearnerPromotionIfNeeded() { + c.Lock() + defer c.Unlock() + + v2Members, _ := membersFromStore(c.lg, c.v2store) + v3Members, _ := c.be.MustReadMembersFromBackend() + + for id, v3Member := range v3Members { + v2Member, ok := v2Members[id] + if !ok { + // This isn't an error. The conf change on the member hasn't been saved to the v2 snapshot yet. + c.lg.Info("Detected member only in v3store but missing in v2store", zap.String("member", fmt.Sprintf("%+v", *v3Member))) + continue + } + + if !v2Member.IsLearner && v3Member.IsLearner { + syncedV3Member := v3Member.Clone() + syncedV3Member.IsLearner = false + c.lg.Warn("Syncing member in v3store", zap.String("member", fmt.Sprintf("%+v", *syncedV3Member))) + c.be.MustHackySaveMemberToBackend(syncedV3Member) + } + } } func (c *RaftCluster) UpdateRaftAttributes(id types.ID, raftAttr RaftAttributes, shouldApplyV3 ShouldApplyV3) { c.Lock() defer c.Unlock() - c.members[id].RaftAttributes = raftAttr if c.v2store != nil { - mustUpdateMemberInStore(c.lg, c.v2store, c.members[id]) + if _, ok := c.members[id]; ok { + m := *(c.members[id]) + m.RaftAttributes = raftAttr + mustUpdateMemberInStore(c.lg, c.v2store, &m) + } else { + c.lg.Info("Skipped updating non-existent member in v2store", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("updated-remote-peer-id", id.String()), + zap.Strings("updated-remote-peer-urls", raftAttr.PeerURLs), + zap.Bool("updated-remote-peer-is-learner", raftAttr.IsLearner), + ) + } } if c.be != nil && shouldApplyV3 { - unsafeSaveMemberToBackend(c.lg, c.be, c.members[id]) - } + c.members[id].RaftAttributes = raftAttr + c.be.MustSaveMemberToBackend(c.members[id]) - c.lg.Info( - "updated member", - zap.String("cluster-id", c.cid.String()), - zap.String("local-member-id", c.localID.String()), - zap.String("updated-remote-peer-id", id.String()), - zap.Strings("updated-remote-peer-urls", raftAttr.PeerURLs), - zap.Bool("updated-remote-peer-is-learner", raftAttr.IsLearner), - ) + c.lg.Info( + "updated member", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("updated-remote-peer-id", id.String()), + zap.Strings("updated-remote-peer-urls", raftAttr.PeerURLs), + zap.Bool("updated-remote-peer-is-learner", raftAttr.IsLearner), + ) + } else { + c.lg.Info( + "ignored already updated member", + zap.String("cluster-id", c.cid.String()), + zap.String("local-member-id", c.localID.String()), + zap.String("updated-remote-peer-id", id.String()), + zap.Strings("updated-remote-peer-urls", raftAttr.PeerURLs), + zap.Bool("updated-remote-peer-is-learner", raftAttr.IsLearner), + ) + } } func (c *RaftCluster) Version() *semver.Version { @@ -594,17 +688,21 @@ func (c *RaftCluster) SetVersion(ver *semver.Version, onSet func(*zap.Logger, *s } oldVer := c.version c.version = ver - mustDetectDowngrade(c.lg, c.version, c.downgradeInfo) + sv := semver.Must(semver.NewVersion(version.Version)) + serverversion.MustDetectDowngrade(c.lg, sv, c.version) if c.v2store != nil { mustSaveClusterVersionToStore(c.lg, c.v2store, ver) } if c.be != nil && shouldApplyV3 { - mustSaveClusterVersionToBackend(c.be, ver) + c.be.MustSaveClusterVersionToBackend(ver) } if oldVer != nil { ClusterVersionMetrics.With(prometheus.Labels{"cluster_version": version.Cluster(oldVer.String())}).Set(0) } ClusterVersionMetrics.With(prometheus.Labels{"cluster_version": version.Cluster(ver.String())}).Set(1) + if c.versionChanged != nil { + c.versionChanged.Notify() + } onSet(c.lg, ver) } @@ -697,6 +795,10 @@ func (c *RaftCluster) IsReadyToPromoteMember(id uint64) bool { return true } +func (c *RaftCluster) MembersFromBackend() (map[types.ID]*Member, map[types.ID]bool) { + return c.be.MustReadMembersFromBackend() +} + func (c *RaftCluster) MembersFromStore() (map[types.ID]*Member, map[types.ID]bool) { return membersFromStore(c.lg, c.v2store) } @@ -737,82 +839,6 @@ func membersFromStore(lg *zap.Logger, st v2store.Store) (map[types.ID]*Member, m return members, removed } -func (c *RaftCluster) MembersFromBackend() (map[types.ID]*Member, map[types.ID]bool) { - return membersFromBackend(c.lg, c.be) -} - -func membersFromBackend(lg *zap.Logger, be backend.Backend) (map[types.ID]*Member, map[types.ID]bool) { - return mustReadMembersFromBackend(lg, be) -} - -func clusterVersionFromStore(lg *zap.Logger, st v2store.Store) *semver.Version { - e, err := st.Get(path.Join(storePrefix, "version"), false, false) - if err != nil { - if isKeyNotFound(err) { - return nil - } - lg.Panic( - "failed to get cluster version from store", - zap.String("path", path.Join(storePrefix, "version")), - zap.Error(err), - ) - } - return semver.Must(semver.NewVersion(*e.Node.Value)) -} - -// The field is populated since etcd v3.5. -func clusterVersionFromBackend(lg *zap.Logger, be backend.Backend) *semver.Version { - ckey := backendClusterVersionKey() - tx := be.ReadTx() - tx.RLock() - defer tx.RUnlock() - keys, vals := tx.UnsafeRange(buckets.Cluster, ckey, nil, 0) - if len(keys) == 0 { - return nil - } - if len(keys) != 1 { - lg.Panic( - "unexpected number of keys when getting cluster version from backend", - zap.Int("number-of-key", len(keys)), - ) - } - return semver.Must(semver.NewVersion(string(vals[0]))) -} - -// The field is populated since etcd v3.5. -func downgradeInfoFromBackend(lg *zap.Logger, be backend.Backend) *DowngradeInfo { - dkey := backendDowngradeKey() - tx := be.ReadTx() - tx.Lock() - defer tx.Unlock() - keys, vals := tx.UnsafeRange(buckets.Cluster, dkey, nil, 0) - if len(keys) == 0 { - return nil - } - - if len(keys) != 1 { - lg.Panic( - "unexpected number of keys when getting cluster version from backend", - zap.Int("number-of-key", len(keys)), - ) - } - var d DowngradeInfo - if err := json.Unmarshal(vals[0], &d); err != nil { - lg.Panic("failed to unmarshal downgrade information", zap.Error(err)) - } - - // verify the downgrade info from backend - if d.Enabled { - if _, err := semver.NewVersion(d.TargetVersion); err != nil { - lg.Panic( - "unexpected version format of the downgrade target version from backend", - zap.String("target-version", d.TargetVersion), - ) - } - } - return &d -} - // ValidateClusterAndAssignIDs validates the local cluster by matching the PeerURLs // with the existing cluster. If the validation succeeds, it assigns the IDs // from the existing cluster to the local cluster. @@ -836,32 +862,17 @@ func ValidateClusterAndAssignIDs(lg *zap.Logger, local *RaftCluster, existing *R } } if !ok { - return fmt.Errorf("PeerURLs: no match found for existing member (%v, %v), last resolver error (%v)", ems[i].ID, ems[i].PeerURLs, err) + return fmt.Errorf("PeerURLs: no match found for existing member (%v, %v), last resolver error (%w)", ems[i].ID, ems[i].PeerURLs, err) } } local.members = make(map[types.ID]*Member) for _, m := range lms { local.members[m.ID] = m } + local.buildMembershipMetric() return nil } -// IsValidVersionChange checks the two scenario when version is valid to change: -// 1. Downgrade: cluster version is 1 minor version higher than local version, -// cluster version should change. -// 2. Cluster start: when not all members version are available, cluster version -// is set to MinVersion(3.0), when all members are at higher version, cluster version -// is lower than local version, cluster version should change -func IsValidVersionChange(cv *semver.Version, lv *semver.Version) bool { - cv = &semver.Version{Major: cv.Major, Minor: cv.Minor} - lv = &semver.Version{Major: lv.Major, Minor: lv.Minor} - - if isValidDowngrade(cv, lv) || (cv.Major == lv.Major && cv.LessThan(*lv)) { - return true - } - return false -} - // IsLocalMemberLearner returns if the local member is raft learner func (c *RaftCluster) IsLocalMemberLearner() bool { c.Lock() @@ -878,40 +889,33 @@ func (c *RaftCluster) IsLocalMemberLearner() bool { } // DowngradeInfo returns the downgrade status of the cluster -func (c *RaftCluster) DowngradeInfo() *DowngradeInfo { +func (c *RaftCluster) DowngradeInfo() *serverversion.DowngradeInfo { c.Lock() defer c.Unlock() if c.downgradeInfo == nil { - return &DowngradeInfo{Enabled: false} + return &serverversion.DowngradeInfo{Enabled: false} } - d := &DowngradeInfo{Enabled: c.downgradeInfo.Enabled, TargetVersion: c.downgradeInfo.TargetVersion} + d := &serverversion.DowngradeInfo{Enabled: c.downgradeInfo.Enabled, TargetVersion: c.downgradeInfo.TargetVersion} return d } -func (c *RaftCluster) SetDowngradeInfo(d *DowngradeInfo, shouldApplyV3 ShouldApplyV3) { +func (c *RaftCluster) SetDowngradeInfo(d *serverversion.DowngradeInfo, shouldApplyV3 ShouldApplyV3) { c.Lock() defer c.Unlock() if c.be != nil && shouldApplyV3 { - mustSaveDowngradeToBackend(c.lg, c.be, d) + c.be.MustSaveDowngradeToBackend(d) } c.downgradeInfo = d - - if d.Enabled { - c.lg.Info( - "The server is ready to downgrade", - zap.String("target-version", d.TargetVersion), - zap.String("server-version", version.Version), - ) - } } // IsMemberExist returns if the member with the given id exists in cluster. func (c *RaftCluster) IsMemberExist(id types.ID) bool { c.Lock() - defer c.Unlock() _, ok := c.members[id] + c.Unlock() + // gofail: var afterIsMemberExist struct{} return ok } @@ -930,23 +934,35 @@ func (c *RaftCluster) VotingMemberIDs() []types.ID { return ids } -// PushMembershipToStorage is overriding storage information about cluster's -// members, such that they fully reflect internal RaftCluster's storage. -func (c *RaftCluster) PushMembershipToStorage() { - if c.be != nil { - TrimMembershipFromBackend(c.lg, c.be) - for _, m := range c.members { - unsafeSaveMemberToBackend(c.lg, c.be, m) - } +// buildMembershipMetric sets the knownPeers metric based on the current +// members of the cluster. +func (c *RaftCluster) buildMembershipMetric() { + if c.localID == 0 { + // We don't know our own id yet. + return } - if c.v2store != nil { - TrimMembershipFromV2Store(c.lg, c.v2store) - for _, m := range c.members { - mustSaveMemberToStore(c.lg, c.v2store, m) - } + for p := range c.members { + knownPeers.WithLabelValues(c.localID.String(), p.String()).Set(1) + } + for p := range c.removed { + knownPeers.WithLabelValues(c.localID.String(), p.String()).Set(0) } } +// updateMembershipMetric updates the knownPeers metric to indicate that +// the given peer is now (un)known. +func (c *RaftCluster) updateMembershipMetric(peer types.ID, known bool) { + if c.localID == 0 { + // We don't know our own id yet. + return + } + v := float64(0) + if known { + v = 1 + } + knownPeers.WithLabelValues(c.localID.String(), peer.String()).Set(v) +} + // ValidateMaxLearnerConfig verifies the existing learner members in the cluster membership and an optional N+1 learner // scale up are not more than maxLearners. func ValidateMaxLearnerConfig(maxLearners int, members []*Member, scaleUpLearners bool) error { @@ -967,3 +983,30 @@ func ValidateMaxLearnerConfig(maxLearners int, members []*Member, scaleUpLearner return nil } + +func (c *RaftCluster) Store(store v2store.Store) { + c.Lock() + defer c.Unlock() + + verifyNoMembersInStore(c.lg, store) + + for _, m := range c.members { + mustSaveMemberToStore(c.lg, store, m) + if m.ClientURLs != nil { + mustUpdateMemberAttrInStore(c.lg, store, m) + } + c.lg.Debug( + "snapshot storing member", + zap.String("id", m.ID.String()), + zap.Strings("peer-urls", m.PeerURLs), + zap.Bool("is-learner", m.IsLearner), + ) + } + for id := range c.removed { + // We do not need to delete the member since the store is empty. + mustAddToRemovedMembersInStore(c.lg, store, id) + } + if c.version != nil { + mustSaveClusterVersionToStore(c.lg, store, c.version) + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/errors.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/errors.go index e944d48c69..ff68297128 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/errors.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/errors.go @@ -30,6 +30,6 @@ var ( ) func isKeyNotFound(err error) bool { - e, ok := err.(*v2error.Error) - return ok && e.ErrorCode == v2error.EcodeKeyNotFound + var e *v2error.Error + return errors.As(err, &e) && e.ErrorCode == v2error.EcodeKeyNotFound } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/member.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/member.go index 696549d2d2..b6037bf9d6 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/member.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/member.go @@ -18,7 +18,6 @@ import ( "crypto/sha1" "encoding/binary" "fmt" - "math/rand" "sort" "strings" "time" @@ -50,18 +49,18 @@ type Member struct { // NewMember creates a Member without an ID and generates one based on the // cluster name, peer URLs, and time. This is used for bootstrapping/adding new member. func NewMember(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Member { - memberId := computeMemberId(peerURLs, clusterName, now) - return newMember(name, peerURLs, memberId, false) + memberID := computeMemberID(peerURLs, clusterName, now) + return newMember(name, peerURLs, memberID, false) } // NewMemberAsLearner creates a learner Member without an ID and generates one based on the // cluster name, peer URLs, and time. This is used for adding new learner member. func NewMemberAsLearner(name string, peerURLs types.URLs, clusterName string, now *time.Time) *Member { - memberId := computeMemberId(peerURLs, clusterName, now) - return newMember(name, peerURLs, memberId, true) + memberID := computeMemberID(peerURLs, clusterName, now) + return newMember(name, peerURLs, memberID, true) } -func computeMemberId(peerURLs types.URLs, clusterName string, now *time.Time) types.ID { +func computeMemberID(peerURLs types.URLs, clusterName string, now *time.Time) types.ID { peerURLstrs := peerURLs.StringSlice() sort.Strings(peerURLstrs) joinedPeerUrls := strings.Join(peerURLstrs, "") @@ -76,27 +75,18 @@ func computeMemberId(peerURLs types.URLs, clusterName string, now *time.Time) ty return types.ID(binary.BigEndian.Uint64(hash[:8])) } -func newMember(name string, peerURLs types.URLs, memberId types.ID, isLearner bool) *Member { +func newMember(name string, peerURLs types.URLs, memberID types.ID, isLearner bool) *Member { m := &Member{ RaftAttributes: RaftAttributes{ PeerURLs: peerURLs.StringSlice(), IsLearner: isLearner, }, Attributes: Attributes{Name: name}, - ID: memberId, + ID: memberID, } return m } -// PickPeerURL chooses a random address from a given Member's PeerURLs. -// It will panic if there is no PeerURLs available in Member. -func (m *Member) PickPeerURL() string { - if len(m.PeerURLs) == 0 { - panic("member should always have some peer url") - } - return m.PeerURLs[rand.Intn(len(m.PeerURLs))] -} - func (m *Member) Clone() *Member { if m == nil { return nil diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/metrics.go index b3212bc80c..ad98dbb052 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/metrics.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/metrics.go @@ -17,15 +17,42 @@ package membership import "github.com/prometheus/client_golang/prometheus" var ( - ClusterVersionMetrics = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + ClusterVersionMetrics = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "cluster", + Name: "version", + Help: "Which version is running. 1 for 'cluster_version' label with current cluster version", + }, + []string{"cluster_version"}, + ) + knownPeers = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "known_peers", + Help: "The current number of known peers.", + }, + []string{"Local", "Remote"}, + ) + isLearner = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: "etcd", - Subsystem: "cluster", - Name: "version", - Help: "Which version is running. 1 for 'cluster_version' label with current cluster version", - }, - []string{"cluster_version"}) + Subsystem: "server", + Name: "is_learner", + Help: "Whether or not this member is a learner. 1 if is, 0 otherwise.", + }) ) +func setIsLearnerMetric(m *Member) { + if m.IsLearner { + isLearner.Set(1) + } else { + isLearner.Set(0) + } +} + func init() { prometheus.MustRegister(ClusterVersionMetrics) + prometheus.MustRegister(knownPeers) + prometheus.MustRegister(isLearner) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/store.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/store.go index 9f52d50f6b..d4bb7341e1 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/store.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/store.go @@ -1,4 +1,4 @@ -// Copyright 2016 The etcd Authors +// Copyright 2021 The etcd Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,329 +15,38 @@ package membership import ( - "bytes" - "encoding/json" - "fmt" "path" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" - "github.com/coreos/go-semver/semver" "go.uber.org/zap" -) - -const ( - attributesSuffix = "attributes" - raftAttributesSuffix = "raftAttributes" - - // the prefix for storing membership related information in store provided by store pkg. - storePrefix = "/0" -) -var ( - StoreMembersPrefix = path.Join(storePrefix, "members") - storeRemovedMembersPrefix = path.Join(storePrefix, "removed_members") - errMemberAlreadyExist = fmt.Errorf("member already exists") - errMemberNotFound = fmt.Errorf("member not found") + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/server/v3/etcdserver/version" ) -func unsafeSaveMemberToBackend(lg *zap.Logger, be backend.Backend, m *Member) error { - mkey := backendMemberKey(m.ID) - mvalue, err := json.Marshal(m) - if err != nil { - lg.Panic("failed to marshal member", zap.Error(err)) - } - - tx := be.BatchTx() - tx.LockInsideApply() - defer tx.Unlock() - tx.UnsafePut(buckets.Members, mkey, mvalue) - return nil -} - -// TrimClusterFromBackend removes all information about cluster (versions) -// from the v3 backend. -func TrimClusterFromBackend(be backend.Backend) error { - tx := be.BatchTx() - tx.LockOutsideApply() - defer tx.Unlock() - tx.UnsafeDeleteBucket(buckets.Cluster) - return nil +type MembershipBackend interface { + ClusterVersionBackend + MemberBackend + DowngradeInfoBackend + MustCreateBackendBuckets() } -func unsafeDeleteMemberFromBackend(be backend.Backend, id types.ID) error { - mkey := backendMemberKey(id) - - tx := be.BatchTx() - tx.LockInsideApply() - defer tx.Unlock() - tx.UnsafePut(buckets.MembersRemoved, mkey, []byte("removed")) - if !unsafeMemberExists(tx, mkey) { - return errMemberNotFound - } - tx.UnsafeDelete(buckets.Members, mkey) - return nil -} - -func unsafeMemberExists(tx backend.ReadTx, mkey []byte) bool { - var found bool - tx.UnsafeForEach(buckets.Members, func(k, v []byte) error { - if bytes.Equal(k, mkey) { - found = true - } - return nil - }) - return found +type ClusterVersionBackend interface { + ClusterVersionFromBackend() *semver.Version + MustSaveClusterVersionToBackend(version *semver.Version) } -func readMembersFromBackend(lg *zap.Logger, be backend.Backend) (map[types.ID]*Member, map[types.ID]bool, error) { - members := make(map[types.ID]*Member) - removed := make(map[types.ID]bool) - - tx := be.ReadTx() - tx.RLock() - defer tx.RUnlock() - err := tx.UnsafeForEach(buckets.Members, func(k, v []byte) error { - memberId := mustParseMemberIDFromBytes(lg, k) - m := &Member{ID: memberId} - if err := json.Unmarshal(v, &m); err != nil { - return err - } - members[memberId] = m - return nil - }) - if err != nil { - return nil, nil, fmt.Errorf("couldn't read members from backend: %w", err) - } - - err = tx.UnsafeForEach(buckets.MembersRemoved, func(k, v []byte) error { - memberId := mustParseMemberIDFromBytes(lg, k) - removed[memberId] = true - return nil - }) - if err != nil { - return nil, nil, fmt.Errorf("couldn't read members_removed from backend: %w", err) - } - return members, removed, nil +type MemberBackend interface { + MustReadMembersFromBackend() (map[types.ID]*Member, map[types.ID]bool) + MustSaveMemberToBackend(*Member) + MustHackySaveMemberToBackend(*Member) + TrimMembershipFromBackend() error + MustDeleteMemberFromBackend(types.ID) } -func mustReadMembersFromBackend(lg *zap.Logger, be backend.Backend) (map[types.ID]*Member, map[types.ID]bool) { - members, removed, err := readMembersFromBackend(lg, be) - if err != nil { - lg.Panic("couldn't read members from backend", zap.Error(err)) - } - return members, removed -} - -// TrimMembershipFromBackend removes all information about members & -// removed_members from the v3 backend. -func TrimMembershipFromBackend(lg *zap.Logger, be backend.Backend) error { - lg.Info("Trimming membership information from the backend...") - tx := be.BatchTx() - tx.LockOutsideApply() - defer tx.Unlock() - err := tx.UnsafeForEach(buckets.Members, func(k, v []byte) error { - tx.UnsafeDelete(buckets.Members, k) - lg.Debug("Removed member from the backend", - zap.Stringer("member", mustParseMemberIDFromBytes(lg, k))) - return nil - }) - if err != nil { - return err - } - return tx.UnsafeForEach(buckets.MembersRemoved, func(k, v []byte) error { - tx.UnsafeDelete(buckets.MembersRemoved, k) - lg.Debug("Removed removed_member from the backend", - zap.Stringer("member", mustParseMemberIDFromBytes(lg, k))) - return nil - }) -} - -// TrimMembershipFromV2Store removes all information about members & -// removed_members from the v2 store. -func TrimMembershipFromV2Store(lg *zap.Logger, s v2store.Store) error { - members, removed := membersFromStore(lg, s) - - for mID := range members { - _, err := s.Delete(MemberStoreKey(mID), true, true) - if err != nil { - return err - } - } - for mID := range removed { - _, err := s.Delete(RemovedMemberStoreKey(mID), true, true) - if err != nil { - return err - } - } - - return nil -} - -// The field is populated since etcd v3.5. -func mustSaveClusterVersionToBackend(be backend.Backend, ver *semver.Version) { - ckey := backendClusterVersionKey() - - tx := be.BatchTx() - tx.LockInsideApply() - defer tx.Unlock() - tx.UnsafePut(buckets.Cluster, ckey, []byte(ver.String())) -} - -// The field is populated since etcd v3.5. -func mustSaveDowngradeToBackend(lg *zap.Logger, be backend.Backend, downgrade *DowngradeInfo) { - dkey := backendDowngradeKey() - dvalue, err := json.Marshal(downgrade) - if err != nil { - lg.Panic("failed to marshal downgrade information", zap.Error(err)) - } - tx := be.BatchTx() - tx.LockInsideApply() - defer tx.Unlock() - tx.UnsafePut(buckets.Cluster, dkey, dvalue) -} - -func mustSaveMemberToStore(lg *zap.Logger, s v2store.Store, m *Member) { - err := unsafeSaveMemberToStore(lg, s, m) - if err != nil { - lg.Panic( - "failed to save member to store", - zap.String("member-id", m.ID.String()), - zap.Error(err), - ) - } -} - -func unsafeSaveMemberToStore(lg *zap.Logger, s v2store.Store, m *Member) error { - b, err := json.Marshal(m.RaftAttributes) - if err != nil { - lg.Panic("failed to marshal raftAttributes", zap.Error(err)) - } - p := path.Join(MemberStoreKey(m.ID), raftAttributesSuffix) - _, err = s.Create(p, false, string(b), false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}) - return err -} - -func unsafeDeleteMemberFromStore(s v2store.Store, id types.ID) error { - if _, err := s.Delete(MemberStoreKey(id), true, true); err != nil { - return err - } - if _, err := s.Create(RemovedMemberStoreKey(id), false, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil { - return err - } - return nil -} - -func mustUpdateMemberInStore(lg *zap.Logger, s v2store.Store, m *Member) { - b, err := json.Marshal(m.RaftAttributes) - if err != nil { - lg.Panic("failed to marshal raftAttributes", zap.Error(err)) - } - p := path.Join(MemberStoreKey(m.ID), raftAttributesSuffix) - if _, err := s.Update(p, string(b), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil { - lg.Panic( - "failed to update raftAttributes", - zap.String("path", p), - zap.Error(err), - ) - } -} - -func mustUpdateMemberAttrInStore(lg *zap.Logger, s v2store.Store, m *Member) { - b, err := json.Marshal(m.Attributes) - if err != nil { - lg.Panic("failed to marshal attributes", zap.Error(err)) - } - p := path.Join(MemberStoreKey(m.ID), attributesSuffix) - if _, err := s.Set(p, false, string(b), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil { - lg.Panic( - "failed to update attributes", - zap.String("path", p), - zap.Error(err), - ) - } -} - -func mustSaveClusterVersionToStore(lg *zap.Logger, s v2store.Store, ver *semver.Version) { - if _, err := s.Set(StoreClusterVersionKey(), false, ver.String(), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil { - lg.Panic( - "failed to save cluster version to store", - zap.String("path", StoreClusterVersionKey()), - zap.Error(err), - ) - } -} - -// nodeToMember builds member from a key value node. -// the child nodes of the given node MUST be sorted by key. -func nodeToMember(lg *zap.Logger, n *v2store.NodeExtern) (*Member, error) { - m := &Member{ID: MustParseMemberIDFromKey(lg, n.Key)} - attrs := make(map[string][]byte) - raftAttrKey := path.Join(n.Key, raftAttributesSuffix) - attrKey := path.Join(n.Key, attributesSuffix) - for _, nn := range n.Nodes { - if nn.Key != raftAttrKey && nn.Key != attrKey { - return nil, fmt.Errorf("unknown key %q", nn.Key) - } - attrs[nn.Key] = []byte(*nn.Value) - } - if data := attrs[raftAttrKey]; data != nil { - if err := json.Unmarshal(data, &m.RaftAttributes); err != nil { - return nil, fmt.Errorf("unmarshal raftAttributes error: %v", err) - } - } else { - return nil, fmt.Errorf("raftAttributes key doesn't exist") - } - if data := attrs[attrKey]; data != nil { - if err := json.Unmarshal(data, &m.Attributes); err != nil { - return m, fmt.Errorf("unmarshal attributes error: %v", err) - } - } - return m, nil -} - -func backendMemberKey(id types.ID) []byte { - return []byte(id.String()) -} - -func backendClusterVersionKey() []byte { - return []byte("clusterVersion") -} - -func backendDowngradeKey() []byte { - return []byte("downgrade") -} - -func mustCreateBackendBuckets(be backend.Backend) { - tx := be.BatchTx() - tx.LockOutsideApply() - defer tx.Unlock() - tx.UnsafeCreateBucket(buckets.Members) - tx.UnsafeCreateBucket(buckets.MembersRemoved) - tx.UnsafeCreateBucket(buckets.Cluster) -} - -func MemberStoreKey(id types.ID) string { - return path.Join(StoreMembersPrefix, id.String()) -} - -func StoreClusterVersionKey() string { - return path.Join(storePrefix, "version") -} - -func MemberAttributesStorePath(id types.ID) string { - return path.Join(MemberStoreKey(id), attributesSuffix) -} - -func mustParseMemberIDFromBytes(lg *zap.Logger, key []byte) types.ID { - id, err := types.IDFromString(string(key)) - if err != nil { - lg.Panic("failed to parse member id from key", zap.Error(err)) - } - return id +type DowngradeInfoBackend interface { + MustSaveDowngradeToBackend(*version.DowngradeInfo) + DowngradeInfoFromBackend() *version.DowngradeInfo } func MustParseMemberIDFromKey(lg *zap.Logger, key string) types.ID { @@ -347,7 +56,3 @@ func MustParseMemberIDFromKey(lg *zap.Logger, key string) types.ID { } return id } - -func RemovedMemberStoreKey(id types.ID) string { - return path.Join(storeRemovedMembersPrefix, id.String()) -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/storev2.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/storev2.go index 8505c63f36..051150520b 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/storev2.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/storev2.go @@ -15,9 +15,30 @@ package membership import ( + "encoding/json" + "fmt" + "path" + + "github.com/coreos/go-semver/semver" + "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" ) +const ( + // the prefix for storing membership related information in store provided by store pkg. + storePrefix = "/0" + + attributesSuffix = "attributes" + raftAttributesSuffix = "raftAttributes" +) + +var ( + StoreMembersPrefix = path.Join(storePrefix, "members") + storeRemovedMembersPrefix = path.Join(storePrefix, "removed_members") +) + // IsMetaStoreOnly verifies if the given `store` contains only // a meta-information (members, version) that can be recovered from the // backend (storev3) as well as opposed to user-data. @@ -26,11 +47,212 @@ func IsMetaStoreOnly(store v2store.Store) (bool, error) { if err != nil { return false, err } + + // storePermsPrefix is the internal prefix of the storage layer dedicated to storing user data. + // refer to https://github.com/etcd-io/etcd/blob/v3.5.21/server/etcdserver/api/v2auth/auth.go#L40 + storePermsPrefix := "/2" for _, n := range event.Node.Nodes { - if n.Key != storePrefix && n.Nodes.Len() > 0 { + if n.Key == storePrefix { + continue + } + + // For auth data, even after we remove all users and roles, the node + // "/2/roles" and "/2/users" are still present in the tree. We need + // to exclude such case. See an example below, + // Refer to https://github.com/etcd-io/etcd/discussions/20231#discussioncomment-13791940 + /* + "2": { + "Path": "/2", + "CreatedIndex": 204749, + "ModifiedIndex": 204749, + "ExpireTime": "0001-01-01T00:00:00Z", + "Value": "", + "Children": { + "enabled": { + "Path": "/2/enabled", + "CreatedIndex": 204752, + "ModifiedIndex": 16546016, + "ExpireTime": "0001-01-01T00:00:00Z", + "Value": "false", + "Children": null + }, + "roles": { + "Path": "/2/roles", + "CreatedIndex": 204751, + "ModifiedIndex": 204751, + "ExpireTime": "0001-01-01T00:00:00Z", + "Value": "", + "Children": {} + }, + "users": { + "Path": "/2/users", + "CreatedIndex": 204750, + "ModifiedIndex": 204750, + "ExpireTime": "0001-01-01T00:00:00Z", + "Value": "", + "Children": {} + } + } + } + */ + if n.Key == storePermsPrefix { + if n.Nodes.Len() > 0 { + for _, child := range n.Nodes { + if child.Nodes.Len() > 0 { + return false, nil + } + } + } + continue + } + + if n.Nodes.Len() > 0 { return false, nil } } return true, nil } + +func verifyNoMembersInStore(lg *zap.Logger, s v2store.Store) { + members, removed := membersFromStore(lg, s) + if len(members) != 0 || len(removed) != 0 { + lg.Panic("store has membership info") + } +} + +func mustSaveMemberToStore(lg *zap.Logger, s v2store.Store, m *Member) { + b, err := json.Marshal(m.RaftAttributes) + if err != nil { + lg.Panic("failed to marshal raftAttributes", zap.Error(err)) + } + p := path.Join(MemberStoreKey(m.ID), raftAttributesSuffix) + if _, err := s.Create(p, false, string(b), false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil { + lg.Panic( + "failed to save member to store", + zap.String("path", p), + zap.Error(err), + ) + } +} + +func mustDeleteMemberFromStore(lg *zap.Logger, s v2store.Store, id types.ID) { + if _, err := s.Delete(MemberStoreKey(id), true, true); err != nil { + lg.Panic( + "failed to delete member from store", + zap.String("path", MemberStoreKey(id)), + zap.Error(err), + ) + } + + mustAddToRemovedMembersInStore(lg, s, id) +} + +func mustAddToRemovedMembersInStore(lg *zap.Logger, s v2store.Store, id types.ID) { + if _, err := s.Create(RemovedMemberStoreKey(id), false, "", false, v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil { + lg.Panic( + "failed to create removedMember", + zap.String("path", RemovedMemberStoreKey(id)), + zap.Error(err), + ) + } +} + +func mustUpdateMemberInStore(lg *zap.Logger, s v2store.Store, m *Member) { + b, err := json.Marshal(m.RaftAttributes) + if err != nil { + lg.Panic("failed to marshal raftAttributes", zap.Error(err)) + } + p := path.Join(MemberStoreKey(m.ID), raftAttributesSuffix) + if _, err := s.Update(p, string(b), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil { + lg.Panic( + "failed to update raftAttributes", + zap.String("path", p), + zap.Error(err), + ) + } +} + +func mustUpdateMemberAttrInStore(lg *zap.Logger, s v2store.Store, m *Member) { + b, err := json.Marshal(m.Attributes) + if err != nil { + lg.Panic("failed to marshal attributes", zap.Error(err)) + } + p := path.Join(MemberStoreKey(m.ID), attributesSuffix) + if _, err := s.Set(p, false, string(b), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil { + lg.Panic( + "failed to update attributes", + zap.String("path", p), + zap.Error(err), + ) + } +} + +func mustSaveClusterVersionToStore(lg *zap.Logger, s v2store.Store, ver *semver.Version) { + if _, err := s.Set(StoreClusterVersionKey(), false, ver.String(), v2store.TTLOptionSet{ExpireTime: v2store.Permanent}); err != nil { + lg.Panic( + "failed to save cluster version to store", + zap.String("path", StoreClusterVersionKey()), + zap.Error(err), + ) + } +} + +// nodeToMember builds member from a key value node. +// the child nodes of the given node MUST be sorted by key. +func nodeToMember(lg *zap.Logger, n *v2store.NodeExtern) (*Member, error) { + m := &Member{ID: MustParseMemberIDFromKey(lg, n.Key)} + attrs := make(map[string][]byte) + raftAttrKey := path.Join(n.Key, raftAttributesSuffix) + attrKey := path.Join(n.Key, attributesSuffix) + for _, nn := range n.Nodes { + if nn.Key != raftAttrKey && nn.Key != attrKey { + return nil, fmt.Errorf("unknown key %q", nn.Key) + } + attrs[nn.Key] = []byte(*nn.Value) + } + if data := attrs[raftAttrKey]; data != nil { + if err := json.Unmarshal(data, &m.RaftAttributes); err != nil { + return nil, fmt.Errorf("unmarshal raftAttributes error: %w", err) + } + } else { + return nil, fmt.Errorf("raftAttributes key doesn't exist") + } + if data := attrs[attrKey]; data != nil { + if err := json.Unmarshal(data, &m.Attributes); err != nil { + return m, fmt.Errorf("unmarshal attributes error: %w", err) + } + } + return m, nil +} + +func StoreClusterVersionKey() string { + return path.Join(storePrefix, "version") +} + +func RemovedMemberStoreKey(id types.ID) string { + return path.Join(storeRemovedMembersPrefix, id.String()) +} + +func MemberStoreKey(id types.ID) string { + return path.Join(StoreMembersPrefix, id.String()) +} + +func MemberAttributesStorePath(id types.ID) string { + return path.Join(MemberStoreKey(id), attributesSuffix) +} + +func clusterVersionFromStore(lg *zap.Logger, st v2store.Store) *semver.Version { + e, err := st.Get(path.Join(storePrefix, "version"), false, false) + if err != nil { + if isKeyNotFound(err) { + return nil + } + lg.Panic( + "failed to get cluster version from store", + zap.String("path", path.Join(storePrefix, "version")), + zap.Error(err), + ) + } + return semver.Must(semver.NewVersion(*e.Node.Value)) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/coder.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/coder.go index cc28249697..9774429989 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/coder.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/coder.go @@ -14,7 +14,7 @@ package rafthttp -import "go.etcd.io/etcd/raft/v3/raftpb" +import "go.etcd.io/raft/v3/raftpb" type encoder interface { // encode encodes the given message to an output stream. diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/doc.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/doc.go index a9486a8bb6..c45dc81782 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/doc.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/doc.go @@ -12,5 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package rafthttp implements HTTP transportation layer for etcd/raft pkg. +// Package rafthttp implements HTTP transportation layer for raft pkg. package rafthttp diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/http.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/http.go index f60383f479..2610240e5a 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/http.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/http.go @@ -18,20 +18,20 @@ import ( "context" "errors" "fmt" - "io/ioutil" + "io" "net/http" "path" "strings" "time" + humanize "github.com/dustin/go-humanize" + "go.uber.org/zap" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/types" pioutil "go.etcd.io/etcd/pkg/v3/ioutil" - "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/etcdserver/api/snap" - - humanize "github.com/dustin/go-humanize" - "go.uber.org/zap" + "go.etcd.io/raft/v3/raftpb" ) const ( @@ -93,7 +93,7 @@ func newPipelineHandler(t *Transport, r Raft, cid types.ID) http.Handler { } func (h *pipelineHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if r.Method != "POST" { + if r.Method != http.MethodPost { w.Header().Set("Allow", "POST") http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return @@ -111,7 +111,7 @@ func (h *pipelineHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Limit the data size that could be read from the request body, which ensures that read from // connection will not time out accidentally due to possible blocking in underlying implementation. limitedr := pioutil.NewLimitedBufferReader(r.Body, connReadLimitByte) - b, err := ioutil.ReadAll(limitedr) + b, err := io.ReadAll(limitedr) if err != nil { h.lg.Warn( "failed to read Raft message", @@ -138,9 +138,10 @@ func (h *pipelineHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { receivedBytes.WithLabelValues(types.ID(m.From).String()).Add(float64(len(b))) if err := h.r.Process(context.TODO(), m); err != nil { - switch v := err.(type) { - case writerToResponse: - v.WriteTo(w) + var writerErr writerToResponse + switch { + case errors.As(err, &writerErr): + writerErr.WriteTo(w) default: h.lg.Warn( "failed to process Raft message", @@ -199,7 +200,7 @@ const unknownSnapshotSender = "UNKNOWN_SNAPSHOT_SENDER" func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { start := time.Now() - if r.Method != "POST" { + if r.Method != http.MethodPost { w.Header().Set("Allow", "POST") http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) snapshotReceiveFailures.WithLabelValues(unknownSnapshotSender).Inc() @@ -294,11 +295,12 @@ func (h *snapshotHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { ) if err := h.r.Process(context.TODO(), m); err != nil { - switch v := err.(type) { + var writerErr writerToResponse + switch { // Process may return writerToResponse error when doing some // additional checks before calling raft.Node.Step. - case writerToResponse: - v.WriteTo(w) + case errors.As(err, &writerErr): + writerErr.WriteTo(w) default: msg := fmt.Sprintf("failed to process raft message (%v)", err) h.lg.Warn( @@ -346,7 +348,7 @@ func newStreamHandler(t *Transport, pg peerGetter, r Raft, id, cid types.ID) htt } func (h *streamHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if r.Method != "GET" { + if r.Method != http.MethodGet { w.Header().Set("Allow", "GET") http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return @@ -484,7 +486,7 @@ func checkClusterCompatibilityFromHeader(lg *zap.Logger, localID types.ID, heade if err != nil { lg.Warn( - "failed to check version compatibility", + "failed version compatibility check", zap.String("local-member-id", localID.String()), zap.String("local-member-cluster-id", cid.String()), zap.String("local-member-server-version", localVs), diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/metrics.go index 02fff84be7..f9e13e2c8f 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/metrics.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/metrics.go @@ -17,150 +17,165 @@ package rafthttp import "github.com/prometheus/client_golang/prometheus" var ( - activePeers = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "active_peers", - Help: "The current number of active peer connections.", - }, + activePeers = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "active_peers", + Help: "The current number of active peer connections.", + }, []string{"Local", "Remote"}, ) - disconnectedPeers = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "disconnected_peers_total", - Help: "The total number of disconnected peers.", - }, + disconnectedPeers = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "disconnected_peers_total", + Help: "The total number of disconnected peers.", + }, []string{"Local", "Remote"}, ) - sentBytes = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "peer_sent_bytes_total", - Help: "The total number of bytes sent to peers.", - }, + sentBytes = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "peer_sent_bytes_total", + Help: "The total number of bytes sent to peers.", + }, []string{"To"}, ) - receivedBytes = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "peer_received_bytes_total", - Help: "The total number of bytes received from peers.", - }, + receivedBytes = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "peer_received_bytes_total", + Help: "The total number of bytes received from peers.", + }, []string{"From"}, ) - sentFailures = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "peer_sent_failures_total", - Help: "The total number of send failures from peers.", - }, + sentFailures = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "peer_sent_failures_total", + Help: "The total number of send failures from peers.", + }, []string{"To"}, ) - recvFailures = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "peer_received_failures_total", - Help: "The total number of receive failures from peers.", - }, + recvFailures = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "peer_received_failures_total", + Help: "The total number of receive failures from peers.", + }, []string{"From"}, ) - snapshotSend = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "snapshot_send_success", - Help: "Total number of successful snapshot sends", - }, + snapshotSend = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "snapshot_send_success", + Help: "Total number of successful snapshot sends", + }, []string{"To"}, ) - snapshotSendInflights = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "snapshot_send_inflights_total", - Help: "Total number of inflight snapshot sends", - }, + snapshotSendInflights = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "snapshot_send_inflights_total", + Help: "Total number of inflight snapshot sends", + }, []string{"To"}, ) - snapshotSendFailures = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "snapshot_send_failures", - Help: "Total number of snapshot send failures", - }, + snapshotSendFailures = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "snapshot_send_failures", + Help: "Total number of snapshot send failures", + }, []string{"To"}, ) - snapshotSendSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "snapshot_send_total_duration_seconds", - Help: "Total latency distributions of v3 snapshot sends", - - // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2 - // highest bucket start of 0.1 sec * 2^9 == 51.2 sec - Buckets: prometheus.ExponentialBuckets(0.1, 2, 10), - }, + snapshotSendSeconds = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "snapshot_send_total_duration_seconds", + Help: "Total latency distributions of v3 snapshot sends", + + // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2 + // highest bucket start of 0.1 sec * 2^9 == 51.2 sec + Buckets: prometheus.ExponentialBuckets(0.1, 2, 10), + }, []string{"To"}, ) - snapshotReceive = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "snapshot_receive_success", - Help: "Total number of successful snapshot receives", - }, + snapshotReceive = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "snapshot_receive_success", + Help: "Total number of successful snapshot receives", + }, []string{"From"}, ) - snapshotReceiveInflights = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "snapshot_receive_inflights_total", - Help: "Total number of inflight snapshot receives", - }, + snapshotReceiveInflights = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "snapshot_receive_inflights_total", + Help: "Total number of inflight snapshot receives", + }, []string{"From"}, ) - snapshotReceiveFailures = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "snapshot_receive_failures", - Help: "Total number of snapshot receive failures", - }, + snapshotReceiveFailures = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "snapshot_receive_failures", + Help: "Total number of snapshot receive failures", + }, []string{"From"}, ) - snapshotReceiveSeconds = prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "snapshot_receive_total_duration_seconds", - Help: "Total latency distributions of v3 snapshot receives", - - // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2 - // highest bucket start of 0.1 sec * 2^9 == 51.2 sec - Buckets: prometheus.ExponentialBuckets(0.1, 2, 10), - }, + snapshotReceiveSeconds = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "snapshot_receive_total_duration_seconds", + Help: "Total latency distributions of v3 snapshot receives", + + // lowest bucket start of upper bound 0.1 sec (100 ms) with factor 2 + // highest bucket start of 0.1 sec * 2^9 == 51.2 sec + Buckets: prometheus.ExponentialBuckets(0.1, 2, 10), + }, []string{"From"}, ) - rttSec = prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "peer_round_trip_time_seconds", - Help: "Round-Trip-Time histogram between peers", - - // lowest bucket start of upper bound 0.0001 sec (0.1 ms) with factor 2 - // highest bucket start of 0.0001 sec * 2^15 == 3.2768 sec - Buckets: prometheus.ExponentialBuckets(0.0001, 2, 16), - }, + rttSec = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "peer_round_trip_time_seconds", + Help: "Round-Trip-Time histogram between peers", + + // lowest bucket start of upper bound 0.0001 sec (0.1 ms) with factor 2 + // highest bucket start of 0.0001 sec * 2^15 == 3.2768 sec + Buckets: prometheus.ExponentialBuckets(0.0001, 2, 16), + }, []string{"To"}, ) ) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msg_codec.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msg_codec.go index 7db880baa2..5444c01f8f 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msg_codec.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msg_codec.go @@ -20,7 +20,7 @@ import ( "io" "go.etcd.io/etcd/pkg/v3/pbutil" - "go.etcd.io/etcd/raft/v3/raftpb" + "go.etcd.io/raft/v3/raftpb" ) // messageEncoder is a encoder that can encode all kinds of messages. diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msgappv2_codec.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msgappv2_codec.go index 9a7f4a1770..59425aeea6 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msgappv2_codec.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/msgappv2_codec.go @@ -22,8 +22,8 @@ import ( "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/pkg/v3/pbutil" - "go.etcd.io/etcd/raft/v3/raftpb" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" + "go.etcd.io/raft/v3/raftpb" ) const ( diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer.go index 444d6bde94..c1e6ba1270 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer.go @@ -19,14 +19,14 @@ import ( "sync" "time" + "go.uber.org/zap" + "golang.org/x/time/rate" + "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/etcdserver/api/snap" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" - - "go.uber.org/zap" - "golang.org/x/time/rate" + "go.etcd.io/raft/v3" + "go.etcd.io/raft/v3/raftpb" ) const ( @@ -250,30 +250,16 @@ func (p *peer) send(m raftpb.Message) { if isMsgSnap(m) { p.r.ReportSnapshot(m.To, raft.SnapshotFailure) } - if p.status.isActive() { - if p.lg != nil { - p.lg.Warn( - "dropped internal Raft message since sending buffer is full (overloaded network)", - zap.String("message-type", m.Type.String()), - zap.String("local-member-id", p.localID.String()), - zap.String("from", types.ID(m.From).String()), - zap.String("remote-peer-id", p.id.String()), - zap.String("remote-peer-name", name), - zap.Bool("remote-peer-active", p.status.isActive()), - ) - } - } else { - if p.lg != nil { - p.lg.Warn( - "dropped internal Raft message since sending buffer is full (overloaded network)", - zap.String("message-type", m.Type.String()), - zap.String("local-member-id", p.localID.String()), - zap.String("from", types.ID(m.From).String()), - zap.String("remote-peer-id", p.id.String()), - zap.String("remote-peer-name", name), - zap.Bool("remote-peer-active", p.status.isActive()), - ) - } + if p.lg != nil { + p.lg.Warn( + "dropped internal Raft message since sending buffer is full", + zap.String("message-type", m.Type.String()), + zap.String("local-member-id", p.localID.String()), + zap.String("from", types.ID(m.From).String()), + zap.String("remote-peer-id", p.id.String()), + zap.String("remote-peer-name", name), + zap.Bool("remote-peer-active", p.status.isActive()), + ) } sentFailures.WithLabelValues(types.ID(m.To).String()).Inc() } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer_status.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer_status.go index cad19b2fbc..01c3ebacfa 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer_status.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/peer_status.go @@ -20,9 +20,9 @@ import ( "sync" "time" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/types" ) type failureType struct { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/pipeline.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/pipeline.go index de3b459118..0790b58d03 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/pipeline.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/pipeline.go @@ -18,18 +18,18 @@ import ( "bytes" "context" "errors" - "io/ioutil" + "io" "runtime" "sync" "time" + "go.uber.org/zap" + "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/pkg/v3/pbutil" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/raft/v3/raftpb" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" - - "go.uber.org/zap" + "go.etcd.io/raft/v3" + "go.etcd.io/raft/v3/raftpb" ) const ( @@ -103,7 +103,7 @@ func (p *pipeline) handle() { if err != nil { p.status.deactivate(failureType{source: pipelineMsg, action: "write"}, err.Error()) - if m.Type == raftpb.MsgApp && p.followerStats != nil { + if isMsgApp(m) && p.followerStats != nil { p.followerStats.Fail() } p.raft.ReportUnreachable(m.To) @@ -115,7 +115,7 @@ func (p *pipeline) handle() { } p.status.activate() - if m.Type == raftpb.MsgApp && p.followerStats != nil { + if isMsgApp(m) && p.followerStats != nil { p.followerStats.Succ(end.Sub(start)) } if isMsgSnap(m) { @@ -154,7 +154,7 @@ func (p *pipeline) post(data []byte) (err error) { return err } defer resp.Body.Close() - b, err := ioutil.ReadAll(resp.Body) + b, err := io.ReadAll(resp.Body) if err != nil { p.picker.unreachable(u) return err @@ -165,7 +165,7 @@ func (p *pipeline) post(data []byte) (err error) { p.picker.unreachable(u) // errMemberRemoved is a critical error since a removed member should // always be stopped. So we use reportCriticalError to report it to errorc. - if err == errMemberRemoved { + if errors.Is(err, errMemberRemoved) { reportCriticalError(err, p.errorc) } return err diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/remote.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/remote.go index eddb3f4da1..3eb2f38680 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/remote.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/remote.go @@ -15,10 +15,10 @@ package rafthttp import ( - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/raft/v3/raftpb" ) type remote struct { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/snapshot_sender.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/snapshot_sender.go index 84eb56bd0b..8dbc11724b 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/snapshot_sender.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/snapshot_sender.go @@ -17,25 +17,23 @@ package rafthttp import ( "bytes" "context" + "errors" "io" - "io/ioutil" "net/http" "time" + "github.com/dustin/go-humanize" + "go.uber.org/zap" + "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/pkg/v3/httputil" pioutil "go.etcd.io/etcd/pkg/v3/ioutil" - "go.etcd.io/etcd/raft/v3" "go.etcd.io/etcd/server/v3/etcdserver/api/snap" - - "github.com/dustin/go-humanize" - "go.uber.org/zap" + "go.etcd.io/raft/v3" ) -var ( - // timeout for reading snapshot response body - snapResponseReadTimeout = 5 * time.Second -) +// timeout for reading snapshot response body +var snapResponseReadTimeout = 5 * time.Second type snapshotSender struct { from, to types.ID @@ -111,7 +109,7 @@ func (s *snapshotSender) send(merged snap.Message) { // errMemberRemoved is a critical error since a removed member should // always be stopped. So we use reportCriticalError to report it to errorc. - if err == errMemberRemoved { + if errors.Is(err, errMemberRemoved) { reportCriticalError(err, s.errorc) } @@ -169,7 +167,7 @@ func (s *snapshotSender) post(req *http.Request) (err error) { // prevents from reading the body forever when the other side dies right after // successfully receives the request body. time.AfterFunc(snapResponseReadTimeout, func() { httputil.GracefulClose(resp) }) - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) result <- responseAndError{resp, body, err} }() diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/stream.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/stream.go index 1b180fca3f..fa02f42b9b 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/stream.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/stream.go @@ -16,25 +16,25 @@ package rafthttp import ( "context" + "errors" "fmt" "io" - "io/ioutil" "net/http" "path" "strings" "sync" "time" + "github.com/coreos/go-semver/semver" + "go.uber.org/zap" + "golang.org/x/time/rate" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/pkg/v3/httputil" - "go.etcd.io/etcd/raft/v3/raftpb" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" - - "github.com/coreos/go-semver/semver" - "go.uber.org/zap" - "golang.org/x/time/rate" + "go.etcd.io/raft/v3/raftpb" ) const ( @@ -59,6 +59,7 @@ var ( "3.3.0": {streamTypeMsgAppV2, streamTypeMessage}, "3.4.0": {streamTypeMsgAppV2, streamTypeMessage}, "3.5.0": {streamTypeMsgAppV2, streamTypeMessage}, + "3.6.0": {streamTypeMsgAppV2, streamTypeMessage}, } ) @@ -89,12 +90,10 @@ func (t streamType) String() string { } } -var ( - // linkHeartbeatMessage is a special message used as heartbeat message in - // link layer. It never conflicts with messages from raft because raft - // doesn't send out messages without From and To fields. - linkHeartbeatMessage = raftpb.Message{Type: raftpb.MsgHeartbeat} -) +// linkHeartbeatMessage is a special message used as heartbeat message in +// link layer. It never conflicts with messages from raft because raft +// doesn't send out messages without From and To fields. +var linkHeartbeatMessage = raftpb.Message{Type: raftpb.MsgHeartbeat} func isLinkHeartbeatMessage(m *raftpb.Message) bool { return m.Type == raftpb.MsgHeartbeat && m.From == 0 && m.To == 0 @@ -403,7 +402,7 @@ func (cr *streamReader) run() { for { rc, err := cr.dial(t) if err != nil { - if err != errUnsupportedStreamType { + if !errors.Is(err, errUnsupportedStreamType) { cr.status.deactivate(failureType{source: t.String(), action: "dial"}, err.Error()) } } else { @@ -428,7 +427,7 @@ func (cr *streamReader) run() { } switch { // all data is read out - case err == io.EOF: + case errors.Is(err, io.EOF): // connection is closed by the remote case transport.IsClosedConnError(err): default: @@ -574,10 +573,10 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) { zap.String("address", uu.String()), ) } - req, err := http.NewRequest("GET", uu.String(), nil) + req, err := http.NewRequest(http.MethodGet, uu.String(), nil) if err != nil { cr.picker.unreachable(u) - return nil, fmt.Errorf("failed to make http request to %v (%v)", u, err) + return nil, fmt.Errorf("failed to make http request to %v (%w)", u, err) } req.Header.Set("X-Server-From", cr.tr.ID.String()) req.Header.Set("X-Server-Version", version.Version) @@ -628,7 +627,7 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) { return nil, fmt.Errorf("peer %s failed to find local node %s", cr.peerID, cr.tr.ID) case http.StatusPreconditionFailed: - b, err := ioutil.ReadAll(resp.Body) + b, err := io.ReadAll(resp.Body) if err != nil { cr.picker.unreachable(u) return nil, err diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/transport.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/transport.go index a1969549a9..b376d578b6 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/transport.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/transport.go @@ -20,16 +20,16 @@ import ( "sync" "time" + "github.com/xiang90/probing" + "go.uber.org/zap" + "golang.org/x/time/rate" + "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/etcdserver/api/snap" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" - - "github.com/xiang90/probing" - "go.uber.org/zap" - "golang.org/x/time/rate" + "go.etcd.io/raft/v3" + "go.etcd.io/raft/v3/raftpb" ) type Raft interface { @@ -110,7 +110,7 @@ type Transport struct { Raft Raft // raft state machine, to which the Transport forwards received messages and reports status Snapshotter *snap.Snapshotter ServerStats *stats.ServerStats // used to record general transportation statistics - // LeaderStats is used to record transportation statistics with followers when + // LeaderStats records transportation statistics with followers when // performing as leader in raft protocol LeaderStats *stats.LeaderStats // ErrorC is used to report detected critical errors, e.g., @@ -186,7 +186,7 @@ func (t *Transport) Send(msgs []raftpb.Message) { t.mu.RUnlock() if pok { - if m.Type == raftpb.MsgApp { + if isMsgApp(m) { t.ServerStats.SendAppendReq(m.Size()) } p.send(m) @@ -339,24 +339,30 @@ func (t *Transport) RemoveAllPeers() { // the caller of this function must have the peers mutex. func (t *Transport) removePeer(id types.ID) { - if peer, ok := t.peers[id]; ok { + // etcd may remove a member again on startup due to WAL files replaying. + peer, ok := t.peers[id] + if ok { peer.stop() - } else { - if t.Logger != nil { - t.Logger.Panic("unexpected removal of unknown remote peer", zap.String("remote-peer-id", id.String())) - } + delete(t.peers, id) + delete(t.LeaderStats.Followers, id.String()) + t.pipelineProber.Remove(id.String()) + t.streamProber.Remove(id.String()) } - delete(t.peers, id) - delete(t.LeaderStats.Followers, id.String()) - t.pipelineProber.Remove(id.String()) - t.streamProber.Remove(id.String()) if t.Logger != nil { - t.Logger.Info( - "removed remote peer", - zap.String("local-member-id", t.ID.String()), - zap.String("removed-remote-peer-id", id.String()), - ) + if ok { + t.Logger.Info( + "removed remote peer", + zap.String("local-member-id", t.ID.String()), + zap.String("removed-remote-peer-id", id.String()), + ) + } else { + t.Logger.Warn( + "skipped removing already removed peer", + zap.String("local-member-id", t.ID.String()), + zap.String("removed-remote-peer-id", id.String()), + ) + } } } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/util.go index 6d0e6bdd6b..5057f539af 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/util.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp/util.go @@ -23,12 +23,12 @@ import ( "strings" "time" + "github.com/coreos/go-semver/semver" + "go.uber.org/zap" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/transport" "go.etcd.io/etcd/client/pkg/v3/types" - - "github.com/coreos/go-semver/semver" - "go.uber.org/zap" ) var ( @@ -64,7 +64,7 @@ func newStreamRoundTripper(tlsInfo transport.TLSInfo, dialTimeout time.Duration) func createPostRequest(lg *zap.Logger, u url.URL, path string, body io.Reader, ct string, urls types.URLs, from, cid types.ID) *http.Request { uu := u uu.Path = path - req, err := http.NewRequest("POST", uu.String(), body) + req, err := http.NewRequest(http.MethodPost, uu.String(), body) if err != nil { if lg != nil { lg.Panic("unexpected new request error", zap.Error(err)) @@ -169,7 +169,8 @@ func minClusterVersion(h http.Header) *semver.Version { func checkVersionCompatibility(name string, server, minCluster *semver.Version) ( localServer *semver.Version, localMinCluster *semver.Version, - err error) { + err error, +) { localServer = semver.Must(semver.NewVersion(version.Version)) localMinCluster = semver.Must(semver.NewVersion(version.MinClusterVersion)) if compareMajorMinorVersion(server, localMinCluster) == -1 { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/db.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/db.go index af653e1d5f..e8add5e327 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/db.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/db.go @@ -18,15 +18,14 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "path/filepath" "time" - "go.etcd.io/etcd/client/pkg/v3/fileutil" - humanize "github.com/dustin/go-humanize" "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/fileutil" ) var ErrNoDBSnapshot = errors.New("snap: snapshot file doesn't exist") @@ -36,7 +35,7 @@ var ErrNoDBSnapshot = errors.New("snap: snapshot file doesn't exist") func (s *Snapshotter) SaveDBFrom(r io.Reader, id uint64) (int64, error) { start := time.Now() - f, err := ioutil.TempFile(s.dir, "tmp") + f, err := os.CreateTemp(s.dir, "tmp") if err != nil { return 0, err } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/message.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/message.go index 523b52b85c..2b4090c981 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/message.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/message.go @@ -18,7 +18,7 @@ import ( "io" "go.etcd.io/etcd/pkg/v3/ioutil" - "go.etcd.io/etcd/raft/v3/raftpb" + "go.etcd.io/raft/v3/raftpb" ) // Message is a struct that contains a raft Message and a ReadCloser. The type diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.pb.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.pb.go index 6fd2b9c008..ff9d39c7ec 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.pb.go @@ -72,15 +72,18 @@ func init() { func init() { proto.RegisterFile("snap.proto", fileDescriptor_f2e3c045ebf84d00) } var fileDescriptor_f2e3c045ebf84d00 = []byte{ - // 126 bytes of a gzipped FileDescriptorProto + // 164 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2a, 0xce, 0x4b, 0x2c, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x03, 0xb1, 0x0b, 0x92, 0xa4, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x42, 0xfa, 0x20, 0x16, 0x44, 0x56, 0xc9, 0x8c, 0x8b, 0x03, 0x24, 0x5f, 0x9c, 0x91, 0x5f, 0x22, 0x24, 0xc6, 0xc5, 0x9c, 0x5c, 0x94, 0x2c, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xeb, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, 0x48, 0x40, 0x48, 0x88, 0x8b, 0x25, 0x25, 0xb1, 0x24, - 0x51, 0x82, 0x49, 0x81, 0x51, 0x83, 0x27, 0x08, 0xcc, 0x76, 0x12, 0x39, 0xf1, 0x50, 0x8e, 0xe1, + 0x51, 0x82, 0x49, 0x81, 0x51, 0x83, 0x27, 0x08, 0xcc, 0x76, 0xf2, 0x3a, 0xf1, 0x50, 0x8e, 0xe1, 0xc4, 0x23, 0x39, 0xc6, 0x0b, 0x8f, 0xe4, 0x18, 0x1f, 0x3c, 0x92, 0x63, 0x9c, 0xf1, 0x58, 0x8e, - 0x01, 0x10, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x0f, 0x32, 0xb2, 0x78, 0x00, 0x00, 0x00, + 0x21, 0xca, 0x24, 0x3d, 0x5f, 0x2f, 0xb5, 0x24, 0x39, 0x45, 0x2f, 0x33, 0x5f, 0x1f, 0x44, 0xeb, + 0x17, 0xa7, 0x16, 0x95, 0xa5, 0x16, 0xe9, 0x97, 0x19, 0x83, 0xb9, 0x50, 0x5e, 0x62, 0x41, 0xa6, + 0x3e, 0xc8, 0x52, 0x7d, 0x88, 0xcb, 0x00, 0x01, 0x00, 0x00, 0xff, 0xff, 0x8d, 0x65, 0xd9, 0x03, + 0xae, 0x00, 0x00, 0x00, } func (m *Snapshot) Marshal() (dAtA []byte, err error) { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.proto b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.proto index cd3d21d0ee..0a74744e4b 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.proto +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb/snap.proto @@ -3,6 +3,8 @@ package snappb; import "gogoproto/gogo.proto"; +option go_package = "go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb"; + option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; option (gogoproto.unmarshaler_all) = true; diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snapshotter.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snapshotter.go index 52cc0ae267..0de6f9b91e 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snapshotter.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/snap/snapshotter.go @@ -18,7 +18,6 @@ import ( "errors" "fmt" "hash/crc32" - "io/ioutil" "os" "path/filepath" "sort" @@ -26,14 +25,15 @@ import ( "strings" "time" + "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/verify" pioutil "go.etcd.io/etcd/pkg/v3/ioutil" "go.etcd.io/etcd/pkg/v3/pbutil" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb" - "go.etcd.io/etcd/server/v3/wal/walpb" - - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" + "go.etcd.io/raft/v3" + "go.etcd.io/raft/v3/raftpb" ) const snapSuffix = ".snap" @@ -88,14 +88,14 @@ func (s *Snapshotter) save(snapshot *raftpb.Snapshot) error { spath := filepath.Join(s.dir, fname) fsyncStart := time.Now() - err = pioutil.WriteAndSyncFile(spath, d, 0666) + err = pioutil.WriteAndSyncFile(spath, d, 0o666) snapFsyncSec.Observe(time.Since(fsyncStart).Seconds()) if err != nil { s.lg.Warn("failed to write a snap file", zap.String("path", spath), zap.Error(err)) rerr := os.Remove(spath) if rerr != nil { - s.lg.Warn("failed to remove a broken snap file", zap.String("path", spath), zap.Error(err)) + s.lg.Warn("failed to remove a broken snap file", zap.String("path", spath), zap.Error(rerr)) } return err } @@ -130,29 +130,23 @@ func (s *Snapshotter) loadMatching(matchFn func(*raftpb.Snapshot) bool) (*raftpb } var snap *raftpb.Snapshot for _, name := range names { - if snap, err = loadSnap(s.lg, s.dir, name); err == nil && matchFn(snap) { + if snap, err = s.loadSnap(name); err == nil && matchFn(snap) { return snap, nil } } return nil, ErrNoSnapshot } -func loadSnap(lg *zap.Logger, dir, name string) (*raftpb.Snapshot, error) { - fpath := filepath.Join(dir, name) - snap, err := Read(lg, fpath) +func (s *Snapshotter) loadSnap(name string) (*raftpb.Snapshot, error) { + fpath := filepath.Join(s.dir, name) + snap, err := Read(s.lg, fpath) if err != nil { brokenPath := fpath + ".broken" - if lg != nil { - lg.Warn("failed to read a snap file", zap.String("path", fpath), zap.Error(err)) - } + s.lg.Warn("failed to read a snap file", zap.String("path", fpath), zap.Error(err)) if rerr := os.Rename(fpath, brokenPath); rerr != nil { - if lg != nil { - lg.Warn("failed to rename a broken snap file", zap.String("path", fpath), zap.String("broken-path", brokenPath), zap.Error(rerr)) - } + s.lg.Warn("failed to rename a broken snap file", zap.String("path", fpath), zap.String("broken-path", brokenPath), zap.Error(rerr)) } else { - if lg != nil { - lg.Warn("renamed to a broken snap file", zap.String("path", fpath), zap.String("broken-path", brokenPath)) - } + s.lg.Warn("renamed to a broken snap file", zap.String("path", fpath), zap.String("broken-path", brokenPath)) } } return snap, err @@ -160,53 +154,42 @@ func loadSnap(lg *zap.Logger, dir, name string) (*raftpb.Snapshot, error) { // Read reads the snapshot named by snapname and returns the snapshot. func Read(lg *zap.Logger, snapname string) (*raftpb.Snapshot, error) { - b, err := ioutil.ReadFile(snapname) + verify.Assert(lg != nil, "the logger should not be nil") + b, err := os.ReadFile(snapname) if err != nil { - if lg != nil { - lg.Warn("failed to read a snap file", zap.String("path", snapname), zap.Error(err)) - } + lg.Warn("failed to read a snap file", zap.String("path", snapname), zap.Error(err)) return nil, err } if len(b) == 0 { - if lg != nil { - lg.Warn("failed to read empty snapshot file", zap.String("path", snapname)) - } + lg.Warn("failed to read empty snapshot file", zap.String("path", snapname)) return nil, ErrEmptySnapshot } var serializedSnap snappb.Snapshot if err = serializedSnap.Unmarshal(b); err != nil { - if lg != nil { - lg.Warn("failed to unmarshal snappb.Snapshot", zap.String("path", snapname), zap.Error(err)) - } + lg.Warn("failed to unmarshal snappb.Snapshot", zap.String("path", snapname), zap.Error(err)) return nil, err } if len(serializedSnap.Data) == 0 || serializedSnap.Crc == 0 { - if lg != nil { - lg.Warn("failed to read empty snapshot data", zap.String("path", snapname)) - } + lg.Warn("failed to read empty snapshot data", zap.String("path", snapname)) return nil, ErrEmptySnapshot } crc := crc32.Update(0, crcTable, serializedSnap.Data) if crc != serializedSnap.Crc { - if lg != nil { - lg.Warn("snap file is corrupt", - zap.String("path", snapname), - zap.Uint32("prev-crc", serializedSnap.Crc), - zap.Uint32("new-crc", crc), - ) - } + lg.Warn("snap file is corrupt", + zap.String("path", snapname), + zap.Uint32("prev-crc", serializedSnap.Crc), + zap.Uint32("new-crc", crc), + ) return nil, ErrCRCMismatch } var snap raftpb.Snapshot if err = snap.Unmarshal(serializedSnap.Data); err != nil { - if lg != nil { - lg.Warn("failed to unmarshal raftpb.Snapshot", zap.String("path", snapname), zap.Error(err)) - } + lg.Warn("failed to unmarshal raftpb.Snapshot", zap.String("path", snapname), zap.Error(err)) return nil, err } return &snap, nil @@ -228,7 +211,7 @@ func (s *Snapshotter) snapNames() ([]string, error) { if err != nil { return nil, err } - snaps := checkSuffix(s.lg, filenames) + snaps := s.checkSuffix(filenames) if len(snaps) == 0 { return nil, ErrNoSnapshot } @@ -236,18 +219,16 @@ func (s *Snapshotter) snapNames() ([]string, error) { return snaps, nil } -func checkSuffix(lg *zap.Logger, names []string) []string { - snaps := []string{} +func (s *Snapshotter) checkSuffix(names []string) []string { + var snaps []string for i := range names { if strings.HasSuffix(names[i], snapSuffix) { snaps = append(snaps, names[i]) } else { // If we find a file which is not a snapshot then check if it's - // a vaild file. If not throw out a warning. + // a valid file. If not throw out a warning. if _, ok := validFiles[names[i]]; !ok { - if lg != nil { - lg.Warn("found unexpected non-snap file; skipping", zap.String("path", names[i])) - } + s.lg.Warn("found unexpected non-snap file; skipping", zap.String("path", names[i])) } } } @@ -262,7 +243,7 @@ func (s *Snapshotter) cleanupSnapdir(filenames []string) (names []string, err er if strings.HasPrefix(filename, "db.tmp") { s.lg.Info("found orphaned defragmentation file; deleting", zap.String("path", filename)) if rmErr := os.Remove(filepath.Join(s.dir, filename)); rmErr != nil && !os.IsNotExist(rmErr) { - return names, fmt.Errorf("failed to remove orphaned .snap.db file %s: %v", filename, rmErr) + return names, fmt.Errorf("failed to remove orphaned .snap.db file %s: %w", filename, rmErr) } } else { names = append(names, filename) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth.go deleted file mode 100644 index e76ee8b2a1..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth.go +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright 2015 The etcd 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 v2auth implements etcd authentication. -package v2auth - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "path" - "reflect" - "sort" - "strings" - "time" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - - "go.uber.org/zap" - "golang.org/x/crypto/bcrypt" -) - -const ( - // StorePermsPrefix is the internal prefix of the storage layer dedicated to storing user data. - StorePermsPrefix = "/2" - - // RootRoleName is the name of the ROOT role, with privileges to manage the cluster. - RootRoleName = "root" - - // GuestRoleName is the name of the role that defines the privileges of an unauthenticated user. - GuestRoleName = "guest" -) - -var rootRole = Role{ - Role: RootRoleName, - Permissions: Permissions{ - KV: RWPermission{ - Read: []string{"/*"}, - Write: []string{"/*"}, - }, - }, -} - -var guestRole = Role{ - Role: GuestRoleName, - Permissions: Permissions{ - KV: RWPermission{ - Read: []string{"/*"}, - Write: []string{"/*"}, - }, - }, -} - -type doer interface { - Do(context.Context, etcdserverpb.Request) (etcdserver.Response, error) -} - -type Store interface { - AllUsers() ([]string, error) - GetUser(name string) (User, error) - CreateOrUpdateUser(user User) (out User, created bool, err error) - CreateUser(user User) (User, error) - DeleteUser(name string) error - UpdateUser(user User) (User, error) - AllRoles() ([]string, error) - GetRole(name string) (Role, error) - CreateRole(role Role) error - DeleteRole(name string) error - UpdateRole(role Role) (Role, error) - AuthEnabled() bool - EnableAuth() error - DisableAuth() error - PasswordStore -} - -type PasswordStore interface { - CheckPassword(user User, password string) bool - HashPassword(password string) (string, error) -} - -type store struct { - lg *zap.Logger - server doer - timeout time.Duration - ensuredOnce bool - - PasswordStore -} - -type User struct { - User string `json:"user"` - Password string `json:"password,omitempty"` - Roles []string `json:"roles"` - Grant []string `json:"grant,omitempty"` - Revoke []string `json:"revoke,omitempty"` -} - -type Role struct { - Role string `json:"role"` - Permissions Permissions `json:"permissions"` - Grant *Permissions `json:"grant,omitempty"` - Revoke *Permissions `json:"revoke,omitempty"` -} - -type Permissions struct { - KV RWPermission `json:"kv"` -} - -func (p *Permissions) IsEmpty() bool { - return p == nil || (len(p.KV.Read) == 0 && len(p.KV.Write) == 0) -} - -type RWPermission struct { - Read []string `json:"read"` - Write []string `json:"write"` -} - -type Error struct { - Status int - Errmsg string -} - -func (ae Error) Error() string { return ae.Errmsg } -func (ae Error) HTTPStatus() int { return ae.Status } - -func authErr(hs int, s string, v ...interface{}) Error { - return Error{Status: hs, Errmsg: fmt.Sprintf("auth: "+s, v...)} -} - -func NewStore(lg *zap.Logger, server doer, timeout time.Duration) Store { - if lg == nil { - lg = zap.NewNop() - } - s := &store{ - lg: lg, - server: server, - timeout: timeout, - PasswordStore: passwordStore{}, - } - return s -} - -// passwordStore implements PasswordStore using bcrypt to hash user passwords -type passwordStore struct{} - -func (passwordStore) CheckPassword(user User, password string) bool { - err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) - return err == nil -} - -func (passwordStore) HashPassword(password string) (string, error) { - hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) - return string(hash), err -} - -func (s *store) AllUsers() ([]string, error) { - resp, err := s.requestResource("/users/", false) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return []string{}, nil - } - } - return nil, err - } - var nodes []string - for _, n := range resp.Event.Node.Nodes { - _, user := path.Split(n.Key) - nodes = append(nodes, user) - } - sort.Strings(nodes) - return nodes, nil -} - -func (s *store) GetUser(name string) (User, error) { return s.getUser(name, false) } - -// CreateOrUpdateUser should be only used for creating the new user or when you are not -// sure if it is a create or update. (When only password is passed in, we are not sure -// if it is a update or create) -func (s *store) CreateOrUpdateUser(user User) (out User, created bool, err error) { - _, err = s.getUser(user.User, true) - if err == nil { - out, err = s.UpdateUser(user) - return out, false, err - } - u, err := s.CreateUser(user) - return u, true, err -} - -func (s *store) CreateUser(user User) (User, error) { - // Attach root role to root user. - if user.User == "root" { - user = attachRootRole(user) - } - u, err := s.createUserInternal(user) - if err == nil { - s.lg.Info("created a user", zap.String("user-name", user.User)) - } - return u, err -} - -func (s *store) createUserInternal(user User) (User, error) { - if user.Password == "" { - return user, authErr(http.StatusBadRequest, "Cannot create user %s with an empty password", user.User) - } - hash, err := s.HashPassword(user.Password) - if err != nil { - return user, err - } - user.Password = hash - - _, err = s.createResource("/users/"+user.User, user) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeNodeExist { - return user, authErr(http.StatusConflict, "User %s already exists.", user.User) - } - } - } - return user, err -} - -func (s *store) DeleteUser(name string) error { - if s.AuthEnabled() && name == "root" { - return authErr(http.StatusForbidden, "Cannot delete root user while auth is enabled.") - } - err := s.deleteResource("/users/" + name) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return authErr(http.StatusNotFound, "User %s does not exist", name) - } - } - return err - } - s.lg.Info("deleted a user", zap.String("user-name", name)) - return nil -} - -func (s *store) UpdateUser(user User) (User, error) { - old, err := s.getUser(user.User, true) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return user, authErr(http.StatusNotFound, "User %s doesn't exist.", user.User) - } - } - return old, err - } - - newUser, err := old.merge(s.lg, user, s.PasswordStore) - if err != nil { - return old, err - } - if reflect.DeepEqual(old, newUser) { - return old, authErr(http.StatusBadRequest, "User not updated. Use grant/revoke/password to update the user.") - } - _, err = s.updateResource("/users/"+user.User, newUser) - if err == nil { - s.lg.Info("updated a user", zap.String("user-name", user.User)) - } - return newUser, err -} - -func (s *store) AllRoles() ([]string, error) { - nodes := []string{RootRoleName} - resp, err := s.requestResource("/roles/", false) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return nodes, nil - } - } - return nil, err - } - for _, n := range resp.Event.Node.Nodes { - _, role := path.Split(n.Key) - nodes = append(nodes, role) - } - sort.Strings(nodes) - return nodes, nil -} - -func (s *store) GetRole(name string) (Role, error) { return s.getRole(name, false) } - -func (s *store) CreateRole(role Role) error { - if role.Role == RootRoleName { - return authErr(http.StatusForbidden, "Cannot modify role %s: is root role.", role.Role) - } - _, err := s.createResource("/roles/"+role.Role, role) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeNodeExist { - return authErr(http.StatusConflict, "Role %s already exists.", role.Role) - } - } - } - if err == nil { - s.lg.Info("created a new role", zap.String("role-name", role.Role)) - } - return err -} - -func (s *store) DeleteRole(name string) error { - if name == RootRoleName { - return authErr(http.StatusForbidden, "Cannot modify role %s: is root role.", name) - } - err := s.deleteResource("/roles/" + name) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return authErr(http.StatusNotFound, "Role %s doesn't exist.", name) - } - } - } - if err == nil { - s.lg.Info("delete a new role", zap.String("role-name", name)) - } - return err -} - -func (s *store) UpdateRole(role Role) (Role, error) { - if role.Role == RootRoleName { - return Role{}, authErr(http.StatusForbidden, "Cannot modify role %s: is root role.", role.Role) - } - old, err := s.getRole(role.Role, true) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return role, authErr(http.StatusNotFound, "Role %s doesn't exist.", role.Role) - } - } - return old, err - } - newRole, err := old.merge(s.lg, role) - if err != nil { - return old, err - } - if reflect.DeepEqual(old, newRole) { - return old, authErr(http.StatusBadRequest, "Role not updated. Use grant/revoke to update the role.") - } - _, err = s.updateResource("/roles/"+role.Role, newRole) - if err == nil { - s.lg.Info("updated a new role", zap.String("role-name", role.Role)) - } - return newRole, err -} - -func (s *store) AuthEnabled() bool { - return s.detectAuth() -} - -func (s *store) EnableAuth() error { - if s.AuthEnabled() { - return authErr(http.StatusConflict, "already enabled") - } - - if _, err := s.getUser("root", true); err != nil { - return authErr(http.StatusConflict, "No root user available, please create one") - } - if _, err := s.getRole(GuestRoleName, true); err != nil { - s.lg.Info( - "no guest role access found; creating default", - zap.String("role-name", GuestRoleName), - ) - if err := s.CreateRole(guestRole); err != nil { - s.lg.Warn( - "failed to create a guest role; aborting auth enable", - zap.String("role-name", GuestRoleName), - zap.Error(err), - ) - return err - } - } - - if err := s.enableAuth(); err != nil { - s.lg.Warn("failed to enable auth", zap.Error(err)) - return err - } - - s.lg.Info("enabled auth") - return nil -} - -func (s *store) DisableAuth() error { - if !s.AuthEnabled() { - return authErr(http.StatusConflict, "already disabled") - } - - err := s.disableAuth() - if err == nil { - s.lg.Info("disabled auth") - } else { - s.lg.Warn("failed to disable auth", zap.Error(err)) - } - return err -} - -// merge applies the properties of the passed-in User to the User on which it -// is called and returns a new User with these modifications applied. Think of -// all Users as immutable sets of data. Merge allows you to perform the set -// operations (desired grants and revokes) atomically -func (ou User) merge(lg *zap.Logger, nu User, s PasswordStore) (User, error) { - var out User - if ou.User != nu.User { - return out, authErr(http.StatusConflict, "Merging user data with conflicting usernames: %s %s", ou.User, nu.User) - } - out.User = ou.User - if nu.Password != "" { - hash, err := s.HashPassword(nu.Password) - if err != nil { - return ou, err - } - out.Password = hash - } else { - out.Password = ou.Password - } - currentRoles := types.NewUnsafeSet(ou.Roles...) - for _, g := range nu.Grant { - if currentRoles.Contains(g) { - lg.Warn( - "attempted to grant a duplicate role for a user", - zap.String("user-name", nu.User), - zap.String("role-name", g), - ) - return User{}, authErr(http.StatusConflict, fmt.Sprintf("Granting duplicate role %s for user %s", g, nu.User)) - } - currentRoles.Add(g) - } - for _, r := range nu.Revoke { - if !currentRoles.Contains(r) { - lg.Warn( - "attempted to revoke a ungranted role for a user", - zap.String("user-name", nu.User), - zap.String("role-name", r), - ) - return User{}, authErr(http.StatusConflict, fmt.Sprintf("Revoking ungranted role %s for user %s", r, nu.User)) - } - currentRoles.Remove(r) - } - out.Roles = currentRoles.Values() - sort.Strings(out.Roles) - return out, nil -} - -// merge for a role works the same as User above -- atomic Role application to -// each of the substructures. -func (r Role) merge(lg *zap.Logger, n Role) (Role, error) { - var out Role - var err error - if r.Role != n.Role { - return out, authErr(http.StatusConflict, "Merging role with conflicting names: %s %s", r.Role, n.Role) - } - out.Role = r.Role - out.Permissions, err = r.Permissions.Grant(n.Grant) - if err != nil { - return out, err - } - out.Permissions, err = out.Permissions.Revoke(lg, n.Revoke) - return out, err -} - -func (r Role) HasKeyAccess(key string, write bool) bool { - if r.Role == RootRoleName { - return true - } - return r.Permissions.KV.HasAccess(key, write) -} - -func (r Role) HasRecursiveAccess(key string, write bool) bool { - if r.Role == RootRoleName { - return true - } - return r.Permissions.KV.HasRecursiveAccess(key, write) -} - -// Grant adds a set of permissions to the permission object on which it is called, -// returning a new permission object. -func (p Permissions) Grant(n *Permissions) (Permissions, error) { - var out Permissions - var err error - if n == nil { - return p, nil - } - out.KV, err = p.KV.Grant(n.KV) - return out, err -} - -// Revoke removes a set of permissions to the permission object on which it is called, -// returning a new permission object. -func (p Permissions) Revoke(lg *zap.Logger, n *Permissions) (Permissions, error) { - var out Permissions - var err error - if n == nil { - return p, nil - } - out.KV, err = p.KV.Revoke(lg, n.KV) - return out, err -} - -// Grant adds a set of permissions to the permission object on which it is called, -// returning a new permission object. -func (rw RWPermission) Grant(n RWPermission) (RWPermission, error) { - var out RWPermission - currentRead := types.NewUnsafeSet(rw.Read...) - for _, r := range n.Read { - if currentRead.Contains(r) { - return out, authErr(http.StatusConflict, "Granting duplicate read permission %s", r) - } - currentRead.Add(r) - } - currentWrite := types.NewUnsafeSet(rw.Write...) - for _, w := range n.Write { - if currentWrite.Contains(w) { - return out, authErr(http.StatusConflict, "Granting duplicate write permission %s", w) - } - currentWrite.Add(w) - } - out.Read = currentRead.Values() - out.Write = currentWrite.Values() - sort.Strings(out.Read) - sort.Strings(out.Write) - return out, nil -} - -// Revoke removes a set of permissions to the permission object on which it is called, -// returning a new permission object. -func (rw RWPermission) Revoke(lg *zap.Logger, n RWPermission) (RWPermission, error) { - var out RWPermission - currentRead := types.NewUnsafeSet(rw.Read...) - for _, r := range n.Read { - if !currentRead.Contains(r) { - lg.Info( - "revoking ungranted read permission", - zap.String("read-permission", r), - ) - continue - } - currentRead.Remove(r) - } - currentWrite := types.NewUnsafeSet(rw.Write...) - for _, w := range n.Write { - if !currentWrite.Contains(w) { - lg.Info( - "revoking ungranted write permission", - zap.String("write-permission", w), - ) - continue - } - currentWrite.Remove(w) - } - out.Read = currentRead.Values() - out.Write = currentWrite.Values() - sort.Strings(out.Read) - sort.Strings(out.Write) - return out, nil -} - -func (rw RWPermission) HasAccess(key string, write bool) bool { - var list []string - if write { - list = rw.Write - } else { - list = rw.Read - } - for _, pat := range list { - match, err := simpleMatch(pat, key) - if err == nil && match { - return true - } - } - return false -} - -func (rw RWPermission) HasRecursiveAccess(key string, write bool) bool { - list := rw.Read - if write { - list = rw.Write - } - for _, pat := range list { - match, err := prefixMatch(pat, key) - if err == nil && match { - return true - } - } - return false -} - -func simpleMatch(pattern string, key string) (match bool, err error) { - if pattern[len(pattern)-1] == '*' { - return strings.HasPrefix(key, pattern[:len(pattern)-1]), nil - } - return key == pattern, nil -} - -func prefixMatch(pattern string, key string) (match bool, err error) { - if pattern[len(pattern)-1] != '*' { - return false, nil - } - return strings.HasPrefix(key, pattern[:len(pattern)-1]), nil -} - -func attachRootRole(u User) User { - inRoles := false - for _, r := range u.Roles { - if r == RootRoleName { - inRoles = true - break - } - } - if !inRoles { - u.Roles = append(u.Roles, RootRoleName) - } - return u -} - -func (s *store) getUser(name string, quorum bool) (User, error) { - resp, err := s.requestResource("/users/"+name, quorum) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return User{}, authErr(http.StatusNotFound, "User %s does not exist.", name) - } - } - return User{}, err - } - var u User - err = json.Unmarshal([]byte(*resp.Event.Node.Value), &u) - if err != nil { - return u, err - } - // Attach root role to root user. - if u.User == "root" { - u = attachRootRole(u) - } - return u, nil -} - -func (s *store) getRole(name string, quorum bool) (Role, error) { - if name == RootRoleName { - return rootRole, nil - } - resp, err := s.requestResource("/roles/"+name, quorum) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return Role{}, authErr(http.StatusNotFound, "Role %s does not exist.", name) - } - } - return Role{}, err - } - var r Role - err = json.Unmarshal([]byte(*resp.Event.Node.Value), &r) - return r, err -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth_requests.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth_requests.go deleted file mode 100644 index 6c8c50c8cc..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2auth/auth_requests.go +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 2015 The etcd 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 v2auth - -import ( - "context" - "encoding/json" - "path" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - - "go.uber.org/zap" -) - -func (s *store) ensureAuthDirectories() error { - if s.ensuredOnce { - return nil - } - for _, res := range []string{StorePermsPrefix, StorePermsPrefix + "/users/", StorePermsPrefix + "/roles/"} { - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - pe := false - rr := etcdserverpb.Request{ - Method: "PUT", - Path: res, - Dir: true, - PrevExist: &pe, - } - _, err := s.server.Do(ctx, rr) - cancel() - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeNodeExist { - continue - } - } - s.lg.Warn( - "failed to create auth directories", - zap.Error(err), - ) - return err - } - } - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - defer cancel() - pe := false - rr := etcdserverpb.Request{ - Method: "PUT", - Path: StorePermsPrefix + "/enabled", - Val: "false", - PrevExist: &pe, - } - _, err := s.server.Do(ctx, rr) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeNodeExist { - s.ensuredOnce = true - return nil - } - } - return err - } - s.ensuredOnce = true - return nil -} - -func (s *store) enableAuth() error { - _, err := s.updateResource("/enabled", true) - return err -} -func (s *store) disableAuth() error { - _, err := s.updateResource("/enabled", false) - return err -} - -func (s *store) detectAuth() bool { - if s.server == nil { - return false - } - value, err := s.requestResource("/enabled", false) - if err != nil { - if e, ok := err.(*v2error.Error); ok { - if e.ErrorCode == v2error.EcodeKeyNotFound { - return false - } - } - s.lg.Warn( - "failed to detect auth settings", - zap.Error(err), - ) - return false - } - - var u bool - err = json.Unmarshal([]byte(*value.Event.Node.Value), &u) - if err != nil { - s.lg.Warn( - "internal bookkeeping value for enabled isn't valid JSON", - zap.Error(err), - ) - return false - } - return u -} - -func (s *store) requestResource(res string, quorum bool) (etcdserver.Response, error) { - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - defer cancel() - p := path.Join(StorePermsPrefix, res) - method := "GET" - if quorum { - method = "QGET" - } - rr := etcdserverpb.Request{ - Method: method, - Path: p, - Dir: false, // TODO: always false? - } - return s.server.Do(ctx, rr) -} - -func (s *store) updateResource(res string, value interface{}) (etcdserver.Response, error) { - return s.setResource(res, value, true) -} -func (s *store) createResource(res string, value interface{}) (etcdserver.Response, error) { - return s.setResource(res, value, false) -} -func (s *store) setResource(res string, value interface{}, prevexist bool) (etcdserver.Response, error) { - err := s.ensureAuthDirectories() - if err != nil { - return etcdserver.Response{}, err - } - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - defer cancel() - data, err := json.Marshal(value) - if err != nil { - return etcdserver.Response{}, err - } - p := path.Join(StorePermsPrefix, res) - rr := etcdserverpb.Request{ - Method: "PUT", - Path: p, - Val: string(data), - PrevExist: &prevexist, - } - return s.server.Do(ctx, rr) -} - -func (s *store) deleteResource(res string) error { - err := s.ensureAuthDirectories() - if err != nil { - return err - } - ctx, cancel := context.WithTimeout(context.Background(), s.timeout) - defer cancel() - pex := true - p := path.Join(StorePermsPrefix, res) - _, err = s.server.Do(ctx, etcdserverpb.Request{ - Method: "DELETE", - Path: p, - PrevExist: &pex, - }) - return err -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery/discovery.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery/discovery.go index 9f1bc0adf5..00a2c7d0c3 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery/discovery.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery/discovery.go @@ -29,12 +29,12 @@ import ( "strings" "time" - "go.etcd.io/etcd/client/pkg/v3/transport" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/client/v2" - "github.com/jonboulle/clockwork" "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/transport" + "go.etcd.io/etcd/client/pkg/v3/types" + client "go.etcd.io/etcd/server/v3/internal/clientv2" ) var ( @@ -110,7 +110,7 @@ func newProxyFunc(lg *zap.Logger, proxy string) (func(*http.Request) (*url.URL, } } if err != nil { - return nil, fmt.Errorf("invalid proxy address %q: %v", proxy, err) + return nil, fmt.Errorf("invalid proxy address %q: %w", proxy, err) } lg.Info("running proxy with discovery", zap.String("proxy-url", proxyURL.String())) @@ -187,7 +187,7 @@ func (d *discovery) joinCluster(config string) (string, error) { func (d *discovery) getCluster() (string, error) { nodes, size, index, err := d.checkCluster() if err != nil { - if err == ErrFullCluster { + if errors.Is(err, ErrFullCluster) { return nodesToCluster(nodes, size) } return "", err @@ -205,7 +205,8 @@ func (d *discovery) createSelf(contents string) error { resp, err := d.c.Create(ctx, d.selfKey(), contents) cancel() if err != nil { - if eerr, ok := err.(client.Error); ok && eerr.Code == client.ErrorCodeNodeExist { + var eerr client.Error + if errors.As(err, &eerr) && eerr.Code == client.ErrorCodeNodeExist { return ErrDuplicateID } return err @@ -224,13 +225,15 @@ func (d *discovery) checkCluster() ([]*client.Node, uint64, uint64, error) { resp, err := d.c.Get(ctx, path.Join(configKey, "size"), nil) cancel() if err != nil { - if eerr, ok := err.(*client.Error); ok && eerr.Code == client.ErrorCodeKeyNotFound { + var eerr *client.Error + if errors.As(err, &eerr) && eerr.Code == client.ErrorCodeKeyNotFound { return nil, 0, 0, ErrSizeNotFound } - if err == client.ErrInvalidJSON { + if errors.Is(err, client.ErrInvalidJSON) { return nil, 0, 0, ErrBadDiscoveryEndpoint } - if ce, ok := err.(*client.ClusterError); ok { + var ce *client.ClusterError + if errors.As(err, &ce) { d.lg.Warn( "failed to get from discovery server", zap.String("discovery-url", d.url.String()), @@ -251,7 +254,8 @@ func (d *discovery) checkCluster() ([]*client.Node, uint64, uint64, error) { resp, err = d.c.Get(ctx, d.cluster, nil) cancel() if err != nil { - if ce, ok := err.(*client.ClusterError); ok { + var ce *client.ClusterError + if errors.As(err, &ce) { d.lg.Warn( "failed to get from discovery server", zap.String("discovery-url", d.url.String()), @@ -357,7 +361,8 @@ func (d *discovery) waitNodes(nodes []*client.Node, size uint64, index uint64) ( ) resp, err := w.Next(context.Background()) if err != nil { - if ce, ok := err.(*client.ClusterError); ok { + var ce *client.ClusterError + if errors.As(err, &ce) { d.lg.Warn( "error while waiting for peers", zap.String("discovery-url", d.url.String()), diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2error/error.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2error/error.go index 623863254a..168796e835 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2error/error.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2error/error.go @@ -27,7 +27,7 @@ import ( var errors = map[int]string{ // command related errors EcodeKeyNotFound: "Key not found", - EcodeTestFailed: "Compare failed", //test and set + EcodeTestFailed: "Compare failed", // test and set EcodeNotFile: "Not a file", ecodeNoMorePeer: "Reached the max number of peers in the cluster", EcodeNotDir: "Not a directory", @@ -125,10 +125,6 @@ type Error struct { Index uint64 `json:"index"` } -func NewRequestError(errorCode int, cause string) *Error { - return NewError(errorCode, cause, 0) -} - func NewError(errorCode int, cause string, index uint64) *Error { return &Error{ ErrorCode: errorCode, @@ -143,7 +139,7 @@ func (e Error) Error() string { return e.Message + " (" + e.Cause + ")" } -func (e Error) toJsonString() string { +func (e Error) toJSONString() string { b, _ := json.Marshal(e) return string(b) } @@ -160,6 +156,6 @@ func (e Error) WriteTo(w http.ResponseWriter) error { w.Header().Add("X-Etcd-Index", fmt.Sprint(e.Index)) w.Header().Set("Content-Type", "application/json") w.WriteHeader(e.StatusCode()) - _, err := w.Write([]byte(e.toJsonString() + "\n")) + _, err := w.Write([]byte(e.toJSONString() + "\n")) return err } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/capability.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/capability.go deleted file mode 100644 index 718b5ed502..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/capability.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2015 The etcd 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 v2http - -import ( - "fmt" - "net/http" - - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" -) - -func authCapabilityHandler(fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - if !api.IsCapabilityEnabled(api.AuthCapability) { - notCapable(w, r, api.AuthCapability) - return - } - fn(w, r) - } -} - -func notCapable(w http.ResponseWriter, r *http.Request, c api.Capability) { - herr := httptypes.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("Not capable of accessing %s feature during rolling upgrades.", c)) - if err := herr.WriteTo(w); err != nil { - // TODO: the following plog was removed, add the logging back if possible - // plog.Debugf("error writing HTTPError (%v) to %s", err, r.RemoteAddr) - } -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client.go deleted file mode 100644 index 7899459500..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client.go +++ /dev/null @@ -1,757 +0,0 @@ -// Copyright 2015 The etcd 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 v2http - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "net/http" - "net/url" - "path" - "strconv" - "strings" - "time" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" - - "github.com/jonboulle/clockwork" - "go.uber.org/zap" -) - -const ( - authPrefix = "/v2/auth" - keysPrefix = "/v2/keys" - machinesPrefix = "/v2/machines" - membersPrefix = "/v2/members" - statsPrefix = "/v2/stats" -) - -// NewClientHandler generates a muxed http.Handler with the given parameters to serve etcd client requests. -func NewClientHandler(lg *zap.Logger, server etcdserver.ServerPeer, timeout time.Duration) http.Handler { - if lg == nil { - lg = zap.NewNop() - } - mux := http.NewServeMux() - etcdhttp.HandleBasic(lg, mux, server) - etcdhttp.HandleMetrics(mux) - etcdhttp.HandleHealthForV2(lg, mux, server) - handleV2(lg, mux, server, timeout) - return requestLogger(lg, mux) -} - -func handleV2(lg *zap.Logger, mux *http.ServeMux, server etcdserver.ServerV2, timeout time.Duration) { - sec := v2auth.NewStore(lg, server, timeout) - kh := &keysHandler{ - lg: lg, - sec: sec, - server: server, - cluster: server.Cluster(), - timeout: timeout, - clientCertAuthEnabled: server.ClientCertAuthEnabled(), - } - - sh := &statsHandler{ - lg: lg, - stats: server, - } - - mh := &membersHandler{ - lg: lg, - sec: sec, - server: server, - cluster: server.Cluster(), - timeout: timeout, - clock: clockwork.NewRealClock(), - clientCertAuthEnabled: server.ClientCertAuthEnabled(), - } - - mah := &machinesHandler{cluster: server.Cluster()} - - sech := &authHandler{ - lg: lg, - sec: sec, - cluster: server.Cluster(), - clientCertAuthEnabled: server.ClientCertAuthEnabled(), - } - mux.HandleFunc("/", http.NotFound) - mux.Handle(keysPrefix, kh) - mux.Handle(keysPrefix+"/", kh) - mux.HandleFunc(statsPrefix+"/store", sh.serveStore) - mux.HandleFunc(statsPrefix+"/self", sh.serveSelf) - mux.HandleFunc(statsPrefix+"/leader", sh.serveLeader) - mux.Handle(membersPrefix, mh) - mux.Handle(membersPrefix+"/", mh) - mux.Handle(machinesPrefix, mah) - handleAuth(mux, sech) -} - -type keysHandler struct { - lg *zap.Logger - sec v2auth.Store - server etcdserver.ServerV2 - cluster api.Cluster - timeout time.Duration - clientCertAuthEnabled bool -} - -func (h *keysHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "HEAD", "GET", "PUT", "POST", "DELETE") { - return - } - - w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String()) - - ctx, cancel := context.WithTimeout(context.Background(), h.timeout) - defer cancel() - clock := clockwork.NewRealClock() - startTime := clock.Now() - rr, noValueOnSuccess, err := parseKeyRequest(r, clock) - if err != nil { - writeKeyError(h.lg, w, err) - return - } - // The path must be valid at this point (we've parsed the request successfully). - if !hasKeyPrefixAccess(h.lg, h.sec, r, r.URL.Path[len(keysPrefix):], rr.Recursive, h.clientCertAuthEnabled) { - writeKeyNoAuth(w) - return - } - if !rr.Wait { - reportRequestReceived(rr) - } - resp, err := h.server.Do(ctx, rr) - if err != nil { - err = trimErrorPrefix(err, etcdserver.StoreKeysPrefix) - writeKeyError(h.lg, w, err) - reportRequestFailed(rr, err) - return - } - switch { - case resp.Event != nil: - if err := writeKeyEvent(w, resp, noValueOnSuccess); err != nil { - // Should never be reached - h.lg.Warn("failed to write key event", zap.Error(err)) - } - reportRequestCompleted(rr, startTime) - case resp.Watcher != nil: - ctx, cancel := context.WithTimeout(context.Background(), defaultWatchTimeout) - defer cancel() - handleKeyWatch(ctx, h.lg, w, resp, rr.Stream) - default: - writeKeyError(h.lg, w, errors.New("received response with no Event/Watcher")) - } -} - -type machinesHandler struct { - cluster api.Cluster -} - -func (h *machinesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET", "HEAD") { - return - } - endpoints := h.cluster.ClientURLs() - w.Write([]byte(strings.Join(endpoints, ", "))) -} - -type membersHandler struct { - lg *zap.Logger - sec v2auth.Store - server etcdserver.ServerV2 - cluster api.Cluster - timeout time.Duration - clock clockwork.Clock - clientCertAuthEnabled bool -} - -func (h *membersHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET", "POST", "DELETE", "PUT") { - return - } - if !hasWriteRootAccess(h.lg, h.sec, r, h.clientCertAuthEnabled) { - writeNoAuth(h.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", h.cluster.ID().String()) - - ctx, cancel := context.WithTimeout(context.Background(), h.timeout) - defer cancel() - - switch r.Method { - case "GET": - switch trimPrefix(r.URL.Path, membersPrefix) { - case "": - mc := newMemberCollection(h.cluster.Members()) - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(mc); err != nil { - h.lg.Warn("failed to encode members response", zap.Error(err)) - } - case "leader": - id := h.server.Leader() - if id == 0 { - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusServiceUnavailable, "During election")) - return - } - m := newMember(h.cluster.Member(id)) - w.Header().Set("Content-Type", "application/json") - if err := json.NewEncoder(w).Encode(m); err != nil { - h.lg.Warn("failed to encode members response", zap.Error(err)) - } - default: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusNotFound, "Not found")) - } - - case "POST": - req := httptypes.MemberCreateRequest{} - if ok := unmarshalRequest(h.lg, r, &req, w); !ok { - return - } - now := h.clock.Now() - m := membership.NewMember("", req.PeerURLs, "", &now) - _, err := h.server.AddMember(ctx, *m) - switch { - case err == membership.ErrIDExists || err == membership.ErrPeerURLexists: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error())) - return - case err != nil: - h.lg.Warn( - "failed to add a member", - zap.String("member-id", m.ID.String()), - zap.Error(err), - ) - writeError(h.lg, w, r, err) - return - } - res := newMember(m) - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusCreated) - if err := json.NewEncoder(w).Encode(res); err != nil { - h.lg.Warn("failed to encode members response", zap.Error(err)) - } - - case "DELETE": - id, ok := getID(h.lg, r.URL.Path, w) - if !ok { - return - } - _, err := h.server.RemoveMember(ctx, uint64(id)) - switch { - case err == membership.ErrIDRemoved: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusGone, fmt.Sprintf("Member permanently removed: %s", id))) - case err == membership.ErrIDNotFound: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusNotFound, fmt.Sprintf("No such member: %s", id))) - case err != nil: - h.lg.Warn( - "failed to remove a member", - zap.String("member-id", id.String()), - zap.Error(err), - ) - writeError(h.lg, w, r, err) - default: - w.WriteHeader(http.StatusNoContent) - } - - case "PUT": - id, ok := getID(h.lg, r.URL.Path, w) - if !ok { - return - } - req := httptypes.MemberUpdateRequest{} - if ok := unmarshalRequest(h.lg, r, &req, w); !ok { - return - } - m := membership.Member{ - ID: id, - RaftAttributes: membership.RaftAttributes{PeerURLs: req.PeerURLs.StringSlice()}, - } - _, err := h.server.UpdateMember(ctx, m) - switch { - case err == membership.ErrPeerURLexists: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusConflict, err.Error())) - case err == membership.ErrIDNotFound: - writeError(h.lg, w, r, httptypes.NewHTTPError(http.StatusNotFound, fmt.Sprintf("No such member: %s", id))) - case err != nil: - h.lg.Warn( - "failed to update a member", - zap.String("member-id", m.ID.String()), - zap.Error(err), - ) - writeError(h.lg, w, r, err) - default: - w.WriteHeader(http.StatusNoContent) - } - } -} - -type statsHandler struct { - lg *zap.Logger - stats stats.Stats -} - -func (h *statsHandler) serveStore(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(h.stats.StoreStats()) -} - -func (h *statsHandler) serveSelf(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(h.stats.SelfStats()) -} - -func (h *statsHandler) serveLeader(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - stats := h.stats.LeaderStats() - if stats == nil { - etcdhttp.WriteError(h.lg, w, r, httptypes.NewHTTPError(http.StatusForbidden, "not current leader")) - return - } - w.Header().Set("Content-Type", "application/json") - w.Write(stats) -} - -// parseKeyRequest converts a received http.Request on keysPrefix to -// a server Request, performing validation of supplied fields as appropriate. -// If any validation fails, an empty Request and non-nil error is returned. -func parseKeyRequest(r *http.Request, clock clockwork.Clock) (etcdserverpb.Request, bool, error) { - var noValueOnSuccess bool - emptyReq := etcdserverpb.Request{} - - err := r.ParseForm() - if err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidForm, - err.Error(), - ) - } - - if !strings.HasPrefix(r.URL.Path, keysPrefix) { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidForm, - "incorrect key prefix", - ) - } - p := path.Join(etcdserver.StoreKeysPrefix, r.URL.Path[len(keysPrefix):]) - - var pIdx, wIdx uint64 - if pIdx, err = getUint64(r.Form, "prevIndex"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeIndexNaN, - `invalid value for "prevIndex"`, - ) - } - if wIdx, err = getUint64(r.Form, "waitIndex"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeIndexNaN, - `invalid value for "waitIndex"`, - ) - } - - var rec, sort, wait, dir, quorum, stream bool - if rec, err = getBool(r.Form, "recursive"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "recursive"`, - ) - } - if sort, err = getBool(r.Form, "sorted"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "sorted"`, - ) - } - if wait, err = getBool(r.Form, "wait"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "wait"`, - ) - } - // TODO(jonboulle): define what parameters dir is/isn't compatible with? - if dir, err = getBool(r.Form, "dir"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "dir"`, - ) - } - if quorum, err = getBool(r.Form, "quorum"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "quorum"`, - ) - } - if stream, err = getBool(r.Form, "stream"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "stream"`, - ) - } - - if wait && r.Method != "GET" { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `"wait" can only be used with GET requests`, - ) - } - - pV := r.FormValue("prevValue") - if _, ok := r.Form["prevValue"]; ok && pV == "" { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodePrevValueRequired, - `"prevValue" cannot be empty`, - ) - } - - if noValueOnSuccess, err = getBool(r.Form, "noValueOnSuccess"); err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - `invalid value for "noValueOnSuccess"`, - ) - } - - // TTL is nullable, so leave it null if not specified - // or an empty string - var ttl *uint64 - if len(r.FormValue("ttl")) > 0 { - i, err := getUint64(r.Form, "ttl") - if err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeTTLNaN, - `invalid value for "ttl"`, - ) - } - ttl = &i - } - - // prevExist is nullable, so leave it null if not specified - var pe *bool - if _, ok := r.Form["prevExist"]; ok { - bv, err := getBool(r.Form, "prevExist") - if err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - "invalid value for prevExist", - ) - } - pe = &bv - } - - // refresh is nullable, so leave it null if not specified - var refresh *bool - if _, ok := r.Form["refresh"]; ok { - bv, err := getBool(r.Form, "refresh") - if err != nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeInvalidField, - "invalid value for refresh", - ) - } - refresh = &bv - if refresh != nil && *refresh { - val := r.FormValue("value") - if _, ok := r.Form["value"]; ok && val != "" { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeRefreshValue, - `A value was provided on a refresh`, - ) - } - if ttl == nil { - return emptyReq, false, v2error.NewRequestError( - v2error.EcodeRefreshTTLRequired, - `No TTL value set`, - ) - } - } - } - - rr := etcdserverpb.Request{ - Method: r.Method, - Path: p, - Val: r.FormValue("value"), - Dir: dir, - PrevValue: pV, - PrevIndex: pIdx, - PrevExist: pe, - Wait: wait, - Since: wIdx, - Recursive: rec, - Sorted: sort, - Quorum: quorum, - Stream: stream, - } - - if pe != nil { - rr.PrevExist = pe - } - - if refresh != nil { - rr.Refresh = refresh - } - - // Null TTL is equivalent to unset Expiration - if ttl != nil { - expr := time.Duration(*ttl) * time.Second - rr.Expiration = clock.Now().Add(expr).UnixNano() - } - - return rr, noValueOnSuccess, nil -} - -// writeKeyEvent trims the prefix of key path in a single Event under -// StoreKeysPrefix, serializes it and writes the resulting JSON to the given -// ResponseWriter, along with the appropriate headers. -func writeKeyEvent(w http.ResponseWriter, resp etcdserver.Response, noValueOnSuccess bool) error { - ev := resp.Event - if ev == nil { - return errors.New("cannot write empty Event") - } - w.Header().Set("Content-Type", "application/json") - w.Header().Set("X-Etcd-Index", fmt.Sprint(ev.EtcdIndex)) - w.Header().Set("X-Raft-Index", fmt.Sprint(resp.Index)) - w.Header().Set("X-Raft-Term", fmt.Sprint(resp.Term)) - - if ev.IsCreated() { - w.WriteHeader(http.StatusCreated) - } - - ev = trimEventPrefix(ev, etcdserver.StoreKeysPrefix) - if noValueOnSuccess && - (ev.Action == v2store.Set || ev.Action == v2store.CompareAndSwap || - ev.Action == v2store.Create || ev.Action == v2store.Update) { - ev.Node = nil - ev.PrevNode = nil - } - return json.NewEncoder(w).Encode(ev) -} - -func writeKeyNoAuth(w http.ResponseWriter) { - e := v2error.NewError(v2error.EcodeUnauthorized, "Insufficient credentials", 0) - e.WriteTo(w) -} - -// writeKeyError logs and writes the given Error to the ResponseWriter. -// If Error is not an etcdErr, the error will be converted to an etcd error. -func writeKeyError(lg *zap.Logger, w http.ResponseWriter, err error) { - if err == nil { - return - } - switch e := err.(type) { - case *v2error.Error: - e.WriteTo(w) - default: - switch err { - case etcdserver.ErrTimeoutDueToLeaderFail, etcdserver.ErrTimeoutDueToConnectionLost: - if lg != nil { - lg.Warn( - "v2 response error", - zap.String("internal-server-error", err.Error()), - ) - } - default: - if lg != nil { - lg.Warn( - "unexpected v2 response error", - zap.String("internal-server-error", err.Error()), - ) - } - } - ee := v2error.NewError(v2error.EcodeRaftInternal, err.Error(), 0) - ee.WriteTo(w) - } -} - -func handleKeyWatch(ctx context.Context, lg *zap.Logger, w http.ResponseWriter, resp etcdserver.Response, stream bool) { - wa := resp.Watcher - defer wa.Remove() - ech := wa.EventChan() - var nch <-chan bool - if x, ok := w.(http.CloseNotifier); ok { - nch = x.CloseNotify() - } - - w.Header().Set("Content-Type", "application/json") - w.Header().Set("X-Etcd-Index", fmt.Sprint(wa.StartIndex())) - w.Header().Set("X-Raft-Index", fmt.Sprint(resp.Index)) - w.Header().Set("X-Raft-Term", fmt.Sprint(resp.Term)) - w.WriteHeader(http.StatusOK) - - // Ensure headers are flushed early, in case of long polling - w.(http.Flusher).Flush() - - for { - select { - case <-nch: - // Client closed connection. Nothing to do. - return - case <-ctx.Done(): - // Timed out. net/http will close the connection for us, so nothing to do. - return - case ev, ok := <-ech: - if !ok { - // If the channel is closed this may be an indication of - // that notifications are much more than we are able to - // send to the client in time. Then we simply end streaming. - return - } - ev = trimEventPrefix(ev, etcdserver.StoreKeysPrefix) - if err := json.NewEncoder(w).Encode(ev); err != nil { - // Should never be reached - lg.Warn("failed to encode event", zap.Error(err)) - return - } - if !stream { - return - } - w.(http.Flusher).Flush() - } - } -} - -func trimEventPrefix(ev *v2store.Event, prefix string) *v2store.Event { - if ev == nil { - return nil - } - // Since the *Event may reference one in the store history - // history, we must copy it before modifying - e := ev.Clone() - trimNodeExternPrefix(e.Node, prefix) - trimNodeExternPrefix(e.PrevNode, prefix) - return e -} - -func trimNodeExternPrefix(n *v2store.NodeExtern, prefix string) { - if n == nil { - return - } - n.Key = strings.TrimPrefix(n.Key, prefix) - for _, nn := range n.Nodes { - trimNodeExternPrefix(nn, prefix) - } -} - -func trimErrorPrefix(err error, prefix string) error { - if e, ok := err.(*v2error.Error); ok { - e.Cause = strings.TrimPrefix(e.Cause, prefix) - } - return err -} - -func unmarshalRequest(lg *zap.Logger, r *http.Request, req json.Unmarshaler, w http.ResponseWriter) bool { - ctype := r.Header.Get("Content-Type") - semicolonPosition := strings.Index(ctype, ";") - if semicolonPosition != -1 { - ctype = strings.TrimSpace(strings.ToLower(ctype[0:semicolonPosition])) - } - if ctype != "application/json" { - writeError(lg, w, r, httptypes.NewHTTPError(http.StatusUnsupportedMediaType, fmt.Sprintf("Bad Content-Type %s, accept application/json", ctype))) - return false - } - b, err := ioutil.ReadAll(r.Body) - if err != nil { - writeError(lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, err.Error())) - return false - } - if err := req.UnmarshalJSON(b); err != nil { - writeError(lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, err.Error())) - return false - } - return true -} - -func getID(lg *zap.Logger, p string, w http.ResponseWriter) (types.ID, bool) { - idStr := trimPrefix(p, membersPrefix) - if idStr == "" { - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - return 0, false - } - id, err := types.IDFromString(idStr) - if err != nil { - writeError(lg, w, nil, httptypes.NewHTTPError(http.StatusNotFound, fmt.Sprintf("No such member: %s", idStr))) - return 0, false - } - return id, true -} - -// getUint64 extracts a uint64 by the given key from a Form. If the key does -// not exist in the form, 0 is returned. If the key exists but the value is -// badly formed, an error is returned. If multiple values are present only the -// first is considered. -func getUint64(form url.Values, key string) (i uint64, err error) { - if vals, ok := form[key]; ok { - i, err = strconv.ParseUint(vals[0], 10, 64) - } - return -} - -// getBool extracts a bool by the given key from a Form. If the key does not -// exist in the form, false is returned. If the key exists but the value is -// badly formed, an error is returned. If multiple values are present only the -// first is considered. -func getBool(form url.Values, key string) (b bool, err error) { - if vals, ok := form[key]; ok { - b, err = strconv.ParseBool(vals[0]) - } - return -} - -// trimPrefix removes a given prefix and any slash following the prefix -// e.g.: trimPrefix("foo", "foo") == trimPrefix("foo/", "foo") == "" -func trimPrefix(p, prefix string) (s string) { - s = strings.TrimPrefix(p, prefix) - s = strings.TrimPrefix(s, "/") - return -} - -func newMemberCollection(ms []*membership.Member) *httptypes.MemberCollection { - c := httptypes.MemberCollection(make([]httptypes.Member, len(ms))) - - for i, m := range ms { - c[i] = newMember(m) - } - - return &c -} - -func newMember(m *membership.Member) httptypes.Member { - tm := httptypes.Member{ - ID: m.ID.String(), - Name: m.Name, - PeerURLs: make([]string, len(m.PeerURLs)), - ClientURLs: make([]string, len(m.ClientURLs)), - } - - copy(tm.PeerURLs, m.PeerURLs) - copy(tm.ClientURLs, m.ClientURLs) - - return tm -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client_auth.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client_auth.go deleted file mode 100644 index 2c6e7744ed..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/client_auth.go +++ /dev/null @@ -1,604 +0,0 @@ -// Copyright 2015 The etcd 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 v2http - -import ( - "encoding/json" - "net/http" - "path" - "strings" - - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - - "go.uber.org/zap" -) - -type authHandler struct { - lg *zap.Logger - sec v2auth.Store - cluster api.Cluster - clientCertAuthEnabled bool -} - -func hasWriteRootAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, clientCertAuthEnabled bool) bool { - if r.Method == "GET" || r.Method == "HEAD" { - return true - } - return hasRootAccess(lg, sec, r, clientCertAuthEnabled) -} - -func userFromBasicAuth(lg *zap.Logger, sec v2auth.Store, r *http.Request) *v2auth.User { - username, password, ok := r.BasicAuth() - if !ok { - lg.Warn("malformed basic auth encoding") - return nil - } - user, err := sec.GetUser(username) - if err != nil { - return nil - } - - ok = sec.CheckPassword(user, password) - if !ok { - lg.Warn("incorrect password", zap.String("user-name", username)) - return nil - } - return &user -} - -func userFromClientCertificate(lg *zap.Logger, sec v2auth.Store, r *http.Request) *v2auth.User { - if r.TLS == nil { - return nil - } - - for _, chains := range r.TLS.VerifiedChains { - for _, chain := range chains { - lg.Debug("found common name", zap.String("common-name", chain.Subject.CommonName)) - user, err := sec.GetUser(chain.Subject.CommonName) - if err == nil { - lg.Debug( - "authenticated a user via common name", - zap.String("user-name", user.User), - zap.String("common-name", chain.Subject.CommonName), - ) - return &user - } - } - } - return nil -} - -func hasRootAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, clientCertAuthEnabled bool) bool { - if sec == nil { - // No store means no auth available, eg, tests. - return true - } - if !sec.AuthEnabled() { - return true - } - - var rootUser *v2auth.User - if r.Header.Get("Authorization") == "" && clientCertAuthEnabled { - rootUser = userFromClientCertificate(lg, sec, r) - if rootUser == nil { - return false - } - } else { - rootUser = userFromBasicAuth(lg, sec, r) - if rootUser == nil { - return false - } - } - - for _, role := range rootUser.Roles { - if role == v2auth.RootRoleName { - return true - } - } - - lg.Warn( - "a user does not have root role for resource", - zap.String("root-user", rootUser.User), - zap.String("root-role-name", v2auth.RootRoleName), - zap.String("resource-path", r.URL.Path), - ) - return false -} - -func hasKeyPrefixAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, key string, recursive, clientCertAuthEnabled bool) bool { - if sec == nil { - // No store means no auth available, eg, tests. - return true - } - if !sec.AuthEnabled() { - return true - } - - var user *v2auth.User - if r.Header.Get("Authorization") == "" { - if clientCertAuthEnabled { - user = userFromClientCertificate(lg, sec, r) - } - if user == nil { - return hasGuestAccess(lg, sec, r, key) - } - } else { - user = userFromBasicAuth(lg, sec, r) - if user == nil { - return false - } - } - - writeAccess := r.Method != "GET" && r.Method != "HEAD" - for _, roleName := range user.Roles { - role, err := sec.GetRole(roleName) - if err != nil { - continue - } - if recursive { - if role.HasRecursiveAccess(key, writeAccess) { - return true - } - } else if role.HasKeyAccess(key, writeAccess) { - return true - } - } - - lg.Warn( - "invalid access for user on key", - zap.String("user-name", user.User), - zap.String("key", key), - ) - return false -} - -func hasGuestAccess(lg *zap.Logger, sec v2auth.Store, r *http.Request, key string) bool { - writeAccess := r.Method != "GET" && r.Method != "HEAD" - role, err := sec.GetRole(v2auth.GuestRoleName) - if err != nil { - return false - } - if role.HasKeyAccess(key, writeAccess) { - return true - } - - lg.Warn( - "invalid access for a guest role on key", - zap.String("role-name", v2auth.GuestRoleName), - zap.String("key", key), - ) - return false -} - -func writeNoAuth(lg *zap.Logger, w http.ResponseWriter, r *http.Request) { - herr := httptypes.NewHTTPError(http.StatusUnauthorized, "Insufficient credentials") - if err := herr.WriteTo(w); err != nil { - lg.Debug( - "failed to write v2 HTTP error", - zap.String("remote-addr", r.RemoteAddr), - zap.Error(err), - ) - } -} - -func handleAuth(mux *http.ServeMux, sh *authHandler) { - mux.HandleFunc(authPrefix+"/roles", authCapabilityHandler(sh.baseRoles)) - mux.HandleFunc(authPrefix+"/roles/", authCapabilityHandler(sh.handleRoles)) - mux.HandleFunc(authPrefix+"/users", authCapabilityHandler(sh.baseUsers)) - mux.HandleFunc(authPrefix+"/users/", authCapabilityHandler(sh.handleUsers)) - mux.HandleFunc(authPrefix+"/enable", authCapabilityHandler(sh.enableDisable)) -} - -func (sh *authHandler) baseRoles(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - - roles, err := sh.sec.AllRoles() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - if roles == nil { - roles = make([]string, 0) - } - - err = r.ParseForm() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - var rolesCollections struct { - Roles []v2auth.Role `json:"roles"` - } - for _, roleName := range roles { - var role v2auth.Role - role, err = sh.sec.GetRole(roleName) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - rolesCollections.Roles = append(rolesCollections.Roles, role) - } - err = json.NewEncoder(w).Encode(rolesCollections) - - if err != nil { - sh.lg.Warn( - "failed to encode base roles", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - writeError(sh.lg, w, r, err) - return - } -} - -func (sh *authHandler) handleRoles(w http.ResponseWriter, r *http.Request) { - subpath := path.Clean(r.URL.Path[len(authPrefix):]) - // Split "/roles/rolename/command". - // First item is an empty string, second is "roles" - pieces := strings.Split(subpath, "/") - if len(pieces) == 2 { - sh.baseRoles(w, r) - return - } - if len(pieces) != 3 { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path")) - return - } - sh.forRole(w, r, pieces[2]) -} - -func (sh *authHandler) forRole(w http.ResponseWriter, r *http.Request, role string) { - if !allowMethod(w, r.Method, "GET", "PUT", "DELETE") { - return - } - if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - - switch r.Method { - case "GET": - data, err := sh.sec.GetRole(role) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - err = json.NewEncoder(w).Encode(data) - if err != nil { - sh.lg.Warn( - "failed to encode a role", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - return - } - return - - case "PUT": - var in v2auth.Role - err := json.NewDecoder(r.Body).Decode(&in) - if err != nil { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body.")) - return - } - if in.Role != role { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON name does not match the name in the URL")) - return - } - - var out v2auth.Role - - // create - if in.Grant.IsEmpty() && in.Revoke.IsEmpty() { - err = sh.sec.CreateRole(in) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - w.WriteHeader(http.StatusCreated) - out = in - } else { - if !in.Permissions.IsEmpty() { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Role JSON contains both permissions and grant/revoke")) - return - } - out, err = sh.sec.UpdateRole(in) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - w.WriteHeader(http.StatusOK) - } - - err = json.NewEncoder(w).Encode(out) - if err != nil { - sh.lg.Warn( - "failed to encode a role", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - return - } - return - - case "DELETE": - err := sh.sec.DeleteRole(role) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } -} - -type userWithRoles struct { - User string `json:"user"` - Roles []v2auth.Role `json:"roles,omitempty"` -} - -type usersCollections struct { - Users []userWithRoles `json:"users"` -} - -func (sh *authHandler) baseUsers(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET") { - return - } - if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - - users, err := sh.sec.AllUsers() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - if users == nil { - users = make([]string, 0) - } - - err = r.ParseForm() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - ucs := usersCollections{} - for _, userName := range users { - var user v2auth.User - user, err = sh.sec.GetUser(userName) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - uwr := userWithRoles{User: user.User} - for _, roleName := range user.Roles { - var role v2auth.Role - role, err = sh.sec.GetRole(roleName) - if err != nil { - continue - } - uwr.Roles = append(uwr.Roles, role) - } - - ucs.Users = append(ucs.Users, uwr) - } - err = json.NewEncoder(w).Encode(ucs) - - if err != nil { - sh.lg.Warn( - "failed to encode users", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - writeError(sh.lg, w, r, err) - return - } -} - -func (sh *authHandler) handleUsers(w http.ResponseWriter, r *http.Request) { - subpath := path.Clean(r.URL.Path[len(authPrefix):]) - // Split "/users/username". - // First item is an empty string, second is "users" - pieces := strings.Split(subpath, "/") - if len(pieces) == 2 { - sh.baseUsers(w, r) - return - } - if len(pieces) != 3 { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid path")) - return - } - sh.forUser(w, r, pieces[2]) -} - -func (sh *authHandler) forUser(w http.ResponseWriter, r *http.Request, user string) { - if !allowMethod(w, r.Method, "GET", "PUT", "DELETE") { - return - } - if !hasRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - - switch r.Method { - case "GET": - u, err := sh.sec.GetUser(user) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - err = r.ParseForm() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - uwr := userWithRoles{User: u.User} - for _, roleName := range u.Roles { - var role v2auth.Role - role, err = sh.sec.GetRole(roleName) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - uwr.Roles = append(uwr.Roles, role) - } - err = json.NewEncoder(w).Encode(uwr) - - if err != nil { - sh.lg.Warn( - "failed to encode roles", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - return - } - return - - case "PUT": - var u v2auth.User - err := json.NewDecoder(r.Body).Decode(&u) - if err != nil { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "Invalid JSON in request body.")) - return - } - if u.User != user { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON name does not match the name in the URL")) - return - } - - var ( - out v2auth.User - created bool - ) - - if len(u.Grant) == 0 && len(u.Revoke) == 0 { - // create or update - if len(u.Roles) != 0 { - out, err = sh.sec.CreateUser(u) - } else { - // if user passes in both password and roles, we are unsure about his/her - // intention. - out, created, err = sh.sec.CreateOrUpdateUser(u) - } - - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } else { - // update case - if len(u.Roles) != 0 { - writeError(sh.lg, w, r, httptypes.NewHTTPError(http.StatusBadRequest, "User JSON contains both roles and grant/revoke")) - return - } - out, err = sh.sec.UpdateUser(u) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } - - if created { - w.WriteHeader(http.StatusCreated) - } else { - w.WriteHeader(http.StatusOK) - } - - out.Password = "" - - err = json.NewEncoder(w).Encode(out) - if err != nil { - sh.lg.Warn( - "failed to encode a user", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - return - } - return - - case "DELETE": - err := sh.sec.DeleteUser(user) - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } -} - -type enabled struct { - Enabled bool `json:"enabled"` -} - -func (sh *authHandler) enableDisable(w http.ResponseWriter, r *http.Request) { - if !allowMethod(w, r.Method, "GET", "PUT", "DELETE") { - return - } - if !hasWriteRootAccess(sh.lg, sh.sec, r, sh.clientCertAuthEnabled) { - writeNoAuth(sh.lg, w, r) - return - } - w.Header().Set("X-Etcd-Cluster-ID", sh.cluster.ID().String()) - w.Header().Set("Content-Type", "application/json") - isEnabled := sh.sec.AuthEnabled() - switch r.Method { - case "GET": - jsonDict := enabled{isEnabled} - err := json.NewEncoder(w).Encode(jsonDict) - if err != nil { - sh.lg.Warn( - "failed to encode a auth state", - zap.String("url", r.URL.String()), - zap.Error(err), - ) - } - - case "PUT": - err := sh.sec.EnableAuth() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - - case "DELETE": - err := sh.sec.DisableAuth() - if err != nil { - writeError(sh.lg, w, r, err) - return - } - } -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/http.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/http.go deleted file mode 100644 index 88138b80a8..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/http.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2015 The etcd 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 v2http - -import ( - "math" - "net/http" - "strings" - "time" - - "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2auth" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - - "go.uber.org/zap" -) - -const ( - // time to wait for a Watch request - defaultWatchTimeout = time.Duration(math.MaxInt64) -) - -func writeError(lg *zap.Logger, w http.ResponseWriter, r *http.Request, err error) { - if err == nil { - return - } - if e, ok := err.(v2auth.Error); ok { - herr := httptypes.NewHTTPError(e.HTTPStatus(), e.Error()) - if et := herr.WriteTo(w); et != nil { - if lg != nil { - lg.Debug( - "failed to write v2 HTTP error", - zap.String("remote-addr", r.RemoteAddr), - zap.String("v2auth-error", e.Error()), - zap.Error(et), - ) - } - } - return - } - etcdhttp.WriteError(lg, w, r, err) -} - -// allowMethod verifies that the given method is one of the allowed methods, -// and if not, it writes an error to w. A boolean is returned indicating -// whether or not the method is allowed. -func allowMethod(w http.ResponseWriter, m string, ms ...string) bool { - for _, meth := range ms { - if m == meth { - return true - } - } - w.Header().Set("Allow", strings.Join(ms, ",")) - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - return false -} - -func requestLogger(lg *zap.Logger, handler http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if lg != nil { - lg.Debug( - "handling HTTP request", - zap.String("method", r.Method), - zap.String("request-uri", r.RequestURI), - zap.String("remote-addr", r.RemoteAddr), - ) - } - handler.ServeHTTP(w, r) - }) -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/member.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/member.go deleted file mode 100644 index a5467be91e..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes/member.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2015 The etcd 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 httptypes defines how etcd's HTTP API entities are serialized to and -// deserialized from JSON. -package httptypes - -import ( - "encoding/json" - - "go.etcd.io/etcd/client/pkg/v3/types" -) - -type Member struct { - ID string `json:"id"` - Name string `json:"name"` - PeerURLs []string `json:"peerURLs"` - ClientURLs []string `json:"clientURLs"` -} - -type MemberCreateRequest struct { - PeerURLs types.URLs -} - -type MemberUpdateRequest struct { - MemberCreateRequest -} - -func (m *MemberCreateRequest) UnmarshalJSON(data []byte) error { - s := struct { - PeerURLs []string `json:"peerURLs"` - }{} - - err := json.Unmarshal(data, &s) - if err != nil { - return err - } - - urls, err := types.NewURLs(s.PeerURLs) - if err != nil { - return err - } - - m.PeerURLs = urls - return nil -} - -type MemberCollection []Member - -func (c *MemberCollection) MarshalJSON() ([]byte, error) { - d := struct { - Members []Member `json:"members"` - }{ - Members: []Member(*c), - } - - return json.Marshal(d) -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/metrics.go deleted file mode 100644 index bdbd8c71c1..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/metrics.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2015 The etcd 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 v2http - -import ( - "net/http" - "strconv" - "time" - - "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" - - "github.com/prometheus/client_golang/prometheus" -) - -var ( - incomingEvents = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "http", - Name: "received_total", - Help: "Counter of requests received into the system (successfully parsed and authd).", - }, []string{"method"}) - - failedEvents = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "http", - Name: "failed_total", - Help: "Counter of handle failures of requests (non-watches), by method (GET/PUT etc.) and code (400, 500 etc.).", - }, []string{"method", "code"}) - - successfulEventsHandlingSec = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Namespace: "etcd", - Subsystem: "http", - Name: "successful_duration_seconds", - Help: "Bucketed histogram of processing time (s) of successfully handled requests (non-watches), by method (GET/PUT etc.).", - - // lowest bucket start of upper bound 0.0005 sec (0.5 ms) with factor 2 - // highest bucket start of 0.0005 sec * 2^12 == 2.048 sec - Buckets: prometheus.ExponentialBuckets(0.0005, 2, 13), - }, []string{"method"}) -) - -func init() { - prometheus.MustRegister(incomingEvents) - prometheus.MustRegister(failedEvents) - prometheus.MustRegister(successfulEventsHandlingSec) -} - -func reportRequestReceived(request etcdserverpb.Request) { - incomingEvents.WithLabelValues(methodFromRequest(request)).Inc() -} - -func reportRequestCompleted(request etcdserverpb.Request, startTime time.Time) { - method := methodFromRequest(request) - successfulEventsHandlingSec.WithLabelValues(method).Observe(time.Since(startTime).Seconds()) -} - -func reportRequestFailed(request etcdserverpb.Request, err error) { - method := methodFromRequest(request) - failedEvents.WithLabelValues(method, strconv.Itoa(codeFromError(err))).Inc() -} - -func methodFromRequest(request etcdserverpb.Request) string { - if request.Method == "GET" && request.Quorum { - return "QGET" - } - return request.Method -} - -func codeFromError(err error) int { - if err == nil { - return http.StatusInternalServerError - } - switch e := err.(type) { - case *v2error.Error: - return e.StatusCode() - case *httptypes.HTTPError: - return e.Code - default: - return http.StatusInternalServerError - } -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/queue.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/queue.go index 2c3dff3d0f..e16cec159c 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/queue.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/queue.go @@ -65,7 +65,7 @@ func (q *statsQueue) Insert(p *RequestStats) { q.back = (q.back + 1) % queueCapacity - if q.size == queueCapacity { //dequeue + if q.size == queueCapacity { // dequeue q.totalReqSize -= q.items[q.front].Size q.front = (q.back + 1) % queueCapacity } else { @@ -74,7 +74,6 @@ func (q *statsQueue) Insert(p *RequestStats) { q.items[q.back] = p q.totalReqSize += q.items[q.back].Size - } // Rate function returns the package rate and byte rate diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/server.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/server.go index 45effb1edc..e8d218a720 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/server.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/server.go @@ -20,7 +20,7 @@ import ( "sync" "time" - "go.etcd.io/etcd/raft/v3" + "go.etcd.io/raft/v3" ) // ServerStats encapsulates various statistics about an EtcdServer and its @@ -59,7 +59,7 @@ type serverStats struct { StartTime time.Time `json:"startTime"` } `json:"leaderInfo"` - RecvAppendRequestCnt uint64 `json:"recvAppendRequestCnt,"` + RecvAppendRequestCnt uint64 `json:"recvAppendRequestCnt"` RecvingPkgRate float64 `json:"recvPkgRate,omitempty"` RecvingBandwidthRate float64 `json:"recvBandwidthRate,omitempty"` diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_history.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_history.go index c9bcdca051..11c8b0176f 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_history.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_history.go @@ -125,5 +125,4 @@ func (eh *EventHistory) clone() *EventHistory { Queue: clonedQueue, LastIndex: eh.LastIndex, } - } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_queue.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_queue.go index 7ea03de8c9..aa2a645d6f 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_queue.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/event_queue.go @@ -26,7 +26,7 @@ func (eq *eventQueue) insert(e *Event) { eq.Events[eq.Back] = e eq.Back = (eq.Back + 1) % eq.Capacity - if eq.Size == eq.Capacity { //dequeue + if eq.Size == eq.Capacity { // dequeue eq.Front = (eq.Front + 1) % eq.Capacity } else { eq.Size++ diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/metrics.go index 5adea1efdd..943457bdf1 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/metrics.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/metrics.go @@ -28,7 +28,9 @@ var ( Subsystem: "store", Name: "reads_total", Help: "Total number of reads action by (get/getRecursive), local to this member.", - }, []string{"action"}) + }, + []string{"action"}, + ) writeCounter = prometheus.NewCounterVec( prometheus.CounterOpts{ @@ -36,7 +38,9 @@ var ( Subsystem: "store", Name: "writes_total", Help: "Total number of writes (e.g. set/compareAndDelete) seen by this member.", - }, []string{"action"}) + }, + []string{"action"}, + ) readFailedCounter = prometheus.NewCounterVec( prometheus.CounterOpts{ @@ -44,7 +48,9 @@ var ( Subsystem: "store", Name: "reads_failed_total", Help: "Failed read actions by (get/getRecursive), local to this member.", - }, []string{"action"}) + }, + []string{"action"}, + ) writeFailedCounter = prometheus.NewCounterVec( prometheus.CounterOpts{ @@ -52,7 +58,9 @@ var ( Subsystem: "store", Name: "writes_failed_total", Help: "Failed write actions (e.g. set/compareAndDelete), seen by this member.", - }, []string{"action"}) + }, + []string{"action"}, + ) expireCounter = prometheus.NewCounter( prometheus.CounterOpts{ @@ -60,7 +68,8 @@ var ( Subsystem: "store", Name: "expires_total", Help: "Total number of expired keys.", - }) + }, + ) watchRequests = prometheus.NewCounter( prometheus.CounterOpts{ @@ -68,7 +77,8 @@ var ( Subsystem: "store", Name: "watch_requests_total", Help: "Total number of incoming watch requests (new or reestablished).", - }) + }, + ) watcherCount = prometheus.NewGauge( prometheus.GaugeOpts{ @@ -76,7 +86,8 @@ var ( Subsystem: "store", Name: "watchers", Help: "Count of currently active watchers.", - }) + }, + ) ) const ( diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node.go index 9fe6263e2e..7e5c3e8deb 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node.go @@ -19,9 +19,9 @@ import ( "sort" "time" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "github.com/jonboulle/clockwork" + + "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" ) // explanations of Compare function result @@ -277,7 +277,6 @@ func (n *node) Repr(recursive, sorted bool, clock clockwork.Clock) *NodeExtern { i := 0 for _, child := range children { - if child.IsHidden() { // get will not list hidden node continue } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node_extern.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node_extern.go index b3bf5f3c97..ff2e13e639 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node_extern.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/node_extern.go @@ -62,7 +62,6 @@ func (eNode *NodeExtern) loadInternalNode(n *node, recursive, sorted bool, clock if sorted { sort.Sort(eNode.Nodes) } - } else { // node is a file value, _ := n.Read() eNode.Value = &value diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/stats.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/stats.go index 9151799da7..55ede56d10 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/stats.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/stats.go @@ -104,7 +104,7 @@ func (s *Stats) clone() *Stats { } } -func (s *Stats) toJson() []byte { +func (s *Stats) toJSON() []byte { b, _ := json.Marshal(s) return b } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/store.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/store.go index 32cb26ad96..2129bd635e 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/store.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/store.go @@ -23,10 +23,10 @@ import ( "sync" "time" + "github.com/jonboulle/clockwork" + "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - - "github.com/jonboulle/clockwork" ) // The default version to set when the store is first initialized. @@ -99,7 +99,7 @@ func newStore(namespaces ...string) *store { } s.Stats = newStats() s.WatcherHub = newWatchHub(1000) - s.ttlKeyHeap = newTtlKeyHeap() + s.ttlKeyHeap = newTTLKeyHeap() s.readonlySet = types.NewUnsafeSet(append(namespaces, "/")...) return s } @@ -257,8 +257,8 @@ func getCompareFailCause(n *node, which int, prevValue string, prevIndex uint64) } func (s *store) CompareAndSwap(nodePath string, prevValue string, prevIndex uint64, - value string, expireOpts TTLOptionSet) (*Event, error) { - + value string, expireOpts TTLOptionSet, +) (*Event, error) { var err *v2error.Error s.worldLock.Lock() @@ -535,7 +535,7 @@ func (s *store) Update(nodePath string, newValue string, expireOpts TTLOptionSet eNode := e.Node if err := n.Write(newValue, nextIndex); err != nil { - return nil, fmt.Errorf("nodePath %v : %v", nodePath, err) + return nil, fmt.Errorf("nodePath %v : %w", nodePath, err) } if n.IsDir() { @@ -564,8 +564,8 @@ func (s *store) Update(nodePath string, newValue string, expireOpts TTLOptionSet } func (s *store) internalCreate(nodePath string, dir bool, value string, unique, replace bool, - expireTime time.Time, action string) (*Event, *v2error.Error) { - + expireTime time.Time, action string, +) (*Event, *v2error.Error) { currIndex, nextIndex := s.CurrentIndex, s.CurrentIndex+1 if unique { // append unique item under the node path @@ -589,7 +589,6 @@ func (s *store) internalCreate(nodePath string, dir bool, value string, unique, // walk through the nodePath, create dirs and get the last directory node d, err := s.walk(dirName, s.checkDir) - if err != nil { s.Stats.Inc(SetFail) reportWriteFailure(action) @@ -604,18 +603,17 @@ func (s *store) internalCreate(nodePath string, dir bool, value string, unique, // force will try to replace an existing file if n != nil { - if replace { - if n.IsDir() { - return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, currIndex) - } - e.PrevNode = n.Repr(false, false, s.clock) - - if err := n.Remove(false, false, nil); err != nil { - return nil, err - } - } else { + if !replace { return nil, v2error.NewError(v2error.EcodeNodeExist, nodePath, currIndex) } + if n.IsDir() { + return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, currIndex) + } + e.PrevNode = n.Repr(false, false, s.clock) + + if err := n.Remove(false, false, nil); err != nil { + return nil, err + } } if !dir { // create file @@ -624,7 +622,6 @@ func (s *store) internalCreate(nodePath string, dir bool, value string, unique, eNode.Value = &valueCopy n = newKV(s, nodePath, value, nextIndex, d, expireTime) - } else { // create directory eNode.Dir = true @@ -653,7 +650,6 @@ func (s *store) internalGet(nodePath string) (*node, *v2error.Error) { nodePath = path.Clean(path.Join("/", nodePath)) walkFunc := func(parent *node, name string) (*node, *v2error.Error) { - if !parent.IsDir() { err := v2error.NewError(v2error.EcodeNotDir, parent.Path, s.CurrentIndex) return nil, err @@ -668,7 +664,6 @@ func (s *store) internalGet(nodePath string) (*node, *v2error.Error) { } f, err := s.walk(nodePath, walkFunc) - if err != nil { return nil, err } @@ -707,7 +702,6 @@ func (s *store) DeleteExpiredKeys(cutoff time.Time) { s.WatcherHub.notify(e) } - } // checkDir will check whether the component is a directory under parent node. @@ -776,20 +770,21 @@ func (s *store) Recovery(state []byte) error { s.worldLock.Lock() defer s.worldLock.Unlock() err := json.Unmarshal(state, s) - if err != nil { return err } - s.ttlKeyHeap = newTtlKeyHeap() + s.ttlKeyHeap = newTTLKeyHeap() s.Root.recoverAndclean() return nil } +//revive:disable:var-naming func (s *store) JsonStats() []byte { + //revive:enable:var-naming s.Stats.Watchers = uint64(s.WatcherHub.count) - return s.Stats.toJson() + return s.Stats.toJSON() } func (s *store) HasTTLKeys() bool { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/ttl_key_heap.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/ttl_key_heap.go index 477d2b9f3a..77ca8e9ed6 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/ttl_key_heap.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/ttl_key_heap.go @@ -22,7 +22,7 @@ type ttlKeyHeap struct { keyMap map[*node]int } -func newTtlKeyHeap() *ttlKeyHeap { +func newTTLKeyHeap() *ttlKeyHeap { h := &ttlKeyHeap{keyMap: make(map[*node]int)} heap.Init(h) return h @@ -45,13 +45,13 @@ func (h ttlKeyHeap) Swap(i, j int) { h.keyMap[h.array[j]] = j } -func (h *ttlKeyHeap) Push(x interface{}) { +func (h *ttlKeyHeap) Push(x any) { n, _ := x.(*node) h.keyMap[n] = len(h.array) h.array = append(h.array, n) } -func (h *ttlKeyHeap) Pop() interface{} { +func (h *ttlKeyHeap) Pop() any { old := h.array n := len(old) x := old[n-1] @@ -77,7 +77,7 @@ func (h *ttlKeyHeap) pop() *node { return n } -func (h *ttlKeyHeap) push(x interface{}) { +func (h *ttlKeyHeap) push(x any) { heap.Push(h, x) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/watcher_hub.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/watcher_hub.go index dc5c8f2bb5..df5ae78b07 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/watcher_hub.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2store/watcher_hub.go @@ -59,7 +59,6 @@ func newWatchHub(capacity int) *watcherHub { func (wh *watcherHub) watch(key string, recursive, stream bool, index, storeIndex uint64) (Watcher, *v2error.Error) { reportWatchRequest() event, err := wh.EventHistory.scan(key, recursive, index) - if err != nil { err.Index = storeIndex return nil, err diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/cluster.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/cluster.go deleted file mode 100644 index d275e05718..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/cluster.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2017 The etcd 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 v2v3 - -import ( - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - - "github.com/coreos/go-semver/semver" -) - -func (s *v2v3Server) ID() types.ID { - // TODO: use an actual member ID - return types.ID(0xe7cd2f00d) -} -func (s *v2v3Server) ClientURLs() []string { panic("STUB") } -func (s *v2v3Server) Members() []*membership.Member { panic("STUB") } -func (s *v2v3Server) Member(id types.ID) *membership.Member { panic("STUB") } -func (s *v2v3Server) Version() *semver.Version { panic("STUB") } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/server.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/server.go deleted file mode 100644 index 71557ceb5c..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/server.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2017 The etcd 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 v2v3 - -import ( - "context" - "net/http" - "time" - - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - - "github.com/coreos/go-semver/semver" - "go.uber.org/zap" -) - -type fakeStats struct{} - -func (s *fakeStats) SelfStats() []byte { return nil } -func (s *fakeStats) LeaderStats() []byte { return nil } -func (s *fakeStats) StoreStats() []byte { return nil } - -type v2v3Server struct { - lg *zap.Logger - c *clientv3.Client - store *v2v3Store - fakeStats -} - -func NewServer(lg *zap.Logger, c *clientv3.Client, pfx string) etcdserver.ServerPeer { - return &v2v3Server{lg: lg, c: c, store: newStore(c, pfx)} -} - -func (s *v2v3Server) ClientCertAuthEnabled() bool { return false } - -func (s *v2v3Server) LeaseHandler() http.Handler { panic("STUB: lease handler") } -func (s *v2v3Server) RaftHandler() http.Handler { panic("STUB: raft handler") } - -func (s *v2v3Server) Leader() types.ID { - ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second) - defer cancel() - resp, err := s.c.Status(ctx, s.c.Endpoints()[0]) - if err != nil { - return 0 - } - return types.ID(resp.Leader) -} - -func (s *v2v3Server) AddMember(ctx context.Context, memb membership.Member) ([]*membership.Member, error) { - // adding member as learner is not supported by V2 Server. - resp, err := s.c.MemberAdd(ctx, memb.PeerURLs) - if err != nil { - return nil, err - } - return v3MembersToMembership(resp.Members), nil -} - -func (s *v2v3Server) RemoveMember(ctx context.Context, id uint64) ([]*membership.Member, error) { - resp, err := s.c.MemberRemove(ctx, id) - if err != nil { - return nil, err - } - return v3MembersToMembership(resp.Members), nil -} - -func (s *v2v3Server) PromoteMember(ctx context.Context, id uint64) ([]*membership.Member, error) { - resp, err := s.c.MemberPromote(ctx, id) - if err != nil { - return nil, err - } - return v3MembersToMembership(resp.Members), nil -} - -func (s *v2v3Server) UpdateMember(ctx context.Context, m membership.Member) ([]*membership.Member, error) { - resp, err := s.c.MemberUpdate(ctx, uint64(m.ID), m.PeerURLs) - if err != nil { - return nil, err - } - return v3MembersToMembership(resp.Members), nil -} - -func v3MembersToMembership(v3membs []*pb.Member) []*membership.Member { - membs := make([]*membership.Member, len(v3membs)) - for i, m := range v3membs { - membs[i] = &membership.Member{ - ID: types.ID(m.ID), - RaftAttributes: membership.RaftAttributes{ - PeerURLs: m.PeerURLs, - IsLearner: m.IsLearner, - }, - Attributes: membership.Attributes{ - Name: m.Name, - ClientURLs: m.ClientURLs, - }, - } - } - return membs -} - -func (s *v2v3Server) ClusterVersion() *semver.Version { return s.Version() } -func (s *v2v3Server) Cluster() api.Cluster { return s } -func (s *v2v3Server) Alarms() []*pb.AlarmMember { return nil } -func (s *v2v3Server) LeaderChangedNotify() <-chan struct{} { return nil } - -func (s *v2v3Server) Do(ctx context.Context, r pb.Request) (etcdserver.Response, error) { - applier := etcdserver.NewApplierV2(s.lg, s.store, nil) - reqHandler := etcdserver.NewStoreRequestV2Handler(s.store, applier) - req := (*etcdserver.RequestV2)(&r) - resp, err := req.Handle(ctx, reqHandler) - if resp.Err != nil { - return resp, resp.Err - } - return resp, err -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/store.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/store.go deleted file mode 100644 index 6d78cab719..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/store.go +++ /dev/null @@ -1,638 +0,0 @@ -// Copyright 2017 The etcd 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 v2v3 - -import ( - "context" - "fmt" - "path" - "sort" - "strings" - "time" - - "go.etcd.io/etcd/api/v3/mvccpb" - "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/client/v3/concurrency" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" -) - -// store implements the Store interface for V2 using -// a v3 client. -type v2v3Store struct { - c *clientv3.Client - // pfx is the v3 prefix where keys should be stored. - pfx string - ctx context.Context -} - -const maxPathDepth = 63 - -var errUnsupported = fmt.Errorf("TTLs are unsupported") - -func NewStore(c *clientv3.Client, pfx string) v2store.Store { return newStore(c, pfx) } - -func newStore(c *clientv3.Client, pfx string) *v2v3Store { return &v2v3Store{c, pfx, c.Ctx()} } - -func (s *v2v3Store) Index() uint64 { panic("STUB") } - -func (s *v2v3Store) Get(nodePath string, recursive, sorted bool) (*v2store.Event, error) { - key := s.mkPath(nodePath) - resp, err := s.c.Txn(s.ctx).Then( - clientv3.OpGet(key+"/"), - clientv3.OpGet(key), - ).Commit() - if err != nil { - return nil, err - } - - if kvs := resp.Responses[0].GetResponseRange().Kvs; len(kvs) != 0 || isRoot(nodePath) { - nodes, err := s.getDir(nodePath, recursive, sorted, resp.Header.Revision) - if err != nil { - return nil, err - } - cidx, midx := uint64(0), uint64(0) - if len(kvs) > 0 { - cidx, midx = mkV2Rev(kvs[0].CreateRevision), mkV2Rev(kvs[0].ModRevision) - } - return &v2store.Event{ - Action: v2store.Get, - Node: &v2store.NodeExtern{ - Key: nodePath, - Dir: true, - Nodes: nodes, - CreatedIndex: cidx, - ModifiedIndex: midx, - }, - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil - } - - kvs := resp.Responses[1].GetResponseRange().Kvs - if len(kvs) == 0 { - return nil, v2error.NewError(v2error.EcodeKeyNotFound, nodePath, mkV2Rev(resp.Header.Revision)) - } - - return &v2store.Event{ - Action: v2store.Get, - Node: s.mkV2Node(kvs[0]), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) getDir(nodePath string, recursive, sorted bool, rev int64) ([]*v2store.NodeExtern, error) { - rootNodes, err := s.getDirDepth(nodePath, 1, rev) - if err != nil || !recursive { - if sorted { - sort.Sort(v2store.NodeExterns(rootNodes)) - } - return rootNodes, err - } - nextNodes := rootNodes - nodes := make(map[string]*v2store.NodeExtern) - // Breadth walk the subdirectories - for i := 2; len(nextNodes) > 0; i++ { - for _, n := range nextNodes { - nodes[n.Key] = n - if parent := nodes[path.Dir(n.Key)]; parent != nil { - parent.Nodes = append(parent.Nodes, n) - } - } - if nextNodes, err = s.getDirDepth(nodePath, i, rev); err != nil { - return nil, err - } - } - - if sorted { - sort.Sort(v2store.NodeExterns(rootNodes)) - } - return rootNodes, nil -} - -func (s *v2v3Store) getDirDepth(nodePath string, depth int, rev int64) ([]*v2store.NodeExtern, error) { - pd := s.mkPathDepth(nodePath, depth) - resp, err := s.c.Get(s.ctx, pd, clientv3.WithPrefix(), clientv3.WithRev(rev)) - if err != nil { - return nil, err - } - - nodes := make([]*v2store.NodeExtern, len(resp.Kvs)) - for i, kv := range resp.Kvs { - nodes[i] = s.mkV2Node(kv) - } - return nodes, nil -} - -func (s *v2v3Store) Set( - nodePath string, - dir bool, - value string, - expireOpts v2store.TTLOptionSet, -) (*v2store.Event, error) { - if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() { - return nil, errUnsupported - } - - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - - ecode := 0 - applyf := func(stm concurrency.STM) error { - // build path if any directories in path do not exist - dirs := []string{} - for p := path.Dir(nodePath); !isRoot(p); p = path.Dir(p) { - pp := s.mkPath(p) - if stm.Rev(pp) > 0 { - ecode = v2error.EcodeNotDir - return nil - } - if stm.Rev(pp+"/") == 0 { - dirs = append(dirs, pp+"/") - } - } - for _, d := range dirs { - stm.Put(d, "") - } - - key := s.mkPath(nodePath) - if dir { - if stm.Rev(key) != 0 { - // exists as non-dir - ecode = v2error.EcodeNotDir - return nil - } - key = key + "/" - } else if stm.Rev(key+"/") != 0 { - ecode = v2error.EcodeNotFile - return nil - } - stm.Put(key, value, clientv3.WithPrevKV()) - stm.Put(s.mkActionKey(), v2store.Set) - return nil - } - - resp, err := s.newSTM(applyf) - if err != nil { - return nil, err - } - if ecode != 0 { - return nil, v2error.NewError(ecode, nodePath, mkV2Rev(resp.Header.Revision)) - } - - createRev := resp.Header.Revision - var pn *v2store.NodeExtern - if pkv := prevKeyFromPuts(resp); pkv != nil { - pn = s.mkV2Node(pkv) - createRev = pkv.CreateRevision - } - - vp := &value - if dir { - vp = nil - } - return &v2store.Event{ - Action: v2store.Set, - Node: &v2store.NodeExtern{ - Key: nodePath, - Value: vp, - Dir: dir, - ModifiedIndex: mkV2Rev(resp.Header.Revision), - CreatedIndex: mkV2Rev(createRev), - }, - PrevNode: pn, - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) Update(nodePath, newValue string, expireOpts v2store.TTLOptionSet) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - - if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() { - return nil, errUnsupported - } - - key := s.mkPath(nodePath) - ecode := 0 - applyf := func(stm concurrency.STM) error { - if rev := stm.Rev(key + "/"); rev != 0 { - ecode = v2error.EcodeNotFile - return nil - } - if rev := stm.Rev(key); rev == 0 { - ecode = v2error.EcodeKeyNotFound - return nil - } - stm.Put(key, newValue, clientv3.WithPrevKV()) - stm.Put(s.mkActionKey(), v2store.Update) - return nil - } - - resp, err := s.newSTM(applyf) - if err != nil { - return nil, err - } - if ecode != 0 { - return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, mkV2Rev(resp.Header.Revision)) - } - - pkv := prevKeyFromPuts(resp) - return &v2store.Event{ - Action: v2store.Update, - Node: &v2store.NodeExtern{ - Key: nodePath, - Value: &newValue, - ModifiedIndex: mkV2Rev(resp.Header.Revision), - CreatedIndex: mkV2Rev(pkv.CreateRevision), - }, - PrevNode: s.mkV2Node(pkv), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) Create( - nodePath string, - dir bool, - value string, - unique bool, - expireOpts v2store.TTLOptionSet, -) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() { - return nil, errUnsupported - } - ecode := 0 - applyf := func(stm concurrency.STM) error { - ecode = 0 - key := s.mkPath(nodePath) - if unique { - // append unique item under the node path - for { - key = nodePath + "/" + fmt.Sprintf("%020s", time.Now()) - key = path.Clean(path.Join("/", key)) - key = s.mkPath(key) - if stm.Rev(key) == 0 { - break - } - } - } - if stm.Rev(key) > 0 || stm.Rev(key+"/") > 0 { - ecode = v2error.EcodeNodeExist - return nil - } - // build path if any directories in path do not exist - dirs := []string{} - for p := path.Dir(nodePath); !isRoot(p); p = path.Dir(p) { - pp := s.mkPath(p) - if stm.Rev(pp) > 0 { - ecode = v2error.EcodeNotDir - return nil - } - if stm.Rev(pp+"/") == 0 { - dirs = append(dirs, pp+"/") - } - } - for _, d := range dirs { - stm.Put(d, "") - } - - if dir { - // directories marked with extra slash in key name - key += "/" - } - stm.Put(key, value) - stm.Put(s.mkActionKey(), v2store.Create) - return nil - } - - resp, err := s.newSTM(applyf) - if err != nil { - return nil, err - } - if ecode != 0 { - return nil, v2error.NewError(ecode, nodePath, mkV2Rev(resp.Header.Revision)) - } - - var v *string - if !dir { - v = &value - } - - return &v2store.Event{ - Action: v2store.Create, - Node: &v2store.NodeExtern{ - Key: nodePath, - Value: v, - Dir: dir, - ModifiedIndex: mkV2Rev(resp.Header.Revision), - CreatedIndex: mkV2Rev(resp.Header.Revision), - }, - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) CompareAndSwap( - nodePath string, - prevValue string, - prevIndex uint64, - value string, - expireOpts v2store.TTLOptionSet, -) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - if expireOpts.Refresh || !expireOpts.ExpireTime.IsZero() { - return nil, errUnsupported - } - - key := s.mkPath(nodePath) - resp, err := s.c.Txn(s.ctx).If( - s.mkCompare(nodePath, prevValue, prevIndex)..., - ).Then( - clientv3.OpPut(key, value, clientv3.WithPrevKV()), - clientv3.OpPut(s.mkActionKey(), v2store.CompareAndSwap), - ).Else( - clientv3.OpGet(key), - clientv3.OpGet(key+"/"), - ).Commit() - - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, compareFail(nodePath, prevValue, prevIndex, resp) - } - - pkv := resp.Responses[0].GetResponsePut().PrevKv - return &v2store.Event{ - Action: v2store.CompareAndSwap, - Node: &v2store.NodeExtern{ - Key: nodePath, - Value: &value, - CreatedIndex: mkV2Rev(pkv.CreateRevision), - ModifiedIndex: mkV2Rev(resp.Header.Revision), - }, - PrevNode: s.mkV2Node(pkv), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) Delete(nodePath string, dir, recursive bool) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - if !dir && !recursive { - return s.deleteNode(nodePath) - } - if !recursive { - return s.deleteEmptyDir(nodePath) - } - - dels := make([]clientv3.Op, maxPathDepth+1) - dels[0] = clientv3.OpDelete(s.mkPath(nodePath)+"/", clientv3.WithPrevKV()) - for i := 1; i < maxPathDepth; i++ { - dels[i] = clientv3.OpDelete(s.mkPathDepth(nodePath, i), clientv3.WithPrefix()) - } - dels[maxPathDepth] = clientv3.OpPut(s.mkActionKey(), v2store.Delete) - - resp, err := s.c.Txn(s.ctx).If( - clientv3.Compare(clientv3.Version(s.mkPath(nodePath)+"/"), ">", 0), - clientv3.Compare(clientv3.Version(s.mkPathDepth(nodePath, maxPathDepth)+"/"), "=", 0), - ).Then( - dels..., - ).Commit() - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, v2error.NewError(v2error.EcodeNodeExist, nodePath, mkV2Rev(resp.Header.Revision)) - } - dresp := resp.Responses[0].GetResponseDeleteRange() - return &v2store.Event{ - Action: v2store.Delete, - PrevNode: s.mkV2Node(dresp.PrevKvs[0]), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) deleteEmptyDir(nodePath string) (*v2store.Event, error) { - resp, err := s.c.Txn(s.ctx).If( - clientv3.Compare(clientv3.Version(s.mkPathDepth(nodePath, 1)), "=", 0).WithPrefix(), - ).Then( - clientv3.OpDelete(s.mkPath(nodePath)+"/", clientv3.WithPrevKV()), - clientv3.OpPut(s.mkActionKey(), v2store.Delete), - ).Commit() - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, v2error.NewError(v2error.EcodeDirNotEmpty, nodePath, mkV2Rev(resp.Header.Revision)) - } - dresp := resp.Responses[0].GetResponseDeleteRange() - if len(dresp.PrevKvs) == 0 { - return nil, v2error.NewError(v2error.EcodeNodeExist, nodePath, mkV2Rev(resp.Header.Revision)) - } - return &v2store.Event{ - Action: v2store.Delete, - PrevNode: s.mkV2Node(dresp.PrevKvs[0]), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) deleteNode(nodePath string) (*v2store.Event, error) { - resp, err := s.c.Txn(s.ctx).If( - clientv3.Compare(clientv3.Version(s.mkPath(nodePath)+"/"), "=", 0), - ).Then( - clientv3.OpDelete(s.mkPath(nodePath), clientv3.WithPrevKV()), - clientv3.OpPut(s.mkActionKey(), v2store.Delete), - ).Commit() - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, v2error.NewError(v2error.EcodeNotFile, nodePath, mkV2Rev(resp.Header.Revision)) - } - pkvs := resp.Responses[0].GetResponseDeleteRange().PrevKvs - if len(pkvs) == 0 { - return nil, v2error.NewError(v2error.EcodeKeyNotFound, nodePath, mkV2Rev(resp.Header.Revision)) - } - pkv := pkvs[0] - return &v2store.Event{ - Action: v2store.Delete, - Node: &v2store.NodeExtern{ - Key: nodePath, - CreatedIndex: mkV2Rev(pkv.CreateRevision), - ModifiedIndex: mkV2Rev(resp.Header.Revision), - }, - PrevNode: s.mkV2Node(pkv), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func (s *v2v3Store) CompareAndDelete(nodePath, prevValue string, prevIndex uint64) (*v2store.Event, error) { - if isRoot(nodePath) { - return nil, v2error.NewError(v2error.EcodeRootROnly, nodePath, 0) - } - - key := s.mkPath(nodePath) - resp, err := s.c.Txn(s.ctx).If( - s.mkCompare(nodePath, prevValue, prevIndex)..., - ).Then( - clientv3.OpDelete(key, clientv3.WithPrevKV()), - clientv3.OpPut(s.mkActionKey(), v2store.CompareAndDelete), - ).Else( - clientv3.OpGet(key), - clientv3.OpGet(key+"/"), - ).Commit() - - if err != nil { - return nil, err - } - if !resp.Succeeded { - return nil, compareFail(nodePath, prevValue, prevIndex, resp) - } - - // len(pkvs) > 1 since txn only succeeds when key exists - pkv := resp.Responses[0].GetResponseDeleteRange().PrevKvs[0] - return &v2store.Event{ - Action: v2store.CompareAndDelete, - Node: &v2store.NodeExtern{ - Key: nodePath, - CreatedIndex: mkV2Rev(pkv.CreateRevision), - ModifiedIndex: mkV2Rev(resp.Header.Revision), - }, - PrevNode: s.mkV2Node(pkv), - EtcdIndex: mkV2Rev(resp.Header.Revision), - }, nil -} - -func compareFail(nodePath, prevValue string, prevIndex uint64, resp *clientv3.TxnResponse) error { - if dkvs := resp.Responses[1].GetResponseRange().Kvs; len(dkvs) > 0 { - return v2error.NewError(v2error.EcodeNotFile, nodePath, mkV2Rev(resp.Header.Revision)) - } - kvs := resp.Responses[0].GetResponseRange().Kvs - if len(kvs) == 0 { - return v2error.NewError(v2error.EcodeKeyNotFound, nodePath, mkV2Rev(resp.Header.Revision)) - } - kv := kvs[0] - indexMatch := prevIndex == 0 || kv.ModRevision == int64(prevIndex) - valueMatch := prevValue == "" || string(kv.Value) == prevValue - var cause string - switch { - case indexMatch && !valueMatch: - cause = fmt.Sprintf("[%v != %v]", prevValue, string(kv.Value)) - case valueMatch && !indexMatch: - cause = fmt.Sprintf("[%v != %v]", prevIndex, kv.ModRevision) - default: - cause = fmt.Sprintf("[%v != %v] [%v != %v]", prevValue, string(kv.Value), prevIndex, kv.ModRevision) - } - return v2error.NewError(v2error.EcodeTestFailed, cause, mkV2Rev(resp.Header.Revision)) -} - -func (s *v2v3Store) mkCompare(nodePath, prevValue string, prevIndex uint64) []clientv3.Cmp { - key := s.mkPath(nodePath) - cmps := []clientv3.Cmp{clientv3.Compare(clientv3.Version(key), ">", 0)} - if prevIndex != 0 { - cmps = append(cmps, clientv3.Compare(clientv3.ModRevision(key), "=", mkV3Rev(prevIndex))) - } - if prevValue != "" { - cmps = append(cmps, clientv3.Compare(clientv3.Value(key), "=", prevValue)) - } - return cmps -} - -func (s *v2v3Store) JsonStats() []byte { panic("STUB") } -func (s *v2v3Store) DeleteExpiredKeys(cutoff time.Time) { panic("STUB") } - -func (s *v2v3Store) Version() int { return 2 } - -// TODO: move this out of the Store interface? - -func (s *v2v3Store) Save() ([]byte, error) { panic("STUB") } -func (s *v2v3Store) Recovery(state []byte) error { panic("STUB") } -func (s *v2v3Store) Clone() v2store.Store { panic("STUB") } -func (s *v2v3Store) SaveNoCopy() ([]byte, error) { panic("STUB") } -func (s *v2v3Store) HasTTLKeys() bool { panic("STUB") } - -func (s *v2v3Store) mkPath(nodePath string) string { return s.mkPathDepth(nodePath, 0) } - -func (s *v2v3Store) mkNodePath(p string) string { - return path.Clean(p[len(s.pfx)+len("/k/000/"):]) -} - -// mkPathDepth makes a path to a key that encodes its directory depth -// for fast directory listing. If a depth is provided, it is added -// to the computed depth. -func (s *v2v3Store) mkPathDepth(nodePath string, depth int) string { - normalForm := path.Clean(path.Join("/", nodePath)) - n := strings.Count(normalForm, "/") + depth - return fmt.Sprintf("%s/%03d/k/%s", s.pfx, n, normalForm) -} - -func (s *v2v3Store) mkActionKey() string { return s.pfx + "/act" } - -func isRoot(s string) bool { return len(s) == 0 || s == "/" || s == "/0" || s == "/1" } - -func mkV2Rev(v3Rev int64) uint64 { - if v3Rev == 0 { - return 0 - } - return uint64(v3Rev - 1) -} - -func mkV3Rev(v2Rev uint64) int64 { - if v2Rev == 0 { - return 0 - } - return int64(v2Rev + 1) -} - -// mkV2Node creates a V2 NodeExtern from a V3 KeyValue -func (s *v2v3Store) mkV2Node(kv *mvccpb.KeyValue) *v2store.NodeExtern { - if kv == nil { - return nil - } - n := &v2store.NodeExtern{ - Key: s.mkNodePath(string(kv.Key)), - Dir: kv.Key[len(kv.Key)-1] == '/', - CreatedIndex: mkV2Rev(kv.CreateRevision), - ModifiedIndex: mkV2Rev(kv.ModRevision), - } - if !n.Dir { - v := string(kv.Value) - n.Value = &v - } - return n -} - -// prevKeyFromPuts gets the prev key that is being put; ignores -// the put action response. -func prevKeyFromPuts(resp *clientv3.TxnResponse) *mvccpb.KeyValue { - for _, r := range resp.Responses { - pkv := r.GetResponsePut().PrevKv - if pkv != nil && pkv.CreateRevision > 0 { - return pkv - } - } - return nil -} - -func (s *v2v3Store) newSTM(applyf func(concurrency.STM) error) (*clientv3.TxnResponse, error) { - return concurrency.NewSTM(s.c, applyf, concurrency.WithIsolation(concurrency.Serializable)) -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/watcher.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/watcher.go deleted file mode 100644 index 046c25d450..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/watcher.go +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2017 The etcd 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 v2v3 - -import ( - "context" - "strings" - - "go.etcd.io/etcd/client/v3" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2error" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" -) - -func (s *v2v3Store) Watch(prefix string, recursive, stream bool, sinceIndex uint64) (v2store.Watcher, error) { - ctx, cancel := context.WithCancel(s.ctx) - wch := s.c.Watch( - ctx, - // TODO: very pricey; use a single store-wide watch in future - s.pfx, - clientv3.WithPrefix(), - clientv3.WithRev(int64(sinceIndex)), - clientv3.WithCreatedNotify(), - clientv3.WithPrevKV()) - resp, ok := <-wch - if err := resp.Err(); err != nil || !ok { - cancel() - return nil, v2error.NewError(v2error.EcodeRaftInternal, prefix, 0) - } - - evc, donec := make(chan *v2store.Event), make(chan struct{}) - go func() { - defer func() { - close(evc) - close(donec) - }() - for resp := range wch { - for _, ev := range s.mkV2Events(resp) { - k := ev.Node.Key - if recursive { - if !strings.HasPrefix(k, prefix) { - continue - } - // accept events on hidden keys given in prefix - k = strings.Replace(k, prefix, "/", 1) - // ignore hidden keys deeper than prefix - if strings.Contains(k, "/_") { - continue - } - } - if !recursive && k != prefix { - continue - } - select { - case evc <- ev: - case <-ctx.Done(): - return - } - if !stream { - return - } - } - } - }() - - return &v2v3Watcher{ - startRev: resp.Header.Revision, - evc: evc, - donec: donec, - cancel: cancel, - }, nil -} - -func (s *v2v3Store) mkV2Events(wr clientv3.WatchResponse) (evs []*v2store.Event) { - ak := s.mkActionKey() - for _, rev := range mkRevs(wr) { - var act, key *clientv3.Event - for _, ev := range rev { - if string(ev.Kv.Key) == ak { - act = ev - } else if key != nil && len(key.Kv.Key) < len(ev.Kv.Key) { - // use longest key to ignore intermediate new - // directories from Create. - key = ev - } else if key == nil { - key = ev - } - } - if act != nil && act.Kv != nil && key != nil { - v2ev := &v2store.Event{ - Action: string(act.Kv.Value), - Node: s.mkV2Node(key.Kv), - PrevNode: s.mkV2Node(key.PrevKv), - EtcdIndex: mkV2Rev(wr.Header.Revision), - } - evs = append(evs, v2ev) - } - } - return evs -} - -func mkRevs(wr clientv3.WatchResponse) (revs [][]*clientv3.Event) { - var curRev []*clientv3.Event - for _, ev := range wr.Events { - if curRev != nil && ev.Kv.ModRevision != curRev[0].Kv.ModRevision { - revs = append(revs, curRev) - curRev = nil - } - curRev = append(curRev, ev) - } - if curRev != nil { - revs = append(revs, curRev) - } - return revs -} - -type v2v3Watcher struct { - startRev int64 - evc chan *v2store.Event - donec chan struct{} - cancel context.CancelFunc -} - -func (w *v2v3Watcher) StartIndex() uint64 { return mkV2Rev(w.startRev) } - -func (w *v2v3Watcher) Remove() { - w.cancel() - <-w.donec -} - -func (w *v2v3Watcher) EventChan() chan *v2store.Event { return w.evc } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm/alarms.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm/alarms.go index 5d4a641cea..bf17929d79 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm/alarms.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm/alarms.go @@ -18,12 +18,12 @@ package v3alarm import ( "sync" + "go.uber.org/zap" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" - - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" ) type BackendGetter interface { @@ -38,14 +38,14 @@ type AlarmStore struct { mu sync.Mutex types map[pb.AlarmType]alarmSet - bg BackendGetter + be schema.AlarmBackend } -func NewAlarmStore(lg *zap.Logger, bg BackendGetter) (*AlarmStore, error) { +func NewAlarmStore(lg *zap.Logger, be schema.AlarmBackend) (*AlarmStore, error) { if lg == nil { lg = zap.NewNop() } - ret := &AlarmStore{lg: lg, types: make(map[pb.AlarmType]alarmSet), bg: bg} + ret := &AlarmStore{lg: lg, types: make(map[pb.AlarmType]alarmSet), be: be} err := ret.restore() return ret, err } @@ -59,16 +59,7 @@ func (a *AlarmStore) Activate(id types.ID, at pb.AlarmType) *pb.AlarmMember { return m } - v, err := newAlarm.Marshal() - if err != nil { - a.lg.Panic("failed to marshal alarm member", zap.Error(err)) - } - - b := a.bg.Backend() - b.BatchTx().LockInsideApply() - b.BatchTx().UnsafePut(buckets.Alarm, v, nil) - b.BatchTx().Unlock() - + a.be.MustPutAlarm(newAlarm) return newAlarm } @@ -88,16 +79,7 @@ func (a *AlarmStore) Deactivate(id types.ID, at pb.AlarmType) *pb.AlarmMember { delete(t, id) - v, err := m.Marshal() - if err != nil { - a.lg.Panic("failed to marshal alarm member", zap.Error(err)) - } - - b := a.bg.Backend() - b.BatchTx().LockInsideApply() - b.BatchTx().UnsafeDelete(buckets.Alarm, v) - b.BatchTx().Unlock() - + a.be.MustDeleteAlarm(m) return m } @@ -119,22 +101,15 @@ func (a *AlarmStore) Get(at pb.AlarmType) (ret []*pb.AlarmMember) { } func (a *AlarmStore) restore() error { - b := a.bg.Backend() - tx := b.BatchTx() - - tx.LockOutsideApply() - tx.UnsafeCreateBucket(buckets.Alarm) - err := tx.UnsafeForEach(buckets.Alarm, func(k, v []byte) error { - var m pb.AlarmMember - if err := m.Unmarshal(k); err != nil { - return err - } - a.addToMap(&m) - return nil - }) - tx.Unlock() - - b.ForceCommit() + a.be.CreateAlarmBucket() + ms, err := a.be.GetAllAlarms() + if err != nil { + return err + } + for _, m := range ms { + a.addToMap(m) + } + a.be.ForceCommit() return err } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/v3client.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/v3client.go index de0da81afb..b9d18399f2 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/v3client.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3client/v3client.go @@ -18,7 +18,7 @@ import ( "context" "time" - "go.etcd.io/etcd/client/v3" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc" "go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter" diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/compactor.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/compactor.go index e352670c12..f916e71141 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/compactor.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/compactor.go @@ -19,10 +19,10 @@ import ( "fmt" "time" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "github.com/jonboulle/clockwork" "go.uber.org/zap" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) const ( diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/periodic.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/periodic.go index 083c72ede2..7468d230b8 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/periodic.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/periodic.go @@ -16,14 +16,15 @@ package v3compactor import ( "context" + "errors" "sync" "time" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/server/v3/mvcc" - "github.com/jonboulle/clockwork" "go.uber.org/zap" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/server/v3/storage/mvcc" ) // Periodic compacts the log by purging revisions older than @@ -54,8 +55,9 @@ func newPeriodic(lg *zap.Logger, clock clockwork.Clock, h time.Duration, rg RevG period: h, rg: rg, c: c, - revs: make([]int64, 0), } + // revs won't be longer than the retentions. + pc.revs = make([]int64, 0, pc.getRetentions()) pc.ctx, pc.cancel = context.WithCancel(context.Background()) return pc } @@ -66,23 +68,23 @@ Compaction period 1-hour: 2. record revisions for every 1/10 of 1-hour (6-minute) 3. keep recording revisions with no compaction for first 1-hour 4. do compact with revs[0] - - success? contiue on for-loop and move sliding window; revs = revs[1:] + - success? continue on for-loop and move sliding window; revs = revs[1:] - failure? update revs, and retry after 1/10 of 1-hour (6-minute) Compaction period 24-hour: - 1. compute compaction period, which is 1-hour - 2. record revisions for every 1/10 of 1-hour (6-minute) + 1. compute compaction period, which is 24-hour + 2. record revisions for every 1/10 of 24-hour (144-minute) 3. keep recording revisions with no compaction for first 24-hour 4. do compact with revs[0] - - success? contiue on for-loop and move sliding window; revs = revs[1:] - - failure? update revs, and retry after 1/10 of 1-hour (6-minute) + - success? continue on for-loop and move sliding window; revs = revs[1:] + - failure? update revs, and retry after 1/10 of 24-hour (144-minute) Compaction period 59-min: 1. compute compaction period, which is 59-min 2. record revisions for every 1/10 of 59-min (5.9-min) 3. keep recording revisions with no compaction for first 59-min 4. do compact with revs[0] - - success? contiue on for-loop and move sliding window; revs = revs[1:] + - success? continue on for-loop and move sliding window; revs = revs[1:] - failure? update revs, and retry after 1/10 of 59-min (5.9-min) Compaction period 5-sec: @@ -90,7 +92,7 @@ Compaction period 5-sec: 2. record revisions for every 1/10 of 5-sec (0.5-sec) 3. keep recording revisions with no compaction for first 5-sec 4. do compact with revs[0] - - success? contiue on for-loop and move sliding window; revs = revs[1:] + - success? continue on for-loop and move sliding window; revs = revs[1:] - failure? update revs, and retry after 1/10 of 5-sec (0.5-sec) */ @@ -101,6 +103,7 @@ func (pc *Periodic) Run() { retentions := pc.getRetentions() go func() { + lastRevision := int64(0) lastSuccess := pc.clock.Now() baseInterval := pc.period for { @@ -113,15 +116,15 @@ func (pc *Periodic) Run() { case <-pc.ctx.Done(): return case <-pc.clock.After(retryInterval): - pc.mu.Lock() + pc.mu.RLock() p := pc.paused - pc.mu.Unlock() + pc.mu.RUnlock() if p { continue } } - - if pc.clock.Now().Sub(lastSuccess) < baseInterval { + rev := pc.revs[0] + if pc.clock.Now().Sub(lastSuccess) < baseInterval || rev == lastRevision { continue } @@ -129,7 +132,6 @@ func (pc *Periodic) Run() { if baseInterval == pc.period { baseInterval = compactInterval } - rev := pc.revs[0] pc.lg.Info( "starting auto periodic compaction", @@ -138,13 +140,14 @@ func (pc *Periodic) Run() { ) startTime := pc.clock.Now() _, err := pc.c.Compact(pc.ctx, &pb.CompactionRequest{Revision: rev}) - if err == nil || err == mvcc.ErrCompacted { + if err == nil || errors.Is(err, mvcc.ErrCompacted) { pc.lg.Info( "completed auto periodic compaction", zap.Int64("revision", rev), zap.Duration("compact-period", pc.period), zap.Duration("took", pc.clock.Now().Sub(startTime)), ) + lastRevision = rev lastSuccess = pc.clock.Now() } else { pc.lg.Warn( diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/revision.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/revision.go index 83be627947..4174861690 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/revision.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor/revision.go @@ -16,14 +16,15 @@ package v3compactor import ( "context" + "errors" "sync" "time" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/server/v3/mvcc" - "github.com/jonboulle/clockwork" "go.uber.org/zap" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/server/v3/storage/mvcc" ) // Revision compacts the log by purging revisions older than @@ -89,7 +90,7 @@ func (rc *Revision) Run() { zap.Int64("revision-compaction-retention", rc.retention), ) _, err := rc.c.Compact(rc.ctx, &pb.CompactionRequest{Revision: rev}) - if err == nil || err == mvcc.ErrCompacted { + if err == nil || errors.Is(err, mvcc.ErrCompacted) { prev = rev rc.lg.Info( "completed auto revision compaction", diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery/discovery.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery/discovery.go new file mode 100644 index 0000000000..7fe231cdb5 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery/discovery.go @@ -0,0 +1,509 @@ +// Copyright 2022 The etcd 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 v3discovery provides an implementation of the cluster discovery that +// is used by etcd with v3 client. +package v3discovery + +import ( + "context" + "errors" + "math" + "path" + "sort" + "strconv" + "strings" + "time" + + "github.com/jonboulle/clockwork" + "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/types" + clientv3 "go.etcd.io/etcd/client/v3" +) + +const ( + discoveryPrefix = "/_etcd/registry" +) + +var ( + ErrInvalidURL = errors.New("discovery: invalid peer URL") + ErrBadSizeKey = errors.New("discovery: size key is bad") + ErrSizeNotFound = errors.New("discovery: size key not found") + ErrFullCluster = errors.New("discovery: cluster is full") + ErrTooManyRetries = errors.New("discovery: too many retries") +) + +var ( + // Number of retries discovery will attempt before giving up and error out. + nRetries = uint(math.MaxUint32) + maxExponentialRetries = uint(8) +) + +type DiscoveryConfig struct { + clientv3.ConfigSpec `json:"client"` + Token string `json:"token"` +} + +type memberInfo struct { + // peerRegKey is the key used by the member when registering in the + // discovery service. + // Format: "/_etcd/registry//members/". + peerRegKey string + // peerURLsMap format: "peerName=peerURLs", i.e., "member1=http://127.0.0.1:2380". + peerURLsMap string + // createRev is the member's CreateRevision in the etcd cluster backing + // the discovery service. + createRev int64 +} + +type clusterInfo struct { + clusterToken string + members []memberInfo +} + +// key prefix for each cluster: "/_etcd/registry/". +func getClusterKeyPrefix(cluster string) string { + return path.Join(discoveryPrefix, cluster) +} + +// key format for cluster size: "/_etcd/registry//_config/size". +func getClusterSizeKey(cluster string) string { + return path.Join(getClusterKeyPrefix(cluster), "_config/size") +} + +// key prefix for each member: "/_etcd/registry//members". +func getMemberKeyPrefix(clusterToken string) string { + return path.Join(getClusterKeyPrefix(clusterToken), "members") +} + +// key format for each member: "/_etcd/registry//members/". +func getMemberKey(cluster, memberID string) string { + return path.Join(getMemberKeyPrefix(cluster), memberID) +} + +// GetCluster will connect to the discovery service at the given endpoints and +// retrieve a string describing the cluster +func GetCluster(lg *zap.Logger, cfg *DiscoveryConfig) (cs string, rerr error) { + d, err := newDiscovery(lg, cfg, 0) + if err != nil { + return "", err + } + + defer d.close() + defer func() { + if rerr != nil { + d.lg.Error( + "discovery failed to get cluster", + zap.String("cluster", cs), + zap.Error(rerr), + ) + } else { + d.lg.Info( + "discovery got cluster successfully", + zap.String("cluster", cs), + ) + } + }() + + return d.getCluster() +} + +// JoinCluster will connect to the discovery service at the endpoints, and +// register the server represented by the given id and config to the cluster. +// The parameter `config` is supposed to be in the format "memberName=peerURLs", +// such as "member1=http://127.0.0.1:2380". +// +// The final returned string has the same format as "--initial-cluster", such as +// "infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380". +func JoinCluster(lg *zap.Logger, cfg *DiscoveryConfig, id types.ID, config string) (cs string, rerr error) { + d, err := newDiscovery(lg, cfg, id) + if err != nil { + return "", err + } + + defer d.close() + defer func() { + if rerr != nil { + d.lg.Error( + "discovery failed to join cluster", + zap.String("cluster", cs), + zap.Error(rerr), + ) + } else { + d.lg.Info( + "discovery joined cluster successfully", + zap.String("cluster", cs), + ) + } + }() + + return d.joinCluster(config) +} + +type discovery struct { + lg *zap.Logger + clusterToken string + memberID types.ID + c *clientv3.Client + retries uint + + cfg *DiscoveryConfig + + clock clockwork.Clock +} + +func newDiscovery(lg *zap.Logger, dcfg *DiscoveryConfig, id types.ID) (*discovery, error) { + if lg == nil { + lg = zap.NewNop() + } + + lg = lg.With(zap.String("discovery-token", dcfg.Token), zap.String("discovery-endpoints", strings.Join(dcfg.Endpoints, ","))) + cfg, err := clientv3.NewClientConfig(&dcfg.ConfigSpec, lg) + if err != nil { + return nil, err + } + + c, err := clientv3.New(*cfg) + if err != nil { + return nil, err + } + return &discovery{ + lg: lg, + clusterToken: dcfg.Token, + memberID: id, + c: c, + cfg: dcfg, + clock: clockwork.NewRealClock(), + }, nil +} + +func (d *discovery) getCluster() (string, error) { + cls, clusterSize, rev, err := d.checkCluster() + if err != nil { + if errors.Is(err, ErrFullCluster) { + return cls.getInitClusterStr(clusterSize) + } + return "", err + } + + for cls.Len() < clusterSize { + d.waitPeers(cls, clusterSize, rev) + } + + return cls.getInitClusterStr(clusterSize) +} + +func (d *discovery) joinCluster(config string) (string, error) { + _, _, _, err := d.checkCluster() + if err != nil { + return "", err + } + + if err = d.registerSelf(config); err != nil { + return "", err + } + + cls, clusterSize, rev, err := d.checkCluster() + if err != nil { + return "", err + } + + for cls.Len() < clusterSize { + d.waitPeers(cls, clusterSize, rev) + } + + return cls.getInitClusterStr(clusterSize) +} + +func (d *discovery) getClusterSize() (int, error) { + configKey := getClusterSizeKey(d.clusterToken) + ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeout) + defer cancel() + + resp, err := d.c.Get(ctx, configKey) + if err != nil { + d.lg.Warn( + "failed to get cluster size from discovery service", + zap.String("clusterSizeKey", configKey), + zap.Error(err), + ) + return 0, err + } + + if len(resp.Kvs) == 0 { + return 0, ErrSizeNotFound + } + + clusterSize, err := strconv.ParseInt(string(resp.Kvs[0].Value), 10, 0) + if err != nil || clusterSize <= 0 { + return 0, ErrBadSizeKey + } + + return int(clusterSize), nil +} + +func (d *discovery) getClusterMembers() (*clusterInfo, int64, error) { + membersKeyPrefix := getMemberKeyPrefix(d.clusterToken) + ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeout) + defer cancel() + + resp, err := d.c.Get(ctx, membersKeyPrefix, clientv3.WithPrefix()) + if err != nil { + d.lg.Warn( + "failed to get cluster members from discovery service", + zap.String("membersKeyPrefix", membersKeyPrefix), + zap.Error(err), + ) + return nil, 0, err + } + + cls := &clusterInfo{clusterToken: d.clusterToken} + for _, kv := range resp.Kvs { + mKey := strings.TrimSpace(string(kv.Key)) + mValue := strings.TrimSpace(string(kv.Value)) + + if err := cls.add(mKey, mValue, kv.CreateRevision); err != nil { + d.lg.Warn( + err.Error(), + zap.String("memberKey", mKey), + zap.String("memberInfo", mValue), + ) + } else { + d.lg.Info( + "found peer from discovery service", + zap.String("memberKey", mKey), + zap.String("memberInfo", mValue), + ) + } + } + + return cls, resp.Header.Revision, nil +} + +func (d *discovery) checkClusterRetry() (*clusterInfo, int, int64, error) { + if d.retries < nRetries { + d.logAndBackoffForRetry("cluster status check") + return d.checkCluster() + } + return nil, 0, 0, ErrTooManyRetries +} + +func (d *discovery) checkCluster() (*clusterInfo, int, int64, error) { + clusterSize, err := d.getClusterSize() + if err != nil { + if errors.Is(err, ErrSizeNotFound) || errors.Is(err, ErrBadSizeKey) { + return nil, 0, 0, err + } + + return d.checkClusterRetry() + } + + cls, rev, err := d.getClusterMembers() + if err != nil { + return d.checkClusterRetry() + } + d.retries = 0 + + // find self position + memberSelfID := getMemberKey(d.clusterToken, d.memberID.String()) + idx := 0 + for _, m := range cls.members { + if m.peerRegKey == memberSelfID { + break + } + if idx >= clusterSize-1 { + return cls, clusterSize, rev, ErrFullCluster + } + idx++ + } + return cls, clusterSize, rev, nil +} + +func (d *discovery) registerSelfRetry(contents string) error { + if d.retries < nRetries { + d.logAndBackoffForRetry("register member itself") + return d.registerSelf(contents) + } + return ErrTooManyRetries +} + +func (d *discovery) registerSelf(contents string) error { + ctx, cancel := context.WithTimeout(context.Background(), d.cfg.RequestTimeout) + memberKey := getMemberKey(d.clusterToken, d.memberID.String()) + _, err := d.c.Put(ctx, memberKey, contents) + cancel() + + if err != nil { + d.lg.Warn( + "failed to register members itself to the discovery service", + zap.String("memberKey", memberKey), + zap.Error(err), + ) + return d.registerSelfRetry(contents) + } + d.retries = 0 + + d.lg.Info( + "register member itself successfully", + zap.String("memberKey", memberKey), + zap.String("memberInfo", contents), + ) + + return nil +} + +func (d *discovery) waitPeers(cls *clusterInfo, clusterSize int, rev int64) { + // watch from the next revision + membersKeyPrefix := getMemberKeyPrefix(d.clusterToken) + w := d.c.Watch(context.Background(), membersKeyPrefix, clientv3.WithPrefix(), clientv3.WithRev(rev+1)) + + d.lg.Info( + "waiting for peers from discovery service", + zap.Int("clusterSize", clusterSize), + zap.Int("found-peers", cls.Len()), + ) + + // waiting for peers until all needed peers are returned + for wresp := range w { + for _, ev := range wresp.Events { + mKey := strings.TrimSpace(string(ev.Kv.Key)) + mValue := strings.TrimSpace(string(ev.Kv.Value)) + + if err := cls.add(mKey, mValue, ev.Kv.CreateRevision); err != nil { + d.lg.Warn( + err.Error(), + zap.String("memberKey", mKey), + zap.String("memberInfo", mValue), + ) + } else { + d.lg.Info( + "found peer from discovery service", + zap.String("memberKey", mKey), + zap.String("memberInfo", mValue), + ) + } + } + + if cls.Len() >= clusterSize { + break + } + } + + d.lg.Info( + "found all needed peers from discovery service", + zap.Int("clusterSize", clusterSize), + zap.Int("found-peers", cls.Len()), + ) +} + +func (d *discovery) logAndBackoffForRetry(step string) { + d.retries++ + // logAndBackoffForRetry stops exponential backoff when the retries are + // more than maxExpoentialRetries and is set to a constant backoff afterward. + retries := d.retries + if retries > maxExponentialRetries { + retries = maxExponentialRetries + } + retryTimeInSecond := time.Duration(0x1< clusterSize { + peerURLs = peerURLs[:clusterSize] + } + + us := strings.Join(peerURLs, ",") + _, err := types.NewURLsMap(us) + if err != nil { + return us, ErrInvalidURL + } + + return us, nil +} + +func (cls *clusterInfo) getPeerURLs() []string { + var peerURLs []string + for _, peer := range cls.members { + peerURLs = append(peerURLs, peer.peerURLsMap) + } + return peerURLs +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/election.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/election.go index 78b26ad7cc..77a9c4bcb4 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/election.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/election.go @@ -18,7 +18,7 @@ import ( "context" "errors" - "go.etcd.io/etcd/client/v3" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/client/v3/concurrency" epb "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb" ) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go index 4a6e5e724c..912149f5ab 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw/v3election.pb.gw.go @@ -9,143 +9,115 @@ It translates gRPC into RESTful JSON APIs. package gw import ( + protov1 "github.com/golang/protobuf/proto" + "context" + "errors" "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb" "io" "net/http" - "github.com/golang/protobuf/descriptor" - "github.com/golang/protobuf/proto" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/grpc-ecosystem/grpc-gateway/utilities" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_Election_Campaign_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3electionpb.CampaignRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3electionpb.CampaignRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Campaign(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Election_Campaign_0(ctx context.Context, marshaler runtime.Marshaler, server v3electionpb.ElectionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3electionpb.CampaignRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3electionpb.CampaignRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Campaign(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Election_Proclaim_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3electionpb.ProclaimRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3electionpb.ProclaimRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Proclaim(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Election_Proclaim_0(ctx context.Context, marshaler runtime.Marshaler, server v3electionpb.ElectionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3electionpb.ProclaimRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3electionpb.ProclaimRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Proclaim(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Election_Leader_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3electionpb.LeaderRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3electionpb.LeaderRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Leader(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Election_Leader_0(ctx context.Context, marshaler runtime.Marshaler, server v3electionpb.ElectionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3electionpb.LeaderRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3electionpb.LeaderRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Leader(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Election_Observe_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (v3electionpb.Election_ObserveClient, runtime.ServerMetadata, error) { - var protoReq v3electionpb.LeaderRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3electionpb.LeaderRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - stream, err := client.Observe(ctx, &protoReq) if err != nil { return nil, metadata, err @@ -156,133 +128,124 @@ func request_Election_Observe_0(ctx context.Context, marshaler runtime.Marshaler } metadata.HeaderMD = header return stream, metadata, nil - } func request_Election_Resign_0(ctx context.Context, marshaler runtime.Marshaler, client v3electionpb.ElectionClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3electionpb.ResignRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3electionpb.ResignRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Resign(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Election_Resign_0(ctx context.Context, marshaler runtime.Marshaler, server v3electionpb.ElectionServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3electionpb.ResignRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3electionpb.ResignRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Resign(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } // v3electionpb.RegisterElectionHandlerServer registers the http handlers for service Election to "mux". // UnaryRPC :call v3electionpb.ElectionServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterElectionHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterElectionHandlerServer(ctx context.Context, mux *runtime.ServeMux, server v3electionpb.ElectionServer) error { - - mux.Handle("POST", pattern_Election_Campaign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Campaign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/v3electionpb.Election/Campaign", runtime.WithHTTPPathPattern("/v3/election/campaign")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Election_Campaign_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Election_Campaign_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Election_Campaign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Election_Campaign_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Election_Proclaim_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Proclaim_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/v3electionpb.Election/Proclaim", runtime.WithHTTPPathPattern("/v3/election/proclaim")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Election_Proclaim_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Election_Proclaim_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Election_Proclaim_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Election_Proclaim_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Election_Leader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Leader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/v3electionpb.Election/Leader", runtime.WithHTTPPathPattern("/v3/election/leader")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Election_Leader_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Election_Leader_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Election_Leader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Election_Leader_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - mux.Handle("POST", pattern_Election_Observe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Observe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return }) - - mux.Handle("POST", pattern_Election_Resign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Resign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/v3electionpb.Election/Resign", runtime.WithHTTPPathPattern("/v3/election/resign")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Election_Resign_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Election_Resign_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Election_Resign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Election_Resign_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) return nil @@ -291,25 +254,24 @@ func RegisterElectionHandlerServer(ctx context.Context, mux *runtime.ServeMux, s // RegisterElectionHandlerFromEndpoint is same as RegisterElectionHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterElectionHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.NewClient(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } }() }() - return RegisterElectionHandler(ctx, mux, conn) } @@ -323,132 +285,111 @@ func RegisterElectionHandler(ctx context.Context, mux *runtime.ServeMux, conn *g // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ElectionClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ElectionClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "ElectionClient" to call the correct interceptors. +// "ElectionClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterElectionHandlerClient(ctx context.Context, mux *runtime.ServeMux, client v3electionpb.ElectionClient) error { - - mux.Handle("POST", pattern_Election_Campaign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Campaign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/v3electionpb.Election/Campaign", runtime.WithHTTPPathPattern("/v3/election/campaign")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Election_Campaign_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Election_Campaign_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Election_Campaign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Election_Campaign_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Election_Proclaim_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Proclaim_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/v3electionpb.Election/Proclaim", runtime.WithHTTPPathPattern("/v3/election/proclaim")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Election_Proclaim_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Election_Proclaim_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Election_Proclaim_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Election_Proclaim_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Election_Leader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Leader_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/v3electionpb.Election/Leader", runtime.WithHTTPPathPattern("/v3/election/leader")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Election_Leader_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Election_Leader_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Election_Leader_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Election_Leader_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Election_Observe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Observe_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/v3electionpb.Election/Observe", runtime.WithHTTPPathPattern("/v3/election/observe")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Election_Observe_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Election_Observe_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Election_Observe_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...) - + forward_Election_Observe_0(annotatedContext, mux, outboundMarshaler, w, req, func() (proto.Message, error) { + m1, err := resp.Recv() + return protov1.MessageV2(m1), err + }, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Election_Resign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Election_Resign_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/v3electionpb.Election/Resign", runtime.WithHTTPPathPattern("/v3/election/resign")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Election_Resign_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Election_Resign_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Election_Resign_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Election_Resign_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - return nil } var ( - pattern_Election_Campaign_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "campaign"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Election_Proclaim_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "proclaim"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Election_Leader_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "leader"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Election_Observe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "observe"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Election_Resign_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "resign"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Election_Campaign_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "campaign"}, "")) + pattern_Election_Proclaim_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "proclaim"}, "")) + pattern_Election_Leader_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "leader"}, "")) + pattern_Election_Observe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "observe"}, "")) + pattern_Election_Resign_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "election", "resign"}, "")) ) var ( forward_Election_Campaign_0 = runtime.ForwardResponseMessage - forward_Election_Proclaim_0 = runtime.ForwardResponseMessage - - forward_Election_Leader_0 = runtime.ForwardResponseMessage - - forward_Election_Observe_0 = runtime.ForwardResponseStream - - forward_Election_Resign_0 = runtime.ForwardResponseMessage + forward_Election_Leader_0 = runtime.ForwardResponseMessage + forward_Election_Observe_0 = runtime.ForwardResponseStream + forward_Election_Resign_0 = runtime.ForwardResponseMessage ) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.pb.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.pb.go index 81cf59b9b2..02369cde56 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.pb.go @@ -157,7 +157,7 @@ func (m *CampaignResponse) GetLeader() *LeaderKey { } type LeaderKey struct { - // name is the election identifier that correponds to the leadership key. + // name is the election identifier that corresponds to the leadership key. Name []byte `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // key is an opaque key representing the ownership of the election. If the key // is deleted, then leadership is lost. @@ -552,41 +552,42 @@ func init() { func init() { proto.RegisterFile("v3election.proto", fileDescriptor_c9b1f26cc432a035) } var fileDescriptor_c9b1f26cc432a035 = []byte{ - // 531 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0xcf, 0x6e, 0xd3, 0x40, - 0x10, 0xc6, 0x59, 0x27, 0x84, 0x32, 0xa4, 0xad, 0x65, 0x82, 0x08, 0x21, 0xb8, 0xd1, 0x72, 0xa9, - 0x72, 0xb0, 0x51, 0xc3, 0x29, 0x27, 0x04, 0x02, 0x55, 0x2a, 0x12, 0xe0, 0x03, 0x82, 0xe3, 0xda, - 0x1d, 0xb9, 0x91, 0x1d, 0xaf, 0xb1, 0x5d, 0x4b, 0xb9, 0xf2, 0x0a, 0x1c, 0xe0, 0x91, 0x38, 0x22, - 0xf1, 0x02, 0x28, 0xf0, 0x20, 0x68, 0x77, 0xed, 0xfa, 0x8f, 0x12, 0x84, 0x9a, 0xdb, 0x78, 0xe7, - 0xdb, 0xf9, 0xcd, 0x37, 0x3b, 0x09, 0xe8, 0xf9, 0x0c, 0x43, 0xf4, 0xb2, 0x05, 0x8f, 0xac, 0x38, - 0xe1, 0x19, 0x37, 0xfa, 0xd5, 0x49, 0xec, 0x8e, 0x06, 0x3e, 0xf7, 0xb9, 0x4c, 0xd8, 0x22, 0x52, - 0x9a, 0xd1, 0x11, 0x66, 0xde, 0xb9, 0xcd, 0xe2, 0x85, 0x2d, 0x82, 0x14, 0x93, 0x1c, 0x93, 0xd8, - 0xb5, 0x93, 0xd8, 0x2b, 0x04, 0xc3, 0x2b, 0xc1, 0x32, 0xf7, 0xbc, 0xd8, 0xb5, 0x83, 0xbc, 0xc8, - 0x8c, 0x7d, 0xce, 0xfd, 0x10, 0x65, 0x8e, 0x45, 0x11, 0xcf, 0x98, 0x20, 0xa5, 0x2a, 0x4b, 0xdf, - 0xc1, 0xe1, 0x0b, 0xb6, 0x8c, 0xd9, 0xc2, 0x8f, 0x1c, 0xfc, 0x74, 0x89, 0x69, 0x66, 0x18, 0xd0, - 0x8d, 0xd8, 0x12, 0x87, 0x64, 0x42, 0x8e, 0xfb, 0x8e, 0x8c, 0x8d, 0x01, 0xdc, 0x0c, 0x91, 0xa5, - 0x38, 0xd4, 0x26, 0xe4, 0xb8, 0xe3, 0xa8, 0x0f, 0x71, 0x9a, 0xb3, 0xf0, 0x12, 0x87, 0x1d, 0x29, - 0x55, 0x1f, 0x74, 0x05, 0x7a, 0x55, 0x32, 0x8d, 0x79, 0x94, 0xa2, 0xf1, 0x14, 0x7a, 0x17, 0xc8, - 0xce, 0x31, 0x91, 0x55, 0xef, 0x9c, 0x8c, 0xad, 0xba, 0x0f, 0xab, 0xd4, 0x9d, 0x4a, 0x8d, 0x53, - 0x68, 0x0d, 0x1b, 0x7a, 0xa1, 0xba, 0xa5, 0xc9, 0x5b, 0xf7, 0xad, 0xfa, 0xa8, 0xac, 0xd7, 0x32, - 0x77, 0x86, 0x2b, 0xa7, 0x90, 0xd1, 0x8f, 0x70, 0xfb, 0xea, 0x70, 0xa3, 0x0f, 0x1d, 0x3a, 0x01, - 0xae, 0x64, 0xb9, 0xbe, 0x23, 0x42, 0x71, 0x92, 0x60, 0x2e, 0x1d, 0x74, 0x1c, 0x11, 0x56, 0x5e, - 0xbb, 0x35, 0xaf, 0xf4, 0x31, 0xec, 0xab, 0xd2, 0xff, 0x18, 0x13, 0xbd, 0x80, 0x83, 0x52, 0xb4, - 0x93, 0xf1, 0x09, 0x68, 0x41, 0x5e, 0x98, 0xd6, 0x2d, 0xf5, 0xa2, 0xd6, 0x19, 0xae, 0xde, 0x8b, - 0x01, 0x3b, 0x5a, 0x90, 0xd3, 0x67, 0xb0, 0xef, 0x60, 0x5a, 0x7b, 0xb5, 0x6a, 0x56, 0xe4, 0xff, - 0x66, 0xf5, 0x0a, 0x0e, 0xca, 0x0a, 0xbb, 0xf4, 0x4a, 0x3f, 0xc0, 0xe1, 0xdb, 0x84, 0x7b, 0x21, - 0x5b, 0x2c, 0xaf, 0xdb, 0x4b, 0xb5, 0x48, 0x5a, 0x7d, 0x91, 0x4e, 0x41, 0xaf, 0x2a, 0xef, 0xd2, - 0xe3, 0xc9, 0xd7, 0x2e, 0xec, 0xbd, 0x2c, 0x1a, 0x30, 0x02, 0xd8, 0x2b, 0xf7, 0xd3, 0x78, 0xd4, - 0xec, 0xac, 0xf5, 0x53, 0x18, 0x99, 0xdb, 0xd2, 0x8a, 0x42, 0x27, 0x9f, 0x7f, 0xfe, 0xf9, 0xa2, - 0x8d, 0xe8, 0x3d, 0x3b, 0x9f, 0xd9, 0xa5, 0xd0, 0xf6, 0x0a, 0xd9, 0x9c, 0x4c, 0x05, 0xac, 0xf4, - 0xd0, 0x86, 0xb5, 0xa6, 0xd6, 0x86, 0xb5, 0xad, 0x6f, 0x81, 0xc5, 0x85, 0x4c, 0xc0, 0x3c, 0xe8, - 0xa9, 0xd9, 0x1a, 0x0f, 0x37, 0x4d, 0xbc, 0x04, 0x8d, 0x37, 0x27, 0x0b, 0x8c, 0x29, 0x31, 0x43, - 0x7a, 0xb7, 0x81, 0x51, 0x0f, 0x25, 0x20, 0x3e, 0xdc, 0x7a, 0xe3, 0xca, 0x81, 0xef, 0x42, 0x39, - 0x92, 0x94, 0x07, 0x74, 0xd0, 0xa0, 0x70, 0x55, 0x78, 0x4e, 0xa6, 0x4f, 0x88, 0x70, 0xa3, 0x16, - 0xb4, 0xcd, 0x69, 0x2c, 0x7e, 0x9b, 0xd3, 0xdc, 0xe9, 0x2d, 0x6e, 0x12, 0x29, 0x9a, 0x93, 0xe9, - 0x73, 0xfd, 0xfb, 0xda, 0x24, 0x3f, 0xd6, 0x26, 0xf9, 0xb5, 0x36, 0xc9, 0xb7, 0xdf, 0xe6, 0x0d, - 0xb7, 0x27, 0xff, 0x18, 0x67, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x9c, 0xe6, 0x7c, 0x66, 0xa9, - 0x05, 0x00, 0x00, + // 556 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x94, 0x41, 0x6f, 0xd3, 0x30, + 0x14, 0xc7, 0x71, 0x5a, 0xca, 0x78, 0x74, 0x5b, 0x15, 0x8a, 0x28, 0xa5, 0x64, 0x95, 0xb9, 0x4c, + 0x3d, 0xc4, 0x68, 0xe5, 0xd4, 0xd3, 0x04, 0x02, 0x4d, 0x1a, 0x12, 0xe0, 0x03, 0x02, 0x6e, 0x6e, + 0xf6, 0x94, 0x55, 0x4d, 0xe3, 0x90, 0x74, 0x91, 0x7a, 0xe5, 0x2b, 0x70, 0x80, 0x8f, 0xc4, 0x11, + 0x89, 0x2f, 0x80, 0x0a, 0x1f, 0x04, 0xd9, 0x4e, 0x9a, 0x34, 0x6a, 0x11, 0x5a, 0x6f, 0x8e, 0xdf, + 0xdf, 0xef, 0xf7, 0xfe, 0xcf, 0x2f, 0x86, 0x56, 0x3a, 0xc4, 0x00, 0xbd, 0xf9, 0x44, 0x86, 0x6e, + 0x14, 0xcb, 0xb9, 0xb4, 0x9b, 0xc5, 0x4e, 0x34, 0xee, 0xb6, 0x7d, 0xe9, 0x4b, 0x1d, 0x60, 0x6a, + 0x65, 0x34, 0xdd, 0x23, 0x9c, 0x7b, 0x17, 0x4c, 0x44, 0x13, 0xa6, 0x16, 0x09, 0xc6, 0x29, 0xc6, + 0xd1, 0x98, 0xc5, 0x91, 0x97, 0x09, 0x3a, 0x2b, 0xc1, 0x2c, 0xf5, 0xbc, 0x68, 0xcc, 0xa6, 0x69, + 0x16, 0xe9, 0xf9, 0x52, 0xfa, 0x01, 0xea, 0x98, 0x08, 0x43, 0x39, 0x17, 0x8a, 0x94, 0x98, 0x28, + 0x7d, 0x0b, 0x87, 0xcf, 0xc5, 0x2c, 0x12, 0x13, 0x3f, 0xe4, 0xf8, 0xe9, 0x0a, 0x93, 0xb9, 0x6d, + 0x43, 0x3d, 0x14, 0x33, 0xec, 0x90, 0x3e, 0x39, 0x6e, 0x72, 0xbd, 0xb6, 0xdb, 0x70, 0x33, 0x40, + 0x91, 0x60, 0xc7, 0xea, 0x93, 0xe3, 0x1a, 0x37, 0x1f, 0x6a, 0x37, 0x15, 0xc1, 0x15, 0x76, 0x6a, + 0x5a, 0x6a, 0x3e, 0xe8, 0x02, 0x5a, 0x45, 0xca, 0x24, 0x92, 0x61, 0x82, 0xf6, 0x53, 0x68, 0x5c, + 0xa2, 0xb8, 0xc0, 0x58, 0x67, 0xbd, 0x73, 0xd2, 0x73, 0xcb, 0x3e, 0xdc, 0x5c, 0x77, 0xa6, 0x35, + 0x3c, 0xd3, 0xda, 0x0c, 0x1a, 0x81, 0x39, 0x65, 0xe9, 0x53, 0xf7, 0xdd, 0x72, 0xab, 0xdc, 0x57, + 0x3a, 0x76, 0x8e, 0x0b, 0x9e, 0xc9, 0xe8, 0x07, 0xb8, 0xbd, 0xda, 0xdc, 0xe8, 0xa3, 0x05, 0xb5, + 0x29, 0x2e, 0x74, 0xba, 0x26, 0x57, 0x4b, 0xb5, 0x13, 0x63, 0xaa, 0x1d, 0xd4, 0xb8, 0x5a, 0x16, + 0x5e, 0xeb, 0x25, 0xaf, 0xf4, 0x31, 0xec, 0x9b, 0xd4, 0xff, 0x68, 0x13, 0xbd, 0x84, 0x83, 0x5c, + 0xb4, 0x93, 0xf1, 0x3e, 0x58, 0xd3, 0x34, 0x33, 0xdd, 0x72, 0xcd, 0x8d, 0xba, 0xe7, 0xb8, 0x78, + 0xa7, 0x1a, 0xcc, 0xad, 0x69, 0x4a, 0x4f, 0x61, 0x9f, 0x63, 0x52, 0xba, 0xb5, 0xa2, 0x57, 0xe4, + 0xff, 0x7a, 0xf5, 0x12, 0x0e, 0xf2, 0x0c, 0xbb, 0xd4, 0x4a, 0xdf, 0xc3, 0xe1, 0x9b, 0x58, 0x7a, + 0x81, 0x98, 0xcc, 0xae, 0x5b, 0x4b, 0x31, 0x48, 0x56, 0x79, 0x90, 0xce, 0xa0, 0x55, 0x64, 0xde, + 0xa5, 0xc6, 0x93, 0xaf, 0x75, 0xd8, 0x7b, 0x91, 0x15, 0x60, 0x4f, 0x61, 0x2f, 0x9f, 0x4f, 0xfb, + 0xd1, 0x7a, 0x65, 0x95, 0x5f, 0xa1, 0xeb, 0x6c, 0x0b, 0x1b, 0x0a, 0xed, 0x7f, 0xfe, 0xf9, 0xe7, + 0x8b, 0xd5, 0xa5, 0xf7, 0x58, 0x3a, 0x64, 0xb9, 0x90, 0x79, 0x99, 0x6c, 0x44, 0x06, 0x0a, 0x96, + 0x7b, 0xa8, 0xc2, 0x2a, 0x5d, 0xab, 0xc2, 0xaa, 0xd6, 0xb7, 0xc0, 0xa2, 0x4c, 0xa6, 0x60, 0x1e, + 0x34, 0x4c, 0x6f, 0xed, 0x87, 0x9b, 0x3a, 0x9e, 0x83, 0x7a, 0x9b, 0x83, 0x19, 0xc6, 0xd1, 0x98, + 0x0e, 0xbd, 0xbb, 0x86, 0x31, 0x17, 0xa5, 0x20, 0x3e, 0xdc, 0x7a, 0x3d, 0xd6, 0x0d, 0xdf, 0x85, + 0x72, 0xa4, 0x29, 0x0f, 0x68, 0x7b, 0x8d, 0x22, 0x4d, 0xe2, 0x11, 0x19, 0x3c, 0x21, 0xca, 0x8d, + 0x19, 0xd0, 0x2a, 0x67, 0x6d, 0xf0, 0xab, 0x9c, 0xf5, 0x99, 0xde, 0xe2, 0x26, 0xd6, 0xa2, 0x11, + 0x19, 0x3c, 0xe3, 0xdf, 0x97, 0x0e, 0xf9, 0xb1, 0x74, 0xc8, 0xaf, 0xa5, 0x43, 0xbe, 0xfd, 0x76, + 0x6e, 0x7c, 0x3c, 0xf5, 0xa5, 0x9e, 0x29, 0x77, 0x22, 0xf5, 0x63, 0xcb, 0xcc, 0x70, 0xe9, 0xf3, + 0xab, 0x51, 0xd3, 0xaf, 0x69, 0xc1, 0x65, 0xe5, 0x12, 0xc6, 0x0d, 0xfd, 0xb4, 0x0e, 0xff, 0x06, + 0x00, 0x00, 0xff, 0xff, 0xcd, 0x58, 0x82, 0xe2, 0xeb, 0x05, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.proto b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.proto index 24ccaf138d..6042776b90 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.proto +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/v3election.proto @@ -8,6 +8,8 @@ import "etcd/api/mvccpb/kv.proto"; // for grpc-gateway import "google/api/annotations.proto"; +option go_package = "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb"; + option (gogoproto.marshaler_all) = true; option (gogoproto.unmarshaler_all) = true; @@ -74,7 +76,7 @@ message CampaignResponse { } message LeaderKey { - // name is the election identifier that correponds to the leadership key. + // name is the election identifier that corresponds to the leadership key. bytes name = 1; // key is an opaque key representing the ownership of the election. If the key // is deleted, then leadership is lost. diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/lock.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/lock.go index 8f9623361c..c8ef56ebae 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/lock.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/lock.go @@ -17,7 +17,7 @@ package v3lock import ( "context" - "go.etcd.io/etcd/client/v3" + clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/client/v3/concurrency" "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb" ) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go index dc573d79cf..5efb75939c 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw/v3lock.pb.gw.go @@ -9,140 +9,128 @@ It translates gRPC into RESTful JSON APIs. package gw import ( + protov1 "github.com/golang/protobuf/proto" + "context" + "errors" "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb" "io" "net/http" - "github.com/golang/protobuf/descriptor" - "github.com/golang/protobuf/proto" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "github.com/grpc-ecosystem/grpc-gateway/utilities" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" ) // Suppress "imported and not used" errors -var _ codes.Code -var _ io.Reader -var _ status.Status -var _ = runtime.String -var _ = utilities.NewDoubleArray -var _ = descriptor.ForMessage +var ( + _ codes.Code + _ io.Reader + _ status.Status + _ = errors.New + _ = runtime.String + _ = utilities.NewDoubleArray + _ = metadata.Join +) func request_Lock_Lock_0(ctx context.Context, marshaler runtime.Marshaler, client v3lockpb.LockClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3lockpb.LockRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3lockpb.LockRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Lock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Lock_Lock_0(ctx context.Context, marshaler runtime.Marshaler, server v3lockpb.LockServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3lockpb.LockRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3lockpb.LockRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Lock(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func request_Lock_Unlock_0(ctx context.Context, marshaler runtime.Marshaler, client v3lockpb.LockClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3lockpb.UnlockRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3lockpb.UnlockRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.Unlock(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } func local_request_Lock_Unlock_0(ctx context.Context, marshaler runtime.Marshaler, server v3lockpb.LockServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq v3lockpb.UnlockRequest - var metadata runtime.ServerMetadata - - newReader, berr := utilities.IOReaderFactory(req.Body) - if berr != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) - } - if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + var ( + protoReq v3lockpb.UnlockRequest + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(protov1.MessageV2(&protoReq)); err != nil && !errors.Is(err, io.EOF) { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := server.Unlock(ctx, &protoReq) - return msg, metadata, err - + return protov1.MessageV2(msg), metadata, err } // v3lockpb.RegisterLockHandlerServer registers the http handlers for service Lock to "mux". // UnaryRPC :call v3lockpb.LockServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterLockHandlerFromEndpoint instead. +// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterLockHandlerServer(ctx context.Context, mux *runtime.ServeMux, server v3lockpb.LockServer) error { - - mux.Handle("POST", pattern_Lock_Lock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lock_Lock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/v3lockpb.Lock/Lock", runtime.WithHTTPPathPattern("/v3/lock/lock")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Lock_Lock_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Lock_Lock_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lock_Lock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lock_Lock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lock_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lock_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/v3lockpb.Lock/Unlock", runtime.WithHTTPPathPattern("/v3/lock/unlock")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := local_request_Lock_Unlock_0(rctx, inboundMarshaler, server, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := local_request_Lock_Unlock_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lock_Unlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lock_Unlock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) return nil @@ -151,25 +139,24 @@ func RegisterLockHandlerServer(ctx context.Context, mux *runtime.ServeMux, serve // RegisterLockHandlerFromEndpoint is same as RegisterLockHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterLockHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { - conn, err := grpc.Dial(endpoint, opts...) + conn, err := grpc.NewClient(endpoint, opts...) if err != nil { return err } defer func() { if err != nil { if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } return } go func() { <-ctx.Done() if cerr := conn.Close(); cerr != nil { - grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr) } }() }() - return RegisterLockHandler(ctx, mux, conn) } @@ -183,60 +170,51 @@ func RegisterLockHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc. // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "LockClient". // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "LockClient" // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in -// "LockClient" to call the correct interceptors. +// "LockClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterLockHandlerClient(ctx context.Context, mux *runtime.ServeMux, client v3lockpb.LockClient) error { - - mux.Handle("POST", pattern_Lock_Lock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lock_Lock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/v3lockpb.Lock/Lock", runtime.WithHTTPPathPattern("/v3/lock/lock")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lock_Lock_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lock_Lock_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lock_Lock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lock_Lock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - - mux.Handle("POST", pattern_Lock_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + mux.Handle(http.MethodPost, pattern_Lock_Unlock_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/v3lockpb.Lock/Unlock", runtime.WithHTTPPathPattern("/v3/lock/unlock")) if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return } - resp, md, err := request_Lock_Unlock_0(rctx, inboundMarshaler, client, req, pathParams) - ctx = runtime.NewServerMetadataContext(ctx, md) + resp, md, err := request_Lock_Unlock_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) return } - - forward_Lock_Unlock_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + forward_Lock_Unlock_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) - return nil } var ( - pattern_Lock_Lock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 1}, []string{"v3", "lock"}, "", runtime.AssumeColonVerbOpt(true))) - - pattern_Lock_Unlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lock", "unlock"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Lock_Lock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 1}, []string{"v3", "lock"}, "")) + pattern_Lock_Unlock_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v3", "lock", "unlock"}, "")) ) var ( - forward_Lock_Lock_0 = runtime.ForwardResponseMessage - + forward_Lock_Lock_0 = runtime.ForwardResponseMessage forward_Lock_Unlock_0 = runtime.ForwardResponseMessage ) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go index 4282ddc85e..39c04abe17 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.pb.go @@ -254,28 +254,30 @@ func init() { func init() { proto.RegisterFile("v3lock.proto", fileDescriptor_52389b3e2f253201) } var fileDescriptor_52389b3e2f253201 = []byte{ - // 330 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0x33, 0xce, 0xc9, - 0x4f, 0xce, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x80, 0xf0, 0x0a, 0x92, 0xa4, 0x44, - 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x82, 0xfa, 0x20, 0x16, 0x44, 0x5e, 0x4a, 0x3e, 0xb5, 0x24, 0x39, - 0x45, 0x3f, 0xb1, 0x20, 0x53, 0x1f, 0xc4, 0x28, 0x4e, 0x2d, 0x2a, 0x4b, 0x2d, 0x2a, 0x48, 0xd2, - 0x2f, 0x2a, 0x48, 0x86, 0x2a, 0x90, 0x49, 0xcf, 0xcf, 0x4f, 0xcf, 0x49, 0x05, 0x2b, 0x49, 0xcc, - 0xcb, 0xcb, 0x2f, 0x49, 0x2c, 0xc9, 0xcc, 0xcf, 0x2b, 0x86, 0xc8, 0x2a, 0x99, 0x73, 0x71, 0xfb, - 0xe4, 0x27, 0x67, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0x09, 0x71, 0xb1, 0xe4, 0x25, - 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x81, 0xd9, 0x42, 0x22, 0x5c, 0xac, 0x39, - 0xa9, 0x89, 0xc5, 0xa9, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x10, 0x8e, 0x52, 0x18, 0x17, - 0x0f, 0x44, 0x63, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0xaa, 0x90, 0x09, 0x17, 0x5b, 0x46, 0x6a, 0x62, - 0x4a, 0x6a, 0x11, 0x58, 0x2f, 0xb7, 0x91, 0x8c, 0x1e, 0xb2, 0x7b, 0xf4, 0x60, 0xea, 0x3c, 0xc0, - 0x6a, 0x82, 0xa0, 0x6a, 0x85, 0x04, 0xb8, 0x98, 0xb3, 0x53, 0x2b, 0xc1, 0x26, 0xf3, 0x04, 0x81, - 0x98, 0x4a, 0x8a, 0x5c, 0xbc, 0xa1, 0x79, 0x39, 0x48, 0x4e, 0x82, 0x2a, 0x61, 0x44, 0x28, 0x71, - 0xe3, 0xe2, 0x83, 0x29, 0xa1, 0xc4, 0x72, 0xa3, 0x0d, 0x8c, 0x5c, 0x2c, 0x20, 0x3f, 0x08, 0xf9, - 0x43, 0x69, 0x51, 0x3d, 0x58, 0x60, 0xeb, 0x21, 0x05, 0x8a, 0x94, 0x18, 0xba, 0x30, 0xc4, 0x34, - 0x25, 0x89, 0xa6, 0xcb, 0x4f, 0x26, 0x33, 0x09, 0x29, 0xf1, 0xea, 0x97, 0x19, 0xeb, 0x83, 0x14, - 0x80, 0x09, 0x2b, 0x46, 0x2d, 0xa1, 0x70, 0x2e, 0x36, 0x88, 0x0b, 0x85, 0xc4, 0x11, 0x7a, 0x51, - 0xbc, 0x25, 0x25, 0x81, 0x29, 0x01, 0x35, 0x56, 0x0a, 0x6c, 0xac, 0x88, 0x12, 0x3f, 0xdc, 0xd8, - 0xd2, 0x3c, 0xa8, 0xc1, 0x4e, 0x02, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, - 0x91, 0x1c, 0xe3, 0x8c, 0xc7, 0x72, 0x0c, 0x49, 0x6c, 0xe0, 0x78, 0x34, 0x06, 0x04, 0x00, 0x00, - 0xff, 0xff, 0x4a, 0x4d, 0xca, 0xbb, 0x36, 0x02, 0x00, 0x00, + // 356 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0xcd, 0x4a, 0xc3, 0x40, + 0x10, 0xc7, 0xdd, 0xb6, 0x16, 0xd9, 0xa6, 0x2a, 0x4b, 0xd5, 0x10, 0x4a, 0xac, 0x39, 0x15, 0x0f, + 0x59, 0x68, 0x05, 0xc5, 0xa3, 0x07, 0x11, 0x11, 0x84, 0x80, 0x0a, 0xde, 0xd2, 0x74, 0x88, 0xa5, + 0x71, 0x27, 0x26, 0x69, 0xc1, 0xab, 0xaf, 0xe0, 0xc5, 0xc7, 0xf0, 0x31, 0x3c, 0x0a, 0xbe, 0x80, + 0x54, 0x1f, 0x44, 0x32, 0x9b, 0xd8, 0xaa, 0x47, 0x2f, 0xc9, 0xec, 0xce, 0x6f, 0xfe, 0xf3, 0xb1, + 0xc3, 0x8d, 0x69, 0x3f, 0xc2, 0x60, 0xec, 0xc6, 0x09, 0x66, 0x28, 0x56, 0xf4, 0x29, 0x1e, 0x58, + 0xad, 0x10, 0x43, 0xa4, 0x4b, 0x99, 0x5b, 0xda, 0x6f, 0x6d, 0x43, 0x16, 0x0c, 0xa5, 0x1f, 0x8f, + 0x64, 0x6e, 0xa4, 0x90, 0x4c, 0x21, 0x89, 0x07, 0x32, 0x89, 0x83, 0x02, 0x68, 0x87, 0x88, 0x61, + 0x04, 0x84, 0xf8, 0x4a, 0x61, 0xe6, 0x67, 0x23, 0x54, 0xa9, 0xf6, 0x3a, 0xfb, 0xbc, 0x71, 0x86, + 0xc1, 0xd8, 0x83, 0xbb, 0x09, 0xa4, 0x99, 0x10, 0xbc, 0xa6, 0xfc, 0x5b, 0x30, 0x59, 0x87, 0x75, + 0x0d, 0x8f, 0x6c, 0xd1, 0xe2, 0xcb, 0x11, 0xf8, 0x29, 0x98, 0x95, 0x0e, 0xeb, 0x56, 0x3d, 0x7d, + 0x70, 0x2e, 0xb9, 0xa1, 0x03, 0xd3, 0x18, 0x55, 0x0a, 0x62, 0x8f, 0xd7, 0x6f, 0xc0, 0x1f, 0x42, + 0x42, 0xb1, 0x8d, 0x5e, 0xdb, 0x5d, 0xac, 0xc7, 0x2d, 0xb9, 0x13, 0x62, 0xbc, 0x82, 0x15, 0xeb, + 0xbc, 0x3a, 0x86, 0x7b, 0x52, 0x36, 0xbc, 0xdc, 0x74, 0x76, 0x78, 0xf3, 0x42, 0x45, 0x0b, 0x25, + 0x15, 0x08, 0x9b, 0x23, 0xc7, 0x7c, 0xb5, 0x44, 0xfe, 0x93, 0xbc, 0xf7, 0xcc, 0x78, 0x2d, 0xef, + 0x41, 0x9c, 0x17, 0xff, 0x0d, 0xb7, 0x1c, 0xb6, 0xbb, 0x30, 0x14, 0x6b, 0xf3, 0xf7, 0xb5, 0x56, + 0x73, 0xcc, 0x87, 0xb7, 0xcf, 0xc7, 0x8a, 0x70, 0x9a, 0x72, 0xda, 0x97, 0x39, 0x40, 0x9f, 0x43, + 0xb6, 0x2b, 0xae, 0x78, 0x5d, 0x57, 0x28, 0xb6, 0xe6, 0xb1, 0x3f, 0xda, 0xb2, 0xcc, 0xbf, 0x8e, + 0x42, 0xd6, 0x22, 0xd9, 0x96, 0xb3, 0xf6, 0x2d, 0x3b, 0x51, 0x85, 0xf0, 0xd1, 0xe9, 0xcb, 0xcc, + 0x66, 0xaf, 0x33, 0x9b, 0xbd, 0xcf, 0x6c, 0xf6, 0xf4, 0x61, 0x2f, 0x5d, 0x1f, 0x84, 0x48, 0xcd, + 0xba, 0x23, 0xa4, 0x0d, 0x90, 0xba, 0xeb, 0x3c, 0x76, 0x3e, 0x03, 0x7a, 0x7c, 0x9d, 0x4f, 0x96, + 0x69, 0x07, 0x75, 0xda, 0x80, 0xfe, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x48, 0x31, 0x4a, + 0x70, 0x02, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.proto b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.proto index 1b5c456ae2..88a1c82428 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.proto +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/v3lock.proto @@ -7,6 +7,8 @@ import "etcd/api/etcdserverpb/rpc.proto"; // for grpc-gateway import "google/api/annotations.proto"; +option go_package = "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb"; + option (gogoproto.marshaler_all) = true; option (gogoproto.unmarshaler_all) = true; diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/auth.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/auth.go index d986037a1b..6c5db76cb8 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/auth.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/auth.go @@ -18,6 +18,7 @@ import ( "context" pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/server/v3/auth" "go.etcd.io/etcd/server/v3/etcdserver" ) @@ -164,3 +165,23 @@ func (as *AuthServer) UserChangePassword(ctx context.Context, r *pb.AuthUserChan } return resp, nil } + +type AuthGetter interface { + AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error) + AuthStore() auth.AuthStore +} + +type AuthAdmin struct { + ag AuthGetter +} + +// isPermitted verifies the user has admin privilege. +// Only users with "root" role are permitted. +func (aa *AuthAdmin) isPermitted(ctx context.Context) error { + authInfo, err := aa.ag.AuthInfoFromCtx(ctx) + if err != nil { + return err + } + + return aa.ag.AuthStore().IsAdminPermitted(authInfo) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/codec.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/codec.go index d599ff63cc..1bbed83971 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/codec.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/codec.go @@ -18,13 +18,13 @@ import "github.com/golang/protobuf/proto" type codec struct{} -func (c *codec) Marshal(v interface{}) ([]byte, error) { +func (c *codec) Marshal(v any) ([]byte, error) { b, err := proto.Marshal(v.(proto.Message)) sentBytes.Add(float64(len(b))) return b, err } -func (c *codec) Unmarshal(data []byte, v interface{}) error { +func (c *codec) Unmarshal(data []byte, v any) error { receivedBytes.Add(float64(len(data))) return proto.Unmarshal(data, v.(proto.Message)) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/grpc.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/grpc.go index 6947903a38..efa151437d 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/grpc.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/grpc.go @@ -18,34 +18,44 @@ import ( "crypto/tls" "math" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/v3/credentials" - "go.etcd.io/etcd/server/v3/etcdserver" - - grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" - grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus" + grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus" + "github.com/prometheus/client_golang/prometheus" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" + "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/client/v3/credentials" + "go.etcd.io/etcd/server/v3/etcdserver" ) const ( - grpcOverheadBytes = 512 * 1024 - maxSendBytes = math.MaxInt32 + maxSendBytes = math.MaxInt32 ) func Server(s *etcdserver.EtcdServer, tls *tls.Config, interceptor grpc.UnaryServerInterceptor, gopts ...grpc.ServerOption) *grpc.Server { var opts []grpc.ServerOption opts = append(opts, grpc.CustomCodec(&codec{})) if tls != nil { - bundle := credentials.NewBundle(credentials.Config{TLSConfig: tls}) - opts = append(opts, grpc.Creds(bundle.TransportCredentials())) + opts = append(opts, grpc.Creds(credentials.NewTransportCredential(tls))) } + + var mopts []grpc_prometheus.ServerMetricsOption + if s.Cfg.Metrics == "extensive" { + mopts = append(mopts, grpc_prometheus.WithServerHandlingTimeHistogram()) + } + serverMetrics := grpc_prometheus.NewServerMetrics(mopts...) + err := prometheus.Register(serverMetrics) + if err != nil { + s.Cfg.Logger.Warn("etcdserver: failed to register grpc metrics", zap.Error(err)) + } + chainUnaryInterceptors := []grpc.UnaryServerInterceptor{ newLogUnaryInterceptor(s), newUnaryInterceptor(s), - grpc_prometheus.UnaryServerInterceptor, + serverMetrics.UnaryServerInterceptor(), } if interceptor != nil { chainUnaryInterceptors = append(chainUnaryInterceptors, interceptor) @@ -53,19 +63,17 @@ func Server(s *etcdserver.EtcdServer, tls *tls.Config, interceptor grpc.UnarySer chainStreamInterceptors := []grpc.StreamServerInterceptor{ newStreamInterceptor(s), - grpc_prometheus.StreamServerInterceptor, + serverMetrics.StreamServerInterceptor(), } - if s.Cfg.ExperimentalEnableDistributedTracing { - chainUnaryInterceptors = append(chainUnaryInterceptors, otelgrpc.UnaryServerInterceptor(s.Cfg.ExperimentalTracerOptions...)) - chainStreamInterceptors = append(chainStreamInterceptors, otelgrpc.StreamServerInterceptor(s.Cfg.ExperimentalTracerOptions...)) - + if s.Cfg.EnableDistributedTracing { + opts = append(opts, grpc.StatsHandler(otelgrpc.NewServerHandler(s.Cfg.TracerOptions...))) } - opts = append(opts, grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(chainUnaryInterceptors...))) - opts = append(opts, grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(chainStreamInterceptors...))) + opts = append(opts, grpc.ChainUnaryInterceptor(chainUnaryInterceptors...)) + opts = append(opts, grpc.ChainStreamInterceptor(chainStreamInterceptors...)) - opts = append(opts, grpc.MaxRecvMsgSize(int(s.Cfg.MaxRequestBytes+grpcOverheadBytes))) + opts = append(opts, grpc.MaxRecvMsgSize(int(s.Cfg.MaxRequestBytesWithOverhead()))) opts = append(opts, grpc.MaxSendMsgSize(maxSendBytes)) opts = append(opts, grpc.MaxConcurrentStreams(s.Cfg.MaxConcurrentStreams)) @@ -79,11 +87,11 @@ func Server(s *etcdserver.EtcdServer, tls *tls.Config, interceptor grpc.UnarySer hsrv := health.NewServer() healthNotifier := newHealthNotifier(hsrv, s) - pb.RegisterMaintenanceServer(grpcServer, NewMaintenanceServer(s, healthNotifier)) healthpb.RegisterHealthServer(grpcServer, hsrv) + pb.RegisterMaintenanceServer(grpcServer, NewMaintenanceServer(s, healthNotifier)) // set zero values for metrics registered for this grpc server - grpc_prometheus.Register(grpcServer) + serverMetrics.InitializeMetrics(grpcServer) return grpcServer } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/header.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/header.go index 112cc922ea..8fe4e5863b 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/header.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/header.go @@ -17,19 +17,20 @@ package v3rpc import ( pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/server/v3/etcdserver" + "go.etcd.io/etcd/server/v3/etcdserver/apply" ) type header struct { clusterID int64 memberID int64 - sg etcdserver.RaftStatusGetter + sg apply.RaftStatusGetter rev func() int64 } func newHeader(s *etcdserver.EtcdServer) header { return header{ clusterID: int64(s.Cluster().ID()), - memberID: int64(s.ID()), + memberID: int64(s.MemberID()), sg: s, rev: func() int64 { return s.KV().Rev() }, } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/health.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/health.go index f58396d1c3..2861e11e6d 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/health.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/health.go @@ -15,10 +15,12 @@ package v3rpc import ( - "go.etcd.io/etcd/server/v3/etcdserver" "go.uber.org/zap" "google.golang.org/grpc/health" healthpb "google.golang.org/grpc/health/grpc_health_v1" + + "go.etcd.io/etcd/server/v3/etcdserver" + "go.etcd.io/etcd/server/v3/features" ) const ( @@ -34,7 +36,7 @@ func newHealthNotifier(hs *health.Server, s *etcdserver.EtcdServer) notifier { if hs == nil { panic("unexpected nil gRPC health server") } - hc := &healthNotifier{hs: hs, lg: s.Logger(), stopGRPCServiceOnDefrag: s.Cfg.ExperimentalStopGRPCServiceOnDefrag} + hc := &healthNotifier{hs: hs, lg: s.Logger(), stopGRPCServiceOnDefrag: s.FeatureEnabled(features.StopGRPCServiceOnDefrag)} // set grpc health server as serving status blindly since // the grpc server will serve iff s.ReadyNotify() is closed. hc.startServe() diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/interceptor.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/interceptor.go index 5c80fcf041..697d0b075e 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/interceptor.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/interceptor.go @@ -18,24 +18,24 @@ import ( "context" "sync" "time" + "unicode/utf8" - "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/etcdserver/api" - - pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/metadata" "google.golang.org/grpc/peer" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/server/v3/etcdserver" + "go.etcd.io/etcd/server/v3/etcdserver/api" + "go.etcd.io/raft/v3" ) const ( - maxNoLeaderCnt = 3 - warnUnaryRequestLatency = 300 * time.Millisecond - snapshotMethod = "/etcdserverpb.Maintenance/Snapshot" + maxNoLeaderCnt = 3 + snapshotMethod = "/etcdserverpb.Maintenance/Snapshot" ) type streamsMap struct { @@ -44,13 +44,13 @@ type streamsMap struct { } func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { if !api.IsCapabilityEnabled(api.V3rpcCapability) { return nil, rpctypes.ErrGRPCNotCapable } - if s.IsMemberExist(s.ID()) && s.IsLearner() && !isRPCSupportedForLearner(req) { - return nil, rpctypes.ErrGPRCNotSupportedForLearner + if s.IsMemberExist(s.MemberID()) && s.IsLearner() && !isRPCSupportedForLearner(req) { + return nil, rpctypes.ErrGRPCNotSupportedForLearner } md, ok := metadata.FromIncomingContext(ctx) @@ -59,6 +59,9 @@ func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor { if len(vs) > 0 { ver = vs[0] } + if !utf8.ValidString(ver) { + return nil, rpctypes.ErrGRPCInvalidClientAPIVersion + } clientRequests.WithLabelValues("unary", ver).Inc() if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader { @@ -73,24 +76,24 @@ func newUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor { } func newLogUnaryInterceptor(s *etcdserver.EtcdServer) grpc.UnaryServerInterceptor { - return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { + return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) { startTime := time.Now() resp, err := handler(ctx, req) lg := s.Logger() - if lg != nil { // acquire stats if debug level is enabled or request is expensive - defer logUnaryRequestStats(ctx, lg, info, startTime, req, resp) + if lg != nil { // acquire stats if debug level is enabled or RequestInfo is expensive + defer logUnaryRequestStats(ctx, lg, s.Cfg.WarningUnaryRequestDuration, info, startTime, req, resp) } return resp, err } } -func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, info *grpc.UnaryServerInfo, startTime time.Time, req interface{}, resp interface{}) { +func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, warnLatency time.Duration, info *grpc.UnaryServerInfo, startTime time.Time, req any, resp any) { duration := time.Since(startTime) var enabledDebugLevel, expensiveRequest bool if lg.Core().Enabled(zap.DebugLevel) { enabledDebugLevel = true } - if duration > warnUnaryRequestLatency { + if duration > warnLatency { expensiveRequest = true } if !enabledDebugLevel && !expensiveRequest { @@ -178,7 +181,8 @@ func logUnaryRequestStats(ctx context.Context, lg *zap.Logger, info *grpc.UnaryS } func logGenericRequestStats(lg *zap.Logger, startTime time.Time, duration time.Duration, remote string, responseType string, - reqCount int64, reqSize int, respCount int64, respSize int, reqContent string) { + reqCount int64, reqSize int, respCount int64, respSize int, reqContent string, +) { lg.Debug("request stats", zap.Time("start time", startTime), zap.Duration("time spent", duration), @@ -193,7 +197,8 @@ func logGenericRequestStats(lg *zap.Logger, startTime time.Time, duration time.D } func logExpensiveRequestStats(lg *zap.Logger, startTime time.Time, duration time.Duration, remote string, responseType string, - reqCount int64, reqSize int, respCount int64, respSize int, reqContent string) { + reqCount int64, reqSize int, respCount int64, respSize int, reqContent string, +) { lg.Warn("request stats", zap.Time("start time", startTime), zap.Duration("time spent", duration), @@ -210,13 +215,13 @@ func logExpensiveRequestStats(lg *zap.Logger, startTime time.Time, duration time func newStreamInterceptor(s *etcdserver.EtcdServer) grpc.StreamServerInterceptor { smap := monitorLeader(s) - return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { + return func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { if !api.IsCapabilityEnabled(api.V3rpcCapability) { return rpctypes.ErrGRPCNotCapable } - if s.IsMemberExist(s.ID()) && s.IsLearner() && info.FullMethod != snapshotMethod { // learner does not support stream RPC except Snapshot - return rpctypes.ErrGPRCNotSupportedForLearner + if s.IsMemberExist(s.MemberID()) && s.IsLearner() && info.FullMethod != snapshotMethod { // learner does not support stream RPC except Snapshot + return rpctypes.ErrGRPCNotSupportedForLearner } md, ok := metadata.FromIncomingContext(ss.Context()) @@ -225,6 +230,9 @@ func newStreamInterceptor(s *etcdserver.EtcdServer) grpc.StreamServerInterceptor if len(vs) > 0 { ver = vs[0] } + if !utf8.ValidString(ver) { + return rpctypes.ErrGRPCInvalidClientAPIVersion + } clientRequests.WithLabelValues("stream", ver).Inc() if ks := md[rpctypes.MetadataRequireLeaderKey]; len(ks) > 0 && ks[0] == rpctypes.MetadataHasLeader { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/key.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/key.go index d1a7ee6334..2c1de2a90d 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/key.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/key.go @@ -115,6 +115,15 @@ func checkRangeRequest(r *pb.RangeRequest) error { if len(r.Key) == 0 { return rpctypes.ErrGRPCEmptyKey } + + if _, ok := pb.RangeRequest_SortOrder_name[int32(r.SortOrder)]; !ok { + return rpctypes.ErrGRPCInvalidSortOption + } + + if _, ok := pb.RangeRequest_SortTarget_name[int32(r.SortTarget)]; !ok { + return rpctypes.ErrGRPCInvalidSortOption + } + return nil } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/lease.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/lease.go index e123dd2a37..f51334eade 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/lease.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/lease.go @@ -16,14 +16,15 @@ package v3rpc import ( "context" + "errors" "io" + "go.uber.org/zap" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/lease" - - "go.uber.org/zap" ) type LeaseServer struct { @@ -42,7 +43,6 @@ func NewLeaseServer(s *etcdserver.EtcdServer) pb.LeaseServer { func (ls *LeaseServer) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { resp, err := ls.le.LeaseGrant(ctx, cr) - if err != nil { return nil, togRPCError(err) } @@ -61,10 +61,10 @@ func (ls *LeaseServer) LeaseRevoke(ctx context.Context, rr *pb.LeaseRevokeReques func (ls *LeaseServer) LeaseTimeToLive(ctx context.Context, rr *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) { resp, err := ls.le.LeaseTimeToLive(ctx, rr) - if err != nil && err != lease.ErrLeaseNotFound { + if err != nil && !errors.Is(err, lease.ErrLeaseNotFound) { return nil, togRPCError(err) } - if err == lease.ErrLeaseNotFound { + if errors.Is(err, lease.ErrLeaseNotFound) { resp = &pb.LeaseTimeToLiveResponse{ Header: &pb.ResponseHeader{}, ID: rr.ID, @@ -77,10 +77,10 @@ func (ls *LeaseServer) LeaseTimeToLive(ctx context.Context, rr *pb.LeaseTimeToLi func (ls *LeaseServer) LeaseLeases(ctx context.Context, rr *pb.LeaseLeasesRequest) (*pb.LeaseLeasesResponse, error) { resp, err := ls.le.LeaseLeases(ctx, rr) - if err != nil && err != lease.ErrLeaseNotFound { + if err != nil && !errors.Is(err, lease.ErrLeaseNotFound) { return nil, togRPCError(err) } - if err == lease.ErrLeaseNotFound { + if errors.Is(err, lease.ErrLeaseNotFound) { resp = &pb.LeaseLeasesResponse{ Header: &pb.ResponseHeader{}, Leases: []*pb.LeaseStatus{}, @@ -100,7 +100,7 @@ func (ls *LeaseServer) LeaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) (err case <-stream.Context().Done(): // the only server-side cancellation is noleader for now. err = stream.Context().Err() - if err == context.Canceled { + if errors.Is(err, context.Canceled) { err = rpctypes.ErrGRPCNoLeader } } @@ -110,7 +110,7 @@ func (ls *LeaseServer) LeaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) (err func (ls *LeaseServer) leaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) error { for { req, err := stream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil } if err != nil { @@ -133,7 +133,7 @@ func (ls *LeaseServer) leaseKeepAlive(stream pb.Lease_LeaseKeepAliveServer) erro ls.hdr.fill(resp.Header) ttl, err := ls.le.LeaseRenew(stream.Context(), lease.LeaseID(req.ID)) - if err == lease.ErrLeaseNotFound { + if errors.Is(err, lease.ErrLeaseNotFound) { err = nil ttl = 0 } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/maintenance.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/maintenance.go index 7db17e1a00..ec7de4467e 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/maintenance.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/maintenance.go @@ -17,20 +17,25 @@ package v3rpc import ( "context" "crypto/sha256" + errorspkg "errors" "io" "time" "github.com/dustin/go-humanize" + "go.uber.org/zap" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/api/v3/version" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/server/v3/auth" + "go.etcd.io/etcd/server/v3/config" "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/mvcc" - "go.etcd.io/etcd/server/v3/mvcc/backend" - - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/etcdserver/apply" + "go.etcd.io/etcd/server/v3/etcdserver/errors" + serverversion "go.etcd.io/etcd/server/v3/etcdserver/version" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/mvcc" + "go.etcd.io/etcd/server/v3/storage/schema" + "go.etcd.io/raft/v3" ) type KVGetter interface { @@ -41,6 +46,10 @@ type BackendGetter interface { Backend() backend.Backend } +type Defrager interface { + Defragment() error +} + type Alarmer interface { // Alarms is implemented in Server interface located in etcdserver/server.go // It returns a list of alarms present in the AlarmStore @@ -56,46 +65,61 @@ type LeaderTransferrer interface { MoveLeader(ctx context.Context, lead, target uint64) error } -type AuthGetter interface { - AuthInfoFromCtx(ctx context.Context) (*auth.AuthInfo, error) - AuthStore() auth.AuthStore -} - type ClusterStatusGetter interface { IsLearner() bool } +type ConfigGetter interface { + Config() config.ServerConfig +} + type maintenanceServer struct { lg *zap.Logger - rg etcdserver.RaftStatusGetter + rg apply.RaftStatusGetter hasher mvcc.HashStorage - kg KVGetter bg BackendGetter + defrag Defrager a Alarmer lt LeaderTransferrer hdr header cs ClusterStatusGetter d Downgrader + vs serverversion.Server + cg ConfigGetter healthNotifier notifier } func NewMaintenanceServer(s *etcdserver.EtcdServer, healthNotifier notifier) pb.MaintenanceServer { - srv := &maintenanceServer{lg: s.Cfg.Logger, rg: s, hasher: s.KV().HashStorage(), kg: s, bg: s, a: s, lt: s, hdr: newHeader(s), cs: s, d: s, healthNotifier: healthNotifier} + srv := &maintenanceServer{ + lg: s.Cfg.Logger, + rg: s, + hasher: s.KV().HashStorage(), + bg: s, + defrag: s, + a: s, + lt: s, + hdr: newHeader(s), + cs: s, + d: s, + vs: etcdserver.NewServerVersionAdapter(s), + healthNotifier: healthNotifier, + cg: s, + } if srv.lg == nil { srv.lg = zap.NewNop() } - return &authMaintenanceServer{srv, s} + return &authMaintenanceServer{srv, &AuthAdmin{s}} } func (ms *maintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) { ms.lg.Info("starting defragment") ms.healthNotifier.defragStarted() defer ms.healthNotifier.defragFinished() - err := ms.bg.Backend().Defrag() + err := ms.defrag.Defragment() if err != nil { ms.lg.Warn("failed to defragment", zap.Error(err)) - return nil, err + return nil, togRPCError(err) } ms.lg.Info("finished defragment") return &pb.DefragmentResponse{}, nil @@ -105,6 +129,11 @@ func (ms *maintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRe const snapshotSendBufferSize = 32 * 1024 func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance_SnapshotServer) error { + ver := schema.ReadStorageVersion(ms.bg.Backend().ReadTx()) + storageVersion := "" + if ver != nil { + storageVersion = ver.String() + } snap := ms.bg.Backend().Snapshot() pr, pw := io.Pipe() @@ -130,6 +159,7 @@ func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance ms.lg.Info("sending database snapshot to client", zap.Int64("total-bytes", total), zap.String("size", size), + zap.String("storage-version", storageVersion), ) for total-sent > 0 { // buffer just holds read bytes from stream @@ -140,7 +170,7 @@ func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance buf := make([]byte, snapshotSendBufferSize) n, err := io.ReadFull(pr, buf) - if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF { + if err != nil && !errorspkg.Is(err, io.EOF) && !errorspkg.Is(err, io.ErrUnexpectedEOF) { return togRPCError(err) } sent += int64(n) @@ -156,6 +186,7 @@ func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance resp := &pb.SnapshotResponse{ RemainingBytes: uint64(total - sent), Blob: buf[:n], + Version: storageVersion, } if err = srv.Send(resp); err != nil { return togRPCError(err) @@ -171,7 +202,7 @@ func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance zap.Int64("total-bytes", total), zap.Int("checksum-size", len(sha)), ) - hresp := &pb.SnapshotResponse{RemainingBytes: 0, Blob: sha} + hresp := &pb.SnapshotResponse{RemainingBytes: 0, Blob: sha, Version: storageVersion} if err := srv.Send(hresp); err != nil { return togRPCError(err) } @@ -179,7 +210,8 @@ func (ms *maintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance ms.lg.Info("successfully sent database snapshot to client", zap.Int64("total-bytes", total), zap.String("size", size), - zap.String("took", humanize.Time(start)), + zap.Duration("took", time.Since(start)), + zap.String("storage-version", storageVersion), ) return nil } @@ -200,7 +232,12 @@ func (ms *maintenanceServer) HashKV(ctx context.Context, r *pb.HashKVRequest) (* return nil, togRPCError(err) } - resp := &pb.HashKVResponse{Header: &pb.ResponseHeader{Revision: rev}, Hash: h.Hash, CompactRevision: h.CompactRevision} + resp := &pb.HashKVResponse{ + Header: &pb.ResponseHeader{Revision: rev}, + Hash: h.Hash, + CompactRevision: h.CompactRevision, + HashRevision: h.Revision, + } ms.hdr.fill(resp.Header) return resp, nil } @@ -230,9 +267,20 @@ func (ms *maintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) ( DbSize: ms.bg.Backend().Size(), DbSizeInUse: ms.bg.Backend().SizeInUse(), IsLearner: ms.cs.IsLearner(), + DbSizeQuota: ms.cg.Config().QuotaBackendBytes, + DowngradeInfo: &pb.DowngradeInfo{Enabled: false}, + } + if storageVersion := ms.vs.GetStorageVersion(); storageVersion != nil { + resp.StorageVersion = storageVersion.String() + } + if downgradeInfo := ms.vs.GetDowngradeInfo(); downgradeInfo != nil { + resp.DowngradeInfo = &pb.DowngradeInfo{ + Enabled: downgradeInfo.Enabled, + TargetVersion: downgradeInfo.TargetVersion, + } } if resp.Leader == raft.None { - resp.Errors = append(resp.Errors, etcdserver.ErrNoLeader.Error()) + resp.Errors = append(resp.Errors, errors.ErrNoLeader.Error()) } for _, a := range ms.a.Alarms() { resp.Errors = append(resp.Errors, a.String()) @@ -241,7 +289,7 @@ func (ms *maintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) ( } func (ms *maintenanceServer) MoveLeader(ctx context.Context, tr *pb.MoveLeaderRequest) (*pb.MoveLeaderResponse, error) { - if ms.rg.ID() != ms.rg.Leader() { + if ms.rg.MemberID() != ms.rg.Leader() { return nil, rpctypes.ErrGRPCNotLeader } @@ -263,57 +311,60 @@ func (ms *maintenanceServer) Downgrade(ctx context.Context, r *pb.DowngradeReque type authMaintenanceServer struct { *maintenanceServer - ag AuthGetter -} - -func (ams *authMaintenanceServer) isAuthenticated(ctx context.Context) error { - authInfo, err := ams.ag.AuthInfoFromCtx(ctx) - if err != nil { - return err - } - - return ams.ag.AuthStore().IsAdminPermitted(authInfo) + *AuthAdmin } func (ams *authMaintenanceServer) Defragment(ctx context.Context, sr *pb.DefragmentRequest) (*pb.DefragmentResponse, error) { - if err := ams.isAuthenticated(ctx); err != nil { - return nil, err + if err := ams.isPermitted(ctx); err != nil { + return nil, togRPCError(err) } return ams.maintenanceServer.Defragment(ctx, sr) } func (ams *authMaintenanceServer) Snapshot(sr *pb.SnapshotRequest, srv pb.Maintenance_SnapshotServer) error { - if err := ams.isAuthenticated(srv.Context()); err != nil { - return err + if err := ams.isPermitted(srv.Context()); err != nil { + return togRPCError(err) } return ams.maintenanceServer.Snapshot(sr, srv) } func (ams *authMaintenanceServer) Hash(ctx context.Context, r *pb.HashRequest) (*pb.HashResponse, error) { - if err := ams.isAuthenticated(ctx); err != nil { - return nil, err + if err := ams.isPermitted(ctx); err != nil { + return nil, togRPCError(err) } return ams.maintenanceServer.Hash(ctx, r) } func (ams *authMaintenanceServer) HashKV(ctx context.Context, r *pb.HashKVRequest) (*pb.HashKVResponse, error) { - if err := ams.isAuthenticated(ctx); err != nil { - return nil, err + if err := ams.isPermitted(ctx); err != nil { + return nil, togRPCError(err) } return ams.maintenanceServer.HashKV(ctx, r) } func (ams *authMaintenanceServer) Status(ctx context.Context, ar *pb.StatusRequest) (*pb.StatusResponse, error) { + if err := ams.isPermitted(ctx); err != nil { + return nil, togRPCError(err) + } + return ams.maintenanceServer.Status(ctx, ar) } func (ams *authMaintenanceServer) MoveLeader(ctx context.Context, tr *pb.MoveLeaderRequest) (*pb.MoveLeaderResponse, error) { + if err := ams.isPermitted(ctx); err != nil { + return nil, togRPCError(err) + } + return ams.maintenanceServer.MoveLeader(ctx, tr) } func (ams *authMaintenanceServer) Downgrade(ctx context.Context, r *pb.DowngradeRequest) (*pb.DowngradeResponse, error) { + if err := ams.isPermitted(ctx); err != nil { + return nil, togRPCError(err) + } + return ams.maintenanceServer.Downgrade(ctx, r) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/member.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/member.go index 54fcc24843..7fd68fe2d6 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/member.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/member.go @@ -106,7 +106,7 @@ func (cs *ClusterServer) MemberPromote(ctx context.Context, r *pb.MemberPromoteR } func (cs *ClusterServer) header() *pb.ResponseHeader { - return &pb.ResponseHeader{ClusterId: uint64(cs.cluster.ID()), MemberId: uint64(cs.server.ID()), RaftTerm: cs.server.Term()} + return &pb.ResponseHeader{ClusterId: uint64(cs.cluster.ID()), MemberId: uint64(cs.server.MemberID()), RaftTerm: cs.server.Term()} } func membersToProtoMembers(membs []*membership.Member) []*pb.Member { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/metrics.go index a4ee723c52..d79506e073 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/metrics.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/metrics.go @@ -14,7 +14,9 @@ package v3rpc -import "github.com/prometheus/client_golang/prometheus" +import ( + "github.com/prometheus/client_golang/prometheus" +) var ( sentBytes = prometheus.NewCounter(prometheus.CounterOpts{ @@ -31,21 +33,23 @@ var ( Help: "The total number of bytes received from grpc clients.", }) - streamFailures = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "network", - Name: "server_stream_failures_total", - Help: "The total number of stream failures from the local server.", - }, + streamFailures = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "network", + Name: "server_stream_failures_total", + Help: "The total number of stream failures from the local server.", + }, []string{"Type", "API"}, ) - clientRequests = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "client_requests_total", - Help: "The total number of client requests per client version.", - }, + clientRequests = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "client_requests_total", + Help: "The total number of client requests per client version.", + }, []string{"type", "client_api_version"}, ) ) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/quota.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/quota.go index 7f53bd966b..13bb83ffcd 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/quota.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/quota.go @@ -21,6 +21,7 @@ import ( "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/server/v3/etcdserver" + "go.etcd.io/etcd/server/v3/storage" ) type quotaKVServer struct { @@ -29,14 +30,14 @@ type quotaKVServer struct { } type quotaAlarmer struct { - q etcdserver.Quota + q storage.Quota a Alarmer id types.ID } // check whether request satisfies the quota. If there is not enough space, // ignore request and raise the free space alarm. -func (qa *quotaAlarmer) check(ctx context.Context, r interface{}) error { +func (qa *quotaAlarmer) check(ctx context.Context, r any) error { if qa.q.Available(r) { return nil } @@ -52,7 +53,7 @@ func (qa *quotaAlarmer) check(ctx context.Context, r interface{}) error { func NewQuotaKVServer(s *etcdserver.EtcdServer) pb.KVServer { return "aKVServer{ NewKVServer(s), - quotaAlarmer{etcdserver.NewBackendQuota(s, "kv"), s, s.ID()}, + quotaAlarmer{newBackendQuota(s, "kv"), s, s.MemberID()}, } } @@ -85,6 +86,10 @@ func (s *quotaLeaseServer) LeaseGrant(ctx context.Context, cr *pb.LeaseGrantRequ func NewQuotaLeaseServer(s *etcdserver.EtcdServer) pb.LeaseServer { return "aLeaseServer{ NewLeaseServer(s), - quotaAlarmer{etcdserver.NewBackendQuota(s, "lease"), s, s.ID()}, + quotaAlarmer{newBackendQuota(s, "lease"), s, s.MemberID()}, } } + +func newBackendQuota(s *etcdserver.EtcdServer, name string) storage.Quota { + return storage.NewBackendQuota(s.Logger(), s.Cfg.QuotaBackendBytes, s.Backend(), name) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/util.go index b238934268..2354b0cb24 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/util.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/util.go @@ -16,54 +16,56 @@ package v3rpc import ( "context" + errorspkg "errors" "strings" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/server/v3/auth" - "go.etcd.io/etcd/server/v3/etcdserver" "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "go.etcd.io/etcd/server/v3/etcdserver/errors" + "go.etcd.io/etcd/server/v3/etcdserver/version" "go.etcd.io/etcd/server/v3/lease" - "go.etcd.io/etcd/server/v3/mvcc" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" + "go.etcd.io/etcd/server/v3/storage/mvcc" ) var toGRPCErrorMap = map[error]error{ - membership.ErrIDRemoved: rpctypes.ErrGRPCMemberNotFound, - membership.ErrIDNotFound: rpctypes.ErrGRPCMemberNotFound, - membership.ErrIDExists: rpctypes.ErrGRPCMemberExist, - membership.ErrPeerURLexists: rpctypes.ErrGRPCPeerURLExist, - membership.ErrMemberNotLearner: rpctypes.ErrGRPCMemberNotLearner, - membership.ErrTooManyLearners: rpctypes.ErrGRPCTooManyLearners, - etcdserver.ErrNotEnoughStartedMembers: rpctypes.ErrMemberNotEnoughStarted, - etcdserver.ErrLearnerNotReady: rpctypes.ErrGRPCLearnerNotReady, - - mvcc.ErrCompacted: rpctypes.ErrGRPCCompacted, - mvcc.ErrFutureRev: rpctypes.ErrGRPCFutureRev, - etcdserver.ErrRequestTooLarge: rpctypes.ErrGRPCRequestTooLarge, - etcdserver.ErrNoSpace: rpctypes.ErrGRPCNoSpace, - etcdserver.ErrTooManyRequests: rpctypes.ErrTooManyRequests, - - etcdserver.ErrNoLeader: rpctypes.ErrGRPCNoLeader, - etcdserver.ErrNotLeader: rpctypes.ErrGRPCNotLeader, - etcdserver.ErrLeaderChanged: rpctypes.ErrGRPCLeaderChanged, - etcdserver.ErrStopped: rpctypes.ErrGRPCStopped, - etcdserver.ErrTimeout: rpctypes.ErrGRPCTimeout, - etcdserver.ErrTimeoutDueToLeaderFail: rpctypes.ErrGRPCTimeoutDueToLeaderFail, - etcdserver.ErrTimeoutDueToConnectionLost: rpctypes.ErrGRPCTimeoutDueToConnectionLost, - etcdserver.ErrTimeoutWaitAppliedIndex: rpctypes.ErrGRPCTimeoutWaitAppliedIndex, - etcdserver.ErrUnhealthy: rpctypes.ErrGRPCUnhealthy, - etcdserver.ErrKeyNotFound: rpctypes.ErrGRPCKeyNotFound, - etcdserver.ErrCorrupt: rpctypes.ErrGRPCCorrupt, - etcdserver.ErrBadLeaderTransferee: rpctypes.ErrGRPCBadLeaderTransferee, - - etcdserver.ErrClusterVersionUnavailable: rpctypes.ErrGRPCClusterVersionUnavailable, - etcdserver.ErrWrongDowngradeVersionFormat: rpctypes.ErrGRPCWrongDowngradeVersionFormat, - etcdserver.ErrInvalidDowngradeTargetVersion: rpctypes.ErrGRPCInvalidDowngradeTargetVersion, - etcdserver.ErrDowngradeInProcess: rpctypes.ErrGRPCDowngradeInProcess, - etcdserver.ErrNoInflightDowngrade: rpctypes.ErrGRPCNoInflightDowngrade, + membership.ErrIDRemoved: rpctypes.ErrGRPCMemberNotFound, + membership.ErrIDNotFound: rpctypes.ErrGRPCMemberNotFound, + membership.ErrIDExists: rpctypes.ErrGRPCMemberExist, + membership.ErrPeerURLexists: rpctypes.ErrGRPCPeerURLExist, + membership.ErrMemberNotLearner: rpctypes.ErrGRPCMemberNotLearner, + membership.ErrTooManyLearners: rpctypes.ErrGRPCTooManyLearners, + errors.ErrNotEnoughStartedMembers: rpctypes.ErrMemberNotEnoughStarted, + errors.ErrLearnerNotReady: rpctypes.ErrGRPCLearnerNotReady, + + mvcc.ErrCompacted: rpctypes.ErrGRPCCompacted, + mvcc.ErrFutureRev: rpctypes.ErrGRPCFutureRev, + errors.ErrRequestTooLarge: rpctypes.ErrGRPCRequestTooLarge, + errors.ErrNoSpace: rpctypes.ErrGRPCNoSpace, + errors.ErrTooManyRequests: rpctypes.ErrTooManyRequests, + + errors.ErrNoLeader: rpctypes.ErrGRPCNoLeader, + errors.ErrNotLeader: rpctypes.ErrGRPCNotLeader, + errors.ErrLeaderChanged: rpctypes.ErrGRPCLeaderChanged, + errors.ErrStopped: rpctypes.ErrGRPCStopped, + errors.ErrTimeout: rpctypes.ErrGRPCTimeout, + errors.ErrTimeoutDueToLeaderFail: rpctypes.ErrGRPCTimeoutDueToLeaderFail, + errors.ErrTimeoutDueToConnectionLost: rpctypes.ErrGRPCTimeoutDueToConnectionLost, + errors.ErrTimeoutWaitAppliedIndex: rpctypes.ErrGRPCTimeoutWaitAppliedIndex, + errors.ErrUnhealthy: rpctypes.ErrGRPCUnhealthy, + errors.ErrKeyNotFound: rpctypes.ErrGRPCKeyNotFound, + errors.ErrCorrupt: rpctypes.ErrGRPCCorrupt, + errors.ErrBadLeaderTransferee: rpctypes.ErrGRPCBadLeaderTransferee, + + errors.ErrClusterVersionUnavailable: rpctypes.ErrGRPCClusterVersionUnavailable, + errors.ErrWrongDowngradeVersionFormat: rpctypes.ErrGRPCWrongDowngradeVersionFormat, + version.ErrInvalidDowngradeTargetVersion: rpctypes.ErrGRPCInvalidDowngradeTargetVersion, + version.ErrDowngradeInProcess: rpctypes.ErrGRPCDowngradeInProcess, + version.ErrNoInflightDowngrade: rpctypes.ErrGRPCNoInflightDowngrade, lease.ErrLeaseNotFound: rpctypes.ErrGRPCLeaseNotFound, lease.ErrLeaseExists: rpctypes.ErrGRPCLeaseExist, @@ -94,7 +96,7 @@ var toGRPCErrorMap = map[error]error{ func togRPCError(err error) error { // let gRPC server convert to codes.Canceled, codes.DeadlineExceeded - if err == context.Canceled || err == context.DeadlineExceeded { + if errorspkg.Is(err, context.Canceled) || errorspkg.Is(err, context.DeadlineExceeded) { return err } grpcErr, ok := toGRPCErrorMap[err] @@ -137,7 +139,7 @@ func isClientCtxErr(ctxErr error, err error) bool { } // in v3.4, learner is allowed to serve serializable read and endpoint status -func isRPCSupportedForLearner(req interface{}) bool { +func isRPCSupportedForLearner(req any) bool { switch r := req.(type) { case *pb.StatusRequest: return true diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/watch.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/watch.go index f722788ca0..d4a5bc3514 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/watch.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc/watch.go @@ -16,21 +16,23 @@ package v3rpc import ( "context" - "fmt" + "errors" "io" "math/rand" "sync" "time" + "go.uber.org/zap" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/mvccpb" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" + "go.etcd.io/etcd/client/pkg/v3/verify" clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/server/v3/auth" "go.etcd.io/etcd/server/v3/etcdserver" - "go.etcd.io/etcd/server/v3/mvcc" - - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/etcdserver/apply" + "go.etcd.io/etcd/server/v3/storage/mvcc" ) const minWatchProgressInterval = 100 * time.Millisecond @@ -41,9 +43,9 @@ type watchServer struct { clusterID int64 memberID int64 - maxRequestBytes int + maxRequestBytes uint - sg etcdserver.RaftStatusGetter + sg apply.RaftStatusGetter watchable mvcc.WatchableKV ag AuthGetter } @@ -54,9 +56,9 @@ func NewWatchServer(s *etcdserver.EtcdServer) pb.WatchServer { lg: s.Cfg.Logger, clusterID: int64(s.Cluster().ID()), - memberID: int64(s.ID()), + memberID: int64(s.MemberID()), - maxRequestBytes: int(s.Cfg.MaxRequestBytes + grpcOverheadBytes), + maxRequestBytes: s.Cfg.MaxRequestBytesWithOverhead(), sg: s, watchable: s.Watchable(), @@ -124,9 +126,9 @@ type serverWatchStream struct { clusterID int64 memberID int64 - maxRequestBytes int + maxRequestBytes uint - sg etcdserver.RaftStatusGetter + sg apply.RaftStatusGetter watchable mvcc.WatchableKV ag AuthGetter @@ -210,13 +212,13 @@ func (ws *watchServer) Watch(stream pb.Watch_WatchServer) (err error) { // revisited. select { case err = <-errc: - if err == context.Canceled { + if errors.Is(err, context.Canceled) { err = rpctypes.ErrGRPCWatchCanceled } close(sws.ctrlStream) case <-stream.Context().Done(): err = stream.Context().Err() - if err == context.Canceled { + if errors.Is(err, context.Canceled) { err = rpctypes.ErrGRPCWatchCanceled } } @@ -240,7 +242,7 @@ func (sws *serverWatchStream) isWatchPermitted(wcr *pb.WatchCreateRequest) error func (sws *serverWatchStream) recvLoop() error { for { req, err := sws.gRPCStream.Recv() - if err == io.EOF { + if errors.Is(err, io.EOF) { return nil } if err != nil { @@ -271,15 +273,15 @@ func (sws *serverWatchStream) recvLoop() error { err := sws.isWatchPermitted(creq) if err != nil { var cancelReason string - switch err { - case auth.ErrInvalidAuthToken: + switch { + case errors.Is(err, auth.ErrInvalidAuthToken): cancelReason = rpctypes.ErrGRPCInvalidAuthToken.Error() - case auth.ErrAuthOldRevision: + case errors.Is(err, auth.ErrAuthOldRevision): cancelReason = rpctypes.ErrGRPCAuthOldRevision.Error() - case auth.ErrUserEmpty: + case errors.Is(err, auth.ErrUserEmpty): cancelReason = rpctypes.ErrGRPCUserEmpty.Error() default: - if err != auth.ErrPermissionDenied { + if !errors.Is(err, auth.ErrPermissionDenied) { sws.lg.Error("unexpected error code", zap.Error(err)) } cancelReason = rpctypes.ErrGRPCPermissionDenied.Error() @@ -303,12 +305,7 @@ func (sws *serverWatchStream) recvLoop() error { filters := FiltersFromRequest(creq) - wsrev := sws.watchStream.Rev() - rev := creq.StartRevision - if rev == 0 { - rev = wsrev + 1 - } - id, err := sws.watchStream.Watch(mvcc.WatchID(creq.WatchId), creq.Key, creq.RangeEnd, rev, filters...) + id, err := sws.watchStream.Watch(mvcc.WatchID(creq.WatchId), creq.Key, creq.RangeEnd, creq.StartRevision, filters...) if err == nil { sws.mu.Lock() if creq.ProgressNotify { @@ -326,7 +323,7 @@ func (sws *serverWatchStream) recvLoop() error { } wr := &pb.WatchResponse{ - Header: sws.newResponseHeader(wsrev), + Header: sws.newResponseHeader(sws.watchStream.Rev()), WatchId: int64(id), Created: true, Canceled: err != nil, @@ -371,8 +368,9 @@ func (sws *serverWatchStream) recvLoop() error { } default: // we probably should not shutdown the entire stream when - // receive an valid command. + // receive an invalid command. // so just do nothing instead. + sws.lg.Sugar().Infof("invalid watch request type %T received in gRPC stream", uv) continue } } @@ -495,9 +493,7 @@ func (sws *serverWatchStream) sendLoop() { // track id creation wid := mvcc.WatchID(c.WatchId) - if !(!(c.Canceled && c.Created) || wid == clientv3.InvalidWatchID) { - panic(fmt.Sprintf("unexpected watchId: %d, wanted: %d, since both 'Canceled' and 'Created' are true", wid, clientv3.InvalidWatchID)) - } + verify.Assert(!(c.Canceled && c.Created) || wid == clientv3.InvalidWatchID, "unexpected watchId: %d, wanted: %d, since both 'Canceled' and 'Created' are true", wid, clientv3.InvalidWatchID) if c.Canceled && wid != clientv3.InvalidWatchID { delete(ids, wid) @@ -543,11 +539,12 @@ func IsCreateEvent(e mvccpb.Event) bool { func sendFragments( wr *pb.WatchResponse, - maxRequestBytes int, - sendFunc func(*pb.WatchResponse) error) error { + maxRequestBytes uint, + sendFunc func(*pb.WatchResponse) error, +) error { // no need to fragment if total request size is smaller // than max request limit or response contains only one event - if wr.Size() < maxRequestBytes || len(wr.Events) < 2 { + if uint(wr.Size()) < maxRequestBytes || len(wr.Events) < 2 { return sendFunc(wr) } @@ -560,7 +557,7 @@ func sendFragments( cur := ow for _, ev := range wr.Events[idx:] { cur.Events = append(cur.Events, ev) - if len(cur.Events) > 1 && cur.Size() >= maxRequestBytes { + if len(cur.Events) > 1 && uint(cur.Size()) >= maxRequestBytes { cur.Events = cur.Events[:len(cur.Events)-1] break } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply.go deleted file mode 100644 index 9a3f18d0f4..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply.go +++ /dev/null @@ -1,1167 +0,0 @@ -// Copyright 2016 The etcd 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 etcdserver - -import ( - "bytes" - "context" - "fmt" - "sort" - "strconv" - "time" - - "github.com/coreos/go-semver/semver" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/api/v3/membershippb" - "go.etcd.io/etcd/api/v3/mvccpb" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/pkg/v3/traceutil" - "go.etcd.io/etcd/server/v3/auth" - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - "go.etcd.io/etcd/server/v3/lease" - "go.etcd.io/etcd/server/v3/mvcc" - - "github.com/gogo/protobuf/proto" - "go.uber.org/zap" -) - -const ( - v3Version = "v3" -) - -type applyResult struct { - resp proto.Message - err error - // physc signals the physical effect of the request has completed in addition - // to being logically reflected by the node. Currently only used for - // Compaction requests. - physc <-chan struct{} - trace *traceutil.Trace -} - -// applierV3Internal is the interface for processing internal V3 raft request -type applierV3Internal interface { - ClusterVersionSet(r *membershippb.ClusterVersionSetRequest, shouldApplyV3 membership.ShouldApplyV3) - ClusterMemberAttrSet(r *membershippb.ClusterMemberAttrSetRequest, shouldApplyV3 membership.ShouldApplyV3) - DowngradeInfoSet(r *membershippb.DowngradeInfoSetRequest, shouldApplyV3 membership.ShouldApplyV3) -} - -// applierV3 is the interface for processing V3 raft messages -type applierV3 interface { - Apply(r *pb.InternalRaftRequest, shouldApplyV3 membership.ShouldApplyV3) *applyResult - - Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) - Range(ctx context.Context, txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.RangeResponse, error) - DeleteRange(txn mvcc.TxnWrite, dr *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) - Txn(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) - Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, *traceutil.Trace, error) - - LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) - LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) - - LeaseCheckpoint(lc *pb.LeaseCheckpointRequest) (*pb.LeaseCheckpointResponse, error) - - Alarm(*pb.AlarmRequest) (*pb.AlarmResponse, error) - - Authenticate(r *pb.InternalAuthenticateRequest) (*pb.AuthenticateResponse, error) - - AuthEnable() (*pb.AuthEnableResponse, error) - AuthDisable() (*pb.AuthDisableResponse, error) - AuthStatus() (*pb.AuthStatusResponse, error) - - UserAdd(ua *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) - UserDelete(ua *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) - UserChangePassword(ua *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) - UserGrantRole(ua *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) - UserGet(ua *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) - UserRevokeRole(ua *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) - RoleAdd(ua *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) - RoleGrantPermission(ua *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) - RoleGet(ua *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) - RoleRevokePermission(ua *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) - RoleDelete(ua *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) - UserList(ua *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) - RoleList(ua *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) -} - -type checkReqFunc func(mvcc.ReadView, *pb.RequestOp) error - -type applierV3backend struct { - s *EtcdServer - - checkPut checkReqFunc - checkRange checkReqFunc -} - -func (s *EtcdServer) newApplierV3Backend() applierV3 { - base := &applierV3backend{s: s} - base.checkPut = func(rv mvcc.ReadView, req *pb.RequestOp) error { - return base.checkRequestPut(rv, req) - } - base.checkRange = func(rv mvcc.ReadView, req *pb.RequestOp) error { - return base.checkRequestRange(rv, req) - } - return base -} - -func (s *EtcdServer) newApplierV3Internal() applierV3Internal { - base := &applierV3backend{s: s} - return base -} - -func (s *EtcdServer) newApplierV3() applierV3 { - return newAuthApplierV3( - s.AuthStore(), - newQuotaApplierV3(s, s.newApplierV3Backend()), - s.lessor, - ) -} - -func (a *applierV3backend) Apply(r *pb.InternalRaftRequest, shouldApplyV3 membership.ShouldApplyV3) *applyResult { - op := "unknown" - ar := &applyResult{} - defer func(start time.Time) { - success := ar.err == nil || ar.err == mvcc.ErrCompacted - applySec.WithLabelValues(v3Version, op, strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) - warnOfExpensiveRequest(a.s.Logger(), a.s.Cfg.WarningApplyDuration, start, &pb.InternalRaftStringer{Request: r}, ar.resp, ar.err) - if !success { - warnOfFailedRequest(a.s.Logger(), start, &pb.InternalRaftStringer{Request: r}, ar.resp, ar.err) - } - }(time.Now()) - - switch { - case r.ClusterVersionSet != nil: // Implemented in 3.5.x - op = "ClusterVersionSet" - a.s.applyV3Internal.ClusterVersionSet(r.ClusterVersionSet, shouldApplyV3) - return nil - case r.ClusterMemberAttrSet != nil: - op = "ClusterMemberAttrSet" // Implemented in 3.5.x - a.s.applyV3Internal.ClusterMemberAttrSet(r.ClusterMemberAttrSet, shouldApplyV3) - return nil - case r.DowngradeInfoSet != nil: - op = "DowngradeInfoSet" // Implemented in 3.5.x - a.s.applyV3Internal.DowngradeInfoSet(r.DowngradeInfoSet, shouldApplyV3) - return nil - } - - if !shouldApplyV3 { - return nil - } - - // call into a.s.applyV3.F instead of a.F so upper appliers can check individual calls - switch { - case r.Range != nil: - op = "Range" - ar.resp, ar.err = a.s.applyV3.Range(context.TODO(), nil, r.Range) - case r.Put != nil: - op = "Put" - ar.resp, ar.trace, ar.err = a.s.applyV3.Put(context.TODO(), nil, r.Put) - case r.DeleteRange != nil: - op = "DeleteRange" - ar.resp, ar.err = a.s.applyV3.DeleteRange(nil, r.DeleteRange) - case r.Txn != nil: - op = "Txn" - ar.resp, ar.trace, ar.err = a.s.applyV3.Txn(context.TODO(), r.Txn) - case r.Compaction != nil: - op = "Compaction" - ar.resp, ar.physc, ar.trace, ar.err = a.s.applyV3.Compaction(r.Compaction) - case r.LeaseGrant != nil: - op = "LeaseGrant" - ar.resp, ar.err = a.s.applyV3.LeaseGrant(r.LeaseGrant) - case r.LeaseRevoke != nil: - op = "LeaseRevoke" - ar.resp, ar.err = a.s.applyV3.LeaseRevoke(r.LeaseRevoke) - case r.LeaseCheckpoint != nil: - op = "LeaseCheckpoint" - ar.resp, ar.err = a.s.applyV3.LeaseCheckpoint(r.LeaseCheckpoint) - case r.Alarm != nil: - op = "Alarm" - ar.resp, ar.err = a.s.applyV3.Alarm(r.Alarm) - case r.Authenticate != nil: - op = "Authenticate" - ar.resp, ar.err = a.s.applyV3.Authenticate(r.Authenticate) - case r.AuthEnable != nil: - op = "AuthEnable" - ar.resp, ar.err = a.s.applyV3.AuthEnable() - case r.AuthDisable != nil: - op = "AuthDisable" - ar.resp, ar.err = a.s.applyV3.AuthDisable() - case r.AuthStatus != nil: - ar.resp, ar.err = a.s.applyV3.AuthStatus() - case r.AuthUserAdd != nil: - op = "AuthUserAdd" - ar.resp, ar.err = a.s.applyV3.UserAdd(r.AuthUserAdd) - case r.AuthUserDelete != nil: - op = "AuthUserDelete" - ar.resp, ar.err = a.s.applyV3.UserDelete(r.AuthUserDelete) - case r.AuthUserChangePassword != nil: - op = "AuthUserChangePassword" - ar.resp, ar.err = a.s.applyV3.UserChangePassword(r.AuthUserChangePassword) - case r.AuthUserGrantRole != nil: - op = "AuthUserGrantRole" - ar.resp, ar.err = a.s.applyV3.UserGrantRole(r.AuthUserGrantRole) - case r.AuthUserGet != nil: - op = "AuthUserGet" - ar.resp, ar.err = a.s.applyV3.UserGet(r.AuthUserGet) - case r.AuthUserRevokeRole != nil: - op = "AuthUserRevokeRole" - ar.resp, ar.err = a.s.applyV3.UserRevokeRole(r.AuthUserRevokeRole) - case r.AuthRoleAdd != nil: - op = "AuthRoleAdd" - ar.resp, ar.err = a.s.applyV3.RoleAdd(r.AuthRoleAdd) - case r.AuthRoleGrantPermission != nil: - op = "AuthRoleGrantPermission" - ar.resp, ar.err = a.s.applyV3.RoleGrantPermission(r.AuthRoleGrantPermission) - case r.AuthRoleGet != nil: - op = "AuthRoleGet" - ar.resp, ar.err = a.s.applyV3.RoleGet(r.AuthRoleGet) - case r.AuthRoleRevokePermission != nil: - op = "AuthRoleRevokePermission" - ar.resp, ar.err = a.s.applyV3.RoleRevokePermission(r.AuthRoleRevokePermission) - case r.AuthRoleDelete != nil: - op = "AuthRoleDelete" - ar.resp, ar.err = a.s.applyV3.RoleDelete(r.AuthRoleDelete) - case r.AuthUserList != nil: - op = "AuthUserList" - ar.resp, ar.err = a.s.applyV3.UserList(r.AuthUserList) - case r.AuthRoleList != nil: - op = "AuthRoleList" - ar.resp, ar.err = a.s.applyV3.RoleList(r.AuthRoleList) - default: - a.s.lg.Panic("not implemented apply", zap.Stringer("raft-request", r)) - } - return ar -} - -func (a *applierV3backend) Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (resp *pb.PutResponse, trace *traceutil.Trace, err error) { - resp = &pb.PutResponse{} - resp.Header = &pb.ResponseHeader{} - trace = traceutil.Get(ctx) - // create put tracing if the trace in context is empty - if trace.IsEmpty() { - trace = traceutil.New("put", - a.s.Logger(), - traceutil.Field{Key: "key", Value: string(p.Key)}, - traceutil.Field{Key: "req_size", Value: p.Size()}, - ) - } - val, leaseID := p.Value, lease.LeaseID(p.Lease) - if txn == nil { - if leaseID != lease.NoLease { - if l := a.s.lessor.Lookup(leaseID); l == nil { - return nil, nil, lease.ErrLeaseNotFound - } - } - txn = a.s.KV().Write(trace) - defer txn.End() - } - - var rr *mvcc.RangeResult - if p.IgnoreValue || p.IgnoreLease || p.PrevKv { - trace.StepWithFunction(func() { - rr, err = txn.Range(context.TODO(), p.Key, nil, mvcc.RangeOptions{}) - }, "get previous kv pair") - - if err != nil { - return nil, nil, err - } - } - if p.IgnoreValue || p.IgnoreLease { - if rr == nil || len(rr.KVs) == 0 { - // ignore_{lease,value} flag expects previous key-value pair - return nil, nil, ErrKeyNotFound - } - } - if p.IgnoreValue { - val = rr.KVs[0].Value - } - if p.IgnoreLease { - leaseID = lease.LeaseID(rr.KVs[0].Lease) - } - if p.PrevKv { - if rr != nil && len(rr.KVs) != 0 { - resp.PrevKv = &rr.KVs[0] - } - } - - resp.Header.Revision = txn.Put(p.Key, val, leaseID) - trace.AddField(traceutil.Field{Key: "response_revision", Value: resp.Header.Revision}) - return resp, trace, nil -} - -func (a *applierV3backend) DeleteRange(txn mvcc.TxnWrite, dr *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) { - resp := &pb.DeleteRangeResponse{} - resp.Header = &pb.ResponseHeader{} - end := mkGteRange(dr.RangeEnd) - - if txn == nil { - txn = a.s.kv.Write(traceutil.TODO()) - defer txn.End() - } - - if dr.PrevKv { - rr, err := txn.Range(context.TODO(), dr.Key, end, mvcc.RangeOptions{}) - if err != nil { - return nil, err - } - if rr != nil { - resp.PrevKvs = make([]*mvccpb.KeyValue, len(rr.KVs)) - for i := range rr.KVs { - resp.PrevKvs[i] = &rr.KVs[i] - } - } - } - - resp.Deleted, resp.Header.Revision = txn.DeleteRange(dr.Key, end) - return resp, nil -} - -func (a *applierV3backend) Range(ctx context.Context, txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.RangeResponse, error) { - trace := traceutil.Get(ctx) - - resp := &pb.RangeResponse{} - resp.Header = &pb.ResponseHeader{} - - if txn == nil { - txn = a.s.kv.Read(mvcc.ConcurrentReadTxMode, trace) - defer txn.End() - } - - limit := r.Limit - if r.SortOrder != pb.RangeRequest_NONE || - r.MinModRevision != 0 || r.MaxModRevision != 0 || - r.MinCreateRevision != 0 || r.MaxCreateRevision != 0 { - // fetch everything; sort and truncate afterwards - limit = 0 - } - if limit > 0 { - // fetch one extra for 'more' flag - limit = limit + 1 - } - - ro := mvcc.RangeOptions{ - Limit: limit, - Rev: r.Revision, - Count: r.CountOnly, - } - - rr, err := txn.Range(ctx, r.Key, mkGteRange(r.RangeEnd), ro) - if err != nil { - return nil, err - } - - if r.MaxModRevision != 0 { - f := func(kv *mvccpb.KeyValue) bool { return kv.ModRevision > r.MaxModRevision } - pruneKVs(rr, f) - } - if r.MinModRevision != 0 { - f := func(kv *mvccpb.KeyValue) bool { return kv.ModRevision < r.MinModRevision } - pruneKVs(rr, f) - } - if r.MaxCreateRevision != 0 { - f := func(kv *mvccpb.KeyValue) bool { return kv.CreateRevision > r.MaxCreateRevision } - pruneKVs(rr, f) - } - if r.MinCreateRevision != 0 { - f := func(kv *mvccpb.KeyValue) bool { return kv.CreateRevision < r.MinCreateRevision } - pruneKVs(rr, f) - } - - sortOrder := r.SortOrder - if r.SortTarget != pb.RangeRequest_KEY && sortOrder == pb.RangeRequest_NONE { - // Since current mvcc.Range implementation returns results - // sorted by keys in lexiographically ascending order, - // sort ASCEND by default only when target is not 'KEY' - sortOrder = pb.RangeRequest_ASCEND - } - if sortOrder != pb.RangeRequest_NONE { - var sorter sort.Interface - switch { - case r.SortTarget == pb.RangeRequest_KEY: - sorter = &kvSortByKey{&kvSort{rr.KVs}} - case r.SortTarget == pb.RangeRequest_VERSION: - sorter = &kvSortByVersion{&kvSort{rr.KVs}} - case r.SortTarget == pb.RangeRequest_CREATE: - sorter = &kvSortByCreate{&kvSort{rr.KVs}} - case r.SortTarget == pb.RangeRequest_MOD: - sorter = &kvSortByMod{&kvSort{rr.KVs}} - case r.SortTarget == pb.RangeRequest_VALUE: - sorter = &kvSortByValue{&kvSort{rr.KVs}} - } - switch { - case sortOrder == pb.RangeRequest_ASCEND: - sort.Sort(sorter) - case sortOrder == pb.RangeRequest_DESCEND: - sort.Sort(sort.Reverse(sorter)) - } - } - - if r.Limit > 0 && len(rr.KVs) > int(r.Limit) { - rr.KVs = rr.KVs[:r.Limit] - resp.More = true - } - trace.Step("filter and sort the key-value pairs") - resp.Header.Revision = rr.Rev - resp.Count = int64(rr.Count) - resp.Kvs = make([]*mvccpb.KeyValue, len(rr.KVs)) - for i := range rr.KVs { - if r.KeysOnly { - rr.KVs[i].Value = nil - } - resp.Kvs[i] = &rr.KVs[i] - } - trace.Step("assemble the response") - return resp, nil -} - -func (a *applierV3backend) Txn(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { - lg := a.s.Logger() - trace := traceutil.Get(ctx) - if trace.IsEmpty() { - trace = traceutil.New("transaction", a.s.Logger()) - ctx = context.WithValue(ctx, traceutil.TraceKey, trace) - } - isWrite := !isTxnReadonly(rt) - - // When the transaction contains write operations, we use ReadTx instead of - // ConcurrentReadTx to avoid extra overhead of copying buffer. - var txn mvcc.TxnWrite - if isWrite && a.s.Cfg.ExperimentalTxnModeWriteWithSharedBuffer { - txn = mvcc.NewReadOnlyTxnWrite(a.s.KV().Read(mvcc.SharedBufReadTxMode, trace)) - } else { - txn = mvcc.NewReadOnlyTxnWrite(a.s.KV().Read(mvcc.ConcurrentReadTxMode, trace)) - } - - var txnPath []bool - trace.StepWithFunction( - func() { - txnPath = compareToPath(txn, rt) - }, - "compare", - ) - - if isWrite { - trace.AddField(traceutil.Field{Key: "read_only", Value: false}) - if _, err := checkRequests(txn, rt, txnPath, a.checkPut); err != nil { - txn.End() - return nil, nil, err - } - } - if _, err := checkRequests(txn, rt, txnPath, a.checkRange); err != nil { - txn.End() - return nil, nil, err - } - trace.Step("check requests") - txnResp, _ := newTxnResp(rt, txnPath) - - // When executing mutable txn ops, etcd must hold the txn lock so - // readers do not see any intermediate results. Since writes are - // serialized on the raft loop, the revision in the read view will - // be the revision of the write txn. - if isWrite { - txn.End() - txn = a.s.KV().Write(trace) - } - _, err := a.applyTxn(ctx, txn, rt, txnPath, txnResp) - if err != nil { - if isWrite { - // CAUTION: When a txn performing write operations starts, we always expect it to be successful. - // If a write failure is seen we SHOULD NOT try to recover the server, but crash with a panic to make the failure explicit. - // Trying to silently recover (e.g by ignoring the failed txn or calling txn.End() early) poses serious risks: - // - violation of transaction atomicity if some write operations have been partially executed - // - data inconsistency across different etcd members if they applied the txn asymmetrically - lg.Panic("unexpected error during txn with writes", zap.Error(err)) - } else { - lg.Error("unexpected error during readonly txn", zap.Error(err)) - } - } - rev := txn.Rev() - if len(txn.Changes()) != 0 { - rev++ - } - txn.End() - - txnResp.Header.Revision = rev - trace.AddField( - traceutil.Field{Key: "number_of_response", Value: len(txnResp.Responses)}, - traceutil.Field{Key: "response_revision", Value: txnResp.Header.Revision}, - ) - return txnResp, trace, err -} - -// newTxnResp allocates a txn response for a txn request given a path. -func newTxnResp(rt *pb.TxnRequest, txnPath []bool) (txnResp *pb.TxnResponse, txnCount int) { - reqs := rt.Success - if !txnPath[0] { - reqs = rt.Failure - } - resps := make([]*pb.ResponseOp, len(reqs)) - txnResp = &pb.TxnResponse{ - Responses: resps, - Succeeded: txnPath[0], - Header: &pb.ResponseHeader{}, - } - for i, req := range reqs { - switch tv := req.Request.(type) { - case *pb.RequestOp_RequestRange: - resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseRange{}} - case *pb.RequestOp_RequestPut: - resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponsePut{}} - case *pb.RequestOp_RequestDeleteRange: - resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseDeleteRange{}} - case *pb.RequestOp_RequestTxn: - resp, txns := newTxnResp(tv.RequestTxn, txnPath[1:]) - resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseTxn{ResponseTxn: resp}} - txnPath = txnPath[1+txns:] - txnCount += txns + 1 - default: - } - } - return txnResp, txnCount -} - -func compareToPath(rv mvcc.ReadView, rt *pb.TxnRequest) []bool { - txnPath := make([]bool, 1) - ops := rt.Success - if txnPath[0] = applyCompares(rv, rt.Compare); !txnPath[0] { - ops = rt.Failure - } - for _, op := range ops { - tv, ok := op.Request.(*pb.RequestOp_RequestTxn) - if !ok || tv.RequestTxn == nil { - continue - } - txnPath = append(txnPath, compareToPath(rv, tv.RequestTxn)...) - } - return txnPath -} - -func applyCompares(rv mvcc.ReadView, cmps []*pb.Compare) bool { - for _, c := range cmps { - if !applyCompare(rv, c) { - return false - } - } - return true -} - -// applyCompare applies the compare request. -// If the comparison succeeds, it returns true. Otherwise, returns false. -func applyCompare(rv mvcc.ReadView, c *pb.Compare) bool { - // TODO: possible optimizations - // * chunk reads for large ranges to conserve memory - // * rewrite rules for common patterns: - // ex. "[a, b) createrev > 0" => "limit 1 /\ kvs > 0" - // * caching - rr, err := rv.Range(context.TODO(), c.Key, mkGteRange(c.RangeEnd), mvcc.RangeOptions{}) - if err != nil { - return false - } - if len(rr.KVs) == 0 { - if c.Target == pb.Compare_VALUE { - // Always fail if comparing a value on a key/keys that doesn't exist; - // nil == empty string in grpc; no way to represent missing value - return false - } - return compareKV(c, mvccpb.KeyValue{}) - } - for _, kv := range rr.KVs { - if !compareKV(c, kv) { - return false - } - } - return true -} - -func compareKV(c *pb.Compare, ckv mvccpb.KeyValue) bool { - var result int - rev := int64(0) - switch c.Target { - case pb.Compare_VALUE: - v := []byte{} - if tv, _ := c.TargetUnion.(*pb.Compare_Value); tv != nil { - v = tv.Value - } - result = bytes.Compare(ckv.Value, v) - case pb.Compare_CREATE: - if tv, _ := c.TargetUnion.(*pb.Compare_CreateRevision); tv != nil { - rev = tv.CreateRevision - } - result = compareInt64(ckv.CreateRevision, rev) - case pb.Compare_MOD: - if tv, _ := c.TargetUnion.(*pb.Compare_ModRevision); tv != nil { - rev = tv.ModRevision - } - result = compareInt64(ckv.ModRevision, rev) - case pb.Compare_VERSION: - if tv, _ := c.TargetUnion.(*pb.Compare_Version); tv != nil { - rev = tv.Version - } - result = compareInt64(ckv.Version, rev) - case pb.Compare_LEASE: - if tv, _ := c.TargetUnion.(*pb.Compare_Lease); tv != nil { - rev = tv.Lease - } - result = compareInt64(ckv.Lease, rev) - } - switch c.Result { - case pb.Compare_EQUAL: - return result == 0 - case pb.Compare_NOT_EQUAL: - return result != 0 - case pb.Compare_GREATER: - return result > 0 - case pb.Compare_LESS: - return result < 0 - } - return true -} - -func (a *applierV3backend) applyTxn(ctx context.Context, txn mvcc.TxnWrite, rt *pb.TxnRequest, txnPath []bool, tresp *pb.TxnResponse) (txns int, err error) { - trace := traceutil.Get(ctx) - reqs := rt.Success - if !txnPath[0] { - reqs = rt.Failure - } - - for i, req := range reqs { - respi := tresp.Responses[i].Response - switch tv := req.Request.(type) { - case *pb.RequestOp_RequestRange: - trace.StartSubTrace( - traceutil.Field{Key: "req_type", Value: "range"}, - traceutil.Field{Key: "range_begin", Value: string(tv.RequestRange.Key)}, - traceutil.Field{Key: "range_end", Value: string(tv.RequestRange.RangeEnd)}) - resp, err := a.Range(ctx, txn, tv.RequestRange) - if err != nil { - return 0, fmt.Errorf("applyTxn: failed Range: %w", err) - } - respi.(*pb.ResponseOp_ResponseRange).ResponseRange = resp - trace.StopSubTrace() - case *pb.RequestOp_RequestPut: - trace.StartSubTrace( - traceutil.Field{Key: "req_type", Value: "put"}, - traceutil.Field{Key: "key", Value: string(tv.RequestPut.Key)}, - traceutil.Field{Key: "req_size", Value: tv.RequestPut.Size()}) - resp, _, err := a.Put(ctx, txn, tv.RequestPut) - if err != nil { - return 0, fmt.Errorf("applyTxn: failed Put: %w", err) - } - respi.(*pb.ResponseOp_ResponsePut).ResponsePut = resp - trace.StopSubTrace() - case *pb.RequestOp_RequestDeleteRange: - resp, err := a.DeleteRange(txn, tv.RequestDeleteRange) - if err != nil { - return 0, fmt.Errorf("applyTxn: failed DeleteRange: %w", err) - } - respi.(*pb.ResponseOp_ResponseDeleteRange).ResponseDeleteRange = resp - case *pb.RequestOp_RequestTxn: - resp := respi.(*pb.ResponseOp_ResponseTxn).ResponseTxn - applyTxns, err := a.applyTxn(ctx, txn, tv.RequestTxn, txnPath[1:], resp) - if err != nil { - // don't wrap the error. It's a recursive call and err should be already wrapped - return 0, err - } - txns += applyTxns + 1 - txnPath = txnPath[applyTxns+1:] - default: - // empty union - } - } - return txns, nil -} - -func (a *applierV3backend) Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, *traceutil.Trace, error) { - resp := &pb.CompactionResponse{} - resp.Header = &pb.ResponseHeader{} - trace := traceutil.New("compact", - a.s.Logger(), - traceutil.Field{Key: "revision", Value: compaction.Revision}, - ) - - ch, err := a.s.KV().Compact(trace, compaction.Revision) - if err != nil { - return nil, ch, nil, err - } - // get the current revision. which key to get is not important. - rr, _ := a.s.KV().Range(context.TODO(), []byte("compaction"), nil, mvcc.RangeOptions{}) - resp.Header.Revision = rr.Rev - return resp, ch, trace, err -} - -func (a *applierV3backend) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { - l, err := a.s.lessor.Grant(lease.LeaseID(lc.ID), lc.TTL) - resp := &pb.LeaseGrantResponse{} - if err == nil { - resp.ID = int64(l.ID) - resp.TTL = l.TTL() - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) { - err := a.s.lessor.Revoke(lease.LeaseID(lc.ID)) - return &pb.LeaseRevokeResponse{Header: newHeader(a.s)}, err -} - -func (a *applierV3backend) LeaseCheckpoint(lc *pb.LeaseCheckpointRequest) (*pb.LeaseCheckpointResponse, error) { - for _, c := range lc.Checkpoints { - err := a.s.lessor.Checkpoint(lease.LeaseID(c.ID), c.Remaining_TTL) - if err != nil { - return &pb.LeaseCheckpointResponse{Header: newHeader(a.s)}, err - } - } - return &pb.LeaseCheckpointResponse{Header: newHeader(a.s)}, nil -} - -func (a *applierV3backend) Alarm(ar *pb.AlarmRequest) (*pb.AlarmResponse, error) { - resp := &pb.AlarmResponse{} - oldCount := len(a.s.alarmStore.Get(ar.Alarm)) - - lg := a.s.Logger() - switch ar.Action { - case pb.AlarmRequest_GET: - resp.Alarms = a.s.alarmStore.Get(ar.Alarm) - case pb.AlarmRequest_ACTIVATE: - if ar.Alarm == pb.AlarmType_NONE { - break - } - m := a.s.alarmStore.Activate(types.ID(ar.MemberID), ar.Alarm) - if m == nil { - break - } - resp.Alarms = append(resp.Alarms, m) - activated := oldCount == 0 && len(a.s.alarmStore.Get(m.Alarm)) == 1 - if !activated { - break - } - - lg.Warn("alarm raised", zap.String("alarm", m.Alarm.String()), zap.String("from", types.ID(m.MemberID).String())) - switch m.Alarm { - case pb.AlarmType_CORRUPT: - a.s.applyV3 = newApplierV3Corrupt(a) - case pb.AlarmType_NOSPACE: - a.s.applyV3 = newApplierV3Capped(a) - default: - lg.Panic("unimplemented alarm activation", zap.String("alarm", fmt.Sprintf("%+v", m))) - } - case pb.AlarmRequest_DEACTIVATE: - m := a.s.alarmStore.Deactivate(types.ID(ar.MemberID), ar.Alarm) - if m == nil { - break - } - resp.Alarms = append(resp.Alarms, m) - deactivated := oldCount > 0 && len(a.s.alarmStore.Get(ar.Alarm)) == 0 - if !deactivated { - break - } - - switch m.Alarm { - case pb.AlarmType_NOSPACE, pb.AlarmType_CORRUPT: - // TODO: check kv hash before deactivating CORRUPT? - lg.Warn("alarm disarmed", zap.String("alarm", m.Alarm.String()), zap.String("from", types.ID(m.MemberID).String())) - a.s.applyV3 = a.s.newApplierV3() - default: - lg.Warn("unimplemented alarm deactivation", zap.String("alarm", fmt.Sprintf("%+v", m))) - } - default: - return nil, nil - } - return resp, nil -} - -type applierV3Capped struct { - applierV3 - q backendQuota -} - -// newApplierV3Capped creates an applyV3 that will reject Puts and transactions -// with Puts so that the number of keys in the store is capped. -func newApplierV3Capped(base applierV3) applierV3 { return &applierV3Capped{applierV3: base} } - -func (a *applierV3Capped) Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) { - return nil, nil, ErrNoSpace -} - -func (a *applierV3Capped) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { - if a.q.Cost(r) > 0 { - return nil, nil, ErrNoSpace - } - return a.applierV3.Txn(ctx, r) -} - -func (a *applierV3Capped) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { - return nil, ErrNoSpace -} - -func (a *applierV3backend) AuthEnable() (*pb.AuthEnableResponse, error) { - err := a.s.AuthStore().AuthEnable() - if err != nil { - return nil, err - } - return &pb.AuthEnableResponse{Header: newHeader(a.s)}, nil -} - -func (a *applierV3backend) AuthDisable() (*pb.AuthDisableResponse, error) { - a.s.AuthStore().AuthDisable() - return &pb.AuthDisableResponse{Header: newHeader(a.s)}, nil -} - -func (a *applierV3backend) AuthStatus() (*pb.AuthStatusResponse, error) { - enabled := a.s.AuthStore().IsAuthEnabled() - authRevision := a.s.AuthStore().Revision() - return &pb.AuthStatusResponse{Header: newHeader(a.s), Enabled: enabled, AuthRevision: authRevision}, nil -} - -func (a *applierV3backend) Authenticate(r *pb.InternalAuthenticateRequest) (*pb.AuthenticateResponse, error) { - ctx := context.WithValue(context.WithValue(a.s.ctx, auth.AuthenticateParamIndex{}, a.s.consistIndex.ConsistentIndex()), auth.AuthenticateParamSimpleTokenPrefix{}, r.SimpleToken) - resp, err := a.s.AuthStore().Authenticate(ctx, r.Name, r.Password) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) { - resp, err := a.s.AuthStore().UserAdd(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) UserDelete(r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) { - resp, err := a.s.AuthStore().UserDelete(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) UserChangePassword(r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) { - resp, err := a.s.AuthStore().UserChangePassword(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) { - resp, err := a.s.AuthStore().UserGrantRole(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) { - resp, err := a.s.AuthStore().UserGet(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) UserRevokeRole(r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) { - resp, err := a.s.AuthStore().UserRevokeRole(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) { - resp, err := a.s.AuthStore().RoleAdd(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) RoleGrantPermission(r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) { - resp, err := a.s.AuthStore().RoleGrantPermission(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) { - resp, err := a.s.AuthStore().RoleGet(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) RoleRevokePermission(r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) { - resp, err := a.s.AuthStore().RoleRevokePermission(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) RoleDelete(r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) { - resp, err := a.s.AuthStore().RoleDelete(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) UserList(r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) { - resp, err := a.s.AuthStore().UserList(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) RoleList(r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) { - resp, err := a.s.AuthStore().RoleList(r) - if resp != nil { - resp.Header = newHeader(a.s) - } - return resp, err -} - -func (a *applierV3backend) ClusterVersionSet(r *membershippb.ClusterVersionSetRequest, shouldApplyV3 membership.ShouldApplyV3) { - a.s.cluster.SetVersion(semver.Must(semver.NewVersion(r.Ver)), api.UpdateCapability, shouldApplyV3) -} - -func (a *applierV3backend) ClusterMemberAttrSet(r *membershippb.ClusterMemberAttrSetRequest, shouldApplyV3 membership.ShouldApplyV3) { - a.s.cluster.UpdateAttributes( - types.ID(r.Member_ID), - membership.Attributes{ - Name: r.MemberAttributes.Name, - ClientURLs: r.MemberAttributes.ClientUrls, - }, - shouldApplyV3, - ) -} - -func (a *applierV3backend) DowngradeInfoSet(r *membershippb.DowngradeInfoSetRequest, shouldApplyV3 membership.ShouldApplyV3) { - d := membership.DowngradeInfo{Enabled: false} - if r.Enabled { - d = membership.DowngradeInfo{Enabled: true, TargetVersion: r.Ver} - } - a.s.cluster.SetDowngradeInfo(&d, shouldApplyV3) -} - -type quotaApplierV3 struct { - applierV3 - q Quota -} - -func newQuotaApplierV3(s *EtcdServer, app applierV3) applierV3 { - return "aApplierV3{app, NewBackendQuota(s, "v3-applier")} -} - -func (a *quotaApplierV3) Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) { - ok := a.q.Available(p) - resp, trace, err := a.applierV3.Put(ctx, txn, p) - if err == nil && !ok { - err = ErrNoSpace - } - return resp, trace, err -} - -func (a *quotaApplierV3) Txn(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { - ok := a.q.Available(rt) - resp, trace, err := a.applierV3.Txn(ctx, rt) - if err == nil && !ok { - err = ErrNoSpace - } - return resp, trace, err -} - -func (a *quotaApplierV3) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { - ok := a.q.Available(lc) - resp, err := a.applierV3.LeaseGrant(lc) - if err == nil && !ok { - err = ErrNoSpace - } - return resp, err -} - -type kvSort struct{ kvs []mvccpb.KeyValue } - -func (s *kvSort) Swap(i, j int) { - t := s.kvs[i] - s.kvs[i] = s.kvs[j] - s.kvs[j] = t -} -func (s *kvSort) Len() int { return len(s.kvs) } - -type kvSortByKey struct{ *kvSort } - -func (s *kvSortByKey) Less(i, j int) bool { - return bytes.Compare(s.kvs[i].Key, s.kvs[j].Key) < 0 -} - -type kvSortByVersion struct{ *kvSort } - -func (s *kvSortByVersion) Less(i, j int) bool { - return (s.kvs[i].Version - s.kvs[j].Version) < 0 -} - -type kvSortByCreate struct{ *kvSort } - -func (s *kvSortByCreate) Less(i, j int) bool { - return (s.kvs[i].CreateRevision - s.kvs[j].CreateRevision) < 0 -} - -type kvSortByMod struct{ *kvSort } - -func (s *kvSortByMod) Less(i, j int) bool { - return (s.kvs[i].ModRevision - s.kvs[j].ModRevision) < 0 -} - -type kvSortByValue struct{ *kvSort } - -func (s *kvSortByValue) Less(i, j int) bool { - return bytes.Compare(s.kvs[i].Value, s.kvs[j].Value) < 0 -} - -func checkRequests(rv mvcc.ReadView, rt *pb.TxnRequest, txnPath []bool, f checkReqFunc) (int, error) { - txnCount := 0 - reqs := rt.Success - if !txnPath[0] { - reqs = rt.Failure - } - for _, req := range reqs { - if tv, ok := req.Request.(*pb.RequestOp_RequestTxn); ok && tv.RequestTxn != nil { - txns, err := checkRequests(rv, tv.RequestTxn, txnPath[1:], f) - if err != nil { - return 0, err - } - txnCount += txns + 1 - txnPath = txnPath[txns+1:] - continue - } - if err := f(rv, req); err != nil { - return 0, err - } - } - return txnCount, nil -} - -func (a *applierV3backend) checkRequestPut(rv mvcc.ReadView, reqOp *pb.RequestOp) error { - tv, ok := reqOp.Request.(*pb.RequestOp_RequestPut) - if !ok || tv.RequestPut == nil { - return nil - } - req := tv.RequestPut - if req.IgnoreValue || req.IgnoreLease { - // expects previous key-value, error if not exist - rr, err := rv.Range(context.TODO(), req.Key, nil, mvcc.RangeOptions{}) - if err != nil { - return err - } - if rr == nil || len(rr.KVs) == 0 { - return ErrKeyNotFound - } - } - if lease.LeaseID(req.Lease) != lease.NoLease { - if l := a.s.lessor.Lookup(lease.LeaseID(req.Lease)); l == nil { - return lease.ErrLeaseNotFound - } - } - return nil -} - -func (a *applierV3backend) checkRequestRange(rv mvcc.ReadView, reqOp *pb.RequestOp) error { - tv, ok := reqOp.Request.(*pb.RequestOp_RequestRange) - if !ok || tv.RequestRange == nil { - return nil - } - req := tv.RequestRange - switch { - case req.Revision == 0: - return nil - case req.Revision > rv.Rev(): - return mvcc.ErrFutureRev - case req.Revision < rv.FirstRev(): - return mvcc.ErrCompacted - } - return nil -} - -func compareInt64(a, b int64) int { - switch { - case a < b: - return -1 - case a > b: - return 1 - default: - return 0 - } -} - -// mkGteRange determines if the range end is a >= range. This works around grpc -// sending empty byte strings as nil; >= is encoded in the range end as '\0'. -// If it is a GTE range, then []byte{} is returned to indicate the empty byte -// string (vs nil being no byte string). -func mkGteRange(rangeEnd []byte) []byte { - if len(rangeEnd) == 1 && rangeEnd[0] == 0 { - return []byte{} - } - return rangeEnd -} - -func noSideEffect(r *pb.InternalRaftRequest) bool { - return r.Range != nil || r.AuthUserGet != nil || r.AuthRoleGet != nil || r.AuthStatus != nil -} - -func removeNeedlessRangeReqs(txn *pb.TxnRequest) { - f := func(ops []*pb.RequestOp) []*pb.RequestOp { - j := 0 - for i := 0; i < len(ops); i++ { - if _, ok := ops[i].Request.(*pb.RequestOp_RequestRange); ok { - continue - } - ops[j] = ops[i] - j++ - } - - return ops[:j] - } - - txn.Success = f(txn.Success) - txn.Failure = f(txn.Failure) -} - -func pruneKVs(rr *mvcc.RangeResult, isPrunable func(*mvccpb.KeyValue) bool) { - j := 0 - for i := range rr.KVs { - rr.KVs[j] = rr.KVs[i] - if !isPrunable(&rr.KVs[i]) { - j++ - } - } - rr.KVs = rr.KVs[:j] -} - -func newHeader(s *EtcdServer) *pb.ResponseHeader { - return &pb.ResponseHeader{ - ClusterId: uint64(s.Cluster().ID()), - MemberId: uint64(s.ID()), - Revision: s.KV().Rev(), - RaftTerm: s.Term(), - } -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/apply.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/apply.go new file mode 100644 index 0000000000..e45d53e17b --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/apply.go @@ -0,0 +1,493 @@ +// Copyright 2016 The etcd 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 apply + +import ( + "context" + + "github.com/coreos/go-semver/semver" + "github.com/gogo/protobuf/proto" + "go.uber.org/zap" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/membershippb" + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/pkg/v3/traceutil" + "go.etcd.io/etcd/server/v3/auth" + "go.etcd.io/etcd/server/v3/etcdserver/api" + "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm" + "go.etcd.io/etcd/server/v3/etcdserver/cindex" + "go.etcd.io/etcd/server/v3/etcdserver/errors" + mvcctxn "go.etcd.io/etcd/server/v3/etcdserver/txn" + "go.etcd.io/etcd/server/v3/etcdserver/version" + "go.etcd.io/etcd/server/v3/lease" + serverstorage "go.etcd.io/etcd/server/v3/storage" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/mvcc" +) + +const ( + v3Version = "v3" +) + +// RaftStatusGetter represents etcd server and Raft progress. +type RaftStatusGetter interface { + MemberID() types.ID + Leader() types.ID + CommittedIndex() uint64 + AppliedIndex() uint64 + Term() uint64 +} + +type Result struct { + Resp proto.Message + Err error + // Physc signals the physical effect of the request has completed in addition + // to being logically reflected by the node. Currently, only used for + // Compaction requests. + Physc <-chan struct{} + Trace *traceutil.Trace +} + +type applyFunc func(r *pb.InternalRaftRequest) *Result + +// applierV3 is the interface for processing V3 raft messages +type applierV3 interface { + // Apply executes the generic portion of application logic for the current applier, but + // delegates the actual execution to the applyFunc method. + Apply(r *pb.InternalRaftRequest, applyFunc applyFunc) *Result + + Put(p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) + Range(r *pb.RangeRequest) (*pb.RangeResponse, *traceutil.Trace, error) + DeleteRange(dr *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, *traceutil.Trace, error) + Txn(rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) + Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, *traceutil.Trace, error) + + LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) + LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) + + LeaseCheckpoint(lc *pb.LeaseCheckpointRequest) (*pb.LeaseCheckpointResponse, error) + + Alarm(*pb.AlarmRequest) (*pb.AlarmResponse, error) + + Authenticate(r *pb.InternalAuthenticateRequest) (*pb.AuthenticateResponse, error) + + AuthEnable() (*pb.AuthEnableResponse, error) + AuthDisable() (*pb.AuthDisableResponse, error) + AuthStatus() (*pb.AuthStatusResponse, error) + + UserAdd(ua *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) + UserDelete(ua *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) + UserChangePassword(ua *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) + UserGrantRole(ua *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) + UserGet(ua *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) + UserRevokeRole(ua *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) + RoleAdd(ua *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) + RoleGrantPermission(ua *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) + RoleGet(ua *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) + RoleRevokePermission(ua *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) + RoleDelete(ua *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) + UserList(ua *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) + RoleList(ua *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) +} + +type SnapshotServer interface { + ForceSnapshot() +} + +type applierV3backend struct { + lg *zap.Logger + kv mvcc.KV + alarmStore *v3alarm.AlarmStore + authStore auth.AuthStore + lessor lease.Lessor + cluster *membership.RaftCluster + raftStatus RaftStatusGetter + snapshotServer SnapshotServer + consistentIndex cindex.ConsistentIndexer + + txnModeWriteWithSharedBuffer bool +} + +func newApplierV3Backend( + lg *zap.Logger, + kv mvcc.KV, + alarmStore *v3alarm.AlarmStore, + authStore auth.AuthStore, + lessor lease.Lessor, + cluster *membership.RaftCluster, + raftStatus RaftStatusGetter, + snapshotServer SnapshotServer, + consistentIndex cindex.ConsistentIndexer, + txnModeWriteWithSharedBuffer bool, +) applierV3 { + return &applierV3backend{ + lg: lg, + kv: kv, + alarmStore: alarmStore, + authStore: authStore, + lessor: lessor, + cluster: cluster, + raftStatus: raftStatus, + snapshotServer: snapshotServer, + consistentIndex: consistentIndex, + txnModeWriteWithSharedBuffer: txnModeWriteWithSharedBuffer, + } +} + +func (a *applierV3backend) Apply(r *pb.InternalRaftRequest, applyFunc applyFunc) *Result { + return applyFunc(r) +} + +func (a *applierV3backend) Put(p *pb.PutRequest) (resp *pb.PutResponse, trace *traceutil.Trace, err error) { + return mvcctxn.Put(context.TODO(), a.lg, a.lessor, a.kv, p) +} + +func (a *applierV3backend) DeleteRange(dr *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, *traceutil.Trace, error) { + return mvcctxn.DeleteRange(context.TODO(), a.lg, a.kv, dr) +} + +func (a *applierV3backend) Range(r *pb.RangeRequest) (*pb.RangeResponse, *traceutil.Trace, error) { + return mvcctxn.Range(context.TODO(), a.lg, a.kv, r) +} + +func (a *applierV3backend) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { + return mvcctxn.Txn(context.TODO(), a.lg, rt, a.txnModeWriteWithSharedBuffer, a.kv, a.lessor) +} + +func (a *applierV3backend) Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, *traceutil.Trace, error) { + resp := &pb.CompactionResponse{} + resp.Header = &pb.ResponseHeader{} + trace := traceutil.New("compact", + a.lg, + traceutil.Field{Key: "revision", Value: compaction.Revision}, + ) + + ch, err := a.kv.Compact(trace, compaction.Revision) + if err != nil { + return nil, ch, nil, err + } + // get the current revision. which key to get is not important. + rr, _ := a.kv.Range(context.TODO(), []byte("compaction"), nil, mvcc.RangeOptions{}) + resp.Header.Revision = rr.Rev + return resp, ch, trace, err +} + +func (a *applierV3backend) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { + l, err := a.lessor.Grant(lease.LeaseID(lc.ID), lc.TTL) + resp := &pb.LeaseGrantResponse{} + if err == nil { + resp.ID = int64(l.ID) + resp.TTL = l.TTL() + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) { + err := a.lessor.Revoke(lease.LeaseID(lc.ID)) + return &pb.LeaseRevokeResponse{Header: a.newHeader()}, err +} + +func (a *applierV3backend) LeaseCheckpoint(lc *pb.LeaseCheckpointRequest) (*pb.LeaseCheckpointResponse, error) { + for _, c := range lc.Checkpoints { + err := a.lessor.Checkpoint(lease.LeaseID(c.ID), c.Remaining_TTL) + if err != nil { + return &pb.LeaseCheckpointResponse{Header: a.newHeader()}, err + } + } + return &pb.LeaseCheckpointResponse{Header: a.newHeader()}, nil +} + +func (a *applierV3backend) Alarm(ar *pb.AlarmRequest) (*pb.AlarmResponse, error) { + resp := &pb.AlarmResponse{} + + switch ar.Action { + case pb.AlarmRequest_GET: + resp.Alarms = a.alarmStore.Get(ar.Alarm) + case pb.AlarmRequest_ACTIVATE: + if ar.Alarm == pb.AlarmType_NONE { + break + } + m := a.alarmStore.Activate(types.ID(ar.MemberID), ar.Alarm) + if m == nil { + break + } + resp.Alarms = append(resp.Alarms, m) + alarms.WithLabelValues(types.ID(ar.MemberID).String(), m.Alarm.String()).Inc() + case pb.AlarmRequest_DEACTIVATE: + m := a.alarmStore.Deactivate(types.ID(ar.MemberID), ar.Alarm) + if m == nil { + break + } + resp.Alarms = append(resp.Alarms, m) + alarms.WithLabelValues(types.ID(ar.MemberID).String(), m.Alarm.String()).Dec() + default: + return nil, nil + } + return resp, nil +} + +type applierV3Capped struct { + applierV3 + q serverstorage.BackendQuota +} + +// newApplierV3Capped creates an applyV3 that will reject Puts and transactions +// with Puts so that the number of keys in the store is capped. +func newApplierV3Capped(base applierV3) applierV3 { return &applierV3Capped{applierV3: base} } + +func (a *applierV3Capped) Put(_ *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) { + return nil, nil, errors.ErrNoSpace +} + +func (a *applierV3Capped) Txn(r *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { + if a.q.Cost(r) > 0 { + return nil, nil, errors.ErrNoSpace + } + return a.applierV3.Txn(r) +} + +func (a *applierV3Capped) LeaseGrant(_ *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { + return nil, errors.ErrNoSpace +} + +func (a *applierV3backend) AuthEnable() (*pb.AuthEnableResponse, error) { + err := a.authStore.AuthEnable() + if err != nil { + return nil, err + } + return &pb.AuthEnableResponse{Header: a.newHeader()}, nil +} + +func (a *applierV3backend) AuthDisable() (*pb.AuthDisableResponse, error) { + a.authStore.AuthDisable() + return &pb.AuthDisableResponse{Header: a.newHeader()}, nil +} + +func (a *applierV3backend) AuthStatus() (*pb.AuthStatusResponse, error) { + enabled := a.authStore.IsAuthEnabled() + authRevision := a.authStore.Revision() + return &pb.AuthStatusResponse{Header: a.newHeader(), Enabled: enabled, AuthRevision: authRevision}, nil +} + +func (a *applierV3backend) Authenticate(r *pb.InternalAuthenticateRequest) (*pb.AuthenticateResponse, error) { + ctx := context.WithValue(context.WithValue(context.Background(), auth.AuthenticateParamIndex{}, a.consistentIndex.ConsistentIndex()), auth.AuthenticateParamSimpleTokenPrefix{}, r.SimpleToken) + resp, err := a.authStore.Authenticate(ctx, r.Name, r.Password) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) UserAdd(r *pb.AuthUserAddRequest) (*pb.AuthUserAddResponse, error) { + resp, err := a.authStore.UserAdd(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) UserDelete(r *pb.AuthUserDeleteRequest) (*pb.AuthUserDeleteResponse, error) { + resp, err := a.authStore.UserDelete(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) UserChangePassword(r *pb.AuthUserChangePasswordRequest) (*pb.AuthUserChangePasswordResponse, error) { + resp, err := a.authStore.UserChangePassword(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) UserGrantRole(r *pb.AuthUserGrantRoleRequest) (*pb.AuthUserGrantRoleResponse, error) { + resp, err := a.authStore.UserGrantRole(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) UserGet(r *pb.AuthUserGetRequest) (*pb.AuthUserGetResponse, error) { + resp, err := a.authStore.UserGet(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) UserRevokeRole(r *pb.AuthUserRevokeRoleRequest) (*pb.AuthUserRevokeRoleResponse, error) { + resp, err := a.authStore.UserRevokeRole(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) RoleAdd(r *pb.AuthRoleAddRequest) (*pb.AuthRoleAddResponse, error) { + resp, err := a.authStore.RoleAdd(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) RoleGrantPermission(r *pb.AuthRoleGrantPermissionRequest) (*pb.AuthRoleGrantPermissionResponse, error) { + resp, err := a.authStore.RoleGrantPermission(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) RoleGet(r *pb.AuthRoleGetRequest) (*pb.AuthRoleGetResponse, error) { + resp, err := a.authStore.RoleGet(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) RoleRevokePermission(r *pb.AuthRoleRevokePermissionRequest) (*pb.AuthRoleRevokePermissionResponse, error) { + resp, err := a.authStore.RoleRevokePermission(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) RoleDelete(r *pb.AuthRoleDeleteRequest) (*pb.AuthRoleDeleteResponse, error) { + resp, err := a.authStore.RoleDelete(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) UserList(r *pb.AuthUserListRequest) (*pb.AuthUserListResponse, error) { + resp, err := a.authStore.UserList(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +func (a *applierV3backend) RoleList(r *pb.AuthRoleListRequest) (*pb.AuthRoleListResponse, error) { + resp, err := a.authStore.RoleList(r) + if resp != nil { + resp.Header = a.newHeader() + } + return resp, err +} + +type applierMembership struct { + lg *zap.Logger + cluster *membership.RaftCluster + snapshotServer SnapshotServer +} + +func NewApplierMembership(lg *zap.Logger, cluster *membership.RaftCluster, snapshotServer SnapshotServer) *applierMembership { + return &applierMembership{ + lg: lg, + cluster: cluster, + snapshotServer: snapshotServer, + } +} + +func (a *applierMembership) ClusterVersionSet(r *membershippb.ClusterVersionSetRequest, shouldApplyV3 membership.ShouldApplyV3) { + prevVersion := a.cluster.Version() + newVersion := semver.Must(semver.NewVersion(r.Ver)) + a.cluster.SetVersion(newVersion, api.UpdateCapability, shouldApplyV3) + // Force snapshot after cluster version downgrade. + if prevVersion != nil && newVersion.LessThan(*prevVersion) { + lg := a.lg + if lg != nil { + lg.Info("Cluster version downgrade detected, forcing snapshot", + zap.String("prev-cluster-version", prevVersion.String()), + zap.String("new-cluster-version", newVersion.String()), + ) + } + a.snapshotServer.ForceSnapshot() + } +} + +func (a *applierMembership) ClusterMemberAttrSet(r *membershippb.ClusterMemberAttrSetRequest, shouldApplyV3 membership.ShouldApplyV3) { + a.cluster.UpdateAttributes( + types.ID(r.Member_ID), + membership.Attributes{ + Name: r.MemberAttributes.Name, + ClientURLs: r.MemberAttributes.ClientUrls, + }, + shouldApplyV3, + ) +} + +func (a *applierMembership) DowngradeInfoSet(r *membershippb.DowngradeInfoSetRequest, shouldApplyV3 membership.ShouldApplyV3) { + d := version.DowngradeInfo{Enabled: false} + if r.Enabled { + d = version.DowngradeInfo{Enabled: true, TargetVersion: r.Ver} + } + a.cluster.SetDowngradeInfo(&d, shouldApplyV3) +} + +type quotaApplierV3 struct { + applierV3 + q serverstorage.Quota +} + +func newQuotaApplierV3(lg *zap.Logger, quotaBackendBytesCfg int64, be backend.Backend, app applierV3) applierV3 { + return "aApplierV3{app, serverstorage.NewBackendQuota(lg, quotaBackendBytesCfg, be, "v3-applier")} +} + +func (a *quotaApplierV3) Put(p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) { + ok := a.q.Available(p) + resp, trace, err := a.applierV3.Put(p) + if err == nil && !ok { + err = errors.ErrNoSpace + } + return resp, trace, err +} + +func (a *quotaApplierV3) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { + ok := a.q.Available(rt) + resp, trace, err := a.applierV3.Txn(rt) + if err == nil && !ok { + err = errors.ErrNoSpace + } + return resp, trace, err +} + +func (a *quotaApplierV3) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { + ok := a.q.Available(lc) + resp, err := a.applierV3.LeaseGrant(lc) + if err == nil && !ok { + err = errors.ErrNoSpace + } + return resp, err +} + +func (a *applierV3backend) newHeader() *pb.ResponseHeader { + return &pb.ResponseHeader{ + ClusterId: uint64(a.cluster.ID()), + MemberId: uint64(a.raftStatus.MemberID()), + Revision: a.kv.Rev(), + RaftTerm: a.raftStatus.Term(), + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_auth.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/apply_auth.go similarity index 66% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_auth.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/apply_auth.go index beafa967ba..3922deebd0 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_auth.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/apply_auth.go @@ -12,18 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -package etcdserver +package apply import ( - "context" "sync" pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/server/v3/auth" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "go.etcd.io/etcd/server/v3/etcdserver/txn" "go.etcd.io/etcd/server/v3/lease" - "go.etcd.io/etcd/server/v3/mvcc" ) type authApplierV3 struct { @@ -42,7 +40,7 @@ func newAuthApplierV3(as auth.AuthStore, base applierV3, lessor lease.Lessor) *a return &authApplierV3{applierV3: base, as: as, lessor: lessor} } -func (aa *authApplierV3) Apply(r *pb.InternalRaftRequest, shouldApplyV3 membership.ShouldApplyV3) *applyResult { +func (aa *authApplierV3) Apply(r *pb.InternalRaftRequest, applyFunc applyFunc) *Result { aa.mu.Lock() defer aa.mu.Unlock() if r.Header != nil { @@ -55,16 +53,16 @@ func (aa *authApplierV3) Apply(r *pb.InternalRaftRequest, shouldApplyV3 membersh if err := aa.as.IsAdminPermitted(&aa.authInfo); err != nil { aa.authInfo.Username = "" aa.authInfo.Revision = 0 - return &applyResult{err: err} + return &Result{Err: err} } } - ret := aa.applierV3.Apply(r, shouldApplyV3) + ret := aa.applierV3.Apply(r, applyFunc) aa.authInfo.Username = "" aa.authInfo.Revision = 0 return ret } -func (aa *authApplierV3) Put(ctx context.Context, txn mvcc.TxnWrite, r *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) { +func (aa *authApplierV3) Put(r *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) { if err := aa.as.IsPutPermitted(&aa.authInfo, r.Key); err != nil { return nil, nil, err } @@ -83,90 +81,35 @@ func (aa *authApplierV3) Put(ctx context.Context, txn mvcc.TxnWrite, r *pb.PutRe return nil, nil, err } } - return aa.applierV3.Put(ctx, txn, r) + return aa.applierV3.Put(r) } -func (aa *authApplierV3) Range(ctx context.Context, txn mvcc.TxnRead, r *pb.RangeRequest) (*pb.RangeResponse, error) { +func (aa *authApplierV3) Range(r *pb.RangeRequest) (*pb.RangeResponse, *traceutil.Trace, error) { if err := aa.as.IsRangePermitted(&aa.authInfo, r.Key, r.RangeEnd); err != nil { - return nil, err + return nil, nil, err } - return aa.applierV3.Range(ctx, txn, r) + return aa.applierV3.Range(r) } -func (aa *authApplierV3) DeleteRange(txn mvcc.TxnWrite, r *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) { +func (aa *authApplierV3) DeleteRange(r *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, *traceutil.Trace, error) { if err := aa.as.IsDeleteRangePermitted(&aa.authInfo, r.Key, r.RangeEnd); err != nil { - return nil, err + return nil, nil, err } if r.PrevKv { err := aa.as.IsRangePermitted(&aa.authInfo, r.Key, r.RangeEnd) if err != nil { - return nil, err - } - } - - return aa.applierV3.DeleteRange(txn, r) -} - -func checkTxnReqsPermission(as auth.AuthStore, ai *auth.AuthInfo, reqs []*pb.RequestOp) error { - for _, requ := range reqs { - switch tv := requ.Request.(type) { - case *pb.RequestOp_RequestRange: - if tv.RequestRange == nil { - continue - } - - if err := as.IsRangePermitted(ai, tv.RequestRange.Key, tv.RequestRange.RangeEnd); err != nil { - return err - } - - case *pb.RequestOp_RequestPut: - if tv.RequestPut == nil { - continue - } - - if err := as.IsPutPermitted(ai, tv.RequestPut.Key); err != nil { - return err - } - - case *pb.RequestOp_RequestDeleteRange: - if tv.RequestDeleteRange == nil { - continue - } - - if tv.RequestDeleteRange.PrevKv { - err := as.IsRangePermitted(ai, tv.RequestDeleteRange.Key, tv.RequestDeleteRange.RangeEnd) - if err != nil { - return err - } - } - - err := as.IsDeleteRangePermitted(ai, tv.RequestDeleteRange.Key, tv.RequestDeleteRange.RangeEnd) - if err != nil { - return err - } + return nil, nil, err } } - return nil -} - -func checkTxnAuth(as auth.AuthStore, ai *auth.AuthInfo, rt *pb.TxnRequest) error { - for _, c := range rt.Compare { - if err := as.IsRangePermitted(ai, c.Key, c.RangeEnd); err != nil { - return err - } - } - if err := checkTxnReqsPermission(as, ai, rt.Success); err != nil { - return err - } - return checkTxnReqsPermission(as, ai, rt.Failure) + return aa.applierV3.DeleteRange(r) } -func (aa *authApplierV3) Txn(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { - if err := checkTxnAuth(aa.as, &aa.authInfo, rt); err != nil { +func (aa *authApplierV3) Txn(rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { + if err := txn.CheckTxnAuth(aa.as, &aa.authInfo, rt); err != nil { return nil, nil, err } - return aa.applierV3.Txn(ctx, rt) + return aa.applierV3.Txn(rt) } func (aa *authApplierV3) LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/corrupt.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/corrupt.go new file mode 100644 index 0000000000..c198119510 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/corrupt.go @@ -0,0 +1,55 @@ +// Copyright 2022 The etcd 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 apply + +import ( + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/pkg/v3/traceutil" + "go.etcd.io/etcd/server/v3/etcdserver/errors" +) + +type applierV3Corrupt struct { + applierV3 +} + +func newApplierV3Corrupt(a applierV3) *applierV3Corrupt { return &applierV3Corrupt{a} } + +func (a *applierV3Corrupt) Put(_ *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) { + return nil, nil, errors.ErrCorrupt +} + +func (a *applierV3Corrupt) Range(_ *pb.RangeRequest) (*pb.RangeResponse, *traceutil.Trace, error) { + return nil, nil, errors.ErrCorrupt +} + +func (a *applierV3Corrupt) DeleteRange(_ *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, *traceutil.Trace, error) { + return nil, nil, errors.ErrCorrupt +} + +func (a *applierV3Corrupt) Txn(_ *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { + return nil, nil, errors.ErrCorrupt +} + +func (a *applierV3Corrupt) Compaction(_ *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, *traceutil.Trace, error) { + return nil, nil, nil, errors.ErrCorrupt +} + +func (a *applierV3Corrupt) LeaseGrant(_ *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { + return nil, errors.ErrCorrupt +} + +func (a *applierV3Corrupt) LeaseRevoke(_ *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) { + return nil, errors.ErrCorrupt +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/stats.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/metrics.go similarity index 53% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/stats.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/metrics.go index cbf60215a2..cafbdc7976 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2stats/stats.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/metrics.go @@ -1,4 +1,4 @@ -// Copyright 2015 The etcd Authors +// Copyright 2022 The etcd Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,15 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package v2stats defines a standard interface for etcd cluster statistics. -package v2stats +package apply -type Stats interface { - // SelfStats returns the struct representing statistics of this server - SelfStats() []byte - // LeaderStats returns the statistics of all followers in the cluster - // if this server is leader. Otherwise, nil is returned. - LeaderStats() []byte - // StoreStats returns statistics of the store backing this EtcdServer - StoreStats() []byte +import "github.com/prometheus/client_golang/prometheus" + +var alarms = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd_debugging", + Subsystem: "server", + Name: "alarms", + Help: "Alarms for every member in cluster. 1 for 'server_id' label with current ID. 2 for 'alarm_type' label with type of this alarm", + }, + []string{"server_id", "alarm_type"}, +) + +func init() { + prometheus.MustRegister(alarms) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/uber_applier.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/uber_applier.go new file mode 100644 index 0000000000..ec7e2aae66 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply/uber_applier.go @@ -0,0 +1,228 @@ +// Copyright 2022 The etcd 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 apply + +import ( + "errors" + "time" + + "go.uber.org/zap" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/server/v3/auth" + "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm" + "go.etcd.io/etcd/server/v3/etcdserver/cindex" + "go.etcd.io/etcd/server/v3/etcdserver/txn" + "go.etcd.io/etcd/server/v3/lease" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/mvcc" +) + +type UberApplier interface { + Apply(r *pb.InternalRaftRequest) *Result +} + +type uberApplier struct { + lg *zap.Logger + + alarmStore *v3alarm.AlarmStore + warningApplyDuration time.Duration + + // This is the applier that is taking in consideration current alarms + applyV3 applierV3 + + // This is the applier used for wrapping when alarms change + applyV3base applierV3 +} + +func NewUberApplier( + lg *zap.Logger, + be backend.Backend, + kv mvcc.KV, + alarmStore *v3alarm.AlarmStore, + authStore auth.AuthStore, + lessor lease.Lessor, + cluster *membership.RaftCluster, + raftStatus RaftStatusGetter, + snapshotServer SnapshotServer, + consistentIndex cindex.ConsistentIndexer, + warningApplyDuration time.Duration, + txnModeWriteWithSharedBuffer bool, + quotaBackendBytesCfg int64, +) UberApplier { + applyV3base := newApplierV3(lg, be, kv, alarmStore, authStore, lessor, cluster, raftStatus, snapshotServer, consistentIndex, txnModeWriteWithSharedBuffer, quotaBackendBytesCfg) + + ua := &uberApplier{ + lg: lg, + alarmStore: alarmStore, + warningApplyDuration: warningApplyDuration, + applyV3: applyV3base, + applyV3base: applyV3base, + } + ua.restoreAlarms() + return ua +} + +func newApplierV3( + lg *zap.Logger, + be backend.Backend, + kv mvcc.KV, + alarmStore *v3alarm.AlarmStore, + authStore auth.AuthStore, + lessor lease.Lessor, + cluster *membership.RaftCluster, + raftStatus RaftStatusGetter, + snapshotServer SnapshotServer, + consistentIndex cindex.ConsistentIndexer, + txnModeWriteWithSharedBuffer bool, + quotaBackendBytesCfg int64, +) applierV3 { + applierBackend := newApplierV3Backend(lg, kv, alarmStore, authStore, lessor, cluster, raftStatus, snapshotServer, consistentIndex, txnModeWriteWithSharedBuffer) + return newAuthApplierV3( + authStore, + newQuotaApplierV3(lg, quotaBackendBytesCfg, be, applierBackend), + lessor, + ) +} + +func (a *uberApplier) restoreAlarms() { + noSpaceAlarms := len(a.alarmStore.Get(pb.AlarmType_NOSPACE)) > 0 + corruptAlarms := len(a.alarmStore.Get(pb.AlarmType_CORRUPT)) > 0 + a.applyV3 = a.applyV3base + if noSpaceAlarms { + a.applyV3 = newApplierV3Capped(a.applyV3) + } + if corruptAlarms { + a.applyV3 = newApplierV3Corrupt(a.applyV3) + } +} + +func (a *uberApplier) Apply(r *pb.InternalRaftRequest) *Result { + // We first execute chain of Apply() calls down the hierarchy: + // (i.e. CorruptApplier -> CappedApplier -> Auth -> Quota -> Backend), + // then dispatch() unpacks the request to a specific method (like Put), + // that gets executed down the hierarchy again: + // i.e. CorruptApplier.Put(CappedApplier.Put(...(BackendApplier.Put(...)))). + return a.applyV3.Apply(r, a.dispatch) +} + +// dispatch translates the request (r) into appropriate call (like Put) on +// the underlying applyV3 object. +func (a *uberApplier) dispatch(r *pb.InternalRaftRequest) *Result { + op := "unknown" + ar := &Result{} + defer func(start time.Time) { + success := ar.Err == nil || errors.Is(ar.Err, mvcc.ErrCompacted) + txn.ApplySecObserve(v3Version, op, success, time.Since(start)) + txn.WarnOfExpensiveRequest(a.lg, a.warningApplyDuration, start, &pb.InternalRaftStringer{Request: r}, ar.Resp, ar.Err) + if !success { + txn.WarnOfFailedRequest(a.lg, start, &pb.InternalRaftStringer{Request: r}, ar.Resp, ar.Err) + } + }(time.Now()) + + switch { + case r.Range != nil: + op = "Range" + ar.Resp, ar.Trace, ar.Err = a.applyV3.Range(r.Range) + case r.Put != nil: + op = "Put" + ar.Resp, ar.Trace, ar.Err = a.applyV3.Put(r.Put) + case r.DeleteRange != nil: + op = "DeleteRange" + ar.Resp, ar.Trace, ar.Err = a.applyV3.DeleteRange(r.DeleteRange) + case r.Txn != nil: + op = "Txn" + ar.Resp, ar.Trace, ar.Err = a.applyV3.Txn(r.Txn) + case r.Compaction != nil: + op = "Compaction" + ar.Resp, ar.Physc, ar.Trace, ar.Err = a.applyV3.Compaction(r.Compaction) + case r.LeaseGrant != nil: + op = "LeaseGrant" + ar.Resp, ar.Err = a.applyV3.LeaseGrant(r.LeaseGrant) + case r.LeaseRevoke != nil: + op = "LeaseRevoke" + ar.Resp, ar.Err = a.applyV3.LeaseRevoke(r.LeaseRevoke) + case r.LeaseCheckpoint != nil: + op = "LeaseCheckpoint" + ar.Resp, ar.Err = a.applyV3.LeaseCheckpoint(r.LeaseCheckpoint) + case r.Alarm != nil: + op = "Alarm" + ar.Resp, ar.Err = a.Alarm(r.Alarm) + case r.Authenticate != nil: + op = "Authenticate" + ar.Resp, ar.Err = a.applyV3.Authenticate(r.Authenticate) + case r.AuthEnable != nil: + op = "AuthEnable" + ar.Resp, ar.Err = a.applyV3.AuthEnable() + case r.AuthDisable != nil: + op = "AuthDisable" + ar.Resp, ar.Err = a.applyV3.AuthDisable() + case r.AuthStatus != nil: + ar.Resp, ar.Err = a.applyV3.AuthStatus() + case r.AuthUserAdd != nil: + op = "AuthUserAdd" + ar.Resp, ar.Err = a.applyV3.UserAdd(r.AuthUserAdd) + case r.AuthUserDelete != nil: + op = "AuthUserDelete" + ar.Resp, ar.Err = a.applyV3.UserDelete(r.AuthUserDelete) + case r.AuthUserChangePassword != nil: + op = "AuthUserChangePassword" + ar.Resp, ar.Err = a.applyV3.UserChangePassword(r.AuthUserChangePassword) + case r.AuthUserGrantRole != nil: + op = "AuthUserGrantRole" + ar.Resp, ar.Err = a.applyV3.UserGrantRole(r.AuthUserGrantRole) + case r.AuthUserGet != nil: + op = "AuthUserGet" + ar.Resp, ar.Err = a.applyV3.UserGet(r.AuthUserGet) + case r.AuthUserRevokeRole != nil: + op = "AuthUserRevokeRole" + ar.Resp, ar.Err = a.applyV3.UserRevokeRole(r.AuthUserRevokeRole) + case r.AuthRoleAdd != nil: + op = "AuthRoleAdd" + ar.Resp, ar.Err = a.applyV3.RoleAdd(r.AuthRoleAdd) + case r.AuthRoleGrantPermission != nil: + op = "AuthRoleGrantPermission" + ar.Resp, ar.Err = a.applyV3.RoleGrantPermission(r.AuthRoleGrantPermission) + case r.AuthRoleGet != nil: + op = "AuthRoleGet" + ar.Resp, ar.Err = a.applyV3.RoleGet(r.AuthRoleGet) + case r.AuthRoleRevokePermission != nil: + op = "AuthRoleRevokePermission" + ar.Resp, ar.Err = a.applyV3.RoleRevokePermission(r.AuthRoleRevokePermission) + case r.AuthRoleDelete != nil: + op = "AuthRoleDelete" + ar.Resp, ar.Err = a.applyV3.RoleDelete(r.AuthRoleDelete) + case r.AuthUserList != nil: + op = "AuthUserList" + ar.Resp, ar.Err = a.applyV3.UserList(r.AuthUserList) + case r.AuthRoleList != nil: + op = "AuthRoleList" + ar.Resp, ar.Err = a.applyV3.RoleList(r.AuthRoleList) + default: + a.lg.Panic("not implemented apply", zap.Stringer("raft-request", r)) + } + return ar +} + +func (a *uberApplier) Alarm(ar *pb.AlarmRequest) (*pb.AlarmResponse, error) { + resp, err := a.applyV3.Alarm(ar) + + if ar.Action == pb.AlarmRequest_ACTIVATE || + ar.Action == pb.AlarmRequest_DEACTIVATE { + a.restoreAlarms() + } + return resp, err +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_v2.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_v2.go index 2f5913f18c..60442fcdfd 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_v2.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/apply_v2.go @@ -16,144 +16,49 @@ package etcdserver import ( "encoding/json" - "fmt" + "net/http" "path" - "strconv" - "time" - - "github.com/coreos/go-semver/semver" - "go.etcd.io/etcd/pkg/v3/pbutil" - "go.etcd.io/etcd/server/v3/etcdserver/api" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" "go.uber.org/zap" -) - -const v2Version = "v2" - -// ApplierV2 is the interface for processing V2 raft messages -type ApplierV2 interface { - Delete(r *RequestV2) Response - Post(r *RequestV2) Response - Put(r *RequestV2, shouldApplyV3 membership.ShouldApplyV3) Response - QGet(r *RequestV2) Response - Sync(r *RequestV2) Response -} - -func NewApplierV2(lg *zap.Logger, s v2store.Store, c *membership.RaftCluster) ApplierV2 { - if lg == nil { - lg = zap.NewNop() - } - return &applierV2store{lg: lg, store: s, cluster: c} -} -type applierV2store struct { - lg *zap.Logger - store v2store.Store - cluster *membership.RaftCluster -} + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/membershippb" + "go.etcd.io/etcd/server/v3/etcdserver/api/membership" +) -func (a *applierV2store) Delete(r *RequestV2) Response { - switch { - case r.PrevIndex > 0 || r.PrevValue != "": - return toResponse(a.store.CompareAndDelete(r.Path, r.PrevValue, r.PrevIndex)) - default: - return toResponse(a.store.Delete(r.Path, r.Dir, r.Recursive)) +func v2ToV3Request(lg *zap.Logger, r *RequestV2) pb.InternalRaftRequest { + if r.Method != http.MethodPut || (!storeMemberAttributeRegexp.MatchString(r.Path) && r.Path != membership.StoreClusterVersionKey()) { + lg.Panic("detected disallowed v2 WAL for stage --v2-deprecation=write-only", zap.String("method", r.Method)) } -} - -func (a *applierV2store) Post(r *RequestV2) Response { - return toResponse(a.store.Create(r.Path, r.Dir, r.Val, true, r.TTLOptions())) -} - -func (a *applierV2store) Put(r *RequestV2, shouldApplyV3 membership.ShouldApplyV3) Response { - ttlOptions := r.TTLOptions() - exists, existsSet := pbutil.GetBool(r.PrevExist) - switch { - case existsSet: - if exists { - if r.PrevIndex == 0 && r.PrevValue == "" { - return toResponse(a.store.Update(r.Path, r.Val, ttlOptions)) - } - return toResponse(a.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, ttlOptions)) + if storeMemberAttributeRegexp.MatchString(r.Path) { + id := membership.MustParseMemberIDFromKey(lg, path.Dir(r.Path)) + var attr membership.Attributes + if err := json.Unmarshal([]byte(r.Val), &attr); err != nil { + lg.Panic("failed to unmarshal", zap.String("value", r.Val), zap.Error(err)) } - return toResponse(a.store.Create(r.Path, r.Dir, r.Val, false, ttlOptions)) - case r.PrevIndex > 0 || r.PrevValue != "": - return toResponse(a.store.CompareAndSwap(r.Path, r.PrevValue, r.PrevIndex, r.Val, ttlOptions)) - default: - if storeMemberAttributeRegexp.MatchString(r.Path) { - id := membership.MustParseMemberIDFromKey(a.lg, path.Dir(r.Path)) - var attr membership.Attributes - if err := json.Unmarshal([]byte(r.Val), &attr); err != nil { - a.lg.Panic("failed to unmarshal", zap.String("value", r.Val), zap.Error(err)) - } - if a.cluster != nil { - a.cluster.UpdateAttributes(id, attr, shouldApplyV3) - } - // return an empty response since there is no consumer. - return Response{} + return pb.InternalRaftRequest{ + Header: &pb.RequestHeader{ + ID: r.ID, + }, + ClusterMemberAttrSet: &membershippb.ClusterMemberAttrSetRequest{ + Member_ID: uint64(id), + MemberAttributes: &membershippb.Attributes{ + Name: attr.Name, + ClientUrls: attr.ClientURLs, + }, + }, } - // TODO remove v2 version set to avoid the conflict between v2 and v3 in etcd 3.6 - if r.Path == membership.StoreClusterVersionKey() { - if a.cluster != nil { - // persist to backend given v2store can be very stale - a.cluster.SetVersion(semver.Must(semver.NewVersion(r.Val)), api.UpdateCapability, shouldApplyV3) - } - return Response{} - } - return toResponse(a.store.Set(r.Path, r.Dir, r.Val, ttlOptions)) - } -} - -func (a *applierV2store) QGet(r *RequestV2) Response { - return toResponse(a.store.Get(r.Path, r.Recursive, r.Sorted)) -} - -func (a *applierV2store) Sync(r *RequestV2) Response { - a.store.DeleteExpiredKeys(time.Unix(0, r.Time)) - return Response{} -} - -// applyV2Request interprets r as a call to v2store.X -// and returns a Response interpreted from v2store.Event -func (s *EtcdServer) applyV2Request(r *RequestV2, shouldApplyV3 membership.ShouldApplyV3) (resp Response) { - stringer := panicAlternativeStringer{ - stringer: r, - alternative: func() string { return fmt.Sprintf("id:%d,method:%s,path:%s", r.ID, r.Method, r.Path) }, } - defer func(start time.Time) { - success := resp.Err == nil - applySec.WithLabelValues(v2Version, r.Method, strconv.FormatBool(success)).Observe(time.Since(start).Seconds()) - warnOfExpensiveRequest(s.Logger(), s.Cfg.WarningApplyDuration, start, stringer, nil, nil) - }(time.Now()) - - switch r.Method { - case "POST": - return s.applyV2.Post(r) - case "PUT": - return s.applyV2.Put(r, shouldApplyV3) - case "DELETE": - return s.applyV2.Delete(r) - case "QGET": - return s.applyV2.QGet(r) - case "SYNC": - return s.applyV2.Sync(r) - default: - // This should never be reached, but just in case: - return Response{Err: ErrUnknownMethod} - } -} - -func (r *RequestV2) TTLOptions() v2store.TTLOptionSet { - refresh, _ := pbutil.GetBool(r.Refresh) - ttlOptions := v2store.TTLOptionSet{Refresh: refresh} - if r.Expiration != 0 { - ttlOptions.ExpireTime = time.Unix(0, r.Expiration) + if r.Path == membership.StoreClusterVersionKey() { + return pb.InternalRaftRequest{ + Header: &pb.RequestHeader{ + ID: r.ID, + }, + ClusterVersionSet: &membershippb.ClusterVersionSetRequest{ + Ver: r.Val, + }, + } } - return ttlOptions -} - -func toResponse(ev *v2store.Event, err error) Response { - return Response{Event: ev, Err: err} + lg.Panic("detected disallowed v2 WAL for stage --v2-deprecation=write-only", zap.String("method", r.Method)) + return pb.InternalRaftRequest{} } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/bootstrap.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/bootstrap.go new file mode 100644 index 0000000000..52df5d040c --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/bootstrap.go @@ -0,0 +1,742 @@ +// Copyright 2021 The etcd 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 etcdserver + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "os" + "strings" + "time" + + "github.com/coreos/go-semver/semver" + "github.com/dustin/go-humanize" + "go.uber.org/zap" + + "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/client/pkg/v3/fileutil" + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/pkg/v3/pbutil" + "go.etcd.io/etcd/server/v3/config" + "go.etcd.io/etcd/server/v3/etcdserver/api" + "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" + "go.etcd.io/etcd/server/v3/etcdserver/api/snap" + "go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery" + "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" + "go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery" + "go.etcd.io/etcd/server/v3/etcdserver/cindex" + servererrors "go.etcd.io/etcd/server/v3/etcdserver/errors" + "go.etcd.io/etcd/server/v3/revbump" + serverstorage "go.etcd.io/etcd/server/v3/storage" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" + "go.etcd.io/etcd/server/v3/storage/wal" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" + "go.etcd.io/raft/v3" + "go.etcd.io/raft/v3/raftpb" +) + +func bootstrap(cfg config.ServerConfig) (b *bootstrappedServer, err error) { + if cfg.MaxRequestBytes > recommendedMaxRequestBytes { + cfg.Logger.Warn( + "exceeded recommended request limit", + zap.Uint("max-request-bytes", cfg.MaxRequestBytes), + zap.String("max-request-size", humanize.Bytes(uint64(cfg.MaxRequestBytes))), + zap.Int("recommended-request-bytes", recommendedMaxRequestBytes), + zap.String("recommended-request-size", recommendedMaxRequestBytesString), + ) + } + + if terr := fileutil.TouchDirAll(cfg.Logger, cfg.DataDir); terr != nil { + return nil, fmt.Errorf("cannot access data directory: %w", terr) + } + + if terr := fileutil.TouchDirAll(cfg.Logger, cfg.MemberDir()); terr != nil { + return nil, fmt.Errorf("cannot access member directory: %w", terr) + } + ss := bootstrapSnapshot(cfg) + prt, err := rafthttp.NewRoundTripper(cfg.PeerTLSInfo, cfg.PeerDialTimeout()) + if err != nil { + return nil, err + } + + haveWAL := wal.Exist(cfg.WALDir()) + st := v2store.New(StoreClusterPrefix, StoreKeysPrefix) + backend, err := bootstrapBackend(cfg, haveWAL, st, ss) + if err != nil { + return nil, err + } + var bwal *bootstrappedWAL + + if haveWAL { + if err = fileutil.IsDirWriteable(cfg.WALDir()); err != nil { + return nil, fmt.Errorf("cannot write to WAL directory: %w", err) + } + cfg.Logger.Info("Bootstrapping WAL from snapshot") + bwal = bootstrapWALFromSnapshot(cfg, backend.snapshot, backend.ci) + + if cfg.ForceNewCluster && cfg.ForceNewClusterBumpAmount > 0 { + err = revbump.UnsafeModifyLastRevision(cfg.Logger, cfg.ForceNewClusterBumpAmount, backend.be) + if err != nil { + cfg.Logger.Fatal("failed to modify last revision", zap.Error(err)) + } + } + } + + cfg.Logger.Info("bootstrapping cluster") + cluster, err := bootstrapCluster(cfg, bwal, prt) + if err != nil { + backend.Close() + return nil, err + } + + cfg.Logger.Info("bootstrapping storage") + s := bootstrapStorage(cfg, st, backend, bwal, cluster) + + if err = cluster.Finalize(cfg, s); err != nil { + backend.Close() + return nil, err + } + + cfg.Logger.Info("bootstrapping raft") + raft := bootstrapRaft(cfg, cluster, s.wal) + return &bootstrappedServer{ + prt: prt, + ss: ss, + storage: s, + cluster: cluster, + raft: raft, + }, nil +} + +type bootstrappedServer struct { + storage *bootstrappedStorage + cluster *bootstrappedCluster + raft *bootstrappedRaft + prt http.RoundTripper + ss *snap.Snapshotter +} + +func (s *bootstrappedServer) Close() { + s.storage.Close() +} + +type bootstrappedStorage struct { + backend *bootstrappedBackend + wal *bootstrappedWAL + st v2store.Store +} + +func (s *bootstrappedStorage) Close() { + s.backend.Close() +} + +type bootstrappedBackend struct { + beHooks *serverstorage.BackendHooks + be backend.Backend + ci cindex.ConsistentIndexer + beExist bool + snapshot *raftpb.Snapshot +} + +func (s *bootstrappedBackend) Close() { + s.be.Close() +} + +type bootstrappedCluster struct { + remotes []*membership.Member + cl *membership.RaftCluster + nodeID types.ID +} + +type bootstrappedRaft struct { + lg *zap.Logger + heartbeat time.Duration + + peers []raft.Peer + config *raft.Config + storage *raft.MemoryStorage +} + +func bootstrapStorage(cfg config.ServerConfig, st v2store.Store, be *bootstrappedBackend, wal *bootstrappedWAL, cl *bootstrappedCluster) *bootstrappedStorage { + if wal == nil { + wal = bootstrapNewWAL(cfg, cl) + } + + return &bootstrappedStorage{ + backend: be, + st: st, + wal: wal, + } +} + +func bootstrapSnapshot(cfg config.ServerConfig) *snap.Snapshotter { + if err := fileutil.TouchDirAll(cfg.Logger, cfg.SnapDir()); err != nil { + cfg.Logger.Fatal( + "failed to create snapshot directory", + zap.String("path", cfg.SnapDir()), + zap.Error(err), + ) + } + + if err := fileutil.RemoveMatchFile(cfg.Logger, cfg.SnapDir(), func(fileName string) bool { + return strings.HasPrefix(fileName, "tmp") + }); err != nil { + cfg.Logger.Error( + "failed to remove temp file(s) in snapshot directory", + zap.String("path", cfg.SnapDir()), + zap.Error(err), + ) + } + return snap.New(cfg.Logger, cfg.SnapDir()) +} + +func bootstrapBackend(cfg config.ServerConfig, haveWAL bool, st v2store.Store, ss *snap.Snapshotter) (backend *bootstrappedBackend, err error) { + beExist := fileutil.Exist(cfg.BackendPath()) + ci := cindex.NewConsistentIndex(nil) + beHooks := serverstorage.NewBackendHooks(cfg.Logger, ci) + be := serverstorage.OpenBackend(cfg, beHooks) + defer func() { + if err != nil && be != nil { + be.Close() + } + }() + ci.SetBackend(be) + schema.CreateMetaBucket(be.BatchTx()) + if cfg.BootstrapDefragThresholdMegabytes != 0 { + err = maybeDefragBackend(cfg, be) + if err != nil { + return nil, err + } + } + cfg.Logger.Info("restore consistentIndex", zap.Uint64("index", ci.ConsistentIndex())) + + // TODO(serathius): Implement schema setup in fresh storage + var snapshot *raftpb.Snapshot + if haveWAL { + snapshot, be, err = recoverSnapshot(cfg, st, be, beExist, beHooks, ci, ss) + if err != nil { + return nil, err + } + } + if beExist { + s1, s2 := be.Size(), be.SizeInUse() + cfg.Logger.Info( + "recovered v3 backend", + zap.Int64("backend-size-bytes", s1), + zap.String("backend-size", humanize.Bytes(uint64(s1))), + zap.Int64("backend-size-in-use-bytes", s2), + zap.String("backend-size-in-use", humanize.Bytes(uint64(s2))), + ) + if err = schema.Validate(cfg.Logger, be.ReadTx()); err != nil { + cfg.Logger.Error("Failed to validate schema", zap.Error(err)) + return nil, err + } + } + + return &bootstrappedBackend{ + beHooks: beHooks, + be: be, + ci: ci, + beExist: beExist, + snapshot: snapshot, + }, nil +} + +func maybeDefragBackend(cfg config.ServerConfig, be backend.Backend) error { + size := be.Size() + sizeInUse := be.SizeInUse() + freeableMemory := uint(size - sizeInUse) + thresholdBytes := cfg.BootstrapDefragThresholdMegabytes * 1024 * 1024 + if freeableMemory < thresholdBytes { + cfg.Logger.Info("Skipping defragmentation", + zap.Int64("current-db-size-bytes", size), + zap.String("current-db-size", humanize.Bytes(uint64(size))), + zap.Int64("current-db-size-in-use-bytes", sizeInUse), + zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse))), + zap.Uint("experimental-bootstrap-defrag-threshold-bytes", thresholdBytes), + zap.String("experimental-bootstrap-defrag-threshold", humanize.Bytes(uint64(thresholdBytes))), + ) + return nil + } + return be.Defrag() +} + +func bootstrapCluster(cfg config.ServerConfig, bwal *bootstrappedWAL, prt http.RoundTripper) (c *bootstrappedCluster, err error) { + switch { + case bwal == nil && !cfg.NewCluster: + c, err = bootstrapExistingClusterNoWAL(cfg, prt) + case bwal == nil && cfg.NewCluster: + c, err = bootstrapNewClusterNoWAL(cfg, prt) + case bwal != nil && bwal.haveWAL: + c, err = bootstrapClusterWithWAL(cfg, bwal.meta) + default: + return nil, fmt.Errorf("unsupported bootstrap config") + } + if err != nil { + return nil, err + } + return c, nil +} + +func bootstrapExistingClusterNoWAL(cfg config.ServerConfig, prt http.RoundTripper) (*bootstrappedCluster, error) { + if err := cfg.VerifyJoinExisting(); err != nil { + return nil, err + } + cl, err := membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap, membership.WithMaxLearners(cfg.MaxLearners)) + if err != nil { + return nil, err + } + existingCluster, gerr := GetClusterFromRemotePeers(cfg.Logger, getRemotePeerURLs(cl, cfg.Name), prt) + if gerr != nil { + return nil, fmt.Errorf("cannot fetch cluster info from peer urls: %w", gerr) + } + if err := membership.ValidateClusterAndAssignIDs(cfg.Logger, cl, existingCluster); err != nil { + return nil, fmt.Errorf("error validating peerURLs %s: %w", existingCluster, err) + } + if !isCompatibleWithCluster(cfg.Logger, cl, cl.MemberByName(cfg.Name).ID, prt, cfg.ReqTimeout()) { + return nil, fmt.Errorf("incompatible with current running cluster") + } + scaleUpLearners := false + if err := membership.ValidateMaxLearnerConfig(cfg.MaxLearners, existingCluster.Members(), scaleUpLearners); err != nil { + return nil, err + } + remotes := existingCluster.Members() + cl.SetID(types.ID(0), existingCluster.ID()) + member := cl.MemberByName(cfg.Name) + return &bootstrappedCluster{ + remotes: remotes, + cl: cl, + nodeID: member.ID, + }, nil +} + +func bootstrapNewClusterNoWAL(cfg config.ServerConfig, prt http.RoundTripper) (*bootstrappedCluster, error) { + if err := cfg.VerifyBootstrap(); err != nil { + return nil, err + } + cl, err := membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap, membership.WithMaxLearners(cfg.MaxLearners)) + if err != nil { + return nil, err + } + m := cl.MemberByName(cfg.Name) + if isMemberBootstrapped(cfg.Logger, cl, cfg.Name, prt, cfg.BootstrapTimeoutEffective()) { + return nil, fmt.Errorf("member %s has already been bootstrapped", m.ID) + } + if cfg.ShouldDiscover() { + var str string + if cfg.DiscoveryURL != "" { + cfg.Logger.Warn("V2 discovery is deprecated!") + str, err = v2discovery.JoinCluster(cfg.Logger, cfg.DiscoveryURL, cfg.DiscoveryProxy, m.ID, cfg.InitialPeerURLsMap.String()) + } else { + cfg.Logger.Info("Bootstrapping cluster using v3 discovery.") + str, err = v3discovery.JoinCluster(cfg.Logger, &cfg.DiscoveryCfg, m.ID, cfg.InitialPeerURLsMap.String()) + } + if err != nil { + return nil, &servererrors.DiscoveryError{Op: "join", Err: err} + } + var urlsmap types.URLsMap + urlsmap, err = types.NewURLsMap(str) + if err != nil { + return nil, err + } + if config.CheckDuplicateURL(urlsmap) { + return nil, fmt.Errorf("discovery cluster %s has duplicate url", urlsmap) + } + if cl, err = membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, urlsmap, membership.WithMaxLearners(cfg.MaxLearners)); err != nil { + return nil, err + } + } + return &bootstrappedCluster{ + remotes: nil, + cl: cl, + nodeID: m.ID, + }, nil +} + +func bootstrapClusterWithWAL(cfg config.ServerConfig, meta *snapshotMetadata) (*bootstrappedCluster, error) { + if err := fileutil.IsDirWriteable(cfg.MemberDir()); err != nil { + return nil, fmt.Errorf("cannot write to member directory: %w", err) + } + + if cfg.ShouldDiscover() { + cfg.Logger.Warn( + "discovery token is ignored since cluster already initialized; valid logs are found", + zap.String("wal-dir", cfg.WALDir()), + ) + } + cl := membership.NewCluster(cfg.Logger, membership.WithMaxLearners(cfg.MaxLearners)) + + scaleUpLearners := false + if err := membership.ValidateMaxLearnerConfig(cfg.MaxLearners, cl.Members(), scaleUpLearners); err != nil { + return nil, err + } + + cl.SetID(meta.nodeID, meta.clusterID) + return &bootstrappedCluster{ + cl: cl, + nodeID: meta.nodeID, + }, nil +} + +func recoverSnapshot(cfg config.ServerConfig, st v2store.Store, be backend.Backend, beExist bool, beHooks *serverstorage.BackendHooks, ci cindex.ConsistentIndexer, ss *snap.Snapshotter) (*raftpb.Snapshot, backend.Backend, error) { + // Find a snapshot to start/restart a raft node + walSnaps, err := wal.ValidSnapshotEntries(cfg.Logger, cfg.WALDir()) + if err != nil { + return nil, be, err + } + // snapshot files can be orphaned if etcd crashes after writing them but before writing the corresponding + // bwal log entries + snapshot, err := ss.LoadNewestAvailable(walSnaps) + if err != nil && !errors.Is(err, snap.ErrNoSnapshot) { + return nil, be, err + } + + if snapshot != nil { + if err = st.Recovery(snapshot.Data); err != nil { + cfg.Logger.Panic("failed to recover from snapshot", zap.Error(err)) + } + + if err = serverstorage.AssertNoV2StoreContent(cfg.Logger, st, cfg.V2Deprecation); err != nil { + cfg.Logger.Error("illegal v2store content", zap.Error(err)) + return nil, be, err + } + + cfg.Logger.Info( + "recovered v2 store from snapshot", + zap.Uint64("snapshot-index", snapshot.Metadata.Index), + zap.String("snapshot-size", humanize.Bytes(uint64(snapshot.Size()))), + ) + + if be, err = serverstorage.RecoverSnapshotBackend(cfg, be, *snapshot, beExist, beHooks); err != nil { + cfg.Logger.Panic("failed to recover v3 backend from snapshot", zap.Error(err)) + } + // A snapshot db may have already been recovered, and the old db should have + // already been closed in this case, so we should set the backend again. + ci.SetBackend(be) + + if beExist { + // TODO: remove kvindex != 0 checking when we do not expect users to upgrade + // etcd from pre-3.0 release. + kvindex := ci.ConsistentIndex() + if kvindex < snapshot.Metadata.Index { + if kvindex != 0 { + return nil, be, fmt.Errorf("database file (%v index %d) does not match with snapshot (index %d)", cfg.BackendPath(), kvindex, snapshot.Metadata.Index) + } + cfg.Logger.Warn( + "consistent index was never saved", + zap.Uint64("snapshot-index", snapshot.Metadata.Index), + ) + } + } + } else { + cfg.Logger.Info("No snapshot found. Recovering WAL from scratch!") + } + return snapshot, be, nil +} + +func (c *bootstrappedCluster) Finalize(cfg config.ServerConfig, s *bootstrappedStorage) error { + if !s.wal.haveWAL { + c.cl.SetID(c.nodeID, c.cl.ID()) + } + c.cl.SetStore(s.st) + c.cl.SetBackend(schema.NewMembershipBackend(cfg.Logger, s.backend.be)) + + // Workaround the issues which have already been affected + // by https://github.com/etcd-io/etcd/issues/19557. + c.cl.SyncLearnerPromotionIfNeeded() + + if s.wal.haveWAL { + c.cl.Recover(api.UpdateCapability) + if c.databaseFileMissing(s) { + bepath := cfg.BackendPath() + os.RemoveAll(bepath) + return fmt.Errorf("database file (%v) of the backend is missing", bepath) + } + } + scaleUpLearners := false + return membership.ValidateMaxLearnerConfig(cfg.MaxLearners, c.cl.Members(), scaleUpLearners) +} + +func (c *bootstrappedCluster) databaseFileMissing(s *bootstrappedStorage) bool { + v3Cluster := c.cl.Version() != nil && !c.cl.Version().LessThan(semver.Version{Major: 3}) + return v3Cluster && !s.backend.beExist +} + +func bootstrapRaft(cfg config.ServerConfig, cluster *bootstrappedCluster, bwal *bootstrappedWAL) *bootstrappedRaft { + switch { + case !bwal.haveWAL && !cfg.NewCluster: + return bootstrapRaftFromCluster(cfg, cluster.cl, nil, bwal) + case !bwal.haveWAL && cfg.NewCluster: + return bootstrapRaftFromCluster(cfg, cluster.cl, cluster.cl.MemberIDs(), bwal) + case bwal.haveWAL: + return bootstrapRaftFromWAL(cfg, bwal) + default: + cfg.Logger.Panic("unsupported bootstrap config") + return nil + } +} + +func bootstrapRaftFromCluster(cfg config.ServerConfig, cl *membership.RaftCluster, ids []types.ID, bwal *bootstrappedWAL) *bootstrappedRaft { + member := cl.MemberByName(cfg.Name) + peers := make([]raft.Peer, len(ids)) + for i, id := range ids { + var ctx []byte + ctx, err := json.Marshal((*cl).Member(id)) + if err != nil { + cfg.Logger.Panic("failed to marshal member", zap.Error(err)) + } + peers[i] = raft.Peer{ID: uint64(id), Context: ctx} + } + cfg.Logger.Info( + "starting local member", + zap.String("local-member-id", member.ID.String()), + zap.String("cluster-id", cl.ID().String()), + ) + s := bwal.MemoryStorage() + return &bootstrappedRaft{ + lg: cfg.Logger, + heartbeat: time.Duration(cfg.TickMs) * time.Millisecond, + config: raftConfig(cfg, uint64(member.ID), s), + peers: peers, + storage: s, + } +} + +func bootstrapRaftFromWAL(cfg config.ServerConfig, bwal *bootstrappedWAL) *bootstrappedRaft { + s := bwal.MemoryStorage() + return &bootstrappedRaft{ + lg: cfg.Logger, + heartbeat: time.Duration(cfg.TickMs) * time.Millisecond, + config: raftConfig(cfg, uint64(bwal.meta.nodeID), s), + storage: s, + } +} + +func raftConfig(cfg config.ServerConfig, id uint64, s *raft.MemoryStorage) *raft.Config { + return &raft.Config{ + ID: id, + ElectionTick: cfg.ElectionTicks, + HeartbeatTick: 1, + Storage: s, + MaxSizePerMsg: maxSizePerMsg, + MaxInflightMsgs: maxInflightMsgs, + CheckQuorum: true, + PreVote: cfg.PreVote, + Logger: NewRaftLoggerZap(cfg.Logger.Named("raft")), + } +} + +func (b *bootstrappedRaft) newRaftNode(ss *snap.Snapshotter, wal *wal.WAL, cl *membership.RaftCluster) *raftNode { + var n raft.Node + if len(b.peers) == 0 { + n = raft.RestartNode(b.config) + } else { + n = raft.StartNode(b.config, b.peers) + } + raftStatusMu.Lock() + raftStatus = n.Status + raftStatusMu.Unlock() + return newRaftNode( + raftNodeConfig{ + lg: b.lg, + isIDRemoved: func(id uint64) bool { return cl.IsIDRemoved(types.ID(id)) }, + Node: n, + heartbeat: b.heartbeat, + raftStorage: b.storage, + storage: serverstorage.NewStorage(b.lg, wal, ss), + }, + ) +} + +func bootstrapWALFromSnapshot(cfg config.ServerConfig, snapshot *raftpb.Snapshot, ci cindex.ConsistentIndexer) *bootstrappedWAL { + wal, st, ents, snap, meta := openWALFromSnapshot(cfg, snapshot) + bwal := &bootstrappedWAL{ + lg: cfg.Logger, + w: wal, + st: st, + ents: ents, + snapshot: snap, + meta: meta, + haveWAL: true, + } + + if cfg.ForceNewCluster { + consistentIndex := ci.ConsistentIndex() + oldCommitIndex := bwal.st.Commit + // If only `HardState.Commit` increases, HardState won't be persisted + // to disk, even though the committed entries might have already been + // applied. This can result in consistent_index > CommitIndex. + // + // When restarting etcd with `--force-new-cluster`, all uncommitted + // entries are dropped. To avoid losing entries that were actually + // committed, we reset Commit to max(HardState.Commit, consistent_index). + // + // See: https://github.com/etcd-io/raft/pull/300 for more details. + bwal.st.Commit = max(oldCommitIndex, consistentIndex) + + // discard the previously uncommitted entries + bwal.ents = bwal.CommitedEntries() + entries := bwal.NewConfigChangeEntries() + // force commit config change entries + bwal.AppendAndCommitEntries(entries) + + cfg.Logger.Info( + "forcing restart member", + zap.String("cluster-id", meta.clusterID.String()), + zap.String("local-member-id", meta.nodeID.String()), + zap.Uint64("wal-commit-index", oldCommitIndex), + zap.Uint64("commit-index", bwal.st.Commit), + ) + } else { + cfg.Logger.Info( + "restarting local member", + zap.String("cluster-id", meta.clusterID.String()), + zap.String("local-member-id", meta.nodeID.String()), + zap.Uint64("commit-index", bwal.st.Commit), + ) + } + return bwal +} + +// openWALFromSnapshot reads the WAL at the given snap and returns the wal, its latest HardState and cluster ID, and all entries that appear +// after the position of the given snap in the WAL. +// The snap must have been previously saved to the WAL, or this call will panic. +func openWALFromSnapshot(cfg config.ServerConfig, snapshot *raftpb.Snapshot) (*wal.WAL, *raftpb.HardState, []raftpb.Entry, *raftpb.Snapshot, *snapshotMetadata) { + var walsnap walpb.Snapshot + if snapshot != nil { + walsnap.Index, walsnap.Term = snapshot.Metadata.Index, snapshot.Metadata.Term + } + repaired := false + for { + w, err := wal.Open(cfg.Logger, cfg.WALDir(), walsnap) + if err != nil { + cfg.Logger.Fatal("failed to open WAL", zap.Error(err)) + } + if cfg.UnsafeNoFsync { + w.SetUnsafeNoFsync() + } + wmetadata, st, ents, err := w.ReadAll() + if err != nil { + w.Close() + // we can only repair ErrUnexpectedEOF and we never repair twice. + if repaired || !errors.Is(err, io.ErrUnexpectedEOF) { + cfg.Logger.Fatal("failed to read WAL, cannot be repaired", zap.Error(err)) + } + if !wal.Repair(cfg.Logger, cfg.WALDir()) { + cfg.Logger.Fatal("failed to repair WAL", zap.Error(err)) + } else { + cfg.Logger.Info("repaired WAL", zap.Error(err)) + repaired = true + } + continue + } + var metadata etcdserverpb.Metadata + pbutil.MustUnmarshal(&metadata, wmetadata) + id := types.ID(metadata.NodeID) + cid := types.ID(metadata.ClusterID) + meta := &snapshotMetadata{clusterID: cid, nodeID: id} + return w, &st, ents, snapshot, meta + } +} + +type snapshotMetadata struct { + nodeID, clusterID types.ID +} + +func bootstrapNewWAL(cfg config.ServerConfig, cl *bootstrappedCluster) *bootstrappedWAL { + metadata := pbutil.MustMarshal( + &etcdserverpb.Metadata{ + NodeID: uint64(cl.nodeID), + ClusterID: uint64(cl.cl.ID()), + }, + ) + w, err := wal.Create(cfg.Logger, cfg.WALDir(), metadata) + if err != nil { + cfg.Logger.Panic("failed to create WAL", zap.Error(err)) + } + if cfg.UnsafeNoFsync { + w.SetUnsafeNoFsync() + } + return &bootstrappedWAL{ + lg: cfg.Logger, + w: w, + } +} + +type bootstrappedWAL struct { + lg *zap.Logger + + haveWAL bool + w *wal.WAL + st *raftpb.HardState + ents []raftpb.Entry + snapshot *raftpb.Snapshot + meta *snapshotMetadata +} + +func (wal *bootstrappedWAL) MemoryStorage() *raft.MemoryStorage { + s := raft.NewMemoryStorage() + if wal.snapshot != nil { + s.ApplySnapshot(*wal.snapshot) + } + if wal.st != nil { + s.SetHardState(*wal.st) + } + if len(wal.ents) != 0 { + s.Append(wal.ents) + } + return s +} + +func (wal *bootstrappedWAL) CommitedEntries() []raftpb.Entry { + for i, ent := range wal.ents { + if ent.Index > wal.st.Commit { + wal.lg.Info( + "discarding uncommitted WAL entries", + zap.Uint64("entry-index", ent.Index), + zap.Uint64("commit-index-from-wal", wal.st.Commit), + zap.Int("number-of-discarded-entries", len(wal.ents)-i), + ) + return wal.ents[:i] + } + } + return wal.ents +} + +func (wal *bootstrappedWAL) NewConfigChangeEntries() []raftpb.Entry { + return serverstorage.CreateConfigChangeEnts( + wal.lg, + serverstorage.GetEffectiveNodeIDsFromWALEntries(wal.lg, wal.snapshot, wal.ents), + uint64(wal.meta.nodeID), + wal.st.Term, + wal.st.Commit, + ) +} + +func (wal *bootstrappedWAL) AppendAndCommitEntries(ents []raftpb.Entry) { + wal.ents = append(wal.ents, ents...) + err := wal.w.Save(raftpb.HardState{}, ents) + if err != nil { + wal.lg.Fatal("failed to save hard state and entries", zap.Error(err)) + } + if len(wal.ents) != 0 { + wal.st.Commit = wal.ents[len(wal.ents)-1].Index + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/cindex.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/cindex.go index ac6ae63742..b865742014 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/cindex.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/cindex/cindex.go @@ -15,22 +15,19 @@ package cindex import ( - "encoding/binary" "sync" "sync/atomic" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" ) type Backend interface { - BatchTx() backend.BatchTx ReadTx() backend.ReadTx } // ConsistentIndexer is an interface that wraps the Get/Set/Save method for consistentIndex. type ConsistentIndexer interface { - // ConsistentIndex returns the consistent index of current executing entry. ConsistentIndex() uint64 @@ -48,7 +45,7 @@ type ConsistentIndexer interface { // UnsafeSave must be called holding the lock on the tx. // It saves consistentIndex to the underlying stable storage. - UnsafeSave(tx backend.BatchTx) + UnsafeSave(tx backend.UnsafeReadWriter) // SetBackend set the available backend.BatchTx for ConsistentIndexer. SetBackend(be Backend) @@ -68,6 +65,13 @@ type consistentIndex struct { // applyingIndex and applyingTerm are just temporary cache of the raftpb.Entry.Index // and raftpb.Entry.Term, and they are not ready to be persisted yet. They will be // saved to consistentIndex and term above in the txPostLockInsideApplyHook. + // + // TODO(ahrtr): try to remove the OnPreCommitUnsafe, and compare the + // performance difference. Afterwards we can make a decision on whether + // or not we should remove OnPreCommitUnsafe. If it is true, then we + // can remove applyingIndex and applyingTerm, and save the e.Index and + // e.Term to consistentIndex and term directly in applyEntries, and + // persist them into db in the txPostLockInsideApplyHook. applyingIndex uint64 applyingTerm uint64 @@ -90,7 +94,7 @@ func (ci *consistentIndex) ConsistentIndex() uint64 { ci.mutex.Lock() defer ci.mutex.Unlock() - v, term := ReadConsistentIndex(ci.be.ReadTx()) + v, term := schema.ReadConsistentIndex(ci.be.ReadTx()) ci.SetConsistentIndex(v, term) return v } @@ -100,7 +104,7 @@ func (ci *consistentIndex) UnsafeConsistentIndex() uint64 { return index } - v, term := unsafeReadConsistentIndex(ci.be.ReadTx()) + v, term := schema.UnsafeReadConsistentIndex(ci.be.ReadTx()) ci.SetConsistentIndex(v, term) return v } @@ -110,10 +114,10 @@ func (ci *consistentIndex) SetConsistentIndex(v uint64, term uint64) { atomic.StoreUint64(&ci.term, term) } -func (ci *consistentIndex) UnsafeSave(tx backend.BatchTx) { +func (ci *consistentIndex) UnsafeSave(tx backend.UnsafeReadWriter) { index := atomic.LoadUint64(&ci.consistentIndex) term := atomic.LoadUint64(&ci.term) - UnsafeUpdateConsistentIndex(tx, index, term) + schema.UnsafeUpdateConsistentIndex(tx, index, term) } func (ci *consistentIndex) SetBackend(be Backend) { @@ -145,9 +149,11 @@ type fakeConsistentIndex struct { func (f *fakeConsistentIndex) ConsistentIndex() uint64 { return atomic.LoadUint64(&f.index) } + func (f *fakeConsistentIndex) ConsistentApplyingIndex() (uint64, uint64) { return atomic.LoadUint64(&f.index), atomic.LoadUint64(&f.term) } + func (f *fakeConsistentIndex) UnsafeConsistentIndex() uint64 { return atomic.LoadUint64(&f.index) } @@ -156,71 +162,17 @@ func (f *fakeConsistentIndex) SetConsistentIndex(index uint64, term uint64) { atomic.StoreUint64(&f.index, index) atomic.StoreUint64(&f.term, term) } + func (f *fakeConsistentIndex) SetConsistentApplyingIndex(index uint64, term uint64) { atomic.StoreUint64(&f.index, index) atomic.StoreUint64(&f.term, term) } -func (f *fakeConsistentIndex) UnsafeSave(_ backend.BatchTx) {} -func (f *fakeConsistentIndex) SetBackend(_ Backend) {} - -// UnsafeCreateMetaBucket creates the `meta` bucket (if it does not exists yet). -func UnsafeCreateMetaBucket(tx backend.BatchTx) { - tx.UnsafeCreateBucket(buckets.Meta) -} - -// CreateMetaBucket creates the `meta` bucket (if it does not exists yet). -func CreateMetaBucket(tx backend.BatchTx) { - tx.LockOutsideApply() - defer tx.Unlock() - tx.UnsafeCreateBucket(buckets.Meta) -} - -// unsafeGetConsistentIndex loads consistent index & term from given transaction. -// returns 0,0 if the data are not found. -// Term is persisted since v3.5. -func unsafeReadConsistentIndex(tx backend.ReadTx) (uint64, uint64) { - _, vs := tx.UnsafeRange(buckets.Meta, buckets.MetaConsistentIndexKeyName, nil, 0) - if len(vs) == 0 { - return 0, 0 - } - v := binary.BigEndian.Uint64(vs[0]) - _, ts := tx.UnsafeRange(buckets.Meta, buckets.MetaTermKeyName, nil, 0) - if len(ts) == 0 { - return v, 0 - } - t := binary.BigEndian.Uint64(ts[0]) - return v, t -} - -// ReadConsistentIndex loads consistent index and term from given transaction. -// returns 0 if the data are not found. -func ReadConsistentIndex(tx backend.ReadTx) (uint64, uint64) { - tx.Lock() - defer tx.Unlock() - return unsafeReadConsistentIndex(tx) -} - -func UnsafeUpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64) { - if index == 0 { - // Never save 0 as it means that we didn't loaded the real index yet. - return - } - - bs1 := make([]byte, 8) - binary.BigEndian.PutUint64(bs1, index) - // put the index into the underlying backend - // tx has been locked in TxnBegin, so there is no need to lock it again - tx.UnsafePut(buckets.Meta, buckets.MetaConsistentIndexKeyName, bs1) - if term > 0 { - bs2 := make([]byte, 8) - binary.BigEndian.PutUint64(bs2, term) - tx.UnsafePut(buckets.Meta, buckets.MetaTermKeyName, bs2) - } -} +func (f *fakeConsistentIndex) UnsafeSave(_ backend.UnsafeReadWriter) {} +func (f *fakeConsistentIndex) SetBackend(_ Backend) {} -func UpdateConsistentIndex(tx backend.BatchTx, index uint64, term uint64) { +func UpdateConsistentIndexForce(tx backend.BatchTx, index uint64, term uint64) { tx.LockOutsideApply() defer tx.Unlock() - UnsafeUpdateConsistentIndex(tx, index, term) + schema.UnsafeUpdateConsistentIndexForce(tx, index, term) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/cluster_util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/cluster_util.go index eace8f69af..425ed971cd 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/cluster_util.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/cluster_util.go @@ -18,19 +18,21 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "sort" "strconv" "strings" "time" + "github.com/coreos/go-semver/semver" + "go.uber.org/zap" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - - "github.com/coreos/go-semver/semver" - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" + "go.etcd.io/etcd/server/v3/etcdserver/errors" ) // isMemberBootstrapped tries to check if the given member has been bootstrapped @@ -83,7 +85,7 @@ func getClusterFromRemotePeers(lg *zap.Logger, urls []string, timeout time.Durat } continue } - b, err := ioutil.ReadAll(resp.Body) + b, err := io.ReadAll(resp.Body) resp.Body.Close() if err != nil { if logerr { @@ -137,11 +139,11 @@ func getRemotePeerURLs(cl *membership.RaftCluster, local string) []string { return us } -// getVersions returns the versions of the members in the given cluster. +// getMembersVersions returns the versions of the members in the given cluster. // The key of the returned map is the member's ID. The value of the returned map // is the semver versions string, including server and cluster. // If it fails to get the version of a member, the key will be nil. -func getVersions(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) map[string]*version.Versions { +func getMembersVersions(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper, timeout time.Duration) map[string]*version.Versions { members := cl.Members() vers := make(map[string]*version.Versions) for _, m := range members { @@ -153,7 +155,7 @@ func getVersions(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt vers[m.ID.String()] = &version.Versions{Server: version.Version, Cluster: cv} continue } - ver, err := getVersion(lg, m, rt) + ver, err := getVersion(lg, m, rt, timeout) if err != nil { lg.Warn("failed to get version", zap.String("remote-member-id", m.ID.String()), zap.Error(err)) vers[m.ID.String()] = nil @@ -164,44 +166,6 @@ func getVersions(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt return vers } -// decideClusterVersion decides the cluster version based on the versions map. -// The returned version is the min server version in the map, or nil if the min -// version in unknown. -func decideClusterVersion(lg *zap.Logger, vers map[string]*version.Versions) *semver.Version { - var cv *semver.Version - lv := semver.Must(semver.NewVersion(version.Version)) - - for mid, ver := range vers { - if ver == nil { - return nil - } - v, err := semver.NewVersion(ver.Server) - if err != nil { - lg.Warn( - "failed to parse server version of remote member", - zap.String("remote-member-id", mid), - zap.String("remote-member-version", ver.Server), - zap.Error(err), - ) - return nil - } - if lv.LessThan(*v) { - lg.Warn( - "leader found higher-versioned member", - zap.String("local-member-version", lv.String()), - zap.String("remote-member-id", mid), - zap.String("remote-member-version", ver.Server), - ) - } - if cv == nil { - cv = v - } else if v.LessThan(*cv) { - cv = v - } - } - return cv -} - // allowedVersionRange decides the available version range of the cluster that local server can join in; // if the downgrade enabled status is true, the version window is [oneMinorHigher, oneMinorHigher] // if the downgrade is not enabled, the version window is [MinClusterVersion, localVersion] @@ -224,9 +188,9 @@ func allowedVersionRange(downgradeEnabled bool) (minV *semver.Version, maxV *sem // cluster version in the range of [MinV, MaxV] and no known members has a cluster version // out of the range. // We set this rule since when the local member joins, another member might be offline. -func isCompatibleWithCluster(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) bool { - vers := getVersions(lg, cl, local, rt) - minV, maxV := allowedVersionRange(getDowngradeEnabledFromRemotePeers(lg, cl, local, rt)) +func isCompatibleWithCluster(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper, timeout time.Duration) bool { + vers := getMembersVersions(lg, cl, local, rt, timeout) + minV, maxV := allowedVersionRange(getDowngradeEnabledFromRemotePeers(lg, cl, local, rt, timeout)) return isCompatibleWithVers(lg, vers, local, minV, maxV) } @@ -264,7 +228,7 @@ func isCompatibleWithVers(lg *zap.Logger, vers map[string]*version.Versions, loc "cluster version of remote member is not compatible; too high", zap.String("remote-member-id", id), zap.String("remote-member-cluster-version", clusterv.String()), - zap.String("minimum-cluster-version-supported", minV.String()), + zap.String("maximum-cluster-version-supported", maxV.String()), ) return false } @@ -275,9 +239,10 @@ func isCompatibleWithVers(lg *zap.Logger, vers map[string]*version.Versions, loc // getVersion returns the Versions of the given member via its // peerURLs. Returns the last error if it fails to get the version. -func getVersion(lg *zap.Logger, m *membership.Member, rt http.RoundTripper) (*version.Versions, error) { +func getVersion(lg *zap.Logger, m *membership.Member, rt http.RoundTripper, timeout time.Duration) (*version.Versions, error) { cc := &http.Client{ Transport: rt, + Timeout: timeout, CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, @@ -300,7 +265,7 @@ func getVersion(lg *zap.Logger, m *membership.Member, rt http.RoundTripper) (*ve continue } var b []byte - b, err = ioutil.ReadAll(resp.Body) + b, err = io.ReadAll(resp.Body) resp.Body.Close() if err != nil { lg.Warn( @@ -335,8 +300,8 @@ func promoteMemberHTTP(ctx context.Context, url string, id uint64, peerRt http.R } // TODO: refactor member http handler code // cannot import etcdhttp, so manually construct url - requestUrl := url + "/members/promote/" + fmt.Sprintf("%d", id) - req, err := http.NewRequest("POST", requestUrl, nil) + requestURL := url + "/members/promote/" + fmt.Sprintf("%d", id) + req, err := http.NewRequest(http.MethodPost, requestURL, nil) if err != nil { return nil, err } @@ -346,30 +311,30 @@ func promoteMemberHTTP(ctx context.Context, url string, id uint64, peerRt http.R return nil, err } defer resp.Body.Close() - b, err := ioutil.ReadAll(resp.Body) + b, err := io.ReadAll(resp.Body) if err != nil { return nil, err } if resp.StatusCode == http.StatusRequestTimeout { - return nil, ErrTimeout + return nil, errors.ErrTimeout } if resp.StatusCode == http.StatusPreconditionFailed { // both ErrMemberNotLearner and ErrLearnerNotReady have same http status code - if strings.Contains(string(b), ErrLearnerNotReady.Error()) { - return nil, ErrLearnerNotReady + if strings.Contains(string(b), errors.ErrLearnerNotReady.Error()) { + return nil, errors.ErrLearnerNotReady } if strings.Contains(string(b), membership.ErrMemberNotLearner.Error()) { return nil, membership.ErrMemberNotLearner } - return nil, fmt.Errorf("member promote: unknown error(%s)", string(b)) + return nil, fmt.Errorf("member promote: unknown error(%s)", b) } if resp.StatusCode == http.StatusNotFound { return nil, membership.ErrIDNotFound } if resp.StatusCode != http.StatusOK { // all other types of errors - return nil, fmt.Errorf("member promote: unknown error(%s)", string(b)) + return nil, fmt.Errorf("member promote: unknown error(%s)", b) } var membs []*membership.Member @@ -380,30 +345,30 @@ func promoteMemberHTTP(ctx context.Context, url string, id uint64, peerRt http.R } // getDowngradeEnabledFromRemotePeers will get the downgrade enabled status of the cluster. -func getDowngradeEnabledFromRemotePeers(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper) bool { +func getDowngradeEnabledFromRemotePeers(lg *zap.Logger, cl *membership.RaftCluster, local types.ID, rt http.RoundTripper, timeout time.Duration) bool { members := cl.Members() for _, m := range members { if m.ID == local { continue } - enable, err := getDowngradeEnabled(lg, m, rt) - if err != nil { - lg.Warn("failed to get downgrade enabled status", zap.String("remote-member-id", m.ID.String()), zap.Error(err)) - } else { + enable, err := getDowngradeEnabled(lg, m, rt, timeout) + if err == nil { // Since the "/downgrade/enabled" serves linearized data, // this function can return once it gets a non-error response from the endpoint. return enable } + lg.Warn("failed to get downgrade enabled status", zap.String("remote-member-id", m.ID.String()), zap.Error(err)) } return false } // getDowngradeEnabled returns the downgrade enabled status of the given member // via its peerURLs. Returns the last error if it fails to get it. -func getDowngradeEnabled(lg *zap.Logger, m *membership.Member, rt http.RoundTripper) (bool, error) { +func getDowngradeEnabled(lg *zap.Logger, m *membership.Member, rt http.RoundTripper, timeout time.Duration) (bool, error) { cc := &http.Client{ Transport: rt, + Timeout: timeout, CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }, @@ -426,7 +391,7 @@ func getDowngradeEnabled(lg *zap.Logger, m *membership.Member, rt http.RoundTrip continue } var b []byte - b, err = ioutil.ReadAll(resp.Body) + b, err = io.ReadAll(resp.Body) resp.Body.Close() if err != nil { lg.Warn( @@ -452,45 +417,26 @@ func getDowngradeEnabled(lg *zap.Logger, m *membership.Member, rt http.RoundTrip return false, err } -// isMatchedVersions returns true if all server versions are equal to target version, otherwise return false. -// It can be used to decide the whether the cluster finishes downgrading to target version. -func isMatchedVersions(lg *zap.Logger, targetVersion *semver.Version, vers map[string]*version.Versions) bool { - for mid, ver := range vers { - if ver == nil { - return false - } - v, err := semver.NewVersion(ver.Cluster) - if err != nil { - lg.Warn( - "failed to parse server version of remote member", - zap.String("remote-member-id", mid), - zap.String("remote-member-version", ver.Server), - zap.Error(err), - ) - return false - } - if !targetVersion.Equal(*v) { - lg.Warn("remotes server has mismatching etcd version", - zap.String("remote-member-id", mid), - zap.String("current-server-version", v.String()), - zap.String("target-version", targetVersion.String()), - ) - return false - } - } - return true -} - func convertToClusterVersion(v string) (*semver.Version, error) { ver, err := semver.NewVersion(v) if err != nil { // allow input version format Major.Minor ver, err = semver.NewVersion(v + ".0") if err != nil { - return nil, ErrWrongDowngradeVersionFormat + return nil, errors.ErrWrongDowngradeVersionFormat } } // cluster version only keeps major.minor, remove patch version ver = &semver.Version{Major: ver.Major, Minor: ver.Minor} return ver, nil } + +func GetMembershipInfoInV2Format(lg *zap.Logger, cl *membership.RaftCluster) []byte { + st := v2store.New(StoreClusterPrefix, StoreKeysPrefix) + cl.Store(st) + d, err := st.SaveNoCopy() + if err != nil { + lg.Panic("failed to save v2 store", zap.Error(err)) + } + return d +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/corrupt.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/corrupt.go index 852b844a86..5ec111bef4 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/corrupt.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/corrupt.go @@ -18,22 +18,22 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" - "io/ioutil" + "io" "net/http" "sort" "strings" "sync" "time" + "go.uber.org/zap" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" - "go.etcd.io/etcd/server/v3/mvcc" - - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/storage/mvcc" ) type CorruptionChecker interface { @@ -54,7 +54,7 @@ type corruptionChecker struct { type Hasher interface { mvcc.HashStorage ReqTimeout() time.Duration - MemberId() types.ID + MemberID() types.ID PeerHashByRev(int64) []*peerHashKVResp LinearizableReadNotify(context.Context) error TriggerCorruptAlarm(types.ID) @@ -72,10 +72,6 @@ type hasherAdapter struct { mvcc.HashStorage } -func (h hasherAdapter) MemberId() types.ID { - return h.EtcdServer.ID() -} - func (h hasherAdapter) ReqTimeout() time.Duration { return h.EtcdServer.Cfg.ReqTimeout() } @@ -92,25 +88,24 @@ func (h hasherAdapter) TriggerCorruptAlarm(memberID types.ID) { // before serving any peer/client traffic. Only mismatch when hashes // are different at requested revision, with same compact revision. func (cm *corruptionChecker) InitialCheck() error { - cm.lg.Info( "starting initial corruption check", - zap.String("local-member-id", cm.hasher.MemberId().String()), + zap.String("local-member-id", cm.hasher.MemberID().String()), zap.Duration("timeout", cm.hasher.ReqTimeout()), ) - h, rev, err := cm.hasher.HashByRev(0) + h, _, err := cm.hasher.HashByRev(0) if err != nil { - return fmt.Errorf("%s failed to fetch hash (%v)", cm.hasher.MemberId(), err) + return fmt.Errorf("%s failed to fetch hash (%w)", cm.hasher.MemberID(), err) } - peers := cm.hasher.PeerHashByRev(rev) + peers := cm.hasher.PeerHashByRev(h.Revision) mismatch := 0 for _, p := range peers { if p.resp != nil { peerID := types.ID(p.resp.Header.MemberId) fields := []zap.Field{ - zap.String("local-member-id", cm.hasher.MemberId().String()), - zap.Int64("local-member-revision", rev), + zap.String("local-member-id", cm.hasher.MemberID().String()), + zap.Int64("local-member-revision", h.Revision), zap.Int64("local-member-compact-revision", h.CompactRevision), zap.Uint32("local-member-hash", h.Hash), zap.String("remote-peer-id", peerID.String()), @@ -133,33 +128,33 @@ func (cm *corruptionChecker) InitialCheck() error { } if p.err != nil { - switch p.err { - case rpctypes.ErrFutureRev: + switch { + case errors.Is(p.err, rpctypes.ErrFutureRev): cm.lg.Warn( "cannot fetch hash from slow remote peer", - zap.String("local-member-id", cm.hasher.MemberId().String()), - zap.Int64("local-member-revision", rev), + zap.String("local-member-id", cm.hasher.MemberID().String()), + zap.Int64("local-member-revision", h.Revision), zap.Int64("local-member-compact-revision", h.CompactRevision), zap.Uint32("local-member-hash", h.Hash), zap.String("remote-peer-id", p.id.String()), zap.Strings("remote-peer-endpoints", p.eps), zap.Error(err), ) - case rpctypes.ErrCompacted: + case errors.Is(p.err, rpctypes.ErrCompacted): cm.lg.Warn( "cannot fetch hash from remote peer; local member is behind", - zap.String("local-member-id", cm.hasher.MemberId().String()), - zap.Int64("local-member-revision", rev), + zap.String("local-member-id", cm.hasher.MemberID().String()), + zap.Int64("local-member-revision", h.Revision), zap.Int64("local-member-compact-revision", h.CompactRevision), zap.Uint32("local-member-hash", h.Hash), zap.String("remote-peer-id", p.id.String()), zap.Strings("remote-peer-endpoints", p.eps), zap.Error(err), ) - case rpctypes.ErrClusterIdMismatch: + case errors.Is(p.err, rpctypes.ErrClusterIDMismatch): cm.lg.Warn( "cluster ID mismatch", - zap.String("local-member-id", cm.hasher.MemberId().String()), + zap.String("local-member-id", cm.hasher.MemberID().String()), zap.Int64("local-member-revision", h.Revision), zap.Int64("local-member-compact-revision", h.CompactRevision), zap.Uint32("local-member-hash", h.Hash), @@ -171,22 +166,22 @@ func (cm *corruptionChecker) InitialCheck() error { } } if mismatch > 0 { - return fmt.Errorf("%s found data inconsistency with peers", cm.hasher.MemberId()) + return fmt.Errorf("%s found data inconsistency with peers", cm.hasher.MemberID()) } cm.lg.Info( "initial corruption checking passed; no corruption", - zap.String("local-member-id", cm.hasher.MemberId().String()), + zap.String("local-member-id", cm.hasher.MemberID().String()), ) return nil } func (cm *corruptionChecker) PeriodicCheck() error { - h, rev, err := cm.hasher.HashByRev(0) + h, _, err := cm.hasher.HashByRev(0) if err != nil { return err } - peers := cm.hasher.PeerHashByRev(rev) + peers := cm.hasher.PeerHashByRev(h.Revision) ctx, cancel := context.WithTimeout(context.Background(), cm.hasher.ReqTimeout()) err = cm.hasher.LinearizableReadNotify(ctx) @@ -206,24 +201,20 @@ func (cm *corruptionChecker) PeriodicCheck() error { return } alarmed = true - // It isn't clear which member's data is corrupted, so we - // intentionally set the memberID as 0. We will identify - // the corrupted members using quorum in 3.6. Please see - // discussion in https://github.com/etcd-io/etcd/pull/14828. - cm.hasher.TriggerCorruptAlarm(types.ID(0)) + cm.hasher.TriggerCorruptAlarm(id) } - if h2.Hash != h.Hash && rev2 == rev && h.CompactRevision == h2.CompactRevision { + if h2.Hash != h.Hash && h2.Revision == h.Revision && h.CompactRevision == h2.CompactRevision { cm.lg.Warn( "found hash mismatch", - zap.Int64("revision-1", rev), + zap.Int64("revision-1", h.Revision), zap.Int64("compact-revision-1", h.CompactRevision), zap.Uint32("hash-1", h.Hash), - zap.Int64("revision-2", rev2), + zap.Int64("revision-2", h2.Revision), zap.Int64("compact-revision-2", h2.CompactRevision), zap.Uint32("hash-2", h2.Hash), ) - mismatch(cm.hasher.MemberId()) + mismatch(cm.hasher.MemberID()) } checkedCount := 0 @@ -272,9 +263,20 @@ func (cm *corruptionChecker) PeriodicCheck() error { return nil } +// CompactHashCheck is based on the fact that 'compactions' are coordinated +// between raft members and performed at the same revision. For each compacted +// revision there is KV store hash computed and saved for some time. +// +// This method communicates with peers to find a recent common revision across +// members, and raises alarm if 2 or more members at the same compact revision +// have different hashes. +// +// We might miss opportunity to perform the check if the compaction is still +// ongoing on one of the members, or it was unresponsive. In such situation the +// method still passes without raising alarm. func (cm *corruptionChecker) CompactHashCheck() { cm.lg.Info("starting compact hash check", - zap.String("local-member-id", cm.hasher.MemberId().String()), + zap.String("local-member-id", cm.hasher.MemberID().String()), zap.Duration("timeout", cm.hasher.ReqTimeout()), ) hashes := cm.uncheckedRevisions() @@ -284,56 +286,131 @@ func (cm *corruptionChecker) CompactHashCheck() { if len(peers) == 0 { continue } - peersChecked := 0 - for _, p := range peers { - if p.resp == nil || p.resp.CompactRevision != hash.CompactRevision { - continue - } + if cm.checkPeerHashes(hash, peers) { + cm.lg.Info("finished compaction hash check", zap.Int("number-of-hashes-checked", i+1)) + return + } + } + cm.lg.Info("finished compaction hash check", zap.Int("number-of-hashes-checked", len(hashes))) +} - // follower's compact revision is leader's old one, then hashes must match - if p.resp.Hash != hash.Hash { - // It isn't clear which member's data is corrupted, so we - // intentionally set the memberID as 0. We will identify - // the corrupted members using quorum in 3.6. Please see - // discussion in https://github.com/etcd-io/etcd/pull/14828. - cm.hasher.TriggerCorruptAlarm(types.ID(0)) - cm.lg.Error("failed compaction hash check", - zap.Int64("revision", hash.Revision), - zap.Int64("leader-compact-revision", hash.CompactRevision), - zap.Uint32("leader-hash", hash.Hash), - zap.Int64("follower-compact-revision", p.resp.CompactRevision), - zap.Uint32("follower-hash", p.resp.Hash), - zap.String("follower-peer-id", p.id.String()), - ) - return - } - peersChecked++ - cm.lg.Info("successfully checked hash on follower", - zap.Int64("revision", hash.Revision), - zap.String("peer-id", p.id.String()), - ) +// check peers hash and raise alarms if detected corruption. +// return a bool indicate whether to check next hash. +// +// true: successfully checked hash on whole cluster or raised alarms, so no need to check next hash +// false: skipped some members, so need to check next hash +func (cm *corruptionChecker) checkPeerHashes(leaderHash mvcc.KeyValueHash, peers []*peerHashKVResp) bool { + leaderID := cm.hasher.MemberID() + hash2members := map[uint32]types.IDSlice{leaderHash.Hash: {leaderID}} + + peersChecked := 0 + // group all peers by hash + for _, peer := range peers { + skipped := false + reason := "" + + if peer.resp == nil { + skipped = true + reason = "no response" + } else if peer.resp.CompactRevision != leaderHash.CompactRevision { + skipped = true + reason = fmt.Sprintf("the peer's CompactRevision %d doesn't match leader's CompactRevision %d", + peer.resp.CompactRevision, leaderHash.CompactRevision) } - if len(peers) == peersChecked { - cm.lg.Info("successfully checked hash on whole cluster", - zap.Int("number-of-peers-checked", peersChecked), - zap.Int64("revision", hash.Revision), - ) - cm.mux.Lock() - if hash.Revision > cm.latestRevisionChecked { - cm.latestRevisionChecked = hash.Revision + if skipped { + cm.lg.Warn("Skipped peer's hash", zap.Int("number-of-peers", len(peers)), + zap.String("leader-id", leaderID.String()), + zap.String("peer-id", peer.id.String()), + zap.String("reason", reason)) + continue + } + + peersChecked++ + if ids, ok := hash2members[peer.resp.Hash]; !ok { + hash2members[peer.resp.Hash] = []types.ID{peer.id} + } else { + ids = append(ids, peer.id) + hash2members[peer.resp.Hash] = ids + } + } + + // All members have the same CompactRevision and Hash. + if len(hash2members) == 1 { + return cm.handleConsistentHash(leaderHash, peersChecked, len(peers)) + } + + // Detected hashes mismatch + // The first step is to figure out the majority with the same hash. + memberCnt := len(peers) + 1 + quorum := memberCnt/2 + 1 + quorumExist := false + for k, v := range hash2members { + if len(v) >= quorum { + quorumExist = true + // remove the majority, and we might raise alarms for the left members. + delete(hash2members, k) + break + } + } + + if !quorumExist { + // If quorum doesn't exist, we don't know which members data are + // corrupted. In such situation, we intentionally set the memberID + // as 0, it means it affects the whole cluster. + cm.lg.Error("Detected compaction hash mismatch but cannot identify the corrupted members, so intentionally set the memberID as 0", + zap.String("leader-id", leaderID.String()), + zap.Int64("leader-revision", leaderHash.Revision), + zap.Int64("leader-compact-revision", leaderHash.CompactRevision), + zap.Uint32("leader-hash", leaderHash.Hash), + ) + cm.hasher.TriggerCorruptAlarm(0) + } + + // Raise alarm for the left members if the quorum is present. + // But we should always generate error log for debugging. + for k, v := range hash2members { + if quorumExist { + for _, pid := range v { + cm.hasher.TriggerCorruptAlarm(pid) } - cm.mux.Unlock() - cm.lg.Info("finished compaction hash check", zap.Int("number-of-hashes-checked", i+1)) - return } - cm.lg.Warn("skipped revision in compaction hash check; was not able to check all peers", + + cm.lg.Error("Detected compaction hash mismatch", + zap.String("leader-id", leaderID.String()), + zap.Int64("leader-revision", leaderHash.Revision), + zap.Int64("leader-compact-revision", leaderHash.CompactRevision), + zap.Uint32("leader-hash", leaderHash.Hash), + zap.Uint32("peer-hash", k), + zap.String("peer-ids", v.String()), + zap.Bool("quorum-exist", quorumExist), + ) + } + + return true +} + +func (cm *corruptionChecker) handleConsistentHash(hash mvcc.KeyValueHash, peersChecked, peerCnt int) bool { + if peersChecked == peerCnt { + cm.lg.Info("successfully checked hash on whole cluster", zap.Int("number-of-peers-checked", peersChecked), - zap.Int("number-of-peers", len(peers)), zap.Int64("revision", hash.Revision), + zap.Int64("compactRevision", hash.CompactRevision), ) + cm.mux.Lock() + if hash.Revision > cm.latestRevisionChecked { + cm.latestRevisionChecked = hash.Revision + } + cm.mux.Unlock() + return true } - cm.lg.Info("finished compaction hash check", zap.Int("number-of-hashes-checked", len(hashes))) - return + cm.lg.Warn("skipped revision in compaction hash check; was not able to check all peers", + zap.Int("number-of-peers-checked", peersChecked), + zap.Int("number-of-peers", peerCnt), + zap.Int64("revision", hash.Revision), + zap.Int64("compactRevision", hash.CompactRevision), + ) + // The only case which needs to check next hash + return false } func (cm *corruptionChecker) uncheckedRevisions() []mvcc.KeyValueHash { @@ -382,7 +459,7 @@ func (s *EtcdServer) getPeerHashKVs(rev int64) []*peerHashKVResp { members := s.cluster.Members() peers := make([]peerInfo, 0, len(members)) for _, m := range members { - if m.ID == s.ID() { + if m.ID == s.MemberID() { continue } peers = append(peers, peerInfo{id: m.ID, eps: m.PeerURLs}) @@ -405,8 +482,10 @@ func (s *EtcdServer) getPeerHashKVs(rev int64) []*peerHashKVResp { respsLen := len(resps) var lastErr error for _, ep := range p.eps { + var resp *pb.HashKVResponse + ctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout()) - resp, lastErr := HashByRev(ctx, s.cluster.ID(), cc, ep, rev) + resp, lastErr = HashByRev(ctx, s.cluster.ID(), cc, ep, rev) cancel() if lastErr == nil { resps = append(resps, &peerHashKVResp{peerInfo: p, resp: resp, err: nil}) @@ -414,7 +493,7 @@ func (s *EtcdServer) getPeerHashKVs(rev int64) []*peerHashKVResp { } lg.Warn( "failed hash kv request", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.Int64("requested-revision", rev), zap.String("remote-peer-endpoint", ep), zap.Error(lastErr), @@ -429,40 +508,6 @@ func (s *EtcdServer) getPeerHashKVs(rev int64) []*peerHashKVResp { return resps } -type applierV3Corrupt struct { - applierV3 -} - -func newApplierV3Corrupt(a applierV3) *applierV3Corrupt { return &applierV3Corrupt{a} } - -func (a *applierV3Corrupt) Put(ctx context.Context, txn mvcc.TxnWrite, p *pb.PutRequest) (*pb.PutResponse, *traceutil.Trace, error) { - return nil, nil, ErrCorrupt -} - -func (a *applierV3Corrupt) Range(ctx context.Context, txn mvcc.TxnRead, p *pb.RangeRequest) (*pb.RangeResponse, error) { - return nil, ErrCorrupt -} - -func (a *applierV3Corrupt) DeleteRange(txn mvcc.TxnWrite, p *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) { - return nil, ErrCorrupt -} - -func (a *applierV3Corrupt) Txn(ctx context.Context, rt *pb.TxnRequest) (*pb.TxnResponse, *traceutil.Trace, error) { - return nil, nil, ErrCorrupt -} - -func (a *applierV3Corrupt) Compaction(compaction *pb.CompactionRequest) (*pb.CompactionResponse, <-chan struct{}, *traceutil.Trace, error) { - return nil, nil, nil, ErrCorrupt -} - -func (a *applierV3Corrupt) LeaseGrant(lc *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) { - return nil, ErrCorrupt -} - -func (a *applierV3Corrupt) LeaseRevoke(lc *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) { - return nil, ErrCorrupt -} - const PeerHashKVPath = "/members/hashkv" type hashKVHandler struct { @@ -490,14 +535,14 @@ func (h *hashKVHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) + b, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "error reading body", http.StatusBadRequest) return } req := &pb.HashKVRequest{} - if err := json.Unmarshal(b, req); err != nil { + if err = json.Unmarshal(b, req); err != nil { h.lg.Warn("failed to unmarshal request", zap.Error(err)) http.Error(w, "error unmarshalling request", http.StatusBadRequest) return @@ -512,7 +557,12 @@ func (h *hashKVHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusBadRequest) return } - resp := &pb.HashKVResponse{Header: &pb.ResponseHeader{Revision: rev}, Hash: hash.Hash, CompactRevision: hash.CompactRevision} + resp := &pb.HashKVResponse{ + Header: &pb.ResponseHeader{Revision: rev}, + Hash: hash.Hash, + CompactRevision: hash.CompactRevision, + HashRevision: hash.Revision, + } respBytes, err := json.Marshal(resp) if err != nil { h.lg.Warn("failed to marshal hashKV response", zap.Error(err)) @@ -532,8 +582,8 @@ func HashByRev(ctx context.Context, cid types.ID, cc *http.Client, url string, r if err != nil { return nil, err } - requestUrl := url + PeerHashKVPath - req, err := http.NewRequest(http.MethodGet, requestUrl, bytes.NewReader(hashReqBytes)) + requestURL := url + PeerHashKVPath + req, err := http.NewRequest(http.MethodGet, requestURL, bytes.NewReader(hashReqBytes)) if err != nil { return nil, err } @@ -547,7 +597,7 @@ func HashByRev(ctx context.Context, cid types.ID, cc *http.Client, url string, r return nil, err } defer resp.Body.Close() - b, err := ioutil.ReadAll(resp.Body) + b, err := io.ReadAll(resp.Body) if err != nil { return nil, err } @@ -561,11 +611,11 @@ func HashByRev(ctx context.Context, cid types.ID, cc *http.Client, url string, r } } else if resp.StatusCode == http.StatusPreconditionFailed { if strings.Contains(string(b), rafthttp.ErrClusterIDMismatch.Error()) { - return nil, rpctypes.ErrClusterIdMismatch + return nil, rpctypes.ErrClusterIDMismatch } } if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("unknown error: %s", string(b)) + return nil, fmt.Errorf("unknown error: %s", b) } hashResp := &pb.HashKVResponse{} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors.go deleted file mode 100644 index f6d77fe72a..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2015 The etcd 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 etcdserver - -import ( - "errors" - "fmt" -) - -var ( - ErrUnknownMethod = errors.New("etcdserver: unknown method") - ErrStopped = errors.New("etcdserver: server stopped") - ErrCanceled = errors.New("etcdserver: request cancelled") - ErrTimeout = errors.New("etcdserver: request timed out") - ErrTimeoutDueToLeaderFail = errors.New("etcdserver: request timed out, possibly due to previous leader failure") - ErrTimeoutDueToConnectionLost = errors.New("etcdserver: request timed out, possibly due to connection lost") - ErrTimeoutLeaderTransfer = errors.New("etcdserver: request timed out, leader transfer took too long") - ErrTimeoutWaitAppliedIndex = errors.New("etcdserver: request timed out, waiting for the applied index took too long") - ErrLeaderChanged = errors.New("etcdserver: leader changed") - ErrNotEnoughStartedMembers = errors.New("etcdserver: re-configuration failed due to not enough started members") - ErrLearnerNotReady = errors.New("etcdserver: can only promote a learner member which is in sync with leader") - ErrNoLeader = errors.New("etcdserver: no leader") - ErrNotLeader = errors.New("etcdserver: not leader") - ErrRequestTooLarge = errors.New("etcdserver: request is too large") - ErrNoSpace = errors.New("etcdserver: no space") - ErrTooManyRequests = errors.New("etcdserver: too many requests") - ErrUnhealthy = errors.New("etcdserver: unhealthy cluster") - ErrKeyNotFound = errors.New("etcdserver: key not found") - ErrCorrupt = errors.New("etcdserver: corrupt cluster") - ErrBadLeaderTransferee = errors.New("etcdserver: bad leader transferee") - ErrClusterVersionUnavailable = errors.New("etcdserver: cluster version not found during downgrade") - ErrWrongDowngradeVersionFormat = errors.New("etcdserver: wrong downgrade target version format") - ErrInvalidDowngradeTargetVersion = errors.New("etcdserver: invalid downgrade target version") - ErrDowngradeInProcess = errors.New("etcdserver: cluster has a downgrade job in progress") - ErrNoInflightDowngrade = errors.New("etcdserver: no inflight downgrade job") -) - -type DiscoveryError struct { - Op string - Err error -} - -func (e DiscoveryError) Error() string { - return fmt.Sprintf("failed to %s discovery cluster (%v)", e.Op, e.Err) -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors/errors.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors/errors.go new file mode 100644 index 0000000000..8de698a1df --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/errors/errors.go @@ -0,0 +1,54 @@ +// Copyright 2022 The etcd 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 errors + +import ( + "errors" + "fmt" +) + +var ( + ErrUnknownMethod = errors.New("etcdserver: unknown method") + ErrStopped = errors.New("etcdserver: server stopped") + ErrCanceled = errors.New("etcdserver: request cancelled") + ErrTimeout = errors.New("etcdserver: request timed out") + ErrTimeoutDueToLeaderFail = errors.New("etcdserver: request timed out, possibly due to previous leader failure") + ErrTimeoutDueToConnectionLost = errors.New("etcdserver: request timed out, possibly due to connection lost") + ErrTimeoutLeaderTransfer = errors.New("etcdserver: request timed out, leader transfer took too long") + ErrTimeoutWaitAppliedIndex = errors.New("etcdserver: request timed out, waiting for the applied index took too long") + ErrLeaderChanged = errors.New("etcdserver: leader changed") + ErrNotEnoughStartedMembers = errors.New("etcdserver: re-configuration failed due to not enough started members") + ErrLearnerNotReady = errors.New("etcdserver: can only promote a learner member which is in sync with leader") + ErrNoLeader = errors.New("etcdserver: no leader") + ErrNotLeader = errors.New("etcdserver: not leader") + ErrRequestTooLarge = errors.New("etcdserver: request is too large") + ErrNoSpace = errors.New("etcdserver: no space") + ErrTooManyRequests = errors.New("etcdserver: too many requests") + ErrUnhealthy = errors.New("etcdserver: unhealthy cluster") + ErrCorrupt = errors.New("etcdserver: corrupt cluster") + ErrBadLeaderTransferee = errors.New("etcdserver: bad leader transferee") + ErrClusterVersionUnavailable = errors.New("etcdserver: cluster version not found during downgrade") + ErrWrongDowngradeVersionFormat = errors.New("etcdserver: wrong downgrade target version format") + ErrKeyNotFound = errors.New("etcdserver: key not found") +) + +type DiscoveryError struct { + Op string + Err error +} + +func (e DiscoveryError) Error() string { + return fmt.Sprintf("failed to %s discovery cluster (%v)", e.Op, e.Err) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/metrics.go index 06263a9cd2..7176d30adb 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/metrics.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/metrics.go @@ -18,11 +18,11 @@ import ( goruntime "runtime" "time" - "go.etcd.io/etcd/api/v3/version" - "go.etcd.io/etcd/pkg/v3/runtime" - "github.com/prometheus/client_golang/prometheus" "go.uber.org/zap" + + "go.etcd.io/etcd/api/v3/version" + "go.etcd.io/etcd/pkg/v3/runtime" ) var ( @@ -44,18 +44,13 @@ var ( Name: "leader_changes_seen_total", Help: "The number of leader changes seen.", }) - isLearner = prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "is_learner", - Help: "Whether or not this member is a learner. 1 if is, 0 otherwise.", - }) - learnerPromoteFailed = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "learner_promote_failures", - Help: "The total number of failed learner promotions (likely learner not ready) while this member is leader.", - }, + learnerPromoteFailed = prometheus.NewCounterVec( + prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "learner_promote_failures", + Help: "The total number of failed learner promotions (likely learner not ready) while this member is leader.", + }, []string{"Reason"}, ) learnerPromoteSucceed = prometheus.NewCounter(prometheus.CounterOpts{ @@ -70,12 +65,6 @@ var ( Name: "heartbeat_send_failures_total", Help: "The total number of leader heartbeat send failures (likely overloaded from slow disk).", }) - slowApplies = prometheus.NewCounter(prometheus.CounterOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "slow_apply_total", - Help: "The total number of slow apply requests (likely overloaded from slow disk).", - }) applySnapshotInProgress = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: "etcd", Subsystem: "server", @@ -124,34 +113,40 @@ var ( Name: "lease_expired_total", Help: "The total number of expired leases.", }) - quotaBackendBytes = prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "quota_backend_bytes", - Help: "Current backend storage quota size in bytes.", - }) - currentVersion = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "version", - Help: "Which version is running. 1 for 'server_version' label with current version.", - }, - []string{"server_version"}) - currentGoVersion = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "go_version", - Help: "Which Go version server is running with. 1 for 'server_go_version' label with current version.", - }, - []string{"server_go_version"}) - serverID = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "id", - Help: "Server or member ID in hexadecimal format. 1 for 'server_id' label with current ID.", - }, - []string{"server_id"}) - + currentVersion = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "version", + Help: "Which version is running. 1 for 'server_version' label with current version.", + }, + []string{"server_version"}, + ) + currentGoVersion = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "go_version", + Help: "Which Go version server is running with. 1 for 'server_go_version' label with current version.", + }, + []string{"server_go_version"}, + ) + serverID = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "id", + Help: "Server or member ID in hexadecimal format. 1 for 'server_id' label with current ID.", + }, + []string{"server_id"}, + ) + serverFeatureEnabled = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "etcd_server_feature_enabled", + Help: "Whether or not a feature is enabled. 1 is enabled, 0 is not.", + }, + []string{"name", "stage"}, + ) fdUsed = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: "os", Subsystem: "fd", @@ -164,17 +159,6 @@ var ( Name: "limit", Help: "The file descriptor limit.", }) - applySec = prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: "etcd", - Subsystem: "server", - Name: "apply_duration_seconds", - Help: "The latency distributions of v2 apply called by backend.", - - // lowest bucket start of upper bound 0.0001 sec (0.1 ms) with factor 2 - // highest bucket start of 0.0001 sec * 2^19 == 52.4288 sec - Buckets: prometheus.ExponentialBuckets(0.0001, 2, 20), - }, - []string{"version", "op", "success"}) ) func init() { @@ -182,7 +166,6 @@ func init() { prometheus.MustRegister(isLeader) prometheus.MustRegister(leaderChanges) prometheus.MustRegister(heartbeatSendFailures) - prometheus.MustRegister(slowApplies) prometheus.MustRegister(applySnapshotInProgress) prometheus.MustRegister(proposalsCommitted) prometheus.MustRegister(proposalsApplied) @@ -191,16 +174,14 @@ func init() { prometheus.MustRegister(slowReadIndex) prometheus.MustRegister(readIndexFailed) prometheus.MustRegister(leaseExpired) - prometheus.MustRegister(quotaBackendBytes) prometheus.MustRegister(currentVersion) prometheus.MustRegister(currentGoVersion) prometheus.MustRegister(serverID) - prometheus.MustRegister(isLearner) + prometheus.MustRegister(serverFeatureEnabled) prometheus.MustRegister(learnerPromoteSucceed) prometheus.MustRegister(learnerPromoteFailed) prometheus.MustRegister(fdUsed) prometheus.MustRegister(fdLimit) - prometheus.MustRegister(applySec) currentVersion.With(prometheus.Labels{ "server_version": version.Version, diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/raft.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/raft.go index b022c68fb0..fd4b5dac33 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/raft.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/raft.go @@ -15,29 +15,20 @@ package etcdserver import ( - "encoding/json" "expvar" "fmt" "log" - "sort" "sync" "time" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.uber.org/zap" + "go.etcd.io/etcd/client/pkg/v3/logutil" - "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/pkg/v3/contention" - "go.etcd.io/etcd/pkg/v3/pbutil" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/config" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/revbump" - "go.etcd.io/etcd/server/v3/wal" - "go.etcd.io/etcd/server/v3/wal/walpb" - "go.uber.org/zap" + serverstorage "go.etcd.io/etcd/server/v3/storage" + "go.etcd.io/raft/v3" + "go.etcd.io/raft/v3/raftpb" ) const ( @@ -61,7 +52,7 @@ var ( ) func init() { - expvar.Publish("raft.status", expvar.Func(func() interface{} { + expvar.Publish("raft.status", expvar.Func(func() any { raftStatusMu.Lock() defer raftStatusMu.Unlock() if raftStatus == nil { @@ -71,15 +62,19 @@ func init() { })) } -// apply contains entries, snapshot to be applied. Once -// an apply is consumed, the entries will be persisted to -// to raft storage concurrently; the application must read -// raftDone before assuming the raft messages are stable. -type apply struct { +// toApply contains entries, snapshot to be applied. Once +// an toApply is consumed, the entries will be persisted to +// raft storage concurrently; the application must read +// notifyc before assuming the raft messages are stable. +type toApply struct { entries []raftpb.Entry snapshot raftpb.Snapshot // notifyc synchronizes etcd server applies with the raft node notifyc chan struct{} + // raftAdvancedC notifies EtcdServer.apply that + // 'raftLog.applied' has advanced by r.Advance + // it should be used only when entries contain raftpb.EntryConfChange + raftAdvancedC <-chan struct{} } type raftNode struct { @@ -94,7 +89,7 @@ type raftNode struct { msgSnapC chan raftpb.Message // a chan to send out apply - applyc chan apply + applyc chan toApply // a chan to send out readState readStateC chan raft.ReadState @@ -115,7 +110,7 @@ type raftNodeConfig struct { isIDRemoved func(id uint64) bool raft.Node raftStorage *raft.MemoryStorage - storage Storage + storage serverstorage.Storage heartbeat time.Duration // for logging // transport specifies the transport to send and receive msgs to members. // Sending messages MUST NOT block. It is okay to drop messages, since @@ -147,7 +142,7 @@ func newRaftNode(cfg raftNodeConfig) *raftNode { td: contention.NewTimeoutDetector(2 * cfg.heartbeat), readStateC: make(chan raft.ReadState, 1), msgSnapC: make(chan raftpb.Message, maxInFlightMsgSnap), - applyc: make(chan apply), + applyc: make(chan toApply), stopped: make(chan struct{}), done: make(chan struct{}), } @@ -221,29 +216,23 @@ func (r *raftNode) start(rh *raftReadyHandler) { } notifyc := make(chan struct{}, 1) - ap := apply{ - entries: rd.CommittedEntries, - snapshot: rd.Snapshot, - notifyc: notifyc, + raftAdvancedC := make(chan struct{}, 1) + ap := toApply{ + entries: rd.CommittedEntries, + snapshot: rd.Snapshot, + notifyc: notifyc, + raftAdvancedC: raftAdvancedC, } updateCommittedIndex(&ap, rh) - waitWALSync := shouldWaitWALSync(rd) - if waitWALSync { - // gofail: var raftBeforeSaveWaitWalSync struct{} - if err := r.storage.Save(rd.HardState, rd.Entries); err != nil { - r.lg.Fatal("failed to save Raft hard state and entries", zap.Error(err)) - } - } - select { case r.applyc <- ap: case <-r.stopped: return } - // the leader can write to its disk in parallel with replicating to the followers and them + // the leader can write to its disk in parallel with replicating to the followers and then // writing to their disks. // For more details, check raft thesis 10.2.1 if islead { @@ -261,11 +250,9 @@ func (r *raftNode) start(rh *raftReadyHandler) { // gofail: var raftAfterSaveSnap struct{} } - if !waitWALSync { - // gofail: var raftBeforeSave struct{} - if err := r.storage.Save(rd.HardState, rd.Entries); err != nil { - r.lg.Fatal("failed to save Raft hard state and entries", zap.Error(err)) - } + // gofail: var raftBeforeSave struct{} + if err := r.storage.Save(rd.HardState, rd.Entries); err != nil { + r.lg.Fatal("failed to save Raft hard state and entries", zap.Error(err)) } if !raft.IsEmptyHardState(rd.HardState) { proposalsCommitted.Set(float64(rd.HardState.Commit)) @@ -297,8 +284,16 @@ func (r *raftNode) start(rh *raftReadyHandler) { r.raftStorage.Append(rd.Entries) + confChanged := false + for _, ent := range rd.CommittedEntries { + if ent.Type == raftpb.EntryConfChange { + confChanged = true + break + } + } + if !islead { - // finish processing incoming messages before we signal raftdone chan + // finish processing incoming messages before we signal notifyc chan msgs := r.processMessages(rd.Messages) // now unblocks 'applyAll' that waits on Raft log disk writes before triggering snapshots @@ -308,17 +303,11 @@ func (r *raftNode) start(rh *raftReadyHandler) { // changes to be applied before sending messages. // Otherwise we might incorrectly count votes (e.g. votes from removed members). // Also slow machine's follower raft-layer could proceed to become the leader - // on its own single-node cluster, before apply-layer applies the config change. + // on its own single-node cluster, before toApply-layer applies the config change. // We simply wait for ALL pending entries to be applied for now. // We might improve this later on if it causes unnecessary long blocking issues. - waitApply := false - for _, ent := range rd.CommittedEntries { - if ent.Type == raftpb.EntryConfChange { - waitApply = true - break - } - } - if waitApply { + + if confChanged { // blocks until 'applyAll' calls 'applyWait.Trigger' // to be in sync with scheduled config-change job // (assume notifyc has cap of 1) @@ -336,7 +325,13 @@ func (r *raftNode) start(rh *raftReadyHandler) { notifyc <- struct{}{} } + // gofail: var raftBeforeAdvance struct{} r.Advance() + + if confChanged { + // notify etcdserver that raft has already been notified or advanced. + raftAdvancedC <- struct{}{} + } case <-r.stopped: return } @@ -344,44 +339,7 @@ func (r *raftNode) start(rh *raftReadyHandler) { }() } -// For a cluster with only one member, the raft may send both the -// unstable entries and committed entries to etcdserver, and there -// may have overlapped log entries between them. -// -// etcd responds to the client once it finishes (actually partially) -// the applying workflow. But when the client receives the response, -// it doesn't mean etcd has already successfully saved the data, -// including BoltDB and WAL, because: -// 1. etcd commits the boltDB transaction periodically instead of on each request; -// 2. etcd saves WAL entries in parallel with applying the committed entries. -// -// Accordingly, it might run into a situation of data loss when the etcd crashes -// immediately after responding to the client and before the boltDB and WAL -// successfully save the data to disk. -// Note that this issue can only happen for clusters with only one member. -// -// For clusters with multiple members, it isn't an issue, because etcd will -// not commit & apply the data before it being replicated to majority members. -// When the client receives the response, it means the data must have been applied. -// It further means the data must have been committed. -// Note: for clusters with multiple members, the raft will never send identical -// unstable entries and committed entries to etcdserver. -// -// Refer to https://github.com/etcd-io/etcd/issues/14370. -func shouldWaitWALSync(rd raft.Ready) bool { - if len(rd.CommittedEntries) == 0 || len(rd.Entries) == 0 { - return false - } - - // Check if there is overlap between unstable and committed entries - // assuming that their index and term are only incrementing. - lastCommittedEntry := rd.CommittedEntries[len(rd.CommittedEntries)-1] - firstUnstableEntry := rd.Entries[0] - return lastCommittedEntry.Term > firstUnstableEntry.Term || - (lastCommittedEntry.Term == firstUnstableEntry.Term && lastCommittedEntry.Index >= firstUnstableEntry.Index) -} - -func updateCommittedIndex(ap *apply, rh *raftReadyHandler) { +func updateCommittedIndex(ap *toApply, rh *raftReadyHandler) { var ci uint64 if len(ap.entries) != 0 { ci = ap.entries[len(ap.entries)-1].Index @@ -399,6 +357,7 @@ func (r *raftNode) processMessages(ms []raftpb.Message) []raftpb.Message { for i := len(ms) - 1; i >= 0; i-- { if r.isIDRemoved(ms[i].To) { ms[i].To = 0 + continue } if ms[i].Type == raftpb.MsgAppResp { @@ -439,12 +398,19 @@ func (r *raftNode) processMessages(ms []raftpb.Message) []raftpb.Message { return ms } -func (r *raftNode) apply() chan apply { +func (r *raftNode) apply() chan toApply { return r.applyc } func (r *raftNode) stop() { - r.stopped <- struct{}{} + select { + case r.stopped <- struct{}{}: + // Not already stopped, so trigger it + case <-r.done: + // Has already been stopped - no need to do anything + return + } + // Block until the stop has been acknowledged by start() <-r.done } @@ -478,279 +444,3 @@ func (r *raftNode) advanceTicks(ticks int) { r.tick() } } - -func startNode(cfg config.ServerConfig, cl *membership.RaftCluster, ids []types.ID) (id types.ID, n raft.Node, s *raft.MemoryStorage, w *wal.WAL) { - var err error - member := cl.MemberByName(cfg.Name) - metadata := pbutil.MustMarshal( - &pb.Metadata{ - NodeID: uint64(member.ID), - ClusterID: uint64(cl.ID()), - }, - ) - if w, err = wal.Create(cfg.Logger, cfg.WALDir(), metadata); err != nil { - cfg.Logger.Panic("failed to create WAL", zap.Error(err)) - } - if cfg.UnsafeNoFsync { - w.SetUnsafeNoFsync() - } - peers := make([]raft.Peer, len(ids)) - for i, id := range ids { - var ctx []byte - ctx, err = json.Marshal((*cl).Member(id)) - if err != nil { - cfg.Logger.Panic("failed to marshal member", zap.Error(err)) - } - peers[i] = raft.Peer{ID: uint64(id), Context: ctx} - } - id = member.ID - cfg.Logger.Info( - "starting local member", - zap.String("local-member-id", id.String()), - zap.String("cluster-id", cl.ID().String()), - ) - s = raft.NewMemoryStorage() - c := &raft.Config{ - ID: uint64(id), - ElectionTick: cfg.ElectionTicks, - HeartbeatTick: 1, - Storage: s, - MaxSizePerMsg: maxSizePerMsg, - MaxInflightMsgs: maxInflightMsgs, - CheckQuorum: true, - PreVote: cfg.PreVote, - Logger: NewRaftLoggerZap(cfg.Logger.Named("raft")), - } - if len(peers) == 0 { - n = raft.RestartNode(c) - } else { - n = raft.StartNode(c, peers) - } - raftStatusMu.Lock() - raftStatus = n.Status - raftStatusMu.Unlock() - return id, n, s, w -} - -func restartNode(cfg config.ServerConfig, snapshot *raftpb.Snapshot) (types.ID, *membership.RaftCluster, raft.Node, *raft.MemoryStorage, *wal.WAL) { - var walsnap walpb.Snapshot - if snapshot != nil { - walsnap.Index, walsnap.Term = snapshot.Metadata.Index, snapshot.Metadata.Term - } - w, id, cid, st, ents := readWAL(cfg.Logger, cfg.WALDir(), walsnap, cfg.UnsafeNoFsync) - - cfg.Logger.Info( - "restarting local member", - zap.String("cluster-id", cid.String()), - zap.String("local-member-id", id.String()), - zap.Uint64("commit-index", st.Commit), - ) - cl := membership.NewCluster(cfg.Logger, membership.WithMaxLearners(cfg.ExperimentalMaxLearners)) - cl.SetID(id, cid) - s := raft.NewMemoryStorage() - if snapshot != nil { - s.ApplySnapshot(*snapshot) - } - s.SetHardState(st) - s.Append(ents) - c := &raft.Config{ - ID: uint64(id), - ElectionTick: cfg.ElectionTicks, - HeartbeatTick: 1, - Storage: s, - MaxSizePerMsg: maxSizePerMsg, - MaxInflightMsgs: maxInflightMsgs, - CheckQuorum: true, - PreVote: cfg.PreVote, - Logger: NewRaftLoggerZap(cfg.Logger.Named("raft")), - } - - n := raft.RestartNode(c) - raftStatusMu.Lock() - raftStatus = n.Status - raftStatusMu.Unlock() - return id, cl, n, s, w -} - -func restartAsStandaloneNode(cfg config.ServerConfig, snapshot *raftpb.Snapshot, be backend.Backend) (types.ID, - *membership.RaftCluster, raft.Node, *raft.MemoryStorage, *wal.WAL) { - var walsnap walpb.Snapshot - if snapshot != nil { - walsnap.Index, walsnap.Term = snapshot.Metadata.Index, snapshot.Metadata.Term - } - w, id, cid, st, ents := readWAL(cfg.Logger, cfg.WALDir(), walsnap, cfg.UnsafeNoFsync) - - // discard the previously uncommitted entries - for i, ent := range ents { - if ent.Index > st.Commit { - cfg.Logger.Info( - "discarding uncommitted WAL entries", - zap.Uint64("entry-index", ent.Index), - zap.Uint64("commit-index-from-wal", st.Commit), - zap.Int("number-of-discarded-entries", len(ents)-i), - ) - ents = ents[:i] - break - } - } - - // force append the configuration change entries - toAppEnts := createConfigChangeEnts( - cfg.Logger, - getIDs(cfg.Logger, snapshot, ents), - uint64(id), - st.Term, - st.Commit, - ) - ents = append(ents, toAppEnts...) - - // force commit newly appended entries - err := w.Save(raftpb.HardState{}, toAppEnts) - if err != nil { - cfg.Logger.Fatal("failed to save hard state and entries", zap.Error(err)) - } - if len(ents) != 0 { - st.Commit = ents[len(ents)-1].Index - } - - if cfg.ForceNewClusterBumpAmount > 0 { - err = revbump.UnsafeModifyLastRevision(cfg.Logger, cfg.ForceNewClusterBumpAmount, be) - if err != nil { - cfg.Logger.Fatal("failed to modify last revision", zap.Error(err)) - } - } - - cfg.Logger.Info( - "forcing restart member", - zap.String("cluster-id", cid.String()), - zap.String("local-member-id", id.String()), - zap.Uint64("commit-index", st.Commit), - ) - - cl := membership.NewCluster(cfg.Logger, membership.WithMaxLearners(cfg.ExperimentalMaxLearners)) - cl.SetID(id, cid) - s := raft.NewMemoryStorage() - if snapshot != nil { - s.ApplySnapshot(*snapshot) - } - s.SetHardState(st) - s.Append(ents) - c := &raft.Config{ - ID: uint64(id), - ElectionTick: cfg.ElectionTicks, - HeartbeatTick: 1, - Storage: s, - MaxSizePerMsg: maxSizePerMsg, - MaxInflightMsgs: maxInflightMsgs, - CheckQuorum: true, - PreVote: cfg.PreVote, - Logger: NewRaftLoggerZap(cfg.Logger.Named("raft")), - } - - n := raft.RestartNode(c) - raftStatus = n.Status - return id, cl, n, s, w -} - -// getIDs returns an ordered set of IDs included in the given snapshot and -// the entries. The given snapshot/entries can contain three kinds of -// ID-related entry: -// - ConfChangeAddNode, in which case the contained ID will be added into the set. -// - ConfChangeRemoveNode, in which case the contained ID will be removed from the set. -// - ConfChangeAddLearnerNode, in which the contained ID will be added into the set. -func getIDs(lg *zap.Logger, snap *raftpb.Snapshot, ents []raftpb.Entry) []uint64 { - ids := make(map[uint64]bool) - if snap != nil { - for _, id := range snap.Metadata.ConfState.Voters { - ids[id] = true - } - } - for _, e := range ents { - if e.Type != raftpb.EntryConfChange { - continue - } - var cc raftpb.ConfChange - pbutil.MustUnmarshal(&cc, e.Data) - switch cc.Type { - case raftpb.ConfChangeAddLearnerNode: - ids[cc.NodeID] = true - case raftpb.ConfChangeAddNode: - ids[cc.NodeID] = true - case raftpb.ConfChangeRemoveNode: - delete(ids, cc.NodeID) - case raftpb.ConfChangeUpdateNode: - // do nothing - default: - lg.Panic("unknown ConfChange Type", zap.String("type", cc.Type.String())) - } - } - sids := make(types.Uint64Slice, 0, len(ids)) - for id := range ids { - sids = append(sids, id) - } - sort.Sort(sids) - return []uint64(sids) -} - -// createConfigChangeEnts creates a series of Raft entries (i.e. -// EntryConfChange) to remove the set of given IDs from the cluster. The ID -// `self` is _not_ removed, even if present in the set. -// If `self` is not inside the given ids, it creates a Raft entry to add a -// default member with the given `self`. -func createConfigChangeEnts(lg *zap.Logger, ids []uint64, self uint64, term, index uint64) []raftpb.Entry { - found := false - for _, id := range ids { - if id == self { - found = true - } - } - - var ents []raftpb.Entry - next := index + 1 - - // NB: always add self first, then remove other nodes. Raft will panic if the - // set of voters ever becomes empty. - if !found { - m := membership.Member{ - ID: types.ID(self), - RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://localhost:2380"}}, - } - ctx, err := json.Marshal(m) - if err != nil { - lg.Panic("failed to marshal member", zap.Error(err)) - } - cc := &raftpb.ConfChange{ - Type: raftpb.ConfChangeAddNode, - NodeID: self, - Context: ctx, - } - e := raftpb.Entry{ - Type: raftpb.EntryConfChange, - Data: pbutil.MustMarshal(cc), - Term: term, - Index: next, - } - ents = append(ents, e) - next++ - } - - for _, id := range ids { - if id == self { - continue - } - cc := &raftpb.ConfChange{ - Type: raftpb.ConfChangeRemoveNode, - NodeID: id, - } - e := raftpb.Entry{ - Type: raftpb.EntryConfChange, - Data: pbutil.MustMarshal(cc), - Term: term, - Index: next, - } - ents = append(ents, e) - next++ - } - - return ents -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/server.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/server.go index 798bdb7059..0eb16b7d3c 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/server.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/server.go @@ -17,17 +17,15 @@ package etcdserver import ( "context" "encoding/json" + errorspkg "errors" "expvar" "fmt" "math" - "math/rand" "net/http" - "os" "path" "reflect" "regexp" "strconv" - "strings" "sync" "sync/atomic" "time" @@ -35,8 +33,6 @@ import ( "github.com/coreos/go-semver/semver" humanize "github.com/dustin/go-humanize" "github.com/prometheus/client_golang/prometheus" - "go.etcd.io/etcd/server/v3/config" - "go.etcd.io/etcd/server/v3/wal/walpb" "go.uber.org/zap" pb "go.etcd.io/etcd/api/v3/etcdserverpb" @@ -44,36 +40,44 @@ import ( "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/client/pkg/v3/verify" + "go.etcd.io/etcd/pkg/v3/featuregate" "go.etcd.io/etcd/pkg/v3/idutil" + "go.etcd.io/etcd/pkg/v3/notify" "go.etcd.io/etcd/pkg/v3/pbutil" "go.etcd.io/etcd/pkg/v3/runtime" "go.etcd.io/etcd/pkg/v3/schedule" "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/pkg/v3/wait" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/raft/v3/raftpb" "go.etcd.io/etcd/server/v3/auth" + "go.etcd.io/etcd/server/v3/config" "go.etcd.io/etcd/server/v3/etcdserver/api" + httptypes "go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/types" "go.etcd.io/etcd/server/v3/etcdserver/api/membership" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" "go.etcd.io/etcd/server/v3/etcdserver/api/snap" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes" stats "go.etcd.io/etcd/server/v3/etcdserver/api/v2stats" "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" "go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm" "go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor" + "go.etcd.io/etcd/server/v3/etcdserver/apply" "go.etcd.io/etcd/server/v3/etcdserver/cindex" + "go.etcd.io/etcd/server/v3/etcdserver/errors" + "go.etcd.io/etcd/server/v3/etcdserver/txn" + serverversion "go.etcd.io/etcd/server/v3/etcdserver/version" + "go.etcd.io/etcd/server/v3/features" "go.etcd.io/etcd/server/v3/lease" "go.etcd.io/etcd/server/v3/lease/leasehttp" - "go.etcd.io/etcd/server/v3/mvcc" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/verify" - "go.etcd.io/etcd/server/v3/wal" + serverstorage "go.etcd.io/etcd/server/v3/storage" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/mvcc" + "go.etcd.io/etcd/server/v3/storage/schema" + "go.etcd.io/raft/v3" + "go.etcd.io/raft/v3/raftpb" ) const ( - DefaultSnapshotCount = 100000 + DefaultSnapshotCount = 10000 // DefaultSnapshotCatchUpEntries is the number of entries for a slow follower // to catch-up after compacting the raft storage entries. @@ -86,7 +90,7 @@ const ( StoreKeysPrefix = "/1" // HealthInterval is the minimum time the cluster should be healthy - // before accepting add member requests. + // before accepting add and delete member requests. HealthInterval = 5 * time.Second purgeFileInterval = 30 * time.Second @@ -102,9 +106,12 @@ const ( recommendedMaxRequestBytes = 10 * 1024 * 1024 - readyPercent = 0.9 + // readyPercentThreshold is a threshold used to determine + // whether a learner is ready for a transition into a full voting member or not. + readyPercentThreshold = 0.9 DowngradeEnabledPath = "/downgrade/enabled" + memorySnapshotCount = 100 ) var ( @@ -118,12 +125,10 @@ var ( ) func init() { - rand.Seed(time.Now().UnixNano()) - expvar.Publish( "file_descriptor_limit", expvar.Func( - func() interface{} { + func() any { n, _ := runtime.FDLimit() return n }, @@ -143,15 +148,12 @@ type ServerV2 interface { Server Leader() types.ID - // Do takes a V2 request and attempts to fulfill it, returning a Response. - Do(ctx context.Context, r pb.Request) (Response, error) - stats.Stats ClientCertAuthEnabled() bool } type ServerV3 interface { Server - RaftStatusGetter + apply.RaftStatusGetter } func (s *EtcdServer) ClientCertAuthEnabled() bool { return s.Cfg.ClientCertAuthEnabled } @@ -189,6 +191,9 @@ type Server interface { // the leader is etcd 2.0. etcd 2.0 leader will not update clusterVersion since // this feature is introduced post 2.0. ClusterVersion() *semver.Version + // StorageVersion is the storage schema version. It's supported starting + // from 3.6. + StorageVersion() *semver.Version Cluster() api.Cluster Alarms() []*pb.AlarmMember @@ -237,11 +242,10 @@ type EtcdServer struct { // done is closed when all goroutines from start() complete. done chan struct{} // leaderChanged is used to notify the linearizable read loop to drop the old read requests. - leaderChanged chan struct{} - leaderChangedMu sync.RWMutex + leaderChanged *notify.Notifier errorc chan error - id types.ID + memberID types.ID attributes membership.Attributes cluster *membership.RaftCluster @@ -249,21 +253,15 @@ type EtcdServer struct { v2store v2store.Store snapshotter *snap.Snapshotter - applyV2 ApplierV2 + uberApply apply.UberApplier - // applyV3 is the applier with auth and quotas - applyV3 applierV3 - // applyV3Base is the core applier without auth or quotas - applyV3Base applierV3 - // applyV3Internal is the applier for internal request - applyV3Internal applierV3Internal - applyWait wait.WaitTime + applyWait wait.WaitTime kv mvcc.WatchableKV lessor lease.Lessor - bemu sync.Mutex + bemu sync.RWMutex be backend.Backend - beHooks *backendHooks + beHooks *serverstorage.BackendHooks authStore auth.AuthStore alarmStore *v3alarm.AlarmStore @@ -292,319 +290,66 @@ type EtcdServer struct { leadTimeMu sync.RWMutex leadElectedTime time.Time - firstCommitInTermMu sync.RWMutex - firstCommitInTermC chan struct{} + firstCommitInTerm *notify.Notifier + clusterVersionChanged *notify.Notifier *AccessController + // forceDiskSnapshot can force snapshot be triggered after apply, independent of the snapshotCount. + // Should only be set within apply code path. Used to force snapshot after cluster version downgrade. + // TODO: Replace with flush db in v3.7 assuming v3.6 bootstraps from db file. + forceDiskSnapshot bool corruptionChecker CorruptionChecker } -type backendHooks struct { - indexer cindex.ConsistentIndexer - lg *zap.Logger - - // confState to be written in the next submitted backend transaction (if dirty) - confState raftpb.ConfState - // first write changes it to 'dirty'. false by default, so - // not initialized `confState` is meaningless. - confStateDirty bool - confStateLock sync.Mutex -} - -func (bh *backendHooks) OnPreCommitUnsafe(tx backend.BatchTx) { - bh.indexer.UnsafeSave(tx) - bh.confStateLock.Lock() - defer bh.confStateLock.Unlock() - if bh.confStateDirty { - membership.MustUnsafeSaveConfStateToBackend(bh.lg, tx, &bh.confState) - // save bh.confState - bh.confStateDirty = false - } -} - -func (bh *backendHooks) SetConfState(confState *raftpb.ConfState) { - bh.confStateLock.Lock() - defer bh.confStateLock.Unlock() - bh.confState = *confState - bh.confStateDirty = true -} - // NewServer creates a new EtcdServer from the supplied configuration. The // configuration is considered static for the lifetime of the EtcdServer. func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { - st := v2store.New(StoreClusterPrefix, StoreKeysPrefix) - - var ( - w *wal.WAL - n raft.Node - s *raft.MemoryStorage - id types.ID - cl *membership.RaftCluster - ) - - if cfg.MaxRequestBytes > recommendedMaxRequestBytes { - cfg.Logger.Warn( - "exceeded recommended request limit", - zap.Uint("max-request-bytes", cfg.MaxRequestBytes), - zap.String("max-request-size", humanize.Bytes(uint64(cfg.MaxRequestBytes))), - zap.Int("recommended-request-bytes", recommendedMaxRequestBytes), - zap.String("recommended-request-size", recommendedMaxRequestBytesString), - ) - } - - if terr := fileutil.TouchDirAll(cfg.Logger, cfg.DataDir); terr != nil { - return nil, fmt.Errorf("cannot access data directory: %v", terr) - } - - haveWAL := wal.Exist(cfg.WALDir()) - - if err = fileutil.TouchDirAll(cfg.Logger, cfg.SnapDir()); err != nil { - cfg.Logger.Fatal( - "failed to create snapshot directory", - zap.String("path", cfg.SnapDir()), - zap.Error(err), - ) - } - - if err = fileutil.RemoveMatchFile(cfg.Logger, cfg.SnapDir(), func(fileName string) bool { - return strings.HasPrefix(fileName, "tmp") - }); err != nil { - cfg.Logger.Error( - "failed to remove temp file(s) in snapshot directory", - zap.String("path", cfg.SnapDir()), - zap.Error(err), - ) - } - - ss := snap.New(cfg.Logger, cfg.SnapDir()) - - bepath := cfg.BackendPath() - beExist := fileutil.Exist(bepath) - - ci := cindex.NewConsistentIndex(nil) - beHooks := &backendHooks{lg: cfg.Logger, indexer: ci} - be := openBackend(cfg, beHooks) - ci.SetBackend(be) - cindex.CreateMetaBucket(be.BatchTx()) - - if cfg.ExperimentalBootstrapDefragThresholdMegabytes != 0 { - err := maybeDefragBackend(cfg, be) - if err != nil { - return nil, err - } - } - - defer func() { - if be != nil && err != nil { - be.Close() - } - }() - - prt, err := rafthttp.NewRoundTripper(cfg.PeerTLSInfo, cfg.PeerDialTimeout()) + b, err := bootstrap(cfg) if err != nil { + cfg.Logger.Error("bootstrap failed", zap.Error(err)) return nil, err } - var ( - remotes []*membership.Member - snapshot *raftpb.Snapshot - ) + cfg.Logger.Info("bootstrap successfully") - switch { - case !haveWAL && !cfg.NewCluster: - if err = cfg.VerifyJoinExisting(); err != nil { - return nil, err - } - cl, err = membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap, membership.WithMaxLearners(cfg.ExperimentalMaxLearners)) - if err != nil { - return nil, err - } - existingCluster, gerr := GetClusterFromRemotePeers(cfg.Logger, getRemotePeerURLs(cl, cfg.Name), prt) - if gerr != nil { - return nil, fmt.Errorf("cannot fetch cluster info from peer urls: %v", gerr) - } - if err = membership.ValidateClusterAndAssignIDs(cfg.Logger, cl, existingCluster); err != nil { - return nil, fmt.Errorf("error validating peerURLs %s: %v", existingCluster, err) - } - if !isCompatibleWithCluster(cfg.Logger, cl, cl.MemberByName(cfg.Name).ID, prt) { - return nil, fmt.Errorf("incompatible with current running cluster") - } - scaleUpLearners := false - if err := membership.ValidateMaxLearnerConfig(cfg.ExperimentalMaxLearners, existingCluster.Members(), scaleUpLearners); err != nil { - return nil, err - } - remotes = existingCluster.Members() - cl.SetID(types.ID(0), existingCluster.ID()) - cl.SetStore(st) - cl.SetBackend(be) - id, n, s, w = startNode(cfg, cl, nil) - cl.SetID(id, existingCluster.ID()) - - case !haveWAL && cfg.NewCluster: - if err = cfg.VerifyBootstrap(); err != nil { - return nil, err - } - cl, err = membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, cfg.InitialPeerURLsMap, membership.WithMaxLearners(cfg.ExperimentalMaxLearners)) - if err != nil { - return nil, err - } - m := cl.MemberByName(cfg.Name) - if isMemberBootstrapped(cfg.Logger, cl, cfg.Name, prt, cfg.BootstrapTimeoutEffective()) { - return nil, fmt.Errorf("member %s has already been bootstrapped", m.ID) - } - if cfg.ShouldDiscover() { - var str string - str, err = v2discovery.JoinCluster(cfg.Logger, cfg.DiscoveryURL, cfg.DiscoveryProxy, m.ID, cfg.InitialPeerURLsMap.String()) - if err != nil { - return nil, &DiscoveryError{Op: "join", Err: err} - } - var urlsmap types.URLsMap - urlsmap, err = types.NewURLsMap(str) - if err != nil { - return nil, err - } - if config.CheckDuplicateURL(urlsmap) { - return nil, fmt.Errorf("discovery cluster %s has duplicate url", urlsmap) - } - if cl, err = membership.NewClusterFromURLsMap(cfg.Logger, cfg.InitialClusterToken, urlsmap, membership.WithMaxLearners(cfg.ExperimentalMaxLearners)); err != nil { - return nil, err - } - } - cl.SetStore(st) - cl.SetBackend(be) - id, n, s, w = startNode(cfg, cl, cl.MemberIDs()) - cl.SetID(id, cl.ID()) - - case haveWAL: - if err = fileutil.IsDirWriteable(cfg.MemberDir()); err != nil { - return nil, fmt.Errorf("cannot write to member directory: %v", err) - } - - if err = fileutil.IsDirWriteable(cfg.WALDir()); err != nil { - return nil, fmt.Errorf("cannot write to WAL directory: %v", err) - } - - if cfg.ShouldDiscover() { - cfg.Logger.Warn( - "discovery token is ignored since cluster already initialized; valid logs are found", - zap.String("wal-dir", cfg.WALDir()), - ) - } - - // Find a snapshot to start/restart a raft node - var walSnaps []walpb.Snapshot - walSnaps, err = wal.ValidSnapshotEntries(cfg.Logger, cfg.WALDir()) + defer func() { if err != nil { - return nil, err - } - // snapshot files can be orphaned if etcd crashes after writing them but before writing the corresponding - // wal log entries - snapshot, err = ss.LoadNewestAvailable(walSnaps) - if err != nil && err != snap.ErrNoSnapshot { - return nil, err - } - - if snapshot != nil { - if err = st.Recovery(snapshot.Data); err != nil { - cfg.Logger.Panic("failed to recover from snapshot", zap.Error(err)) - } - - if err = assertNoV2StoreContent(cfg.Logger, st, cfg.V2Deprecation); err != nil { - cfg.Logger.Error("illegal v2store content", zap.Error(err)) - return nil, err - } - - cfg.Logger.Info( - "recovered v2 store from snapshot", - zap.Uint64("snapshot-index", snapshot.Metadata.Index), - zap.String("snapshot-size", humanize.Bytes(uint64(snapshot.Size()))), - ) - - if be, err = recoverSnapshotBackend(cfg, be, *snapshot, beExist, beHooks); err != nil { - cfg.Logger.Panic("failed to recover v3 backend from snapshot", zap.Error(err)) - } - // A snapshot db may have already been recovered, and the old db should have - // already been closed in this case, so we should set the backend again. - ci.SetBackend(be) - s1, s2 := be.Size(), be.SizeInUse() - cfg.Logger.Info( - "recovered v3 backend from snapshot", - zap.Int64("backend-size-bytes", s1), - zap.String("backend-size", humanize.Bytes(uint64(s1))), - zap.Int64("backend-size-in-use-bytes", s2), - zap.String("backend-size-in-use", humanize.Bytes(uint64(s2))), - ) - } else { - cfg.Logger.Info("No snapshot found. Recovering WAL from scratch!") - } - - if !cfg.ForceNewCluster { - id, cl, n, s, w = restartNode(cfg, snapshot) - } else { - id, cl, n, s, w = restartAsStandaloneNode(cfg, snapshot, be) - } - - cl.SetStore(st) - cl.SetBackend(be) - cl.Recover(api.UpdateCapability) - - scaleUpLearners := false - if err := membership.ValidateMaxLearnerConfig(cfg.ExperimentalMaxLearners, cl.Members(), scaleUpLearners); err != nil { - return nil, err + b.Close() } + }() - if cl.Version() != nil && !cl.Version().LessThan(semver.Version{Major: 3}) && !beExist { - os.RemoveAll(bepath) - return nil, fmt.Errorf("database file (%v) of the backend is missing", bepath) - } - - default: - return nil, fmt.Errorf("unsupported bootstrap config") - } - - if terr := fileutil.TouchDirAll(cfg.Logger, cfg.MemberDir()); terr != nil { - return nil, fmt.Errorf("cannot access member directory: %v", terr) - } - - sstats := stats.NewServerStats(cfg.Name, id.String()) - lstats := stats.NewLeaderStats(cfg.Logger, id.String()) + sstats := stats.NewServerStats(cfg.Name, b.cluster.cl.String()) + lstats := stats.NewLeaderStats(cfg.Logger, b.cluster.nodeID.String()) heartbeat := time.Duration(cfg.TickMs) * time.Millisecond srv = &EtcdServer{ - readych: make(chan struct{}), - Cfg: cfg, - lgMu: new(sync.RWMutex), - lg: cfg.Logger, - errorc: make(chan error, 1), - v2store: st, - snapshotter: ss, - r: *newRaftNode( - raftNodeConfig{ - lg: cfg.Logger, - isIDRemoved: func(id uint64) bool { return cl.IsIDRemoved(types.ID(id)) }, - Node: n, - heartbeat: heartbeat, - raftStorage: s, - storage: NewStorage(w, ss), - }, - ), - id: id, - attributes: membership.Attributes{Name: cfg.Name, ClientURLs: cfg.ClientURLs.StringSlice()}, - cluster: cl, - stats: sstats, - lstats: lstats, - SyncTicker: time.NewTicker(500 * time.Millisecond), - peerRt: prt, - reqIDGen: idutil.NewGenerator(uint16(id), time.Now()), - AccessController: &AccessController{CORS: cfg.CORS, HostWhitelist: cfg.HostWhitelist}, - consistIndex: ci, - firstCommitInTermC: make(chan struct{}), - } - serverID.With(prometheus.Labels{"server_id": id.String()}).Set(1) - - srv.applyV2 = NewApplierV2(cfg.Logger, srv.v2store, srv.cluster) - - srv.be = be - srv.beHooks = beHooks + readych: make(chan struct{}), + Cfg: cfg, + lgMu: new(sync.RWMutex), + lg: cfg.Logger, + errorc: make(chan error, 1), + v2store: b.storage.st, + snapshotter: b.ss, + r: *b.raft.newRaftNode(b.ss, b.storage.wal.w, b.cluster.cl), + memberID: b.cluster.nodeID, + attributes: membership.Attributes{Name: cfg.Name, ClientURLs: cfg.ClientURLs.StringSlice()}, + cluster: b.cluster.cl, + stats: sstats, + lstats: lstats, + SyncTicker: time.NewTicker(500 * time.Millisecond), + peerRt: b.prt, + reqIDGen: idutil.NewGenerator(uint16(b.cluster.nodeID), time.Now()), + AccessController: &AccessController{CORS: cfg.CORS, HostWhitelist: cfg.HostWhitelist}, + consistIndex: b.storage.backend.ci, + firstCommitInTerm: notify.NewNotifier(), + clusterVersionChanged: notify.NewNotifier(), + } + + addFeatureGateMetrics(cfg.ServerFeatureGate, serverFeatureEnabled) + serverID.With(prometheus.Labels{"server_id": b.cluster.nodeID.String()}).Set(1) + srv.cluster.SetVersionChangedNotifier(srv.clusterVersionChanged) + + srv.be = b.storage.backend.be + srv.beHooks = b.storage.backend.beHooks minTTL := time.Duration((3*cfg.ElectionTicks)/2) * heartbeat // always recover lessor before kv. When we recover the mvcc.KV it will reattach keys to its leases. @@ -612,7 +357,7 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { srv.lessor = lease.NewLessor(srv.Logger(), srv.be, srv.cluster, lease.LessorConfig{ MinLeaseTTL: int64(math.Ceil(minTTL.Seconds())), CheckpointInterval: cfg.LeaseCheckpointInterval, - CheckpointPersist: cfg.LeaseCheckpointPersist, + CheckpointPersist: cfg.ServerFeatureGate.Enabled(features.LeaseCheckpointPersist), ExpiredLeasesRetryInterval: srv.Cfg.ReqTimeout(), }) @@ -632,26 +377,9 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { CompactionSleepInterval: cfg.CompactionSleepInterval, } srv.kv = mvcc.New(srv.Logger(), srv.be, srv.lessor, mvccStoreConfig) - - kvindex := ci.ConsistentIndex() - srv.lg.Info("restore consistentIndex", zap.Uint64("index", kvindex)) - - if beExist { - // TODO: remove kvindex != 0 checking when we do not expect users to upgrade - // etcd from pre-3.0 release. - if snapshot != nil && kvindex < snapshot.Metadata.Index { - if kvindex != 0 { - return nil, fmt.Errorf("database file (%v index %d) does not match with snapshot (index %d)", bepath, kvindex, snapshot.Metadata.Index) - } - cfg.Logger.Warn( - "consistent index was never saved", - zap.Uint64("snapshot-index", snapshot.Metadata.Index), - ) - } - } srv.corruptionChecker = newCorruptionChecker(cfg.Logger, srv, srv.kv.HashStorage()) - srv.authStore = auth.NewAuthStore(srv.Logger(), srv.be, tp, int(cfg.BcryptCost)) + srv.authStore = auth.NewAuthStore(srv.Logger(), schema.NewAuthBackend(srv.Logger(), srv.be), tp, int(cfg.BcryptCost)) newSrv := srv // since srv == nil in defer if srv is returned as nil defer func() { @@ -669,18 +397,17 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { srv.compactor.Run() } - srv.applyV3Base = srv.newApplierV3Backend() - srv.applyV3Internal = srv.newApplierV3Internal() if err = srv.restoreAlarms(); err != nil { return nil, err } + srv.uberApply = srv.NewUberApplier() - if srv.Cfg.EnableLeaseCheckpoint { + if srv.FeatureEnabled(features.LeaseCheckpoint) { // setting checkpointer enables lease checkpoint feature. srv.lessor.SetCheckpointer(func(ctx context.Context, cp *pb.LeaseCheckpointRequest) error { if !srv.ensureLeadership() { srv.lg.Warn("Ignore the checkpoint request because current member isn't a leader", - zap.Uint64("local-member-id", uint64(srv.ID()))) + zap.Uint64("local-member-id", uint64(srv.MemberID()))) return lease.ErrNotPrimary } @@ -698,11 +425,11 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { Logger: cfg.Logger, TLSInfo: cfg.PeerTLSInfo, DialTimeout: cfg.PeerDialTimeout(), - ID: id, + ID: b.cluster.nodeID, URLs: cfg.PeerURLs, - ClusterID: cl.ID(), + ClusterID: b.cluster.cl.ID(), Raft: srv, - Snapshotter: ss, + Snapshotter: b.ss, ServerStats: sstats, LeaderStats: lstats, ErrorC: srv.errorc, @@ -711,13 +438,13 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { return nil, err } // add all remotes into transport - for _, m := range remotes { - if m.ID != id { + for _, m := range b.cluster.remotes { + if m.ID != b.cluster.nodeID { tr.AddRemote(m.ID, m.PeerURLs) } } - for _, m := range cl.Members() { - if m.ID != id { + for _, m := range b.cluster.cl.Members() { + if m.ID != b.cluster.nodeID { tr.AddPeer(m.ID, m.PeerURLs) } } @@ -726,23 +453,6 @@ func NewServer(cfg config.ServerConfig) (srv *EtcdServer, err error) { return srv, nil } -// assertNoV2StoreContent -> depending on the deprecation stage, warns or report an error -// if the v2store contains custom content. -func assertNoV2StoreContent(lg *zap.Logger, st v2store.Store, deprecationStage config.V2DeprecationEnum) error { - metaOnly, err := membership.IsMetaStoreOnly(st) - if err != nil { - return err - } - if metaOnly { - return nil - } - if deprecationStage.IsAtLeast(config.V2_DEPR_1_WRITE_ONLY) { - return fmt.Errorf("detected disallowed custom content in v2store for stage --v2-deprecation=%s", deprecationStage) - } - lg.Warn("detected custom v2store content. Etcd v3.5 is the last version allowing to access it using API v2. Please remove the content.") - return nil -} - func (s *EtcdServer) Logger() *zap.Logger { s.lgMu.RLock() l := s.lg @@ -754,6 +464,11 @@ func (s *EtcdServer) Config() config.ServerConfig { return s.Cfg } +// FeatureEnabled returns true if the feature is enabled by the etcd server, false otherwise. +func (s *EtcdServer) FeatureEnabled(f featuregate.Feature) bool { + return s.Cfg.ServerFeatureGate.Enabled(f) +} + func tickToDur(ticks int, tickMs uint) string { return fmt.Sprintf("%v", time.Duration(ticks)*time.Duration(tickMs)*time.Millisecond) } @@ -767,7 +482,7 @@ func (s *EtcdServer) adjustTicks() { ticks := s.Cfg.ElectionTicks - 1 lg.Info( "started as single-node; fast-forwarding election ticks", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.Int("forward-ticks", ticks), zap.String("forward-duration", tickToDur(ticks, s.Cfg.TickMs)), zap.Int("election-ticks", s.Cfg.ElectionTicks), @@ -806,7 +521,7 @@ func (s *EtcdServer) adjustTicks() { lg.Info( "initialized peer connections; fast-forwarding election ticks", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.Int("forward-ticks", ticks), zap.String("forward-duration", tickToDur(ticks, s.Cfg.TickMs)), zap.Int("election-ticks", s.Cfg.ElectionTicks), @@ -827,12 +542,11 @@ func (s *EtcdServer) adjustTicks() { func (s *EtcdServer) Start() { s.start() s.GoAttach(func() { s.adjustTicks() }) - // TODO: Switch to publishV3 in 3.6. - // Support for cluster_member_set_attr was added in 3.5. - s.GoAttach(func() { s.publish(s.Cfg.ReqTimeout()) }) + s.GoAttach(func() { s.publishV3(s.Cfg.ReqTimeout()) }) s.GoAttach(s.purgeFile) s.GoAttach(func() { monitorFileDescriptor(s.Logger(), s.stopping) }) - s.GoAttach(s.monitorVersions) + s.GoAttach(s.monitorClusterVersions) + s.GoAttach(s.monitorStorageVersion) s.GoAttach(s.linearizableReadLoop) s.GoAttach(s.monitorKVHash) s.GoAttach(s.monitorCompactHash) @@ -870,11 +584,11 @@ func (s *EtcdServer) start() { s.ctx, s.cancel = context.WithCancel(context.Background()) s.readwaitc = make(chan struct{}, 1) s.readNotifier = newNotifier() - s.leaderChanged = make(chan struct{}) + s.leaderChanged = notify.NewNotifier() if s.ClusterVersion() != nil { lg.Info( "starting etcd server", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("local-server-version", version.Version), zap.String("cluster-id", s.Cluster().ID().String()), zap.String("cluster-version", version.Cluster(s.ClusterVersion().String())), @@ -883,7 +597,7 @@ func (s *EtcdServer) start() { } else { lg.Info( "starting etcd server", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("local-server-version", version.Version), zap.String("cluster-version", "to_be_decided"), ) @@ -952,7 +666,7 @@ type ServerPeerV2 interface { DowngradeEnabledHandler() http.Handler } -func (s *EtcdServer) DowngradeInfo() *membership.DowngradeInfo { return s.cluster.DowngradeInfo() } +func (s *EtcdServer) DowngradeInfo() *serverversion.DowngradeInfo { return s.cluster.DowngradeInfo() } type downgradeEnabledHandler struct { lg *zap.Logger @@ -1003,15 +717,15 @@ func (s *EtcdServer) Process(ctx context.Context, m raftpb.Message) error { if s.cluster.IsIDRemoved(types.ID(m.From)) { lg.Warn( "rejected Raft message from removed member", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("removed-member-id", types.ID(m.From).String()), ) return httptypes.NewHTTPError(http.StatusForbidden, "cannot process message from removed member") } - if s.ID() != types.ID(m.To) { + if s.MemberID() != types.ID(m.To) { lg.Warn( "rejected Raft message to mismatch member", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("mismatch-member-id", types.ID(m.To).String()), ) return httptypes.NewHTTPError(http.StatusForbidden, "cannot process message to mismatch member") @@ -1033,15 +747,16 @@ func (s *EtcdServer) ReportSnapshot(id uint64, status raft.SnapshotStatus) { } type etcdProgress struct { - confState raftpb.ConfState - snapi uint64 - appliedt uint64 - appliedi uint64 + confState raftpb.ConfState + diskSnapshotIndex uint64 + memorySnapshotIndex uint64 + appliedt uint64 + appliedi uint64 } // raftReadyHandler contains a set of EtcdServer operations to be called by raftNode, // and helps decouple state machine logic from Raft algorithms. -// TODO: add a state machine interface to apply the commit entries and do snapshot/recover +// TODO: add a state machine interface to toApply the commit entries and do snapshot/recover type raftReadyHandler struct { getLead func() (lead uint64) updateLead func(lead uint64) @@ -1057,24 +772,9 @@ func (s *EtcdServer) run() { lg.Panic("failed to get snapshot from Raft storage", zap.Error(err)) } - // asynchronously accept apply packets, dispatch progress in-order - sched := schedule.NewFIFOScheduler() + // asynchronously accept toApply packets, dispatch progress in-order + sched := schedule.NewFIFOScheduler(lg) - var ( - smu sync.RWMutex - syncC <-chan time.Time - ) - setSyncC := func(ch <-chan time.Time) { - smu.Lock() - syncC = ch - smu.Unlock() - } - getSyncC := func() (ch <-chan time.Time) { - smu.RLock() - ch = syncC - smu.RUnlock() - return - } rh := &raftReadyHandler{ getLead: func() (lead uint64) { return s.getLead() }, updateLead: func(lead uint64) { s.setLead(lead) }, @@ -1086,7 +786,6 @@ func (s *EtcdServer) run() { if s.compactor != nil { s.compactor.Pause() } - setSyncC(nil) } else { if newLeader { t := time.Now() @@ -1094,17 +793,12 @@ func (s *EtcdServer) run() { s.leadElectedTime = t s.leadTimeMu.Unlock() } - setSyncC(s.SyncTicker.C) if s.compactor != nil { s.compactor.Resume() } } if newLeader { - s.leaderChangedMu.Lock() - lc := s.leaderChanged - s.leaderChanged = make(chan struct{}) - close(lc) - s.leaderChangedMu.Unlock() + s.leaderChanged.Notify() } // TODO: remove the nil checking // current test utility does not provide the stats @@ -1122,10 +816,11 @@ func (s *EtcdServer) run() { s.r.start(rh) ep := etcdProgress{ - confState: sn.Metadata.ConfState, - snapi: sn.Metadata.Index, - appliedt: sn.Metadata.Term, - appliedi: sn.Metadata.Index, + confState: sn.Metadata.ConfState, + diskSnapshotIndex: sn.Metadata.Index, + memorySnapshotIndex: sn.Metadata.Index, + appliedt: sn.Metadata.Term, + appliedi: sn.Metadata.Index, } defer func() { @@ -1135,7 +830,7 @@ func (s *EtcdServer) run() { s.cancel() sched.Stop() - // wait for gouroutines before closing raft so wal stays open + // wait for goroutines before closing raft so wal stays open s.wg.Wait() s.SyncTicker.Stop() @@ -1157,7 +852,7 @@ func (s *EtcdServer) run() { for { select { case ap := <-s.r.apply(): - f := func(context.Context) { s.applyAll(&ep, &ap) } + f := schedule.NewJob("server_applyAll", func(context.Context) { s.applyAll(&ep, &ap) }) sched.Schedule(f) case leases := <-expiredLeaseC: s.revokeExpiredLeases(leases) @@ -1165,10 +860,6 @@ func (s *EtcdServer) run() { lg.Warn("server error", zap.Error(err)) lg.Warn("data-dir used by this member must be removed") return - case <-getSyncC(): - if s.v2store.HasTTLKeys() { - s.sync(s.Cfg.ReqTimeout()) - } case <-s.stop: return } @@ -1186,7 +877,7 @@ func (s *EtcdServer) revokeExpiredLeases(leases []*lease.Lease) { lg := s.Logger() if !s.ensureLeadership() { lg.Warn("Ignore the lease revoking request because current member isn't a leader", - zap.Uint64("local-member-id", uint64(s.ID()))) + zap.Uint64("local-member-id", uint64(s.MemberID()))) return } @@ -1250,11 +941,11 @@ func (s *EtcdServer) ensureLeadership() bool { return false } - newLeaderId := s.raftStatus().Lead - if newLeaderId != uint64(s.ID()) { + newLeaderID := s.raftStatus().Lead + if newLeaderID != uint64(s.MemberID()) { lg.Warn("Current member isn't a leader", - zap.Uint64("local-member-id", uint64(s.ID())), - zap.Uint64("new-lead", newLeaderId)) + zap.Uint64("local-member-id", uint64(s.MemberID())), + zap.Uint64("new-lead", newLeaderID)) return false } @@ -1283,19 +974,26 @@ func (s *EtcdServer) Cleanup() { } } -func (s *EtcdServer) applyAll(ep *etcdProgress, apply *apply) { +func (s *EtcdServer) Defragment() error { + s.bemu.Lock() + defer s.bemu.Unlock() + return s.be.Defrag() +} + +func (s *EtcdServer) applyAll(ep *etcdProgress, apply *toApply) { s.applySnapshot(ep, apply) s.applyEntries(ep, apply) + backend.VerifyBackendConsistency(s.Backend(), s.Logger(), true, schema.AllBuckets...) proposalsApplied.Set(float64(ep.appliedi)) s.applyWait.Trigger(ep.appliedi) // wait for the raft routine to finish the disk writes before triggering a // snapshot. or applied index might be greater than the last index in raft - // storage, since the raft routine might be slower than apply routine. + // storage, since the raft routine might be slower than toApply routine. <-apply.notifyc - s.triggerSnapshot(ep) + s.snapshotIfNeededAndCompactRaftLog(ep) select { // snapshot requested via send() case m := <-s.r.msgSnapC: @@ -1305,8 +1003,8 @@ func (s *EtcdServer) applyAll(ep *etcdProgress, apply *apply) { } } -func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { - if raft.IsEmptySnap(apply.snapshot) { +func (s *EtcdServer) applySnapshot(ep *etcdProgress, toApply *toApply) { + if raft.IsEmptySnap(toApply.snapshot) { return } applySnapshotInProgress.Inc() @@ -1314,40 +1012,50 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { lg := s.Logger() lg.Info( "applying snapshot", - zap.Uint64("current-snapshot-index", ep.snapi), + zap.Uint64("current-snapshot-index", ep.diskSnapshotIndex), zap.Uint64("current-applied-index", ep.appliedi), - zap.Uint64("incoming-leader-snapshot-index", apply.snapshot.Metadata.Index), - zap.Uint64("incoming-leader-snapshot-term", apply.snapshot.Metadata.Term), + zap.Uint64("incoming-leader-snapshot-index", toApply.snapshot.Metadata.Index), + zap.Uint64("incoming-leader-snapshot-term", toApply.snapshot.Metadata.Term), ) defer func() { lg.Info( "applied snapshot", - zap.Uint64("current-snapshot-index", ep.snapi), + zap.Uint64("current-snapshot-index", ep.diskSnapshotIndex), zap.Uint64("current-applied-index", ep.appliedi), - zap.Uint64("incoming-leader-snapshot-index", apply.snapshot.Metadata.Index), - zap.Uint64("incoming-leader-snapshot-term", apply.snapshot.Metadata.Term), + zap.Uint64("incoming-leader-snapshot-index", toApply.snapshot.Metadata.Index), + zap.Uint64("incoming-leader-snapshot-term", toApply.snapshot.Metadata.Term), ) applySnapshotInProgress.Dec() }() - if apply.snapshot.Metadata.Index <= ep.appliedi { + if toApply.snapshot.Metadata.Index <= ep.appliedi { lg.Panic( "unexpected leader snapshot from outdated index", - zap.Uint64("current-snapshot-index", ep.snapi), + zap.Uint64("current-snapshot-index", ep.diskSnapshotIndex), zap.Uint64("current-applied-index", ep.appliedi), - zap.Uint64("incoming-leader-snapshot-index", apply.snapshot.Metadata.Index), - zap.Uint64("incoming-leader-snapshot-term", apply.snapshot.Metadata.Term), + zap.Uint64("incoming-leader-snapshot-index", toApply.snapshot.Metadata.Index), + zap.Uint64("incoming-leader-snapshot-term", toApply.snapshot.Metadata.Term), ) } // wait for raftNode to persist snapshot onto the disk - <-apply.notifyc + <-toApply.notifyc + + bemuUnlocked := false + s.bemu.Lock() + defer func() { + if !bemuUnlocked { + s.bemu.Unlock() + } + }() // gofail: var applyBeforeOpenSnapshot struct{} - newbe, err := openSnapshotBackend(s.Cfg, s.snapshotter, apply.snapshot, s.beHooks) + newbe, err := serverstorage.OpenSnapshotBackend(s.Cfg, s.snapshotter, toApply.snapshot, s.beHooks) if err != nil { lg.Panic("failed to open snapshot backend", zap.Error(err)) } + lg.Info("applySnapshot: opened snapshot backend") + // gofail: var applyAfterOpenSnapshot struct{} // We need to set the backend to consistIndex before recovering the lessor, // because lessor.Recover will commit the boltDB transaction, accordingly it @@ -1355,6 +1063,7 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { // Eventually the new consistent_index value coming from snapshot is overwritten // by the old value. s.consistIndex.SetBackend(newbe) + verifySnapshotIndex(toApply.snapshot, s.consistIndex.ConsistentIndex()) // always recover lessor before kv. When we recover the mvcc.KV it will reattach keys to its leases. // If we recover mvcc.KV first, it will attach the keys to the wrong lessor before it recovers. @@ -1373,13 +1082,17 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { } newbe.SetTxPostLockInsideApplyHook(s.getTxPostLockInsideApplyHook()) + lg.Info("restored mvcc store", zap.Uint64("consistent-index", s.consistIndex.ConsistentIndex())) + oldbe := s.be + s.be = newbe + s.bemu.Unlock() + bemuUnlocked = true + // Closing old backend might block until all the txns // on the backend are finished. // We do not want to wait on closing the old backend. - s.bemu.Lock() - oldbe := s.be go func() { lg.Info("closing old backend file") defer func() { @@ -1390,9 +1103,6 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { } }() - s.be = newbe - s.bemu.Unlock() - lg.Info("restoring alarm store") if err := s.restoreAlarms(); err != nil { @@ -1404,23 +1114,23 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { if s.authStore != nil { lg.Info("restoring auth store") - s.authStore.Recover(newbe) + s.authStore.Recover(schema.NewAuthBackend(lg, newbe)) lg.Info("restored auth store") } lg.Info("restoring v2 store") - if err := s.v2store.Recovery(apply.snapshot.Data); err != nil { + if err := s.v2store.Recovery(toApply.snapshot.Data); err != nil { lg.Panic("failed to restore v2 store", zap.Error(err)) } - if err := assertNoV2StoreContent(lg, s.v2store, s.Cfg.V2Deprecation); err != nil { + if err := serverstorage.AssertNoV2StoreContent(lg, s.v2store, s.Cfg.V2Deprecation); err != nil { lg.Panic("illegal v2store content", zap.Error(err)) } lg.Info("restored v2 store") - s.cluster.SetBackend(newbe) + s.cluster.SetBackend(schema.NewMembershipBackend(lg, newbe)) lg.Info("restoring cluster configuration") @@ -1436,7 +1146,7 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { lg.Info("adding peers from new cluster configuration") for _, m := range s.cluster.Members() { - if m.ID == s.ID() { + if m.ID == s.MemberID() { continue } s.r.transport.AddPeer(m.ID, m.PeerURLs) @@ -1444,13 +1154,39 @@ func (s *EtcdServer) applySnapshot(ep *etcdProgress, apply *apply) { lg.Info("added peers from new cluster configuration") - ep.appliedt = apply.snapshot.Metadata.Term - ep.appliedi = apply.snapshot.Metadata.Index - ep.snapi = ep.appliedi - ep.confState = apply.snapshot.Metadata.ConfState + ep.appliedt = toApply.snapshot.Metadata.Term + ep.appliedi = toApply.snapshot.Metadata.Index + ep.diskSnapshotIndex = ep.appliedi + ep.memorySnapshotIndex = ep.appliedi + ep.confState = toApply.snapshot.Metadata.ConfState + + // As backends and implementations like alarmsStore changed, we need + // to re-bootstrap Appliers. + s.uberApply = s.NewUberApplier() +} + +func (s *EtcdServer) NewUberApplier() apply.UberApplier { + return apply.NewUberApplier(s.lg, s.be, s.KV(), s.alarmStore, s.authStore, s.lessor, s.cluster, s, s, s.consistIndex, + s.Cfg.WarningApplyDuration, s.Cfg.ServerFeatureGate.Enabled(features.TxnModeWriteWithSharedBuffer), s.Cfg.QuotaBackendBytes) +} + +func verifySnapshotIndex(snapshot raftpb.Snapshot, cindex uint64) { + verify.Verify(func() { + if cindex != snapshot.Metadata.Index { + panic(fmt.Sprintf("consistent_index(%d) isn't equal to snapshot index (%d)", cindex, snapshot.Metadata.Index)) + } + }) } -func (s *EtcdServer) applyEntries(ep *etcdProgress, apply *apply) { +func verifyConsistentIndexIsLatest(lg *zap.Logger, snapshot raftpb.Snapshot, cindex uint64) { + verify.Verify(func() { + if cindex < snapshot.Metadata.Index { + lg.Panic(fmt.Sprintf("consistent_index(%d) is older than snapshot index (%d)", cindex, snapshot.Metadata.Index)) + } + }) +} + +func (s *EtcdServer) applyEntries(ep *etcdProgress, apply *toApply) { if len(apply.entries) == 0 { return } @@ -1471,27 +1207,32 @@ func (s *EtcdServer) applyEntries(ep *etcdProgress, apply *apply) { return } var shouldstop bool - if ep.appliedt, ep.appliedi, shouldstop = s.apply(ents, &ep.confState); shouldstop { + if ep.appliedt, ep.appliedi, shouldstop = s.apply(ents, &ep.confState, apply.raftAdvancedC); shouldstop { go s.stopWithDelay(10*100*time.Millisecond, fmt.Errorf("the member has been permanently removed from the cluster")) } } -func (s *EtcdServer) triggerSnapshot(ep *etcdProgress) { - if ep.appliedi-ep.snapi <= s.Cfg.SnapshotCount { +func (s *EtcdServer) ForceSnapshot() { + s.forceDiskSnapshot = true +} + +func (s *EtcdServer) snapshotIfNeededAndCompactRaftLog(ep *etcdProgress) { + // TODO: Remove disk snapshot in v3.7 + shouldSnapshotToDisk := s.shouldSnapshotToDisk(ep) + shouldSnapshotToMemory := s.shouldSnapshotToMemory(ep) + if !shouldSnapshotToDisk && !shouldSnapshotToMemory { return } + s.snapshot(ep, shouldSnapshotToDisk) + s.compactRaftLog(ep.appliedi) +} - lg := s.Logger() - lg.Info( - "triggering snapshot", - zap.String("local-member-id", s.ID().String()), - zap.Uint64("local-member-applied-index", ep.appliedi), - zap.Uint64("local-member-snapshot-index", ep.snapi), - zap.Uint64("local-member-snapshot-count", s.Cfg.SnapshotCount), - ) +func (s *EtcdServer) shouldSnapshotToDisk(ep *etcdProgress) bool { + return (s.forceDiskSnapshot && ep.appliedi != ep.diskSnapshotIndex) || (ep.appliedi-ep.diskSnapshotIndex > s.Cfg.SnapshotCount) +} - s.snapshot(ep.appliedi, ep.confState) - ep.snapi = ep.appliedi +func (s *EtcdServer) shouldSnapshotToMemory(ep *etcdProgress) bool { + return ep.appliedi > ep.memorySnapshotIndex+memorySnapshotCount } func (s *EtcdServer) hasMultipleVotingMembers() bool { @@ -1499,13 +1240,14 @@ func (s *EtcdServer) hasMultipleVotingMembers() bool { } func (s *EtcdServer) isLeader() bool { - return uint64(s.ID()) == s.Lead() + return uint64(s.MemberID()) == s.Lead() } // MoveLeader transfers the leader to the given transferee. func (s *EtcdServer) MoveLeader(ctx context.Context, lead, transferee uint64) error { - if !s.cluster.IsMemberExist(types.ID(transferee)) || s.cluster.Member(types.ID(transferee)).IsLearner { - return ErrBadLeaderTransferee + member := s.cluster.Member(types.ID(transferee)) + if member == nil || member.IsLearner { + return errors.ErrBadLeaderTransferee } now := time.Now() @@ -1514,7 +1256,7 @@ func (s *EtcdServer) MoveLeader(ctx context.Context, lead, transferee uint64) er lg := s.Logger() lg.Info( "leadership transfer starting", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("current-leader-member-id", types.ID(lead).String()), zap.String("transferee-member-id", types.ID(transferee).String()), ) @@ -1523,7 +1265,7 @@ func (s *EtcdServer) MoveLeader(ctx context.Context, lead, transferee uint64) er for s.Lead() != transferee { select { case <-ctx.Done(): // time out - return ErrTimeoutLeaderTransfer + return errors.ErrTimeoutLeaderTransfer case <-time.After(interval): } } @@ -1531,7 +1273,7 @@ func (s *EtcdServer) MoveLeader(ctx context.Context, lead, transferee uint64) er // TODO: drain all requests, or drop all messages to the old leader lg.Info( "leadership transfer finished", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("old-leader-member-id", types.ID(lead).String()), zap.String("new-leader-member-id", types.ID(transferee).String()), zap.Duration("took", time.Since(now)), @@ -1539,13 +1281,13 @@ func (s *EtcdServer) MoveLeader(ctx context.Context, lead, transferee uint64) er return nil } -// TransferLeadership transfers the leader to the chosen transferee. -func (s *EtcdServer) TransferLeadership() error { +// TryTransferLeadershipOnShutdown transfers the leader to the chosen transferee. It is only used in server graceful shutdown. +func (s *EtcdServer) TryTransferLeadershipOnShutdown() error { lg := s.Logger() if !s.isLeader() { lg.Info( "skipped leadership transfer; local server is not leader", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("current-leader-member-id", types.ID(s.Lead()).String()), ) return nil @@ -1554,7 +1296,7 @@ func (s *EtcdServer) TransferLeadership() error { if !s.hasMultipleVotingMembers() { lg.Info( "skipped leadership transfer for single voting member cluster", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("current-leader-member-id", types.ID(s.Lead()).String()), ) return nil @@ -1562,7 +1304,7 @@ func (s *EtcdServer) TransferLeadership() error { transferee, ok := longestConnected(s.r.transport, s.cluster.VotingMemberIDs()) if !ok { - return ErrUnhealthy + return errors.ErrUnhealthy } tm := s.Cfg.ReqTimeout() @@ -1590,8 +1332,8 @@ func (s *EtcdServer) HardStop() { // Do and Process cannot be called after Stop has been invoked. func (s *EtcdServer) Stop() { lg := s.Logger() - if err := s.TransferLeadership(); err != nil { - lg.Warn("leadership transfer failed", zap.String("local-member-id", s.ID().String()), zap.Error(err)) + if err := s.TryTransferLeadershipOnShutdown(); err != nil { + lg.Warn("leadership transfer failed", zap.String("local-member-id", s.MemberID().String()), zap.Error(err)) } s.HardStop() } @@ -1611,26 +1353,14 @@ func (s *EtcdServer) stopWithDelay(d time.Duration, err error) { } } -// StopNotify returns a channel that receives a empty struct +// StopNotify returns a channel that receives an empty struct // when the server is stopped. func (s *EtcdServer) StopNotify() <-chan struct{} { return s.done } -// StoppingNotify returns a channel that receives a empty struct +// StoppingNotify returns a channel that receives an empty struct // when the server is being stopped. func (s *EtcdServer) StoppingNotify() <-chan struct{} { return s.stopping } -func (s *EtcdServer) SelfStats() []byte { return s.stats.JSON() } - -func (s *EtcdServer) LeaderStats() []byte { - lead := s.getLead() - if lead != uint64(s.id) { - return nil - } - return s.lstats.JSON() -} - -func (s *EtcdServer) StoreStats() []byte { return s.v2store.JsonStats() } - func (s *EtcdServer) checkMembershipOperationPermission(ctx context.Context) error { if s.authStore == nil { // In the context of ordinary etcd process, s.authStore will never be nil. @@ -1640,7 +1370,7 @@ func (s *EtcdServer) checkMembershipOperationPermission(ctx context.Context) err // Note that this permission check is done in the API layer, // so TOCTOU problem can be caused potentially in a schedule like this: - // update membership with user A -> revoke root role of A -> apply membership change + // update membership with user A -> revoke root role of A -> toApply membership change // in the state machine layer // However, both of membership change and role management requires the root privilege. // So careful operation by admins can prevent the problem. @@ -1691,21 +1421,21 @@ func (s *EtcdServer) mayAddMember(memb membership.Member) error { if !memb.IsLearner && !s.cluster.IsReadyToAddVotingMember() { lg.Warn( "rejecting member add request; not enough healthy members", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("requested-member-add", fmt.Sprintf("%+v", memb)), - zap.Error(ErrNotEnoughStartedMembers), + zap.Error(errors.ErrNotEnoughStartedMembers), ) - return ErrNotEnoughStartedMembers + return errors.ErrNotEnoughStartedMembers } - if !isConnectedFullySince(s.r.transport, time.Now().Add(-HealthInterval), s.ID(), s.cluster.VotingMembers()) { + if !isConnectedFullySince(s.r.transport, time.Now().Add(-HealthInterval), s.MemberID(), s.cluster.VotingMembers()) { lg.Warn( "rejecting member add request; local member has not been connected to all peers, reconfigure breaks active quorum", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("requested-member-add", fmt.Sprintf("%+v", memb)), - zap.Error(ErrUnhealthy), + zap.Error(errors.ErrUnhealthy), ) - return ErrUnhealthy + return errors.ErrUnhealthy } return nil @@ -1738,7 +1468,7 @@ func (s *EtcdServer) PromoteMember(ctx context.Context, id uint64) ([]*membershi learnerPromoteSucceed.Inc() return resp, nil } - if err != ErrNotLeader { + if !errorspkg.Is(err, errors.ErrNotLeader) { learnerPromoteFailed.WithLabelValues(err.Error()).Inc() return resp, err } @@ -1757,16 +1487,16 @@ func (s *EtcdServer) PromoteMember(ctx context.Context, id uint64) ([]*membershi return resp, nil } // If member promotion failed, return early. Otherwise keep retry. - if err == ErrLearnerNotReady || err == membership.ErrIDNotFound || err == membership.ErrMemberNotLearner { + if errorspkg.Is(err, errors.ErrLearnerNotReady) || errorspkg.Is(err, membership.ErrIDNotFound) || errorspkg.Is(err, membership.ErrMemberNotLearner) { return nil, err } } } - if cctx.Err() == context.DeadlineExceeded { - return nil, ErrTimeout + if errorspkg.Is(cctx.Err(), context.DeadlineExceeded) { + return nil, errors.ErrTimeout } - return nil, ErrCanceled + return nil, errors.ErrCanceled } // promoteMember checks whether the to-be-promoted learner node is ready before sending the promote @@ -1809,8 +1539,7 @@ func (s *EtcdServer) promoteMember(ctx context.Context, id uint64) ([]*membershi func (s *EtcdServer) mayPromoteMember(id types.ID) error { lg := s.Logger() - err := s.isLearnerReady(uint64(id)) - if err != nil { + if err := s.isLearnerReady(lg, uint64(id)); err != nil { return err } @@ -1820,11 +1549,11 @@ func (s *EtcdServer) mayPromoteMember(id types.ID) error { if !s.cluster.IsReadyToPromoteMember(uint64(id)) { lg.Warn( "rejecting member promote request; not enough healthy members", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("requested-member-remove-id", id.String()), - zap.Error(ErrNotEnoughStartedMembers), + zap.Error(errors.ErrNotEnoughStartedMembers), ) - return ErrNotEnoughStartedMembers + return errors.ErrNotEnoughStartedMembers } return nil @@ -1832,8 +1561,8 @@ func (s *EtcdServer) mayPromoteMember(id types.ID) error { // check whether the learner catches up with leader or not. // Note: it will return nil if member is not found in cluster or if member is not learner. -// These two conditions will be checked before apply phase later. -func (s *EtcdServer) isLearnerReady(id uint64) error { +// These two conditions will be checked before toApply phase later. +func (s *EtcdServer) isLearnerReady(lg *zap.Logger, id uint64) error { if err := s.waitAppliedIndex(); err != nil { return err } @@ -1842,7 +1571,7 @@ func (s *EtcdServer) isLearnerReady(id uint64) error { // leader's raftStatus.Progress is not nil if rs.Progress == nil { - return ErrNotLeader + return errors.ErrNotLeader } var learnerMatch uint64 @@ -1864,9 +1593,17 @@ func (s *EtcdServer) isLearnerReady(id uint64) error { } leaderMatch := rs.Progress[leaderID].Match + + learnerReadyPercent := float64(learnerMatch) / float64(leaderMatch) + // the learner's Match not caught up with leader yet - if float64(learnerMatch) < float64(leaderMatch)*readyPercent { - return ErrLearnerNotReady + if learnerReadyPercent < readyPercentThreshold { + lg.Error( + "rejecting promote learner: learner is not ready", + zap.Float64("learner-ready-percent", learnerReadyPercent), + zap.Float64("ready-percent-threshold", readyPercentThreshold), + ) + return errors.ErrLearnerNotReady } return nil @@ -1878,39 +1615,39 @@ func (s *EtcdServer) mayRemoveMember(id types.ID) error { } lg := s.Logger() - isLearner := s.cluster.IsMemberExist(id) && s.cluster.Member(id).IsLearner + member := s.cluster.Member(id) // no need to check quorum when removing non-voting member - if isLearner { + if member != nil && member.IsLearner { return nil } if !s.cluster.IsReadyToRemoveVotingMember(uint64(id)) { lg.Warn( "rejecting member remove request; not enough healthy members", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("requested-member-remove-id", id.String()), - zap.Error(ErrNotEnoughStartedMembers), + zap.Error(errors.ErrNotEnoughStartedMembers), ) - return ErrNotEnoughStartedMembers + return errors.ErrNotEnoughStartedMembers } // downed member is safe to remove since it's not part of the active quorum - if t := s.r.transport.ActiveSince(id); id != s.ID() && t.IsZero() { + if t := s.r.transport.ActiveSince(id); id != s.MemberID() && t.IsZero() { return nil } // protect quorum if some members are down m := s.cluster.VotingMembers() - active := numConnectedSince(s.r.transport, time.Now().Add(-HealthInterval), s.ID(), m) + active := numConnectedSince(s.r.transport, time.Now().Add(-HealthInterval), s.MemberID(), m) if (active - 1) < 1+((len(m)-1)/2) { lg.Warn( "rejecting member remove request; local member has not been connected to all peers, reconfigure breaks active quorum", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("requested-member-remove", id.String()), zap.Int("active-peers", active), - zap.Error(ErrUnhealthy), + zap.Error(errors.ErrUnhealthy), ) - return ErrUnhealthy + return errors.ErrUnhealthy } return nil @@ -1966,9 +1703,7 @@ func (s *EtcdServer) getLead() uint64 { } func (s *EtcdServer) LeaderChangedNotify() <-chan struct{} { - s.leaderChangedMu.RLock() - defer s.leaderChangedMu.RUnlock() - return s.leaderChanged + return s.leaderChanged.Receive() } // FirstCommitInTermNotify returns channel that will be unlocked on first @@ -1976,21 +1711,18 @@ func (s *EtcdServer) LeaderChangedNotify() <-chan struct{} { // read-only requests (leader is not able to respond any read-only requests // as long as linearizable semantic is required) func (s *EtcdServer) FirstCommitInTermNotify() <-chan struct{} { - s.firstCommitInTermMu.RLock() - defer s.firstCommitInTermMu.RUnlock() - return s.firstCommitInTermC + return s.firstCommitInTerm.Receive() } -// RaftStatusGetter represents etcd server and Raft progress. -type RaftStatusGetter interface { - ID() types.ID - Leader() types.ID - CommittedIndex() uint64 - AppliedIndex() uint64 - Term() uint64 -} +// MemberId returns the ID of the local member. +// Deprecated: Please use (*EtcdServer) MemberID instead. +// +//revive:disable:var-naming +func (s *EtcdServer) MemberId() types.ID { return s.MemberID() } + +//revive:enable:var-naming -func (s *EtcdServer) ID() types.ID { return s.id } +func (s *EtcdServer) MemberID() types.ID { return s.memberID } func (s *EtcdServer) Leader() types.ID { return types.ID(s.getLead()) } @@ -2003,8 +1735,9 @@ func (s *EtcdServer) AppliedIndex() uint64 { return s.getAppliedIndex() } func (s *EtcdServer) Term() uint64 { return s.getTerm() } type confChangeResponse struct { - membs []*membership.Member - err error + membs []*membership.Member + raftAdvanceC <-chan struct{} + err error } // configure sends a configuration change through consensus and @@ -2027,9 +1760,14 @@ func (s *EtcdServer) configure(ctx context.Context, cc raftpb.ConfChange) ([]*me lg.Panic("failed to configure") } resp := x.(*confChangeResponse) + // etcdserver need to ensure the raft has already been notified + // or advanced before it responds to the client. Otherwise, the + // following config change request may be rejected. + // See https://github.com/etcd-io/etcd/issues/15528. + <-resp.raftAdvanceC lg.Info( "applied a configuration change through raft", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("raft-conf-change", cc.Type.String()), zap.String("raft-conf-change-node-id", types.ID(cc.NodeID).String()), ) @@ -2040,29 +1778,10 @@ func (s *EtcdServer) configure(ctx context.Context, cc raftpb.ConfChange) ([]*me return nil, s.parseProposeCtxErr(ctx.Err(), start) case <-s.stopping: - return nil, ErrStopped + return nil, errors.ErrStopped } } -// sync proposes a SYNC request and is non-blocking. -// This makes no guarantee that the request will be proposed or performed. -// The request will be canceled after the given timeout. -func (s *EtcdServer) sync(timeout time.Duration) { - req := pb.Request{ - Method: "SYNC", - ID: s.reqIDGen.Next(), - Time: time.Now().UnixNano(), - } - data := pbutil.MustMarshal(&req) - // There is no promise that node has leader when do SYNC request, - // so it uses goroutine to propose. - ctx, cancel := context.WithTimeout(s.ctx, timeout) - s.GoAttach(func() { - s.r.Propose(ctx, data) - cancel() - }) -} - // publishV3 registers server information into the cluster using v3 request. The // information is the JSON representation of this server's member struct, updated // with the static clientURLs of the server. @@ -2070,19 +1789,20 @@ func (s *EtcdServer) sync(timeout time.Duration) { // or its server is stopped. func (s *EtcdServer) publishV3(timeout time.Duration) { req := &membershippb.ClusterMemberAttrSetRequest{ - Member_ID: uint64(s.id), + Member_ID: uint64(s.MemberID()), MemberAttributes: &membershippb.Attributes{ Name: s.attributes.Name, ClientUrls: s.attributes.ClientURLs, }, } + // gofail: var beforePublishing struct{} lg := s.Logger() for { select { case <-s.stopping: lg.Warn( "stopped publish because server is stopping", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)), zap.Duration("publish-timeout", timeout), ) @@ -2099,83 +1819,18 @@ func (s *EtcdServer) publishV3(timeout time.Duration) { close(s.readych) lg.Info( "published local member to cluster through raft", - zap.String("local-member-id", s.ID().String()), - zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)), - zap.String("cluster-id", s.cluster.ID().String()), - zap.Duration("publish-timeout", timeout), - ) - return - - default: - lg.Warn( - "failed to publish local member to cluster through raft", - zap.String("local-member-id", s.ID().String()), - zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)), - zap.Duration("publish-timeout", timeout), - zap.Error(err), - ) - } - } -} - -// publish registers server information into the cluster. The information -// is the JSON representation of this server's member struct, updated with the -// static clientURLs of the server. -// The function keeps attempting to register until it succeeds, -// or its server is stopped. -// -// Use v2 store to encode member attributes, and apply through Raft -// but does not go through v2 API endpoint, which means even with v2 -// client handler disabled (e.g. --enable-v2=false), cluster can still -// process publish requests through rafthttp -// TODO: Remove in 3.6 (start using publishV3) -func (s *EtcdServer) publish(timeout time.Duration) { - lg := s.Logger() - b, err := json.Marshal(s.attributes) - if err != nil { - lg.Panic("failed to marshal JSON", zap.Error(err)) - return - } - req := pb.Request{ - Method: "PUT", - Path: membership.MemberAttributesStorePath(s.id), - Val: string(b), - } - - // gofail: var beforePublishing struct{} - for { - ctx, cancel := context.WithTimeout(s.ctx, timeout) - _, err := s.Do(ctx, req) - cancel() - switch err { - case nil: - close(s.readych) - lg.Info( - "published local member to cluster through raft", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)), - zap.String("request-path", req.Path), zap.String("cluster-id", s.cluster.ID().String()), zap.Duration("publish-timeout", timeout), ) return - case ErrStopped: - lg.Warn( - "stopped publish because server is stopped", - zap.String("local-member-id", s.ID().String()), - zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)), - zap.Duration("publish-timeout", timeout), - zap.Error(err), - ) - return - default: lg.Warn( "failed to publish local member to cluster through raft", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.String("local-member-attributes", fmt.Sprintf("%+v", s.attributes)), - zap.String("request-path", req.Path), zap.Duration("publish-timeout", timeout), zap.Error(err), ) @@ -2188,7 +1843,7 @@ func (s *EtcdServer) sendMergedSnap(merged snap.Message) { lg := s.Logger() fields := []zap.Field{ - zap.String("from", s.ID().String()), + zap.String("from", s.MemberID().String()), zap.String("to", types.ID(merged.To).String()), zap.Int64("bytes", merged.TotalSize), zap.String("size", humanize.Bytes(uint64(merged.TotalSize))), @@ -2223,37 +1878,40 @@ func (s *EtcdServer) sendMergedSnap(merged snap.Message) { }) } -// apply takes entries received from Raft (after it has been committed) and +// toApply takes entries received from Raft (after it has been committed) and // applies them to the current state of the EtcdServer. // The given entries should not be empty. func (s *EtcdServer) apply( es []raftpb.Entry, confState *raftpb.ConfState, + raftAdvancedC <-chan struct{}, ) (appliedt uint64, appliedi uint64, shouldStop bool) { s.lg.Debug("Applying entries", zap.Int("num-entries", len(es))) for i := range es { e := es[i] + index := s.consistIndex.ConsistentIndex() s.lg.Debug("Applying entry", - zap.Uint64("index", e.Index), - zap.Uint64("term", e.Term), - zap.Stringer("type", e.Type)) + zap.Uint64("consistent-index", index), + zap.Uint64("entry-index", e.Index), + zap.Uint64("entry-term", e.Term), + zap.Stringer("entry-type", e.Type)) + + // We need to toApply all WAL entries on top of v2store + // and only 'unapplied' (e.Index>backend.ConsistentIndex) on the backend. + shouldApplyV3 := membership.ApplyV2storeOnly + if e.Index > index { + shouldApplyV3 = membership.ApplyBoth + // set the consistent index of current executing entry + s.consistIndex.SetConsistentApplyingIndex(e.Index, e.Term) + } switch e.Type { case raftpb.EntryNormal: // gofail: var beforeApplyOneEntryNormal struct{} - s.applyEntryNormal(&e) + s.applyEntryNormal(&e, shouldApplyV3) s.setAppliedIndex(e.Index) s.setTerm(e.Term) case raftpb.EntryConfChange: - // We need to apply all WAL entries on top of v2store - // and only 'unapplied' (e.Index>backend.ConsistentIndex) on the backend. - shouldApplyV3 := membership.ApplyV2storeOnly - - // set the consistent index of current executing entry - if e.Index > s.consistIndex.ConsistentIndex() { - s.consistIndex.SetConsistentApplyingIndex(e.Index, e.Term) - shouldApplyV3 = membership.ApplyBoth - } // gofail: var beforeApplyOneConfChange struct{} var cc raftpb.ConfChange pbutil.MustUnmarshal(&cc, e.Data) @@ -2261,7 +1919,7 @@ func (s *EtcdServer) apply( s.setAppliedIndex(e.Index) s.setTerm(e.Term) shouldStop = shouldStop || removedSelf - s.w.Trigger(cc.ID, &confChangeResponse{s.cluster.Members(), err}) + s.w.Trigger(cc.ID, &confChangeResponse{s.cluster.Members(), raftAdvancedC, err}) default: lg := s.Logger() @@ -2275,15 +1933,10 @@ func (s *EtcdServer) apply( return appliedt, appliedi, shouldStop } -// applyEntryNormal apples an EntryNormal type raftpb request to the EtcdServer -func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { - shouldApplyV3 := membership.ApplyV2storeOnly - var ar *applyResult - index := s.consistIndex.ConsistentIndex() - if e.Index > index { - // set the consistent index of current executing entry - s.consistIndex.SetConsistentApplyingIndex(e.Index, e.Term) - shouldApplyV3 = membership.ApplyBoth +// applyEntryNormal applies an EntryNormal type raftpb request to the EtcdServer +func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry, shouldApplyV3 membership.ShouldApplyV3) { + var ar *apply.Result + if shouldApplyV3 { defer func() { // The txPostLockInsideApplyHook will not get called in some cases, // in which we should move the consistent index forward directly. @@ -2293,15 +1946,11 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { } }() } - s.lg.Debug("apply entry normal", - zap.Uint64("consistent-index", index), - zap.Uint64("entry-index", e.Index), - zap.Bool("should-applyV3", bool(shouldApplyV3))) // raft state machine may generate noop entry when leader confirmation. // skip it in advance to avoid some potential bug in the future if len(e.Data) == 0 { - s.notifyAboutFirstCommitInTerm() + s.firstCommitInTerm.Notify() // promote lessor when the local member is leader and finished // applying all entries from the last term. @@ -2317,19 +1966,20 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { rp := &r pbutil.MustUnmarshal(rp, e.Data) s.lg.Debug("applyEntryNormal", zap.Stringer("V2request", rp)) - s.w.Trigger(r.ID, s.applyV2Request((*RequestV2)(rp), shouldApplyV3)) - return + raftReq = v2ToV3Request(s.lg, (*RequestV2)(rp)) } s.lg.Debug("applyEntryNormal", zap.Stringer("raftReq", &raftReq)) if raftReq.V2 != nil { req := (*RequestV2)(raftReq.V2) - s.w.Trigger(req.ID, s.applyV2Request(req, shouldApplyV3)) - return + raftReq = v2ToV3Request(s.lg, req) } id := raftReq.ID if id == 0 { + if raftReq.Header == nil { + s.lg.Panic("applyEntryNormal, could not find a header") + } id = raftReq.Header.ID } @@ -2338,10 +1988,10 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { if !needResult && raftReq.Txn != nil { removeNeedlessRangeReqs(raftReq.Txn) } - ar = s.applyV3.Apply(&raftReq, shouldApplyV3) + ar = s.applyInternalRaftRequest(&raftReq, shouldApplyV3) } - // do not re-apply applied entries. + // do not re-toApply applied entries. if !shouldApplyV3 { return } @@ -2350,7 +2000,7 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { return } - if ar.err != ErrNoSpace || len(s.alarmStore.Get(pb.AlarmType_NOSPACE)) > 0 { + if !errorspkg.Is(ar.Err, errors.ErrNoSpace) || len(s.alarmStore.Get(pb.AlarmType_NOSPACE)) > 0 { s.w.Trigger(id, ar) return } @@ -2360,12 +2010,12 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { "message exceeded backend quota; raising alarm", zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes), zap.String("quota-size", humanize.Bytes(uint64(s.Cfg.QuotaBackendBytes))), - zap.Error(ar.err), + zap.Error(ar.Err), ) s.GoAttach(func() { a := &pb.AlarmRequest{ - MemberID: uint64(s.ID()), + MemberID: uint64(s.MemberID()), Action: pb.AlarmRequest_ACTIVATE, Alarm: pb.AlarmType_NOSPACE, } @@ -2374,20 +2024,69 @@ func (s *EtcdServer) applyEntryNormal(e *raftpb.Entry) { }) } -func (s *EtcdServer) notifyAboutFirstCommitInTerm() { - newNotifier := make(chan struct{}) - s.firstCommitInTermMu.Lock() - notifierToClose := s.firstCommitInTermC - s.firstCommitInTermC = newNotifier - s.firstCommitInTermMu.Unlock() - close(notifierToClose) +func (s *EtcdServer) applyInternalRaftRequest(r *pb.InternalRaftRequest, shouldApplyV3 membership.ShouldApplyV3) *apply.Result { + if r.ClusterVersionSet == nil && r.ClusterMemberAttrSet == nil && r.DowngradeInfoSet == nil && r.DowngradeVersionTest == nil { + if !shouldApplyV3 { + return nil + } + return s.uberApply.Apply(r) + } + membershipApplier := apply.NewApplierMembership(s.lg, s.cluster, s) + op := "unknown" + defer func(start time.Time) { + txn.ApplySecObserve("v3", op, true, time.Since(start)) + txn.WarnOfExpensiveRequest(s.lg, s.Cfg.WarningApplyDuration, start, &pb.InternalRaftStringer{Request: r}, nil, nil) + }(time.Now()) + switch { + case r.ClusterVersionSet != nil: + op = "ClusterVersionSet" // Implemented in 3.5.x + membershipApplier.ClusterVersionSet(r.ClusterVersionSet, shouldApplyV3) + return &apply.Result{} + case r.ClusterMemberAttrSet != nil: + op = "ClusterMemberAttrSet" // Implemented in 3.5.x + membershipApplier.ClusterMemberAttrSet(r.ClusterMemberAttrSet, shouldApplyV3) + case r.DowngradeInfoSet != nil: + op = "DowngradeInfoSet" // Implemented in 3.5.x + membershipApplier.DowngradeInfoSet(r.DowngradeInfoSet, shouldApplyV3) + case r.DowngradeVersionTest != nil: + op = "DowngradeVersionTest" // Implemented in 3.6 for test only + // do nothing, we are just to ensure etcdserver don't panic in case + // users(test cases) intentionally inject DowngradeVersionTestRequest + // into the WAL files. + default: + s.lg.Panic("not implemented apply", zap.Stringer("raft-request", r)) + return nil + } + return &apply.Result{} +} + +func noSideEffect(r *pb.InternalRaftRequest) bool { + return r.Range != nil || r.AuthUserGet != nil || r.AuthRoleGet != nil || r.AuthStatus != nil +} + +func removeNeedlessRangeReqs(txn *pb.TxnRequest) { + f := func(ops []*pb.RequestOp) []*pb.RequestOp { + j := 0 + for i := 0; i < len(ops); i++ { + if _, ok := ops[i].Request.(*pb.RequestOp_RequestRange); ok { + continue + } + ops[j] = ops[i] + j++ + } + + return ops[:j] + } + + txn.Success = f(txn.Success) + txn.Failure = f(txn.Failure) } // applyConfChange applies a ConfChange to the server. It is only // invoked with a ConfChange that has already passed through Raft func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.ConfState, shouldApplyV3 membership.ShouldApplyV3) (bool, error) { lg := s.Logger() - if err := s.cluster.ValidateConfigurationChange(cc); err != nil { + if err := s.cluster.ValidateConfigurationChange(cc, shouldApplyV3); err != nil { lg.Error("Validation on configuration change failed", zap.Bool("shouldApplyV3", bool(shouldApplyV3)), zap.Error(err)) cc.NodeID = raft.None s.r.ApplyConfChange(cc) @@ -2421,24 +2120,15 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con } else { s.cluster.AddMember(&confChangeContext.Member, shouldApplyV3) - if confChangeContext.Member.ID != s.id { + if confChangeContext.Member.ID != s.MemberID() { s.r.transport.AddPeer(confChangeContext.Member.ID, confChangeContext.PeerURLs) } } - // update the isLearner metric when this server id is equal to the id in raft member confChange - if confChangeContext.Member.ID == s.id { - if cc.Type == raftpb.ConfChangeAddLearnerNode { - isLearner.Set(1) - } else { - isLearner.Set(0) - } - } - case raftpb.ConfChangeRemoveNode: id := types.ID(cc.NodeID) s.cluster.RemoveMember(id, shouldApplyV3) - if id == s.id { + if id == s.MemberID() { return true, nil } s.r.transport.RemovePeer(id) @@ -2456,21 +2146,19 @@ func (s *EtcdServer) applyConfChange(cc raftpb.ConfChange, confState *raftpb.Con ) } s.cluster.UpdateRaftAttributes(m.ID, m.RaftAttributes, shouldApplyV3) - if m.ID != s.id { + if m.ID != s.MemberID() { s.r.transport.UpdatePeer(m.ID, m.PeerURLs) } } - s.verifyV3StoreInSyncWithV2Store(shouldApplyV3) + verify.Verify(func() { + s.verifyV3StoreInSyncWithV2Store(shouldApplyV3) + }) return false, nil } func (s *EtcdServer) verifyV3StoreInSyncWithV2Store(shouldApplyV3 membership.ShouldApplyV3) { - if !verify.VerifyEnabled() { - return - } - // If shouldApplyV3 == false, then it means v2store hasn't caught up with v3store. if !shouldApplyV3 { return @@ -2506,80 +2194,93 @@ func (s *EtcdServer) verifyV3StoreInSyncWithV2Store(shouldApplyV3 membership.Sho } // TODO: non-blocking snapshot -func (s *EtcdServer) snapshot(snapi uint64, confState raftpb.ConfState) { - clone := s.v2store.Clone() - // commit kv to write metadata (for example: consistent index) to disk. - // - // This guarantees that Backend's consistent_index is >= index of last snapshot. - // - // KV().commit() updates the consistent index in backend. - // All operations that update consistent index must be called sequentially - // from applyAll function. - // So KV().Commit() cannot run in parallel with apply. It has to be called outside - // the go routine created below. - s.KV().Commit() +func (s *EtcdServer) snapshot(ep *etcdProgress, toDisk bool) { + lg := s.Logger() + d := GetMembershipInfoInV2Format(lg, s.cluster) + if toDisk { + s.Logger().Info( + "triggering snapshot", + zap.String("local-member-id", s.MemberID().String()), + zap.Uint64("local-member-applied-index", ep.appliedi), + zap.Uint64("local-member-snapshot-index", ep.diskSnapshotIndex), + zap.Uint64("local-member-snapshot-count", s.Cfg.SnapshotCount), + zap.Bool("snapshot-forced", s.forceDiskSnapshot), + ) + s.forceDiskSnapshot = false + // commit kv to write metadata (for example: consistent index) to disk. + // + // This guarantees that Backend's consistent_index is >= index of last snapshot. + // + // KV().commit() updates the consistent index in backend. + // All operations that update consistent index must be called sequentially + // from applyAll function. + // So KV().Commit() cannot run in parallel with toApply. It has to be called outside + // the go routine created below. + s.KV().Commit() + } + + // For backward compatibility, generate v2 snapshot from v3 state. + snap, err := s.r.raftStorage.CreateSnapshot(ep.appliedi, &ep.confState, d) + if err != nil { + // the snapshot was done asynchronously with the progress of raft. + // raft might have already got a newer snapshot. + if errorspkg.Is(err, raft.ErrSnapOutOfDate) { + return + } + lg.Panic("failed to create snapshot", zap.Error(err)) + } + ep.memorySnapshotIndex = ep.appliedi - s.GoAttach(func() { - lg := s.Logger() + verifyConsistentIndexIsLatest(lg, snap, s.consistIndex.ConsistentIndex()) - d, err := clone.SaveNoCopy() - // TODO: current store will never fail to do a snapshot - // what should we do if the store might fail? - if err != nil { - lg.Panic("failed to save v2 store", zap.Error(err)) - } - snap, err := s.r.raftStorage.CreateSnapshot(snapi, &confState, d) - if err != nil { - // the snapshot was done asynchronously with the progress of raft. - // raft might have already got a newer snapshot. - if err == raft.ErrSnapOutOfDate { - return - } - lg.Panic("failed to create snapshot", zap.Error(err)) - } + if toDisk { // SaveSnap saves the snapshot to file and appends the corresponding WAL entry. if err = s.r.storage.SaveSnap(snap); err != nil { lg.Panic("failed to save snapshot", zap.Error(err)) } + ep.diskSnapshotIndex = ep.appliedi if err = s.r.storage.Release(snap); err != nil { lg.Panic("failed to release wal", zap.Error(err)) } lg.Info( - "saved snapshot", + "saved snapshot to disk", zap.Uint64("snapshot-index", snap.Metadata.Index), ) + } +} - // When sending a snapshot, etcd will pause compaction. - // After receives a snapshot, the slow follower needs to get all the entries right after - // the snapshot sent to catch up. If we do not pause compaction, the log entries right after - // the snapshot sent might already be compacted. It happens when the snapshot takes long time - // to send and save. Pausing compaction avoids triggering a snapshot sending cycle. - if atomic.LoadInt64(&s.inflightSnapshots) != 0 { - lg.Info("skip compaction since there is an inflight snapshot") - return - } +func (s *EtcdServer) compactRaftLog(snapi uint64) { + lg := s.Logger() - // keep some in memory log entries for slow followers. - compacti := uint64(1) - if snapi > s.Cfg.SnapshotCatchUpEntries { - compacti = snapi - s.Cfg.SnapshotCatchUpEntries - } + // When sending a snapshot, etcd will pause compaction. + // After receives a snapshot, the slow follower needs to get all the entries right after + // the snapshot sent to catch up. If we do not pause compaction, the log entries right after + // the snapshot sent might already be compacted. It happens when the snapshot takes long time + // to send and save. Pausing compaction avoids triggering a snapshot sending cycle. + if atomic.LoadInt64(&s.inflightSnapshots) != 0 { + lg.Info("skip compaction since there is an inflight snapshot") + return + } - err = s.r.raftStorage.Compact(compacti) - if err != nil { - // the compaction was done asynchronously with the progress of raft. - // raft log might already been compact. - if err == raft.ErrCompacted { - return - } - lg.Panic("failed to compact", zap.Error(err)) + // keep some in memory log entries for slow followers. + compacti := uint64(1) + if snapi > s.Cfg.SnapshotCatchUpEntries { + compacti = snapi - s.Cfg.SnapshotCatchUpEntries + } + err := s.r.raftStorage.Compact(compacti) + if err != nil { + // the compaction was done asynchronously with the progress of raft. + // raft log might already been compact. + if errorspkg.Is(err, raft.ErrCompacted) { + return } - lg.Info( - "compacted Raft logs", - zap.Uint64("compact-index", compacti), - ) - }) + lg.Panic("failed to compact", zap.Error(err)) + } + lg.Debug( + "compacted Raft logs", + zap.Uint64("compact-index", compacti), + ) } // CutPeer drops messages to the specified peer. @@ -2609,48 +2310,55 @@ func (s *EtcdServer) ClusterVersion() *semver.Version { return s.cluster.Version() } -// monitorVersions checks the member's version every monitorVersionInterval. -// It updates the cluster version if all members agrees on a higher one. -// It prints out log if there is a member with a higher version than the -// local version. -// TODO switch to updateClusterVersionV3 in 3.6 -func (s *EtcdServer) monitorVersions() { +func (s *EtcdServer) StorageVersion() *semver.Version { + // `applySnapshot` sets a new backend instance, so we need to acquire the bemu lock. + s.bemu.RLock() + defer s.bemu.RUnlock() + + v, err := schema.DetectSchemaVersion(s.lg, s.be.ReadTx()) + if err != nil { + s.lg.Warn("Failed to detect schema version", zap.Error(err)) + return nil + } + return &v +} + +// monitorClusterVersions every monitorVersionInterval checks if it's the leader and updates cluster version if needed. +func (s *EtcdServer) monitorClusterVersions() { + lg := s.Logger() + monitor := serverversion.NewMonitor(lg, NewServerVersionAdapter(s)) for { select { - case <-s.FirstCommitInTermNotify(): + case <-s.firstCommitInTerm.Receive(): case <-time.After(monitorVersionInterval): case <-s.stopping: + lg.Info("server has stopped; stopping cluster version's monitor") return } - if s.Leader() != s.ID() { + if s.Leader() != s.MemberID() { continue } - - v := decideClusterVersion(s.Logger(), getVersions(s.Logger(), s.cluster, s.id, s.peerRt)) - if v != nil { - // only keep major.minor version for comparison - v = &semver.Version{ - Major: v.Major, - Minor: v.Minor, - } - } - - // if the current version is nil: - // 1. use the decided version if possible - // 2. or use the min cluster version - if s.cluster.Version() == nil { - verStr := version.MinClusterVersion - if v != nil { - verStr = v.String() - } - s.GoAttach(func() { s.updateClusterVersionV2(verStr) }) - continue + err := monitor.UpdateClusterVersionIfNeeded() + if err != nil { + s.lg.Error("Failed to monitor cluster version", zap.Error(err)) } + } +} - if v != nil && membership.IsValidVersionChange(s.cluster.Version(), v) { - s.GoAttach(func() { s.updateClusterVersionV2(v.String()) }) +// monitorStorageVersion every monitorVersionInterval updates storage version if needed. +func (s *EtcdServer) monitorStorageVersion() { + lg := s.Logger() + monitor := serverversion.NewMonitor(lg, NewServerVersionAdapter(s)) + for { + select { + case <-time.After(monitorVersionInterval): + case <-s.clusterVersionChanged.Receive(): + case <-s.stopping: + lg.Info("server has stopped; stopping storage version's monitor") + return } + monitor.UpdateStorageVersionIfNeeded() } } @@ -2659,19 +2367,23 @@ func (s *EtcdServer) monitorKVHash() { if t == 0 { return } + checkTicker := time.NewTicker(t) + defer checkTicker.Stop() lg := s.Logger() lg.Info( "enabled corruption checking", - zap.String("local-member-id", s.ID().String()), + zap.String("local-member-id", s.MemberID().String()), zap.Duration("interval", t), ) for { select { case <-s.stopping: + lg.Info("server has stopped; stopping kv hash's monitor") return - case <-time.After(t): + case <-checkTicker.C: } + backend.VerifyBackendConsistency(s.be, lg, false, schema.AllBuckets...) if !s.isLeader() { continue } @@ -2682,7 +2394,7 @@ func (s *EtcdServer) monitorKVHash() { } func (s *EtcdServer) monitorCompactHash() { - if !s.Cfg.CompactHashCheckEnabled { + if !s.FeatureEnabled(features.CompactHashCheck) { return } t := s.Cfg.CompactHashCheckTime @@ -2690,6 +2402,8 @@ func (s *EtcdServer) monitorCompactHash() { select { case <-time.After(t): case <-s.stopping: + lg := s.Logger() + lg.Info("server has stopped; stopping compact hash's monitor") return } if !s.isLeader() { @@ -2699,46 +2413,6 @@ func (s *EtcdServer) monitorCompactHash() { } } -func (s *EtcdServer) updateClusterVersionV2(ver string) { - lg := s.Logger() - - if s.cluster.Version() == nil { - lg.Info( - "setting up initial cluster version using v2 API", - zap.String("cluster-version", version.Cluster(ver)), - ) - } else { - lg.Info( - "updating cluster version using v2 API", - zap.String("from", version.Cluster(s.cluster.Version().String())), - zap.String("to", version.Cluster(ver)), - ) - } - - req := pb.Request{ - Method: "PUT", - Path: membership.StoreClusterVersionKey(), - Val: ver, - } - - ctx, cancel := context.WithTimeout(s.ctx, s.Cfg.ReqTimeout()) - _, err := s.Do(ctx, req) - cancel() - - switch err { - case nil: - lg.Info("cluster version is updated", zap.String("cluster-version", version.Cluster(ver))) - return - - case ErrStopped: - lg.Warn("aborting cluster version update; server is stopped", zap.Error(err)) - return - - default: - lg.Warn("failed to update cluster version", zap.Error(err)) - } -} - func (s *EtcdServer) updateClusterVersionV3(ver string) { lg := s.Logger() @@ -2761,12 +2435,12 @@ func (s *EtcdServer) updateClusterVersionV3(ver string) { _, err := s.raftRequest(ctx, pb.InternalRaftRequest{ClusterVersionSet: &req}) cancel() - switch err { - case nil: + switch { + case errorspkg.Is(err, nil): lg.Info("cluster version is updated", zap.String("cluster-version", version.Cluster(ver))) return - case ErrStopped: + case errorspkg.Is(err, errors.ErrStopped): lg.Warn("aborting cluster version update; server is stopped", zap.Error(err)) return @@ -2775,12 +2449,13 @@ func (s *EtcdServer) updateClusterVersionV3(ver string) { } } +// monitorDowngrade every DowngradeCheckTime checks if it's the leader and cancels downgrade if needed. func (s *EtcdServer) monitorDowngrade() { + monitor := serverversion.NewMonitor(s.Logger(), NewServerVersionAdapter(s)) t := s.Cfg.DowngradeCheckTime if t == 0 { return } - lg := s.Logger() for { select { case <-time.After(t): @@ -2791,52 +2466,37 @@ func (s *EtcdServer) monitorDowngrade() { if !s.isLeader() { continue } - - d := s.cluster.DowngradeInfo() - if !d.Enabled { - continue - } - - targetVersion := d.TargetVersion - v := semver.Must(semver.NewVersion(targetVersion)) - if isMatchedVersions(s.Logger(), v, getVersions(s.Logger(), s.cluster, s.id, s.peerRt)) { - lg.Info("the cluster has been downgraded", zap.String("cluster-version", targetVersion)) - ctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout()) - if _, err := s.downgradeCancel(ctx); err != nil { - lg.Warn("failed to cancel downgrade", zap.Error(err)) - } - cancel() - } + monitor.CancelDowngradeIfNeeded() } } func (s *EtcdServer) parseProposeCtxErr(err error, start time.Time) error { - switch err { - case context.Canceled: - return ErrCanceled + switch { + case errorspkg.Is(err, context.Canceled): + return errors.ErrCanceled - case context.DeadlineExceeded: + case errorspkg.Is(err, context.DeadlineExceeded): s.leadTimeMu.RLock() curLeadElected := s.leadElectedTime s.leadTimeMu.RUnlock() prevLeadLost := curLeadElected.Add(-2 * time.Duration(s.Cfg.ElectionTicks) * time.Duration(s.Cfg.TickMs) * time.Millisecond) if start.After(prevLeadLost) && start.Before(curLeadElected) { - return ErrTimeoutDueToLeaderFail + return errors.ErrTimeoutDueToLeaderFail } lead := types.ID(s.getLead()) switch lead { case types.ID(raft.None): // TODO: return error to specify it happens because the cluster does not have leader now - case s.ID(): - if !isConnectedToQuorumSince(s.r.transport, start, s.ID(), s.cluster.Members()) { - return ErrTimeoutDueToConnectionLost + case s.MemberID(): + if !isConnectedToQuorumSince(s.r.transport, start, s.MemberID(), s.cluster.Members()) { + return errors.ErrTimeoutDueToConnectionLost } default: if !isConnectedSince(s.r.transport, start, lead) { - return ErrTimeoutDueToConnectionLost + return errors.ErrTimeoutDueToConnectionLost } } - return ErrTimeout + return errors.ErrTimeout default: return err @@ -2845,26 +2505,19 @@ func (s *EtcdServer) parseProposeCtxErr(err error, start time.Time) error { func (s *EtcdServer) KV() mvcc.WatchableKV { return s.kv } func (s *EtcdServer) Backend() backend.Backend { - s.bemu.Lock() - defer s.bemu.Unlock() + s.bemu.RLock() + defer s.bemu.RUnlock() return s.be } func (s *EtcdServer) AuthStore() auth.AuthStore { return s.authStore } func (s *EtcdServer) restoreAlarms() error { - s.applyV3 = s.newApplierV3() - as, err := v3alarm.NewAlarmStore(s.lg, s) + as, err := v3alarm.NewAlarmStore(s.lg, schema.NewAlarmBackend(s.lg, s.be)) if err != nil { return err } s.alarmStore = as - if len(as.Get(pb.AlarmType_NOSPACE)) > 0 { - s.applyV3 = newApplierV3Capped(s.applyV3) - } - if len(as.Get(pb.AlarmType_CORRUPT)) > 0 { - s.applyV3 = newApplierV3Corrupt(s.applyV3) - } return nil } @@ -2909,6 +2562,10 @@ func (s *EtcdServer) raftStatus() raft.Status { return s.r.Node.Status() } +func (s *EtcdServer) Version() *serverversion.Manager { + return serverversion.NewManager(s.Logger(), NewServerVersionAdapter(s)) +} + func (s *EtcdServer) getTxPostLockInsideApplyHook() func() { return func() { applyingIdx, applyingTerm := s.consistIndex.ConsistentApplyingIndex() @@ -2918,25 +2575,18 @@ func (s *EtcdServer) getTxPostLockInsideApplyHook() func() { } } -func maybeDefragBackend(cfg config.ServerConfig, be backend.Backend) error { - size := be.Size() - sizeInUse := be.SizeInUse() - freeableMemory := uint(size - sizeInUse) - thresholdBytes := cfg.ExperimentalBootstrapDefragThresholdMegabytes * 1024 * 1024 - if freeableMemory < thresholdBytes { - cfg.Logger.Info("Skipping defragmentation", - zap.Int64("current-db-size-bytes", size), - zap.String("current-db-size", humanize.Bytes(uint64(size))), - zap.Int64("current-db-size-in-use-bytes", sizeInUse), - zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse))), - zap.Uint("experimental-bootstrap-defrag-threshold-bytes", thresholdBytes), - zap.String("experimental-bootstrap-defrag-threshold", humanize.Bytes(uint64(thresholdBytes))), - ) - return nil - } - return be.Defrag() -} - func (s *EtcdServer) CorruptionChecker() CorruptionChecker { return s.corruptionChecker } + +func addFeatureGateMetrics(fg featuregate.FeatureGate, guageVec *prometheus.GaugeVec) { + for feature, featureSpec := range fg.(featuregate.MutableFeatureGate).GetAll() { + var metricVal float64 + if fg.Enabled(feature) { + metricVal = 1 + } else { + metricVal = 0 + } + guageVec.With(prometheus.Labels{"name": string(feature), "stage": string(featureSpec.PreRelease)}).Set(metricVal) + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/snapshot_merge.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/snapshot_merge.go index 72d10c1796..cc3c545bee 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/snapshot_merge.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/snapshot_merge.go @@ -17,12 +17,12 @@ package etcdserver import ( "io" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/etcdserver/api/snap" - "go.etcd.io/etcd/server/v3/mvcc/backend" - humanize "github.com/dustin/go-humanize" "go.uber.org/zap" + + "go.etcd.io/etcd/server/v3/etcdserver/api/snap" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/raft/v3/raftpb" ) // createMergedSnapshotMessage creates a snapshot message that contains: raft status (term, conf), @@ -31,11 +31,7 @@ import ( func (s *EtcdServer) createMergedSnapshotMessage(m raftpb.Message, snapt, snapi uint64, confState raftpb.ConfState) snap.Message { lg := s.Logger() // get a snapshot of v2 store as []byte - clone := s.v2store.Clone() - d, err := clone.SaveNoCopy() - if err != nil { - lg.Panic("failed to save v2 store data", zap.Error(err)) - } + d := GetMembershipInfoInV2Format(lg, s.cluster) // commit kv to write metadata(for example: consistent index). s.KV().Commit() @@ -53,7 +49,9 @@ func (s *EtcdServer) createMergedSnapshotMessage(m raftpb.Message, snapt, snapi }, Data: d, } - m.Snapshot = snapshot + m.Snapshot = &snapshot + + verifySnapshotIndex(snapshot, s.consistIndex.ConsistentIndex()) return *snap.NewMessage(m, rc, dbsnap.Size()) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/metrics.go new file mode 100644 index 0000000000..93f2e0753d --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/metrics.go @@ -0,0 +1,71 @@ +// Copyright 2015 The etcd 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 txn + +import ( + "strconv" + "time" + + "github.com/prometheus/client_golang/prometheus" +) + +var ( + slowApplies = prometheus.NewCounter(prometheus.CounterOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "slow_apply_total", + Help: "The total number of slow apply requests (likely overloaded from slow disk).", + }) + applySec = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "apply_duration_seconds", + Help: "The latency distributions of v2 apply called by backend.", + + // lowest bucket start of upper bound 0.0001 sec (0.1 ms) with factor 2 + // highest bucket start of 0.0001 sec * 2^19 == 52.4288 sec + Buckets: prometheus.ExponentialBuckets(0.0001, 2, 20), + }, + []string{"version", "op", "success"}, + ) + rangeSec = prometheus.NewHistogramVec( + prometheus.HistogramOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "range_duration_seconds", + Help: "The latency distributions of txn.Range", + + // lowest bucket start of upper bound 0.0001 sec (0.1 ms) with factor 2 + // highest bucket start of 0.0001 sec * 2^19 == 52.4288 sec + Buckets: prometheus.ExponentialBuckets(0.0001, 2, 20), + }, + []string{"success"}, + ) +) + +func ApplySecObserve(version, op string, success bool, latency time.Duration) { + applySec.WithLabelValues(version, op, strconv.FormatBool(success)).Observe(float64(latency.Microseconds()) / 1000000.0) +} + +func RangeSecObserve(success bool, latency time.Duration) { + rangeSec.WithLabelValues(strconv.FormatBool(success)).Observe(float64(latency.Microseconds()) / 1000000.0) +} + +func init() { + prometheus.MustRegister(applySec) + prometheus.MustRegister(rangeSec) + prometheus.MustRegister(slowApplies) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/txn.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/txn.go new file mode 100644 index 0000000000..51f70a06a4 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/txn.go @@ -0,0 +1,723 @@ +// Copyright 2022 The etcd 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 txn + +import ( + "bytes" + "context" + "fmt" + "sort" + "time" + + "go.uber.org/zap" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/mvccpb" + "go.etcd.io/etcd/pkg/v3/traceutil" + "go.etcd.io/etcd/server/v3/auth" + "go.etcd.io/etcd/server/v3/etcdserver/errors" + "go.etcd.io/etcd/server/v3/lease" + "go.etcd.io/etcd/server/v3/storage/mvcc" +) + +func Put(ctx context.Context, lg *zap.Logger, lessor lease.Lessor, kv mvcc.KV, p *pb.PutRequest) (resp *pb.PutResponse, trace *traceutil.Trace, err error) { + trace = traceutil.Get(ctx) + // create put tracing if the trace in context is empty + if trace.IsEmpty() { + trace = traceutil.New("put", + lg, + traceutil.Field{Key: "key", Value: string(p.Key)}, + traceutil.Field{Key: "req_size", Value: p.Size()}, + ) + ctx = context.WithValue(ctx, traceutil.TraceKey{}, trace) + } + leaseID := lease.LeaseID(p.Lease) + if leaseID != lease.NoLease { + if l := lessor.Lookup(leaseID); l == nil { + return nil, nil, lease.ErrLeaseNotFound + } + } + txnWrite := kv.Write(trace) + defer txnWrite.End() + resp, err = put(ctx, txnWrite, p) + return resp, trace, err +} + +func put(ctx context.Context, txnWrite mvcc.TxnWrite, p *pb.PutRequest) (resp *pb.PutResponse, err error) { + trace := traceutil.Get(ctx) + resp = &pb.PutResponse{} + resp.Header = &pb.ResponseHeader{} + val, leaseID := p.Value, lease.LeaseID(p.Lease) + + var rr *mvcc.RangeResult + if p.IgnoreValue || p.IgnoreLease || p.PrevKv { + trace.StepWithFunction(func() { + rr, err = txnWrite.Range(context.TODO(), p.Key, nil, mvcc.RangeOptions{}) + }, "get previous kv pair") + + if err != nil { + return nil, err + } + } + if p.IgnoreValue || p.IgnoreLease { + if rr == nil || len(rr.KVs) == 0 { + // ignore_{lease,value} flag expects previous key-value pair + return nil, errors.ErrKeyNotFound + } + } + if p.IgnoreValue { + val = rr.KVs[0].Value + } + if p.IgnoreLease { + leaseID = lease.LeaseID(rr.KVs[0].Lease) + } + if p.PrevKv { + if rr != nil && len(rr.KVs) != 0 { + resp.PrevKv = &rr.KVs[0] + } + } + + resp.Header.Revision = txnWrite.Put(p.Key, val, leaseID) + trace.AddField(traceutil.Field{Key: "response_revision", Value: resp.Header.Revision}) + return resp, nil +} + +func DeleteRange(ctx context.Context, lg *zap.Logger, kv mvcc.KV, dr *pb.DeleteRangeRequest) (resp *pb.DeleteRangeResponse, trace *traceutil.Trace, err error) { + trace = traceutil.Get(ctx) + // create delete tracing if the trace in context is empty + if trace.IsEmpty() { + trace = traceutil.New("delete_range", + lg, + traceutil.Field{Key: "key", Value: string(dr.Key)}, + traceutil.Field{Key: "range_end", Value: string(dr.RangeEnd)}, + ) + ctx = context.WithValue(ctx, traceutil.TraceKey{}, trace) + } + txnWrite := kv.Write(trace) + defer txnWrite.End() + resp, err = deleteRange(ctx, txnWrite, dr) + return resp, trace, err +} + +func deleteRange(ctx context.Context, txnWrite mvcc.TxnWrite, dr *pb.DeleteRangeRequest) (*pb.DeleteRangeResponse, error) { + resp := &pb.DeleteRangeResponse{} + resp.Header = &pb.ResponseHeader{} + end := mkGteRange(dr.RangeEnd) + + if dr.PrevKv { + rr, err := txnWrite.Range(ctx, dr.Key, end, mvcc.RangeOptions{}) + if err != nil { + return nil, err + } + if rr != nil { + resp.PrevKvs = make([]*mvccpb.KeyValue, len(rr.KVs)) + for i := range rr.KVs { + resp.PrevKvs[i] = &rr.KVs[i] + } + } + } + + resp.Deleted, resp.Header.Revision = txnWrite.DeleteRange(dr.Key, end) + return resp, nil +} + +func Range(ctx context.Context, lg *zap.Logger, kv mvcc.KV, r *pb.RangeRequest) (resp *pb.RangeResponse, trace *traceutil.Trace, err error) { + trace = traceutil.Get(ctx) + if trace.IsEmpty() { + trace = traceutil.New("range", lg) + ctx = context.WithValue(ctx, traceutil.TraceKey{}, trace) + } + defer func(start time.Time) { + success := err == nil + RangeSecObserve(success, time.Since(start)) + }(time.Now()) + txnRead := kv.Read(mvcc.ConcurrentReadTxMode, trace) + defer txnRead.End() + resp, err = executeRange(ctx, lg, txnRead, r) + return resp, trace, err +} + +func executeRange(ctx context.Context, lg *zap.Logger, txnRead mvcc.TxnRead, r *pb.RangeRequest) (*pb.RangeResponse, error) { + trace := traceutil.Get(ctx) + + resp := &pb.RangeResponse{} + resp.Header = &pb.ResponseHeader{} + + limit := r.Limit + if r.SortOrder != pb.RangeRequest_NONE || + r.MinModRevision != 0 || r.MaxModRevision != 0 || + r.MinCreateRevision != 0 || r.MaxCreateRevision != 0 { + // fetch everything; sort and truncate afterwards + limit = 0 + } + if limit > 0 { + // fetch one extra for 'more' flag + limit = limit + 1 + } + + ro := mvcc.RangeOptions{ + Limit: limit, + Rev: r.Revision, + Count: r.CountOnly, + } + + rr, err := txnRead.Range(ctx, r.Key, mkGteRange(r.RangeEnd), ro) + if err != nil { + return nil, err + } + + if r.MaxModRevision != 0 { + f := func(kv *mvccpb.KeyValue) bool { return kv.ModRevision > r.MaxModRevision } + pruneKVs(rr, f) + } + if r.MinModRevision != 0 { + f := func(kv *mvccpb.KeyValue) bool { return kv.ModRevision < r.MinModRevision } + pruneKVs(rr, f) + } + if r.MaxCreateRevision != 0 { + f := func(kv *mvccpb.KeyValue) bool { return kv.CreateRevision > r.MaxCreateRevision } + pruneKVs(rr, f) + } + if r.MinCreateRevision != 0 { + f := func(kv *mvccpb.KeyValue) bool { return kv.CreateRevision < r.MinCreateRevision } + pruneKVs(rr, f) + } + + sortOrder := r.SortOrder + if r.SortTarget != pb.RangeRequest_KEY && sortOrder == pb.RangeRequest_NONE { + // Since current mvcc.Range implementation returns results + // sorted by keys in lexiographically ascending order, + // sort ASCEND by default only when target is not 'KEY' + sortOrder = pb.RangeRequest_ASCEND + } else if r.SortTarget == pb.RangeRequest_KEY && sortOrder == pb.RangeRequest_ASCEND { + // Since current mvcc.Range implementation returns results + // sorted by keys in lexiographically ascending order, + // don't re-sort when target is 'KEY' and order is ASCEND + sortOrder = pb.RangeRequest_NONE + } + if sortOrder != pb.RangeRequest_NONE { + var sorter sort.Interface + switch { + case r.SortTarget == pb.RangeRequest_KEY: + sorter = &kvSortByKey{&kvSort{rr.KVs}} + case r.SortTarget == pb.RangeRequest_VERSION: + sorter = &kvSortByVersion{&kvSort{rr.KVs}} + case r.SortTarget == pb.RangeRequest_CREATE: + sorter = &kvSortByCreate{&kvSort{rr.KVs}} + case r.SortTarget == pb.RangeRequest_MOD: + sorter = &kvSortByMod{&kvSort{rr.KVs}} + case r.SortTarget == pb.RangeRequest_VALUE: + sorter = &kvSortByValue{&kvSort{rr.KVs}} + default: + lg.Panic("unexpected sort target", zap.Int32("sort-target", int32(r.SortTarget))) + } + switch { + case sortOrder == pb.RangeRequest_ASCEND: + sort.Sort(sorter) + case sortOrder == pb.RangeRequest_DESCEND: + sort.Sort(sort.Reverse(sorter)) + } + } + + if r.Limit > 0 && len(rr.KVs) > int(r.Limit) { + rr.KVs = rr.KVs[:r.Limit] + resp.More = true + } + trace.Step("filter and sort the key-value pairs") + resp.Header.Revision = rr.Rev + resp.Count = int64(rr.Count) + resp.Kvs = make([]*mvccpb.KeyValue, len(rr.KVs)) + for i := range rr.KVs { + if r.KeysOnly { + rr.KVs[i].Value = nil + } + resp.Kvs[i] = &rr.KVs[i] + } + trace.Step("assemble the response") + return resp, nil +} + +func Txn(ctx context.Context, lg *zap.Logger, rt *pb.TxnRequest, txnModeWriteWithSharedBuffer bool, kv mvcc.KV, lessor lease.Lessor) (*pb.TxnResponse, *traceutil.Trace, error) { + trace := traceutil.Get(ctx) + if trace.IsEmpty() { + trace = traceutil.New("transaction", lg) + ctx = context.WithValue(ctx, traceutil.TraceKey{}, trace) + } + isWrite := !IsTxnReadonly(rt) + // When the transaction contains write operations, we use ReadTx instead of + // ConcurrentReadTx to avoid extra overhead of copying buffer. + var mode mvcc.ReadTxMode + if isWrite && txnModeWriteWithSharedBuffer /*a.s.Cfg.ServerFeatureGate.Enabled(features.TxnModeWriteWithSharedBuffer)*/ { + mode = mvcc.SharedBufReadTxMode + } else { + mode = mvcc.ConcurrentReadTxMode + } + txnRead := kv.Read(mode, trace) + var txnPath []bool + trace.StepWithFunction( + func() { + txnPath = compareToPath(txnRead, rt) + }, + "compare", + ) + if isWrite { + trace.AddField(traceutil.Field{Key: "read_only", Value: false}) + } + _, err := checkTxn(txnRead, rt, lessor, txnPath) + if err != nil { + txnRead.End() + return nil, nil, err + } + trace.Step("check requests") + // When executing mutable txnWrite ops, etcd must hold the txnWrite lock so + // readers do not see any intermediate results. Since writes are + // serialized on the raft loop, the revision in the read view will + // be the revision of the write txnWrite. + var txnWrite mvcc.TxnWrite + if isWrite { + txnRead.End() + txnWrite = kv.Write(trace) + } else { + txnWrite = mvcc.NewReadOnlyTxnWrite(txnRead) + } + txnResp, err := txn(ctx, lg, txnWrite, rt, isWrite, txnPath) + txnWrite.End() + + trace.AddField( + traceutil.Field{Key: "number_of_response", Value: len(txnResp.Responses)}, + traceutil.Field{Key: "response_revision", Value: txnResp.Header.Revision}, + ) + return txnResp, trace, err +} + +func txn(ctx context.Context, lg *zap.Logger, txnWrite mvcc.TxnWrite, rt *pb.TxnRequest, isWrite bool, txnPath []bool) (*pb.TxnResponse, error) { + txnResp, _ := newTxnResp(rt, txnPath) + _, err := executeTxn(ctx, lg, txnWrite, rt, txnPath, txnResp) + if err != nil { + if isWrite { + // CAUTION: When a txn performing write operations starts, we always expect it to be successful. + // If a write failure is seen we SHOULD NOT try to recover the server, but crash with a panic to make the failure explicit. + // Trying to silently recover (e.g by ignoring the failed txn or calling txn.End() early) poses serious risks: + // - violation of transaction atomicity if some write operations have been partially executed + // - data inconsistency across different etcd members if they applied the txn asymmetrically + lg.Panic("unexpected error during txn with writes", zap.Error(err)) + } else { + lg.Error("unexpected error during readonly txn", zap.Error(err)) + } + } + rev := txnWrite.Rev() + if len(txnWrite.Changes()) != 0 { + rev++ + } + txnResp.Header.Revision = rev + return txnResp, err +} + +// newTxnResp allocates a txn response for a txn request given a path. +func newTxnResp(rt *pb.TxnRequest, txnPath []bool) (txnResp *pb.TxnResponse, txnCount int) { + reqs := rt.Success + if !txnPath[0] { + reqs = rt.Failure + } + resps := make([]*pb.ResponseOp, len(reqs)) + txnResp = &pb.TxnResponse{ + Responses: resps, + Succeeded: txnPath[0], + Header: &pb.ResponseHeader{}, + } + for i, req := range reqs { + switch tv := req.Request.(type) { + case *pb.RequestOp_RequestRange: + resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseRange{}} + case *pb.RequestOp_RequestPut: + resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponsePut{}} + case *pb.RequestOp_RequestDeleteRange: + resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseDeleteRange{}} + case *pb.RequestOp_RequestTxn: + resp, txns := newTxnResp(tv.RequestTxn, txnPath[1:]) + resps[i] = &pb.ResponseOp{Response: &pb.ResponseOp_ResponseTxn{ResponseTxn: resp}} + txnPath = txnPath[1+txns:] + txnCount += txns + 1 + default: + } + } + return txnResp, txnCount +} + +func executeTxn(ctx context.Context, lg *zap.Logger, txnWrite mvcc.TxnWrite, rt *pb.TxnRequest, txnPath []bool, tresp *pb.TxnResponse) (txns int, err error) { + trace := traceutil.Get(ctx) + reqs := rt.Success + if !txnPath[0] { + reqs = rt.Failure + } + + for i, req := range reqs { + respi := tresp.Responses[i].Response + switch tv := req.Request.(type) { + case *pb.RequestOp_RequestRange: + trace.StartSubTrace( + traceutil.Field{Key: "req_type", Value: "range"}, + traceutil.Field{Key: "range_begin", Value: string(tv.RequestRange.Key)}, + traceutil.Field{Key: "range_end", Value: string(tv.RequestRange.RangeEnd)}) + resp, err := executeRange(ctx, lg, txnWrite, tv.RequestRange) + if err != nil { + return 0, fmt.Errorf("applyTxn: failed Range: %w", err) + } + respi.(*pb.ResponseOp_ResponseRange).ResponseRange = resp + trace.StopSubTrace() + case *pb.RequestOp_RequestPut: + trace.StartSubTrace( + traceutil.Field{Key: "req_type", Value: "put"}, + traceutil.Field{Key: "key", Value: string(tv.RequestPut.Key)}, + traceutil.Field{Key: "req_size", Value: tv.RequestPut.Size()}) + resp, err := put(ctx, txnWrite, tv.RequestPut) + if err != nil { + return 0, fmt.Errorf("applyTxn: failed Put: %w", err) + } + respi.(*pb.ResponseOp_ResponsePut).ResponsePut = resp + trace.StopSubTrace() + case *pb.RequestOp_RequestDeleteRange: + resp, err := deleteRange(ctx, txnWrite, tv.RequestDeleteRange) + if err != nil { + return 0, fmt.Errorf("applyTxn: failed DeleteRange: %w", err) + } + respi.(*pb.ResponseOp_ResponseDeleteRange).ResponseDeleteRange = resp + case *pb.RequestOp_RequestTxn: + resp := respi.(*pb.ResponseOp_ResponseTxn).ResponseTxn + applyTxns, err := executeTxn(ctx, lg, txnWrite, tv.RequestTxn, txnPath[1:], resp) + if err != nil { + // don't wrap the error. It's a recursive call and err should be already wrapped + return 0, err + } + txns += applyTxns + 1 + txnPath = txnPath[applyTxns+1:] + default: + // empty union + } + } + return txns, nil +} + +func checkPut(rv mvcc.ReadView, lessor lease.Lessor, req *pb.PutRequest) error { + if req.IgnoreValue || req.IgnoreLease { + // expects previous key-value, error if not exist + rr, err := rv.Range(context.TODO(), req.Key, nil, mvcc.RangeOptions{}) + if err != nil { + return err + } + if rr == nil || len(rr.KVs) == 0 { + return errors.ErrKeyNotFound + } + } + if lease.LeaseID(req.Lease) != lease.NoLease { + if l := lessor.Lookup(lease.LeaseID(req.Lease)); l == nil { + return lease.ErrLeaseNotFound + } + } + return nil +} + +func checkRange(rv mvcc.ReadView, req *pb.RangeRequest) error { + switch { + case req.Revision == 0: + return nil + case req.Revision > rv.Rev(): + return mvcc.ErrFutureRev + case req.Revision < rv.FirstRev(): + return mvcc.ErrCompacted + } + return nil +} + +func checkTxn(rv mvcc.ReadView, rt *pb.TxnRequest, lessor lease.Lessor, txnPath []bool) (int, error) { + txnCount := 0 + reqs := rt.Success + if !txnPath[0] { + reqs = rt.Failure + } + for _, req := range reqs { + var err error + var txns int + switch tv := req.Request.(type) { + case *pb.RequestOp_RequestRange: + err = checkRange(rv, tv.RequestRange) + case *pb.RequestOp_RequestPut: + err = checkPut(rv, lessor, tv.RequestPut) + case *pb.RequestOp_RequestDeleteRange: + case *pb.RequestOp_RequestTxn: + txns, err = checkTxn(rv, tv.RequestTxn, lessor, txnPath[1:]) + txnCount += txns + 1 + txnPath = txnPath[txns+1:] + default: + // empty union + } + if err != nil { + return 0, err + } + } + return txnCount, nil +} + +// mkGteRange determines if the range end is a >= range. This works around grpc +// sending empty byte strings as nil; >= is encoded in the range end as '\0'. +// If it is a GTE range, then []byte{} is returned to indicate the empty byte +// string (vs nil being no byte string). +func mkGteRange(rangeEnd []byte) []byte { + if len(rangeEnd) == 1 && rangeEnd[0] == 0 { + return []byte{} + } + return rangeEnd +} + +func pruneKVs(rr *mvcc.RangeResult, isPrunable func(*mvccpb.KeyValue) bool) { + j := 0 + for i := range rr.KVs { + rr.KVs[j] = rr.KVs[i] + if !isPrunable(&rr.KVs[i]) { + j++ + } + } + rr.KVs = rr.KVs[:j] +} + +type kvSort struct{ kvs []mvccpb.KeyValue } + +func (s *kvSort) Swap(i, j int) { + t := s.kvs[i] + s.kvs[i] = s.kvs[j] + s.kvs[j] = t +} +func (s *kvSort) Len() int { return len(s.kvs) } + +type kvSortByKey struct{ *kvSort } + +func (s *kvSortByKey) Less(i, j int) bool { + return bytes.Compare(s.kvs[i].Key, s.kvs[j].Key) < 0 +} + +type kvSortByVersion struct{ *kvSort } + +func (s *kvSortByVersion) Less(i, j int) bool { + return (s.kvs[i].Version - s.kvs[j].Version) < 0 +} + +type kvSortByCreate struct{ *kvSort } + +func (s *kvSortByCreate) Less(i, j int) bool { + return (s.kvs[i].CreateRevision - s.kvs[j].CreateRevision) < 0 +} + +type kvSortByMod struct{ *kvSort } + +func (s *kvSortByMod) Less(i, j int) bool { + return (s.kvs[i].ModRevision - s.kvs[j].ModRevision) < 0 +} + +type kvSortByValue struct{ *kvSort } + +func (s *kvSortByValue) Less(i, j int) bool { + return bytes.Compare(s.kvs[i].Value, s.kvs[j].Value) < 0 +} + +func compareInt64(a, b int64) int { + switch { + case a < b: + return -1 + case a > b: + return 1 + default: + return 0 + } +} + +func compareToPath(rv mvcc.ReadView, rt *pb.TxnRequest) []bool { + txnPath := make([]bool, 1) + ops := rt.Success + if txnPath[0] = applyCompares(rv, rt.Compare); !txnPath[0] { + ops = rt.Failure + } + for _, op := range ops { + tv, ok := op.Request.(*pb.RequestOp_RequestTxn) + if !ok || tv.RequestTxn == nil { + continue + } + txnPath = append(txnPath, compareToPath(rv, tv.RequestTxn)...) + } + return txnPath +} + +func applyCompares(rv mvcc.ReadView, cmps []*pb.Compare) bool { + for _, c := range cmps { + if !applyCompare(rv, c) { + return false + } + } + return true +} + +// applyCompare applies the compare request. +// If the comparison succeeds, it returns true. Otherwise, returns false. +func applyCompare(rv mvcc.ReadView, c *pb.Compare) bool { + // TODO: possible optimizations + // * chunk reads for large ranges to conserve memory + // * rewrite rules for common patterns: + // ex. "[a, b) createrev > 0" => "limit 1 /\ kvs > 0" + // * caching + rr, err := rv.Range(context.TODO(), c.Key, mkGteRange(c.RangeEnd), mvcc.RangeOptions{}) + if err != nil { + return false + } + if len(rr.KVs) == 0 { + if c.Target == pb.Compare_VALUE { + // Always fail if comparing a value on a key/keys that doesn't exist; + // nil == empty string in grpc; no way to represent missing value + return false + } + return compareKV(c, mvccpb.KeyValue{}) + } + for _, kv := range rr.KVs { + if !compareKV(c, kv) { + return false + } + } + return true +} + +func compareKV(c *pb.Compare, ckv mvccpb.KeyValue) bool { + var result int + rev := int64(0) + switch c.Target { + case pb.Compare_VALUE: + var v []byte + if tv, _ := c.TargetUnion.(*pb.Compare_Value); tv != nil { + v = tv.Value + } + result = bytes.Compare(ckv.Value, v) + case pb.Compare_CREATE: + if tv, _ := c.TargetUnion.(*pb.Compare_CreateRevision); tv != nil { + rev = tv.CreateRevision + } + result = compareInt64(ckv.CreateRevision, rev) + case pb.Compare_MOD: + if tv, _ := c.TargetUnion.(*pb.Compare_ModRevision); tv != nil { + rev = tv.ModRevision + } + result = compareInt64(ckv.ModRevision, rev) + case pb.Compare_VERSION: + if tv, _ := c.TargetUnion.(*pb.Compare_Version); tv != nil { + rev = tv.Version + } + result = compareInt64(ckv.Version, rev) + case pb.Compare_LEASE: + if tv, _ := c.TargetUnion.(*pb.Compare_Lease); tv != nil { + rev = tv.Lease + } + result = compareInt64(ckv.Lease, rev) + } + switch c.Result { + case pb.Compare_EQUAL: + return result == 0 + case pb.Compare_NOT_EQUAL: + return result != 0 + case pb.Compare_GREATER: + return result > 0 + case pb.Compare_LESS: + return result < 0 + } + return true +} + +func IsTxnSerializable(r *pb.TxnRequest) bool { + for _, u := range r.Success { + if r := u.GetRequestRange(); r == nil || !r.Serializable { + return false + } + } + for _, u := range r.Failure { + if r := u.GetRequestRange(); r == nil || !r.Serializable { + return false + } + } + return true +} + +func IsTxnReadonly(r *pb.TxnRequest) bool { + for _, u := range r.Success { + if r := u.GetRequestRange(); r == nil { + return false + } + } + for _, u := range r.Failure { + if r := u.GetRequestRange(); r == nil { + return false + } + } + return true +} + +func CheckTxnAuth(as auth.AuthStore, ai *auth.AuthInfo, rt *pb.TxnRequest) error { + for _, c := range rt.Compare { + if err := as.IsRangePermitted(ai, c.Key, c.RangeEnd); err != nil { + return err + } + } + if err := checkTxnReqsPermission(as, ai, rt.Success); err != nil { + return err + } + return checkTxnReqsPermission(as, ai, rt.Failure) +} + +func checkTxnReqsPermission(as auth.AuthStore, ai *auth.AuthInfo, reqs []*pb.RequestOp) error { + for _, requ := range reqs { + switch tv := requ.Request.(type) { + case *pb.RequestOp_RequestRange: + if tv.RequestRange == nil { + continue + } + + if err := as.IsRangePermitted(ai, tv.RequestRange.Key, tv.RequestRange.RangeEnd); err != nil { + return err + } + + case *pb.RequestOp_RequestPut: + if tv.RequestPut == nil { + continue + } + + if err := as.IsPutPermitted(ai, tv.RequestPut.Key); err != nil { + return err + } + + case *pb.RequestOp_RequestDeleteRange: + if tv.RequestDeleteRange == nil { + continue + } + + if tv.RequestDeleteRange.PrevKv { + err := as.IsRangePermitted(ai, tv.RequestDeleteRange.Key, tv.RequestDeleteRange.RangeEnd) + if err != nil { + return err + } + } + + err := as.IsDeleteRangePermitted(ai, tv.RequestDeleteRange.Key, tv.RequestDeleteRange.RangeEnd) + if err != nil { + return err + } + } + } + + return nil +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/util.go new file mode 100644 index 0000000000..f9987c6d5d --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/txn/util.go @@ -0,0 +1,107 @@ +// Copyright 2015 The etcd 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 txn + +import ( + "fmt" + "reflect" + "strings" + "time" + + "github.com/golang/protobuf/proto" + "go.uber.org/zap" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" +) + +func WarnOfExpensiveRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, reqStringer fmt.Stringer, respMsg proto.Message, err error) { + if time.Since(now) <= warningApplyDuration { + return + } + var resp string + if !isNil(respMsg) { + resp = fmt.Sprintf("size:%d", proto.Size(respMsg)) + } + warnOfExpensiveGenericRequest(lg, warningApplyDuration, now, reqStringer, "", resp, err) +} + +func WarnOfFailedRequest(lg *zap.Logger, now time.Time, reqStringer fmt.Stringer, respMsg proto.Message, err error) { + var resp string + if !isNil(respMsg) { + resp = fmt.Sprintf("size:%d", proto.Size(respMsg)) + } + d := time.Since(now) + lg.Warn( + "failed to apply request", + zap.Duration("took", d), + zap.String("request", reqStringer.String()), + zap.String("response", resp), + zap.Error(err), + ) +} + +func WarnOfExpensiveReadOnlyTxnRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, r *pb.TxnRequest, txnResponse *pb.TxnResponse, err error) { + if time.Since(now) <= warningApplyDuration { + return + } + reqStringer := pb.NewLoggableTxnRequest(r) + var resp string + if !isNil(txnResponse) { + var resps []string + for _, r := range txnResponse.Responses { + switch r.Response.(type) { + case *pb.ResponseOp_ResponseRange: + if op := r.GetResponseRange(); op != nil { + resps = append(resps, fmt.Sprintf("range_response_count:%d", len(op.GetKvs()))) + } else { + resps = append(resps, "range_response:nil") + } + default: + // only range responses should be in a read only txn request + } + } + resp = fmt.Sprintf("responses:<%s> size:%d", strings.Join(resps, " "), txnResponse.Size()) + } + warnOfExpensiveGenericRequest(lg, warningApplyDuration, now, reqStringer, "read-only txn ", resp, err) +} + +func WarnOfExpensiveReadOnlyRangeRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, reqStringer fmt.Stringer, rangeResponse *pb.RangeResponse, err error) { + if time.Since(now) <= warningApplyDuration { + return + } + var resp string + if !isNil(rangeResponse) { + resp = fmt.Sprintf("range_response_count:%d size:%d", len(rangeResponse.Kvs), rangeResponse.Size()) + } + warnOfExpensiveGenericRequest(lg, warningApplyDuration, now, reqStringer, "read-only range ", resp, err) +} + +// callers need make sure time has passed warningApplyDuration +func warnOfExpensiveGenericRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, reqStringer fmt.Stringer, prefix string, resp string, err error) { + lg.Warn( + "apply request took too long", + zap.Duration("took", time.Since(now)), + zap.Duration("expected-duration", warningApplyDuration), + zap.String("prefix", prefix), + zap.String("request", reqStringer.String()), + zap.String("response", resp), + zap.Error(err), + ) + slowApplies.Inc() +} + +func isNil(msg proto.Message) bool { + return msg == nil || reflect.ValueOf(msg).IsNil() +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/util.go index b048b86416..fbba5491b0 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/util.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/util.go @@ -16,17 +16,11 @@ package etcdserver import ( "fmt" - "reflect" - "strings" "time" - "github.com/golang/protobuf/proto" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" "go.etcd.io/etcd/client/pkg/v3/types" "go.etcd.io/etcd/server/v3/etcdserver/api/membership" "go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp" - - "go.uber.org/zap" ) // isConnectedToQuorumSince checks whether the local member is connected to the @@ -103,86 +97,6 @@ func (nc *notifier) notify(err error) { close(nc.c) } -func warnOfExpensiveRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, reqStringer fmt.Stringer, respMsg proto.Message, err error) { - if time.Since(now) <= warningApplyDuration { - return - } - var resp string - if !isNil(respMsg) { - resp = fmt.Sprintf("size:%d", proto.Size(respMsg)) - } - warnOfExpensiveGenericRequest(lg, warningApplyDuration, now, reqStringer, "", resp, err) -} - -func warnOfFailedRequest(lg *zap.Logger, now time.Time, reqStringer fmt.Stringer, respMsg proto.Message, err error) { - var resp string - if !isNil(respMsg) { - resp = fmt.Sprintf("size:%d", proto.Size(respMsg)) - } - d := time.Since(now) - lg.Warn( - "failed to apply request", - zap.Duration("took", d), - zap.String("request", reqStringer.String()), - zap.String("response", resp), - zap.Error(err), - ) -} - -func warnOfExpensiveReadOnlyTxnRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, r *pb.TxnRequest, txnResponse *pb.TxnResponse, err error) { - if time.Since(now) <= warningApplyDuration { - return - } - reqStringer := pb.NewLoggableTxnRequest(r) - var resp string - if !isNil(txnResponse) { - var resps []string - for _, r := range txnResponse.Responses { - switch op := r.Response.(type) { - case *pb.ResponseOp_ResponseRange: - if op.ResponseRange != nil { - resps = append(resps, fmt.Sprintf("range_response_count:%d", len(op.ResponseRange.Kvs))) - } else { - resps = append(resps, "range_response:nil") - } - default: - // only range responses should be in a read only txn request - } - } - resp = fmt.Sprintf("responses:<%s> size:%d", strings.Join(resps, " "), txnResponse.Size()) - } - warnOfExpensiveGenericRequest(lg, warningApplyDuration, now, reqStringer, "read-only txn ", resp, err) -} - -func warnOfExpensiveReadOnlyRangeRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, reqStringer fmt.Stringer, rangeResponse *pb.RangeResponse, err error) { - if time.Since(now) <= warningApplyDuration { - return - } - var resp string - if !isNil(rangeResponse) { - resp = fmt.Sprintf("range_response_count:%d size:%d", len(rangeResponse.Kvs), rangeResponse.Size()) - } - warnOfExpensiveGenericRequest(lg, warningApplyDuration, now, reqStringer, "read-only range ", resp, err) -} - -// callers need make sure time has passed warningApplyDuration -func warnOfExpensiveGenericRequest(lg *zap.Logger, warningApplyDuration time.Duration, now time.Time, reqStringer fmt.Stringer, prefix string, resp string, err error) { - lg.Warn( - "apply request took too long", - zap.Duration("took", time.Since(now)), - zap.Duration("expected-duration", warningApplyDuration), - zap.String("prefix", prefix), - zap.String("request", reqStringer.String()), - zap.String("response", resp), - zap.Error(err), - ) - slowApplies.Inc() -} - -func isNil(msg proto.Message) bool { - return msg == nil || reflect.ValueOf(msg).IsNil() -} - // panicAlternativeStringer wraps a fmt.Stringer, and if calling String() panics, calls the alternative instead. // This is needed to ensure logging slow v2 requests does not panic, which occurs when running integration tests // with the embedded server with github.com/golang/protobuf v1.4.0+. See https://github.com/etcd-io/etcd/issues/12197. diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/v2_server.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/v2_server.go index 24c97c924a..8636204b54 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/v2_server.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/v2_server.go @@ -15,151 +15,11 @@ package etcdserver import ( - "context" - "time" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/server/v3/etcdserver/api/membership" - "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" ) type RequestV2 pb.Request -type RequestV2Handler interface { - Post(ctx context.Context, r *RequestV2) (Response, error) - Put(ctx context.Context, r *RequestV2) (Response, error) - Delete(ctx context.Context, r *RequestV2) (Response, error) - QGet(ctx context.Context, r *RequestV2) (Response, error) - Get(ctx context.Context, r *RequestV2) (Response, error) - Head(ctx context.Context, r *RequestV2) (Response, error) -} - -type reqV2HandlerEtcdServer struct { - reqV2HandlerStore - s *EtcdServer -} - -type reqV2HandlerStore struct { - store v2store.Store - applier ApplierV2 -} - -func NewStoreRequestV2Handler(s v2store.Store, applier ApplierV2) RequestV2Handler { - return &reqV2HandlerStore{s, applier} -} - -func (a *reqV2HandlerStore) Post(ctx context.Context, r *RequestV2) (Response, error) { - return a.applier.Post(r), nil -} - -func (a *reqV2HandlerStore) Put(ctx context.Context, r *RequestV2) (Response, error) { - return a.applier.Put(r, membership.ApplyBoth), nil -} - -func (a *reqV2HandlerStore) Delete(ctx context.Context, r *RequestV2) (Response, error) { - return a.applier.Delete(r), nil -} - -func (a *reqV2HandlerStore) QGet(ctx context.Context, r *RequestV2) (Response, error) { - return a.applier.QGet(r), nil -} - -func (a *reqV2HandlerStore) Get(ctx context.Context, r *RequestV2) (Response, error) { - if r.Wait { - wc, err := a.store.Watch(r.Path, r.Recursive, r.Stream, r.Since) - return Response{Watcher: wc}, err - } - ev, err := a.store.Get(r.Path, r.Recursive, r.Sorted) - return Response{Event: ev}, err -} - -func (a *reqV2HandlerStore) Head(ctx context.Context, r *RequestV2) (Response, error) { - ev, err := a.store.Get(r.Path, r.Recursive, r.Sorted) - return Response{Event: ev}, err -} - -func (a *reqV2HandlerEtcdServer) Post(ctx context.Context, r *RequestV2) (Response, error) { - return a.processRaftRequest(ctx, r) -} - -func (a *reqV2HandlerEtcdServer) Put(ctx context.Context, r *RequestV2) (Response, error) { - return a.processRaftRequest(ctx, r) -} - -func (a *reqV2HandlerEtcdServer) Delete(ctx context.Context, r *RequestV2) (Response, error) { - return a.processRaftRequest(ctx, r) -} - -func (a *reqV2HandlerEtcdServer) QGet(ctx context.Context, r *RequestV2) (Response, error) { - return a.processRaftRequest(ctx, r) -} - -func (a *reqV2HandlerEtcdServer) processRaftRequest(ctx context.Context, r *RequestV2) (Response, error) { - data, err := ((*pb.Request)(r)).Marshal() - if err != nil { - return Response{}, err - } - ch := a.s.w.Register(r.ID) - - start := time.Now() - a.s.r.Propose(ctx, data) - proposalsPending.Inc() - defer proposalsPending.Dec() - - select { - case x := <-ch: - resp := x.(Response) - return resp, resp.Err - case <-ctx.Done(): - proposalsFailed.Inc() - a.s.w.Trigger(r.ID, nil) // GC wait - return Response{}, a.s.parseProposeCtxErr(ctx.Err(), start) - case <-a.s.stopping: - } - return Response{}, ErrStopped -} - -func (s *EtcdServer) Do(ctx context.Context, r pb.Request) (Response, error) { - r.ID = s.reqIDGen.Next() - h := &reqV2HandlerEtcdServer{ - reqV2HandlerStore: reqV2HandlerStore{ - store: s.v2store, - applier: s.applyV2, - }, - s: s, - } - rp := &r - resp, err := ((*RequestV2)(rp)).Handle(ctx, h) - resp.Term, resp.Index = s.Term(), s.CommittedIndex() - return resp, err -} - -// Handle interprets r and performs an operation on s.store according to r.Method -// and other fields. If r.Method is "POST", "PUT", "DELETE", or a "GET" with -// Quorum == true, r will be sent through consensus before performing its -// respective operation. Do will block until an action is performed or there is -// an error. -func (r *RequestV2) Handle(ctx context.Context, v2api RequestV2Handler) (Response, error) { - if r.Method == "GET" && r.Quorum { - r.Method = "QGET" - } - switch r.Method { - case "POST": - return v2api.Post(ctx, r) - case "PUT": - return v2api.Put(ctx, r) - case "DELETE": - return v2api.Delete(ctx, r) - case "QGET": - return v2api.QGet(ctx, r) - case "GET": - return v2api.Get(ctx, r) - case "HEAD": - return v2api.Head(ctx, r) - } - return Response{}, ErrUnknownMethod -} - func (r *RequestV2) String() string { rpb := pb.Request(*r) return rpb.String() diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/v3_server.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/v3_server.go index a9e1f3586a..c6953604aa 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/v3_server.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/v3_server.go @@ -19,28 +19,33 @@ import ( "context" "encoding/base64" "encoding/binary" + errorspkg "errors" "strconv" "time" + "github.com/gogo/protobuf/proto" + "go.uber.org/zap" + "golang.org/x/crypto/bcrypt" + pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/api/v3/membershippb" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/pkg/v3/traceutil" - "go.etcd.io/etcd/raft/v3" "go.etcd.io/etcd/server/v3/auth" "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + apply2 "go.etcd.io/etcd/server/v3/etcdserver/apply" + "go.etcd.io/etcd/server/v3/etcdserver/errors" + "go.etcd.io/etcd/server/v3/etcdserver/txn" + "go.etcd.io/etcd/server/v3/features" "go.etcd.io/etcd/server/v3/lease" "go.etcd.io/etcd/server/v3/lease/leasehttp" - "go.etcd.io/etcd/server/v3/mvcc" - - "github.com/gogo/protobuf/proto" - "go.uber.org/zap" - "golang.org/x/crypto/bcrypt" + "go.etcd.io/etcd/server/v3/storage/mvcc" + "go.etcd.io/raft/v3" ) const ( // In the health case, there might be a small gap (10s of entries) between // the applied index and committed index. - // However, if the committed entries are very heavy to apply, the gap might grow. + // However, if the committed entries are very heavy to toApply, the gap might grow. // We should stop accepting new proposals if the gap growing to a certain point. maxGapBetweenApplyAndCommitIndex = 5000 traceThreshold = 100 * time.Millisecond @@ -60,9 +65,9 @@ type RaftKV interface { } type Lessor interface { - // LeaseGrant sends LeaseGrant request to raft and apply it after committed. + // LeaseGrant sends LeaseGrant request to raft and toApply it after committed. LeaseGrant(ctx context.Context, r *pb.LeaseGrantRequest) (*pb.LeaseGrantResponse, error) - // LeaseRevoke sends LeaseRevoke request to raft and apply it after committed. + // LeaseRevoke sends LeaseRevoke request to raft and toApply it after committed. LeaseRevoke(ctx context.Context, r *pb.LeaseRevokeRequest) (*pb.LeaseRevokeResponse, error) // LeaseRenew renews the lease with given ID. The renewed TTL is returned. Or an error @@ -102,12 +107,12 @@ func (s *EtcdServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeRe traceutil.Field{Key: "range_begin", Value: string(r.Key)}, traceutil.Field{Key: "range_end", Value: string(r.RangeEnd)}, ) - ctx = context.WithValue(ctx, traceutil.TraceKey, trace) + ctx = context.WithValue(ctx, traceutil.TraceKey{}, trace) var resp *pb.RangeResponse var err error defer func(start time.Time) { - warnOfExpensiveReadOnlyRangeRequest(s.Logger(), s.Cfg.WarningApplyDuration, start, r, resp, err) + txn.WarnOfExpensiveReadOnlyRangeRequest(s.Logger(), s.Cfg.WarningApplyDuration, start, r, resp, err) if resp != nil { trace.AddField( traceutil.Field{Key: "response_count", Value: len(resp.Kvs)}, @@ -128,7 +133,7 @@ func (s *EtcdServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeRe return s.authStore.IsRangePermitted(ai, r.Key, r.RangeEnd) } - get := func() { resp, err = s.applyV3Base.Range(ctx, nil, r) } + get := func() { resp, _, err = txn.Range(ctx, s.Logger(), s.KV(), r) } if serr := s.doSerialize(ctx, chk, get); serr != nil { err = serr return nil, err @@ -137,7 +142,7 @@ func (s *EtcdServer) Range(ctx context.Context, r *pb.RangeRequest) (*pb.RangeRe } func (s *EtcdServer) Put(ctx context.Context, r *pb.PutRequest) (*pb.PutResponse, error) { - ctx = context.WithValue(ctx, traceutil.StartTimeKey, time.Now()) + ctx = context.WithValue(ctx, traceutil.StartTimeKey{}, time.Now()) resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{Put: r}) if err != nil { return nil, err @@ -154,13 +159,13 @@ func (s *EtcdServer) DeleteRange(ctx context.Context, r *pb.DeleteRangeRequest) } func (s *EtcdServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse, error) { - if isTxnReadonly(r) { + if txn.IsTxnReadonly(r) { trace := traceutil.New("transaction", s.Logger(), traceutil.Field{Key: "read_only", Value: true}, ) - ctx = context.WithValue(ctx, traceutil.TraceKey, trace) - if !isTxnSerializable(r) { + ctx = context.WithValue(ctx, traceutil.TraceKey{}, trace) + if !txn.IsTxnSerializable(r) { err := s.linearizableReadNotify(ctx) trace.Step("agreement among raft nodes before linearized reading") if err != nil { @@ -170,22 +175,24 @@ func (s *EtcdServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse var resp *pb.TxnResponse var err error chk := func(ai *auth.AuthInfo) error { - return checkTxnAuth(s.authStore, ai, r) + return txn.CheckTxnAuth(s.authStore, ai, r) } defer func(start time.Time) { - warnOfExpensiveReadOnlyTxnRequest(s.Logger(), s.Cfg.WarningApplyDuration, start, r, resp, err) + txn.WarnOfExpensiveReadOnlyTxnRequest(s.Logger(), s.Cfg.WarningApplyDuration, start, r, resp, err) trace.LogIfLong(traceThreshold) }(time.Now()) - get := func() { resp, _, err = s.applyV3Base.Txn(ctx, r) } + get := func() { + resp, _, err = txn.Txn(ctx, s.Logger(), r, s.Cfg.ServerFeatureGate.Enabled(features.TxnModeWriteWithSharedBuffer), s.KV(), s.lessor) + } if serr := s.doSerialize(ctx, chk, get); serr != nil { return nil, serr } return resp, err } - ctx = context.WithValue(ctx, traceutil.StartTimeKey, time.Now()) + ctx = context.WithValue(ctx, traceutil.StartTimeKey{}, time.Now()) resp, err := s.raftRequest(ctx, pb.InternalRaftRequest{Txn: r}) if err != nil { return nil, err @@ -193,64 +200,40 @@ func (s *EtcdServer) Txn(ctx context.Context, r *pb.TxnRequest) (*pb.TxnResponse return resp.(*pb.TxnResponse), nil } -func isTxnSerializable(r *pb.TxnRequest) bool { - for _, u := range r.Success { - if r := u.GetRequestRange(); r == nil || !r.Serializable { - return false - } - } - for _, u := range r.Failure { - if r := u.GetRequestRange(); r == nil || !r.Serializable { - return false - } - } - return true -} - -func isTxnReadonly(r *pb.TxnRequest) bool { - for _, u := range r.Success { - if r := u.GetRequestRange(); r == nil { - return false - } - } - for _, u := range r.Failure { - if r := u.GetRequestRange(); r == nil { - return false - } - } - return true -} - func (s *EtcdServer) Compact(ctx context.Context, r *pb.CompactionRequest) (*pb.CompactionResponse, error) { startTime := time.Now() result, err := s.processInternalRaftRequestOnce(ctx, pb.InternalRaftRequest{Compaction: r}) trace := traceutil.TODO() - if result != nil && result.trace != nil { - trace = result.trace + if result != nil && result.Trace != nil { + trace = result.Trace defer func() { trace.LogIfLong(traceThreshold) }() - applyStart := result.trace.GetStartTime() - result.trace.SetStartTime(startTime) + applyStart := result.Trace.GetStartTime() + result.Trace.SetStartTime(startTime) trace.InsertStep(0, applyStart, "process raft request") } - if r.Physical && result != nil && result.physc != nil { - <-result.physc + if r.Physical && result != nil && result.Physc != nil { + <-result.Physc // The compaction is done deleting keys; the hash is now settled // but the data is not necessarily committed. If there's a crash, // the hash may revert to a hash prior to compaction completing // if the compaction resumes. Force the finished compaction to // commit so it won't resume following a crash. + // + // `applySnapshot` sets a new backend instance, so we need to acquire the bemu lock. + s.bemu.RLock() s.be.ForceCommit() - trace.Step("physically apply compaction") + s.bemu.RUnlock() + trace.Step("physically toApply compaction") } if err != nil { return nil, err } - if result.err != nil { - return nil, result.err + if result.Err != nil { + return nil, result.Err } - resp := result.resp.(*pb.CompactionResponse) + resp := result.Resp.(*pb.CompactionResponse) if resp == nil { resp = &pb.CompactionResponse{} } @@ -279,9 +262,9 @@ func (s *EtcdServer) waitAppliedIndex() error { select { case <-s.ApplyWait(): case <-s.stopping: - return ErrStopped + return errors.ErrStopped case <-time.After(applyTimeout): - return ErrTimeoutWaitAppliedIndex + return errors.ErrTimeoutWaitAppliedIndex } return nil @@ -307,7 +290,6 @@ func (s *EtcdServer) LeaseRenew(ctx context.Context, id lease.LeaseID) (int64, e if !s.ensureLeadership() { return -1, lease.ErrNotPrimary } - if err := s.waitAppliedIndex(); err != nil { return 0, err } @@ -316,7 +298,7 @@ func (s *EtcdServer) LeaseRenew(ctx context.Context, id lease.LeaseID) (int64, e if err == nil { // already requested to primary lessor(leader) return ttl, nil } - if err != lease.ErrNotPrimary { + if !errorspkg.Is(err, lease.ErrNotPrimary) { return -1, err } } @@ -333,7 +315,7 @@ func (s *EtcdServer) LeaseRenew(ctx context.Context, id lease.LeaseID) (int64, e for _, url := range leader.PeerURLs { lurl := url + leasehttp.LeasePrefix ttl, err := leasehttp.RenewHTTP(cctx, id, lurl, s.peerRt) - if err == nil || err == lease.ErrLeaseNotFound { + if err == nil || errorspkg.Is(err, lease.ErrLeaseNotFound) { return ttl, err } } @@ -341,10 +323,10 @@ func (s *EtcdServer) LeaseRenew(ctx context.Context, id lease.LeaseID) (int64, e time.Sleep(50 * time.Millisecond) } - if cctx.Err() == context.DeadlineExceeded { - return -1, ErrTimeout + if errorspkg.Is(cctx.Err(), context.DeadlineExceeded) { + return -1, errors.ErrTimeout } - return -1, ErrCanceled + return -1, errors.ErrCanceled } func (s *EtcdServer) checkLeaseTimeToLive(ctx context.Context, leaseID lease.LeaseID) (uint64, error) { @@ -402,7 +384,7 @@ func (s *EtcdServer) leaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveR if le.Demoted() { // NOTE: lease.ErrNotPrimary is not retryable error for // client. Instead, uses ErrLeaderChanged. - return nil, ErrLeaderChanged + return nil, errors.ErrLeaderChanged } return resp, nil } @@ -422,16 +404,16 @@ func (s *EtcdServer) leaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveR if err == nil { return resp.LeaseTimeToLiveResponse, nil } - if err == lease.ErrLeaseNotFound { + if errorspkg.Is(err, lease.ErrLeaseNotFound) { return nil, err } } } - if cctx.Err() == context.DeadlineExceeded { - return nil, ErrTimeout + if errorspkg.Is(cctx.Err(), context.DeadlineExceeded) { + return nil, errors.ErrTimeout } - return nil, ErrCanceled + return nil, errors.ErrCanceled } func (s *EtcdServer) LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveRequest) (*pb.LeaseTimeToLiveResponse, error) { @@ -458,14 +440,23 @@ func (s *EtcdServer) LeaseTimeToLive(ctx context.Context, r *pb.LeaseTimeToLiveR return resp, nil } +func (s *EtcdServer) newHeader() *pb.ResponseHeader { + return &pb.ResponseHeader{ + ClusterId: uint64(s.cluster.ID()), + MemberId: uint64(s.MemberID()), + Revision: s.KV().Rev(), + RaftTerm: s.Term(), + } +} + // LeaseLeases is really ListLeases !??? -func (s *EtcdServer) LeaseLeases(ctx context.Context, r *pb.LeaseLeasesRequest) (*pb.LeaseLeasesResponse, error) { +func (s *EtcdServer) LeaseLeases(_ context.Context, _ *pb.LeaseLeasesRequest) (*pb.LeaseLeasesResponse, error) { ls := s.lessor.Leases() lss := make([]*pb.LeaseStatus, len(ls)) for i := range ls { lss[i] = &pb.LeaseStatus{ID: int64(ls[i].ID)} } - return &pb.LeaseLeasesResponse{Header: newHeader(s), Leases: lss}, nil + return &pb.LeaseLeasesResponse{Header: s.newHeader(), Leases: lss}, nil } func (s *EtcdServer) waitLeader(ctx context.Context) (*membership.Member, error) { @@ -477,13 +468,13 @@ func (s *EtcdServer) waitLeader(ctx context.Context) (*membership.Member, error) case <-time.After(dur): leader = s.cluster.Member(s.Leader()) case <-s.stopping: - return nil, ErrStopped + return nil, errors.ErrStopped case <-ctx.Done(): - return nil, ErrNoLeader + return nil, errors.ErrNoLeader } } - if leader == nil || len(leader.PeerURLs) == 0 { - return nil, ErrNoLeader + if len(leader.PeerURLs) == 0 { + return nil, errors.ErrNoLeader } return leader, nil } @@ -538,7 +529,7 @@ func (s *EtcdServer) Authenticate(ctx context.Context, r *pb.AuthenticateRequest for { checkedRevision, err := s.AuthStore().CheckPassword(r.Name, r.Password) if err != nil { - if err != auth.ErrAuthNotEnabled { + if !errorspkg.Is(err, auth.ErrAuthNotEnabled) { lg.Warn( "invalid authentication was requested", zap.String("user", r.Name), @@ -701,19 +692,19 @@ func (s *EtcdServer) raftRequestOnce(ctx context.Context, r pb.InternalRaftReque if err != nil { return nil, err } - if result.err != nil { - return nil, result.err + if result.Err != nil { + return nil, result.Err } - if startTime, ok := ctx.Value(traceutil.StartTimeKey).(time.Time); ok && result.trace != nil { - applyStart := result.trace.GetStartTime() - // The trace object is created in apply. Here reset the start time to trace + if startTime, ok := ctx.Value(traceutil.StartTimeKey{}).(time.Time); ok && result.Trace != nil { + applyStart := result.Trace.GetStartTime() + // The trace object is created in toApply. Here reset the start time to trace // the raft request time by the difference between the request start time - // and apply start time - result.trace.SetStartTime(startTime) - result.trace.InsertStep(0, applyStart, "process raft request") - result.trace.LogIfLong(traceThreshold) + // and toApply start time + result.Trace.SetStartTime(startTime) + result.Trace.InsertStep(0, applyStart, "process raft request") + result.Trace.LogIfLong(traceThreshold) } - return result.resp, nil + return result.Resp, nil } func (s *EtcdServer) raftRequest(ctx context.Context, r pb.InternalRaftRequest) (proto.Message, error) { @@ -745,11 +736,11 @@ func (s *EtcdServer) doSerialize(ctx context.Context, chk func(*auth.AuthInfo) e return nil } -func (s *EtcdServer) processInternalRaftRequestOnce(ctx context.Context, r pb.InternalRaftRequest) (*applyResult, error) { +func (s *EtcdServer) processInternalRaftRequestOnce(ctx context.Context, r pb.InternalRaftRequest) (*apply2.Result, error) { ai := s.getAppliedIndex() ci := s.getCommittedIndex() if ci > ai+maxGapBetweenApplyAndCommitIndex { - return nil, ErrTooManyRequests + return nil, errors.ErrTooManyRequests } r.Header = &pb.RequestHeader{ @@ -774,7 +765,7 @@ func (s *EtcdServer) processInternalRaftRequestOnce(ctx context.Context, r pb.In } if len(data) > int(s.Cfg.MaxRequestBytes) { - return nil, ErrRequestTooLarge + return nil, errors.ErrRequestTooLarge } id := r.ID @@ -798,13 +789,13 @@ func (s *EtcdServer) processInternalRaftRequestOnce(ctx context.Context, r pb.In select { case x := <-ch: - return x.(*applyResult), nil + return x.(*apply2.Result), nil case <-cctx.Done(): proposalsFailed.Inc() s.w.Trigger(id, nil) // GC wait return nil, s.parseProposeCtxErr(cctx.Err(), start) case <-s.done: - return nil, ErrStopped + return nil, errors.ErrStopped } } @@ -813,8 +804,8 @@ func (s *EtcdServer) Watchable() mvcc.WatchableKV { return s.KV() } func (s *EtcdServer) linearizableReadLoop() { for { - requestId := s.reqIDGen.Next() - leaderChangedNotifier := s.LeaderChangedNotify() + requestID := s.reqIDGen.Next() + leaderChangedNotifier := s.leaderChanged.Receive() select { case <-leaderChangedNotifier: continue @@ -833,7 +824,7 @@ func (s *EtcdServer) linearizableReadLoop() { s.readNotifier = nextnr s.readMu.Unlock() - confirmedIndex, err := s.requestCurrentIndex(leaderChangedNotifier, requestId) + confirmedIndex, err := s.requestCurrentIndex(leaderChangedNotifier, requestID) if isStopped(err) { return } @@ -865,11 +856,11 @@ func (s *EtcdServer) linearizableReadLoop() { } func isStopped(err error) bool { - return err == raft.ErrStopped || err == ErrStopped + return errorspkg.Is(err, raft.ErrStopped) || errorspkg.Is(err, errors.ErrStopped) } -func (s *EtcdServer) requestCurrentIndex(leaderChangedNotifier <-chan struct{}, requestId uint64) (uint64, error) { - err := s.sendReadIndex(requestId) +func (s *EtcdServer) requestCurrentIndex(leaderChangedNotifier <-chan struct{}, requestID uint64) (uint64, error) { + err := s.sendReadIndex(requestID) if err != nil { return 0, err } @@ -880,24 +871,24 @@ func (s *EtcdServer) requestCurrentIndex(leaderChangedNotifier <-chan struct{}, retryTimer := time.NewTimer(readIndexRetryTime) defer retryTimer.Stop() - firstCommitInTermNotifier := s.FirstCommitInTermNotify() + firstCommitInTermNotifier := s.firstCommitInTerm.Receive() for { select { case rs := <-s.r.readStateC: - requestIdBytes := uint64ToBigEndianBytes(requestId) - gotOwnResponse := bytes.Equal(rs.RequestCtx, requestIdBytes) + requestIDBytes := uint64ToBigEndianBytes(requestID) + gotOwnResponse := bytes.Equal(rs.RequestCtx, requestIDBytes) if !gotOwnResponse { // a previous request might time out. now we should ignore the response of it and // continue waiting for the response of the current requests. - responseId := uint64(0) + responseID := uint64(0) if len(rs.RequestCtx) == 8 { - responseId = binary.BigEndian.Uint64(rs.RequestCtx) + responseID = binary.BigEndian.Uint64(rs.RequestCtx) } lg.Warn( "ignored out-of-date read index response; local node read indexes queueing up and waiting to be in sync with leader", - zap.Uint64("sent-request-id", requestId), - zap.Uint64("received-request-id", responseId), + zap.Uint64("sent-request-id", requestID), + zap.Uint64("received-request-id", responseID), ) slowReadIndex.Inc() continue @@ -906,11 +897,11 @@ func (s *EtcdServer) requestCurrentIndex(leaderChangedNotifier <-chan struct{}, case <-leaderChangedNotifier: readIndexFailed.Inc() // return a retryable error. - return 0, ErrLeaderChanged + return 0, errors.ErrLeaderChanged case <-firstCommitInTermNotifier: - firstCommitInTermNotifier = s.FirstCommitInTermNotify() + firstCommitInTermNotifier = s.firstCommitInTerm.Receive() lg.Info("first commit in current term: resending ReadIndex request") - err := s.sendReadIndex(requestId) + err := s.sendReadIndex(requestID) if err != nil { return 0, err } @@ -919,10 +910,10 @@ func (s *EtcdServer) requestCurrentIndex(leaderChangedNotifier <-chan struct{}, case <-retryTimer.C: lg.Warn( "waiting for ReadIndex response took too long, retrying", - zap.Uint64("sent-request-id", requestId), + zap.Uint64("sent-request-id", requestID), zap.Duration("retry-timeout", readIndexRetryTime), ) - err := s.sendReadIndex(requestId) + err := s.sendReadIndex(requestID) if err != nil { return 0, err } @@ -934,9 +925,9 @@ func (s *EtcdServer) requestCurrentIndex(leaderChangedNotifier <-chan struct{}, zap.Duration("timeout", s.Cfg.ReqTimeout()), ) slowReadIndex.Inc() - return 0, ErrTimeout + return 0, errors.ErrTimeout case <-s.stopping: - return 0, ErrStopped + return 0, errors.ErrStopped } } } @@ -953,7 +944,7 @@ func (s *EtcdServer) sendReadIndex(requestIndex uint64) error { cctx, cancel := context.WithTimeout(context.Background(), s.Cfg.ReqTimeout()) err := s.r.ReadIndex(cctx, ctxToSend) cancel() - if err == raft.ErrStopped { + if errorspkg.Is(err, raft.ErrStopped) { return err } if err != nil { @@ -987,7 +978,7 @@ func (s *EtcdServer) linearizableReadNotify(ctx context.Context) error { case <-ctx.Done(): return ctx.Err() case <-s.done: - return ErrStopped + return errors.ErrStopped } } @@ -1012,7 +1003,7 @@ func (s *EtcdServer) Downgrade(ctx context.Context, r *pb.DowngradeRequest) (*pb case pb.DowngradeRequest_CANCEL: return s.downgradeCancel(ctx) default: - return nil, ErrUnknownMethod + return nil, errors.ErrUnknownMethod } } @@ -1024,73 +1015,40 @@ func (s *EtcdServer) downgradeValidate(ctx context.Context, v string) (*pb.Downg return nil, err } - // gets leaders commit index and wait for local store to finish applying that index - // to avoid using stale downgrade information - err = s.linearizableReadNotify(ctx) - if err != nil { - return nil, err - } - cv := s.ClusterVersion() if cv == nil { - return nil, ErrClusterVersionUnavailable + return nil, errors.ErrClusterVersionUnavailable } - resp.Version = cv.String() - - allowedTargetVersion := membership.AllowedDowngradeVersion(cv) - if !targetVersion.Equal(*allowedTargetVersion) { - return nil, ErrInvalidDowngradeTargetVersion + resp.Version = version.Cluster(cv.String()) + err = s.Version().DowngradeValidate(ctx, targetVersion) + if err != nil { + return nil, err } - downgradeInfo := s.cluster.DowngradeInfo() - if downgradeInfo.Enabled { - // Todo: return the downgrade status along with the error msg - return nil, ErrDowngradeInProcess - } return resp, nil } func (s *EtcdServer) downgradeEnable(ctx context.Context, r *pb.DowngradeRequest) (*pb.DowngradeResponse, error) { - // validate downgrade capability before starting downgrade - v := r.Version lg := s.Logger() - if resp, err := s.downgradeValidate(ctx, v); err != nil { - lg.Warn("reject downgrade request", zap.Error(err)) - return resp, err - } - targetVersion, err := convertToClusterVersion(v) + targetVersion, err := convertToClusterVersion(r.Version) if err != nil { lg.Warn("reject downgrade request", zap.Error(err)) return nil, err } - - raftRequest := membershippb.DowngradeInfoSetRequest{Enabled: true, Ver: targetVersion.String()} - _, err = s.raftRequest(ctx, pb.InternalRaftRequest{DowngradeInfoSet: &raftRequest}) + err = s.Version().DowngradeEnable(ctx, targetVersion) if err != nil { lg.Warn("reject downgrade request", zap.Error(err)) return nil, err } - resp := pb.DowngradeResponse{Version: s.ClusterVersion().String()} + resp := pb.DowngradeResponse{Version: version.Cluster(s.ClusterVersion().String())} return &resp, nil } func (s *EtcdServer) downgradeCancel(ctx context.Context) (*pb.DowngradeResponse, error) { - // gets leaders commit index and wait for local store to finish applying that index - // to avoid using stale downgrade information - if err := s.linearizableReadNotify(ctx); err != nil { - return nil, err - } - - downgradeInfo := s.cluster.DowngradeInfo() - if !downgradeInfo.Enabled { - return nil, ErrNoInflightDowngrade - } - - raftRequest := membershippb.DowngradeInfoSetRequest{Enabled: false} - _, err := s.raftRequest(ctx, pb.InternalRaftRequest{DowngradeInfoSet: &raftRequest}) + err := s.Version().DowngradeCancel(ctx) if err != nil { - return nil, err + s.lg.Warn("failed to cancel downgrade", zap.Error(err)) } - resp := pb.DowngradeResponse{Version: s.ClusterVersion().String()} + resp := pb.DowngradeResponse{Version: version.Cluster(s.ClusterVersion().String())} return &resp, nil } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/doc.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/doc.go similarity index 81% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/doc.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/doc.go index 475c4b1f95..c34f905119 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2http/doc.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/doc.go @@ -1,4 +1,4 @@ -// Copyright 2015 The etcd Authors +// Copyright 2021 The etcd Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,5 +12,5 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package v2http provides etcd client and server implementations. -package v2http +// Package version provides functions for getting/saving storage version. +package version diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/downgrade.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/downgrade.go similarity index 60% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/downgrade.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/downgrade.go index 9fdafe22aa..f2c6e11946 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/downgrade.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/downgrade.go @@ -12,12 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -package membership +package version import ( "github.com/coreos/go-semver/semver" - "go.etcd.io/etcd/api/v3/version" "go.uber.org/zap" + + "go.etcd.io/etcd/api/v3/version" ) type DowngradeInfo struct { @@ -34,47 +35,42 @@ func (d *DowngradeInfo) GetTargetVersion() *semver.Version { // isValidDowngrade verifies whether the cluster can be downgraded from verFrom to verTo func isValidDowngrade(verFrom *semver.Version, verTo *semver.Version) bool { - return verTo.Equal(*AllowedDowngradeVersion(verFrom)) + return verTo.Equal(*allowedDowngradeVersion(verFrom)) } -// mustDetectDowngrade will detect unexpected downgrade when the local server is recovered. -func mustDetectDowngrade(lg *zap.Logger, cv *semver.Version, d *DowngradeInfo) { - lv := semver.Must(semver.NewVersion(version.Version)) +// MustDetectDowngrade will detect local server joining cluster that doesn't support it's version. +func MustDetectDowngrade(lg *zap.Logger, sv, cv *semver.Version) { // only keep major.minor version for comparison against cluster version - lv = &semver.Version{Major: lv.Major, Minor: lv.Minor} - - // if the cluster enables downgrade, check local version against downgrade target version. - if d != nil && d.Enabled && d.TargetVersion != "" { - if lv.Equal(*d.GetTargetVersion()) { - if cv != nil { - lg.Info( - "cluster is downgrading to target version", - zap.String("target-cluster-version", d.TargetVersion), - zap.String("determined-cluster-version", version.Cluster(cv.String())), - zap.String("current-server-version", version.Version), - ) - } - return - } - lg.Fatal( - "invalid downgrade; server version is not allowed to join when downgrade is enabled", - zap.String("current-server-version", version.Version), - zap.String("target-cluster-version", d.TargetVersion), - ) - } + sv = &semver.Version{Major: sv.Major, Minor: sv.Minor} // if the cluster disables downgrade, check local version against determined cluster version. // the validation passes when local version is not less than cluster version - if cv != nil && lv.LessThan(*cv) { - lg.Fatal( + if cv != nil && sv.LessThan(*cv) { + lg.Panic( "invalid downgrade; server version is lower than determined cluster version", - zap.String("current-server-version", version.Version), + zap.String("current-server-version", sv.String()), zap.String("determined-cluster-version", version.Cluster(cv.String())), ) } } -func AllowedDowngradeVersion(ver *semver.Version) *semver.Version { +func allowedDowngradeVersion(ver *semver.Version) *semver.Version { // Todo: handle the case that downgrading from higher major version(e.g. downgrade from v4.0 to v3.x) return &semver.Version{Major: ver.Major, Minor: ver.Minor - 1} } + +// IsValidClusterVersionChange checks the two scenario when version is valid to change: +// 1. Downgrade: cluster version is 1 minor version higher than local version, +// cluster version should change. +// 2. Cluster start: when not all members version are available, cluster version +// is set to MinVersion(3.0), when all members are at higher version, cluster version +// is lower than minimal server version, cluster version should change +func IsValidClusterVersionChange(verFrom *semver.Version, verTo *semver.Version) bool { + verFrom = &semver.Version{Major: verFrom.Major, Minor: verFrom.Minor} + verTo = &semver.Version{Major: verTo.Major, Minor: verTo.Minor} + + if isValidDowngrade(verFrom, verTo) || (verFrom.Major == verTo.Major && verFrom.LessThan(*verTo)) { + return true + } + return false +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/doc.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/errors.go similarity index 60% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/doc.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/errors.go index 2ff372f187..906aa9f413 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/v2v3/doc.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/errors.go @@ -1,4 +1,4 @@ -// Copyright 2017 The etcd Authors +// Copyright 2021 The etcd Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,5 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package v2v3 provides a ServerV2 implementation backed by clientv3.Client. -package v2v3 +package version + +import "errors" + +var ( + ErrInvalidDowngradeTargetVersion = errors.New("etcdserver: invalid downgrade target version") + ErrDowngradeInProcess = errors.New("etcdserver: cluster has a downgrade job in progress") + ErrNoInflightDowngrade = errors.New("etcdserver: no inflight downgrade job") +) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/monitor.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/monitor.go new file mode 100644 index 0000000000..b3e7f5804e --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/monitor.go @@ -0,0 +1,221 @@ +// Copyright 2021 The etcd 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 version + +import ( + "context" + "errors" + + "github.com/coreos/go-semver/semver" + "go.uber.org/zap" + + "go.etcd.io/etcd/api/v3/version" +) + +// Monitor contains logic used by cluster leader to monitor version changes and decide on cluster version or downgrade progress. +type Monitor struct { + lg *zap.Logger + s Server +} + +// Server lists EtcdServer methods needed by Monitor +type Server interface { + GetClusterVersion() *semver.Version + GetDowngradeInfo() *DowngradeInfo + GetMembersVersions() map[string]*version.Versions + UpdateClusterVersion(string) + LinearizableReadNotify(ctx context.Context) error + DowngradeEnable(ctx context.Context, targetVersion *semver.Version) error + DowngradeCancel(ctx context.Context) error + + GetStorageVersion() *semver.Version + UpdateStorageVersion(semver.Version) error +} + +func NewMonitor(lg *zap.Logger, storage Server) *Monitor { + return &Monitor{ + lg: lg, + s: storage, + } +} + +// UpdateClusterVersionIfNeeded updates the cluster version. +func (m *Monitor) UpdateClusterVersionIfNeeded() error { + newClusterVersion, err := m.decideClusterVersion() + if newClusterVersion != nil { + newClusterVersion = &semver.Version{Major: newClusterVersion.Major, Minor: newClusterVersion.Minor} + m.s.UpdateClusterVersion(newClusterVersion.String()) + } + return err +} + +// decideClusterVersion decides whether to change cluster version and its next value. +// New cluster version is based on the members versions server and whether cluster is downgrading. +// Returns nil if cluster version should be left unchanged. +func (m *Monitor) decideClusterVersion() (*semver.Version, error) { + clusterVersion := m.s.GetClusterVersion() + minimalServerVersion := m.membersMinimalServerVersion() + if clusterVersion == nil { + if minimalServerVersion != nil { + return minimalServerVersion, nil + } + return semver.New(version.MinClusterVersion), nil + } + if minimalServerVersion == nil { + return nil, nil + } + downgrade := m.s.GetDowngradeInfo() + if downgrade != nil && downgrade.Enabled { + if downgrade.GetTargetVersion().Equal(*clusterVersion) { + return nil, nil + } + if !isValidDowngrade(clusterVersion, downgrade.GetTargetVersion()) { + m.lg.Error("Cannot downgrade from cluster-version to downgrade-target", + zap.String("downgrade-target", downgrade.TargetVersion), + zap.String("cluster-version", clusterVersion.String()), + ) + return nil, errors.New("invalid downgrade target") + } + if !isValidDowngrade(minimalServerVersion, downgrade.GetTargetVersion()) { + m.lg.Error("Cannot downgrade from minimal-server-version to downgrade-target", + zap.String("downgrade-target", downgrade.TargetVersion), + zap.String("minimal-server-version", minimalServerVersion.String()), + ) + return nil, errors.New("invalid downgrade target") + } + return downgrade.GetTargetVersion(), nil + } + if clusterVersion.LessThan(*minimalServerVersion) && IsValidClusterVersionChange(clusterVersion, minimalServerVersion) { + return minimalServerVersion, nil + } + return nil, nil +} + +// UpdateStorageVersionIfNeeded updates the storage version if it differs from cluster version. +func (m *Monitor) UpdateStorageVersionIfNeeded() { + cv := m.s.GetClusterVersion() + if cv == nil || cv.String() == version.MinClusterVersion { + return + } + sv := m.s.GetStorageVersion() + + if sv == nil || sv.Major != cv.Major || sv.Minor != cv.Minor { + if sv != nil { + m.lg.Info("cluster version differs from storage version.", zap.String("cluster-version", cv.String()), zap.String("storage-version", sv.String())) + } + err := m.s.UpdateStorageVersion(semver.Version{Major: cv.Major, Minor: cv.Minor}) + if err != nil { + m.lg.Error("failed to update storage version", zap.String("cluster-version", cv.String()), zap.Error(err)) + return + } + d := m.s.GetDowngradeInfo() + if d != nil && d.Enabled { + m.lg.Info( + "The server is ready to downgrade", + zap.String("target-version", d.TargetVersion), + zap.String("server-version", version.Version), + ) + } + } +} + +func (m *Monitor) CancelDowngradeIfNeeded() { + d := m.s.GetDowngradeInfo() + if d == nil || !d.Enabled { + return + } + + targetVersion := d.TargetVersion + v := semver.Must(semver.NewVersion(targetVersion)) + if m.versionsMatchTarget(v) { + m.lg.Info("the cluster has been downgraded", zap.String("cluster-version", targetVersion)) + err := m.s.DowngradeCancel(context.Background()) + if err != nil { + m.lg.Warn("failed to cancel downgrade", zap.Error(err)) + } + } +} + +// membersMinimalServerVersion returns the min server version in the map, or nil if the min +// version in unknown. +// It prints out log if there is a member with a higher version than the +// local version. +func (m *Monitor) membersMinimalServerVersion() *semver.Version { + vers := m.s.GetMembersVersions() + var minV *semver.Version + lv := semver.Must(semver.NewVersion(version.Version)) + + for mid, ver := range vers { + if ver == nil { + return nil + } + v, err := semver.NewVersion(ver.Server) + if err != nil { + m.lg.Warn( + "failed to parse server version of remote member", + zap.String("remote-member-id", mid), + zap.String("remote-member-version", ver.Server), + zap.Error(err), + ) + return nil + } + if lv.LessThan(*v) { + m.lg.Warn( + "leader found higher-versioned member", + zap.String("local-member-version", lv.String()), + zap.String("remote-member-id", mid), + zap.String("remote-member-version", ver.Server), + ) + } + if minV == nil { + minV = v + } else if v.LessThan(*minV) { + minV = v + } + } + return minV +} + +// versionsMatchTarget returns true if all server versions are equal to target version, otherwise return false. +// It can be used to decide the whether the cluster finishes downgrading to target version. +func (m *Monitor) versionsMatchTarget(targetVersion *semver.Version) bool { + vers := m.s.GetMembersVersions() + targetVersion = &semver.Version{Major: targetVersion.Major, Minor: targetVersion.Minor} + for mid, ver := range vers { + if ver == nil { + return false + } + v, err := semver.NewVersion(ver.Server) + if err != nil { + m.lg.Warn( + "failed to parse server version of remote member", + zap.String("remote-member-id", mid), + zap.String("remote-member-version", ver.Server), + zap.Error(err), + ) + return false + } + v = &semver.Version{Major: v.Major, Minor: v.Minor} + if !targetVersion.Equal(*v) { + m.lg.Warn("remotes server has mismatching etcd version", + zap.String("remote-member-id", mid), + zap.String("current-server-version", v.String()), + zap.String("target-version", targetVersion.String()), + ) + return false + } + } + return true +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/version.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/version.go new file mode 100644 index 0000000000..0a2f99a1fa --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/version/version.go @@ -0,0 +1,81 @@ +// Copyright 2021 The etcd 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 version + +import ( + "context" + + "github.com/coreos/go-semver/semver" + "go.uber.org/zap" +) + +// Manager contains logic to manage etcd cluster version downgrade process. +type Manager struct { + lg *zap.Logger + s Server +} + +// NewManager returns a new manager instance +func NewManager(lg *zap.Logger, s Server) *Manager { + return &Manager{ + lg: lg, + s: s, + } +} + +// DowngradeValidate validates if cluster is downloadable to provided target version and returns error if not. +func (m *Manager) DowngradeValidate(ctx context.Context, targetVersion *semver.Version) error { + // gets leaders commit index and wait for local store to finish applying that index + // to avoid using stale downgrade information + err := m.s.LinearizableReadNotify(ctx) + if err != nil { + return err + } + cv := m.s.GetClusterVersion() + allowedTargetVersion := allowedDowngradeVersion(cv) + if !targetVersion.Equal(*allowedTargetVersion) { + return ErrInvalidDowngradeTargetVersion + } + + downgradeInfo := m.s.GetDowngradeInfo() + if downgradeInfo != nil && downgradeInfo.Enabled { + // Todo: return the downgrade status along with the error msg + return ErrDowngradeInProcess + } + return nil +} + +// DowngradeEnable initiates etcd cluster version downgrade process. +func (m *Manager) DowngradeEnable(ctx context.Context, targetVersion *semver.Version) error { + // validate downgrade capability before starting downgrade + err := m.DowngradeValidate(ctx, targetVersion) + if err != nil { + return err + } + return m.s.DowngradeEnable(ctx, targetVersion) +} + +// DowngradeCancel cancels ongoing downgrade process. +func (m *Manager) DowngradeCancel(ctx context.Context) error { + err := m.s.LinearizableReadNotify(ctx) + if err != nil { + return err + } + downgradeInfo := m.s.GetDowngradeInfo() + if !downgradeInfo.Enabled { + return ErrNoInflightDowngrade + } + return m.s.DowngradeCancel(ctx) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/zap_raft.go b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/zap_raft.go index e8174f396f..7672bdfbc4 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/zap_raft.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/zap_raft.go @@ -17,10 +17,10 @@ package etcdserver import ( "errors" - "go.etcd.io/etcd/raft/v3" - "go.uber.org/zap" "go.uber.org/zap/zapcore" + + "go.etcd.io/raft/v3" ) // NewRaftLogger builds "raft.Logger" from "*zap.Config". @@ -37,7 +37,8 @@ func NewRaftLogger(lcfg *zap.Config) (raft.Logger, error) { // NewRaftLoggerZap converts "*zap.Logger" to "raft.Logger". func NewRaftLoggerZap(lg *zap.Logger) raft.Logger { - return &zapRaftLogger{lg: lg, sugar: lg.Sugar()} + skipCallerLg := lg.WithOptions(zap.AddCallerSkip(1)) + return &zapRaftLogger{lg: skipCallerLg, sugar: skipCallerLg.Sugar()} } // NewRaftLoggerFromZapCore creates "raft.Logger" from "zap.Core" @@ -53,50 +54,50 @@ type zapRaftLogger struct { sugar *zap.SugaredLogger } -func (zl *zapRaftLogger) Debug(args ...interface{}) { +func (zl *zapRaftLogger) Debug(args ...any) { zl.sugar.Debug(args...) } -func (zl *zapRaftLogger) Debugf(format string, args ...interface{}) { +func (zl *zapRaftLogger) Debugf(format string, args ...any) { zl.sugar.Debugf(format, args...) } -func (zl *zapRaftLogger) Error(args ...interface{}) { +func (zl *zapRaftLogger) Error(args ...any) { zl.sugar.Error(args...) } -func (zl *zapRaftLogger) Errorf(format string, args ...interface{}) { +func (zl *zapRaftLogger) Errorf(format string, args ...any) { zl.sugar.Errorf(format, args...) } -func (zl *zapRaftLogger) Info(args ...interface{}) { +func (zl *zapRaftLogger) Info(args ...any) { zl.sugar.Info(args...) } -func (zl *zapRaftLogger) Infof(format string, args ...interface{}) { +func (zl *zapRaftLogger) Infof(format string, args ...any) { zl.sugar.Infof(format, args...) } -func (zl *zapRaftLogger) Warning(args ...interface{}) { +func (zl *zapRaftLogger) Warning(args ...any) { zl.sugar.Warn(args...) } -func (zl *zapRaftLogger) Warningf(format string, args ...interface{}) { +func (zl *zapRaftLogger) Warningf(format string, args ...any) { zl.sugar.Warnf(format, args...) } -func (zl *zapRaftLogger) Fatal(args ...interface{}) { +func (zl *zapRaftLogger) Fatal(args ...any) { zl.sugar.Fatal(args...) } -func (zl *zapRaftLogger) Fatalf(format string, args ...interface{}) { +func (zl *zapRaftLogger) Fatalf(format string, args ...any) { zl.sugar.Fatalf(format, args...) } -func (zl *zapRaftLogger) Panic(args ...interface{}) { +func (zl *zapRaftLogger) Panic(args ...any) { zl.sugar.Panic(args...) } -func (zl *zapRaftLogger) Panicf(format string, args ...interface{}) { +func (zl *zapRaftLogger) Panicf(format string, args ...any) { zl.sugar.Panicf(format, args...) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/features/etcd_features.go b/etcd/vendor/go.etcd.io/etcd/server/v3/features/etcd_features.go new file mode 100644 index 0000000000..230b37c703 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/features/etcd_features.go @@ -0,0 +1,108 @@ +// Copyright 2024 The etcd 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 features + +import ( + "fmt" + + "go.uber.org/zap" + + "go.etcd.io/etcd/pkg/v3/featuregate" +) + +const ( + // Every feature gate should add method here following this template: + // + // // owner: @username + // // kep: https://kep.k8s.io/NNN (or issue: https://github.com/etcd-io/etcd/issues/NNN, or main PR: https://github.com/etcd-io/etcd/pull/NNN) + // // alpha: v3.X + // MyFeature featuregate.Feature = "MyFeature" + // + // Feature gates should be listed in alphabetical, case-sensitive + // (upper before any lower case character) order. This reduces the risk + // of code conflicts because changes are more likely to be scattered + // across the file. + + // StopGRPCServiceOnDefrag enables etcd gRPC service to stop serving client requests on defragmentation. + // owner: @chaochn47 + // alpha: v3.6 + // main PR: https://github.com/etcd-io/etcd/pull/18279 + StopGRPCServiceOnDefrag featuregate.Feature = "StopGRPCServiceOnDefrag" + // TxnModeWriteWithSharedBuffer enables the write transaction to use a shared buffer in its readonly check operations. + // owner: @wilsonwang371 + // beta: v3.5 + // main PR: https://github.com/etcd-io/etcd/pull/12896 + TxnModeWriteWithSharedBuffer featuregate.Feature = "TxnModeWriteWithSharedBuffer" + // InitialCorruptCheck enable to check data corruption before serving any client/peer traffic. + // owner: @serathius + // alpha: v3.6 + // main PR: https://github.com/etcd-io/etcd/pull/10524 + InitialCorruptCheck featuregate.Feature = "InitialCorruptCheck" + // CompactHashCheck enables leader to periodically check followers compaction hashes. + // owner: @serathius + // alpha: v3.6 + // main PR: https://github.com/etcd-io/etcd/pull/14120 + CompactHashCheck featuregate.Feature = "CompactHashCheck" + // LeaseCheckpoint enables leader to send regular checkpoints to other members to prevent reset of remaining TTL on leader change. + // owner: @serathius + // alpha: v3.6 + // main PR: https://github.com/etcd-io/etcd/pull/13508 + LeaseCheckpoint featuregate.Feature = "LeaseCheckpoint" + // LeaseCheckpointPersist enables persisting remainingTTL to prevent indefinite auto-renewal of long lived leases. Always enabled in v3.6. Should be used to ensure smooth upgrade from v3.5 clusters with this feature enabled. + // Requires EnableLeaseCheckpoint featuragate to be enabled. + // TODO: Delete in v3.7 + // owner: @serathius + // alpha: v3.6 + // main PR: https://github.com/etcd-io/etcd/pull/13508 + // Deprecated: Enabled by default in v3.6, to be removed in v3.7. + LeaseCheckpointPersist featuregate.Feature = "LeaseCheckpointPersist" + // SetMemberLocalAddr enables using the first specified and non-loopback local address from initial-advertise-peer-urls as the local address when communicating with a peer. + // Requires SetMemberLocalAddr featuragate to be enabled. + // owner: @flawedmatrix + // alpha: v3.6 + // main PR: https://github.com/etcd-io/etcd/pull/17661 + SetMemberLocalAddr featuregate.Feature = "SetMemberLocalAddr" +) + +var ( + DefaultEtcdServerFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{ + StopGRPCServiceOnDefrag: {Default: false, PreRelease: featuregate.Alpha}, + InitialCorruptCheck: {Default: false, PreRelease: featuregate.Alpha}, + CompactHashCheck: {Default: false, PreRelease: featuregate.Alpha}, + TxnModeWriteWithSharedBuffer: {Default: true, PreRelease: featuregate.Beta}, + LeaseCheckpoint: {Default: false, PreRelease: featuregate.Alpha}, + LeaseCheckpointPersist: {Default: false, PreRelease: featuregate.Alpha}, + SetMemberLocalAddr: {Default: false, PreRelease: featuregate.Alpha}, + } + // ExperimentalFlagToFeatureMap is the map from the cmd line flags of experimental features + // to their corresponding feature gates. + // Deprecated: Only add existing experimental features here. DO NOT use for new features. + ExperimentalFlagToFeatureMap = map[string]featuregate.Feature{ + "experimental-stop-grpc-service-on-defrag": StopGRPCServiceOnDefrag, + "experimental-initial-corrupt-check": InitialCorruptCheck, + "experimental-compact-hash-check-enabled": CompactHashCheck, + "experimental-txn-mode-write-with-shared-buffer": TxnModeWriteWithSharedBuffer, + "experimental-enable-lease-checkpoint": LeaseCheckpoint, + "experimental-enable-lease-checkpoint-persist": LeaseCheckpointPersist, + } +) + +func NewDefaultServerFeatureGate(name string, lg *zap.Logger) featuregate.FeatureGate { + fg := featuregate.New(fmt.Sprintf("%sServerFeatureGate", name), lg) + if err := fg.Add(DefaultEtcdServerFeatureGates); err != nil { + panic(err) + } + return fg +} diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/README.md b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/README.md similarity index 94% rename from etcd/vendor/go.etcd.io/etcd/client/v2/README.md rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/README.md index 5ecb67820f..ff070c72db 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/README.md +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/README.md @@ -18,11 +18,11 @@ go get go.etcd.io/etcd/v3/client package main import ( - "log" - "time" - "context" - - "go.etcd.io/etcd/v3/client" + "context" + "log" + "time" + + "go.etcd.io/etcd/v3/client" ) func main() { @@ -88,11 +88,12 @@ if err != nil { kapi := client.NewKeysAPI(c) resp, err := kapi.Set(ctx, "test", "bar", nil) if err != nil { - if err == context.Canceled { + var cerr *client.ClusterError + if errors.Is(err, context.Canceled) { // ctx is canceled by another routine - } else if err == context.DeadlineExceeded { + } else if errors.Is(err, context.DeadlineExceeded) { // ctx is attached with a deadline and it exceeded - } else if cerr, ok := err.(*client.ClusterError); ok { + } else if errors.As(err, &cerr) { // process (cerr.Errors) } else { // bad cluster endpoints, which are not etcd servers diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/auth_role.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/auth_role.go similarity index 96% rename from etcd/vendor/go.etcd.io/etcd/client/v2/auth_role.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/auth_role.go index b6ba7e150d..b9ef1aae84 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/auth_role.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/auth_role.go @@ -88,7 +88,7 @@ type authRoleAPIList struct{} func (list *authRoleAPIList) HTTPRequest(ep url.URL) *http.Request { u := v2AuthURL(ep, "roles", "") - req, _ := http.NewRequest("GET", u.String(), nil) + req, _ := http.NewRequest(http.MethodGet, u.String(), nil) req.Header.Set("Content-Type", "application/json") return req } @@ -135,7 +135,7 @@ func (r *httpAuthRoleAPI) AddRole(ctx context.Context, rolename string) error { Role: rolename, } return r.addRemoveRole(ctx, &authRoleAPIAction{ - verb: "PUT", + verb: http.MethodPut, name: rolename, role: role, }) @@ -143,7 +143,7 @@ func (r *httpAuthRoleAPI) AddRole(ctx context.Context, rolename string) error { func (r *httpAuthRoleAPI) RemoveRole(ctx context.Context, rolename string) error { return r.addRemoveRole(ctx, &authRoleAPIAction{ - verb: "DELETE", + verb: http.MethodDelete, name: rolename, }) } @@ -166,7 +166,7 @@ func (r *httpAuthRoleAPI) addRemoveRole(ctx context.Context, req *authRoleAPIAct func (r *httpAuthRoleAPI) GetRole(ctx context.Context, rolename string) (*Role, error) { return r.modRole(ctx, &authRoleAPIAction{ - verb: "GET", + verb: http.MethodGet, name: rolename, }) } @@ -194,7 +194,7 @@ func (r *httpAuthRoleAPI) GrantRoleKV(ctx context.Context, rolename string, pref }, } return r.modRole(ctx, &authRoleAPIAction{ - verb: "PUT", + verb: http.MethodPut, name: rolename, role: role, }) @@ -209,7 +209,7 @@ func (r *httpAuthRoleAPI) RevokeRoleKV(ctx context.Context, rolename string, pre }, } return r.modRole(ctx, &authRoleAPIAction{ - verb: "PUT", + verb: http.MethodPut, name: rolename, role: role, }) diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/auth_user.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/auth_user.go similarity index 94% rename from etcd/vendor/go.etcd.io/etcd/client/v2/auth_user.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/auth_user.go index 8e7e2efe83..75b636c020 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/auth_user.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/auth_user.go @@ -23,9 +23,7 @@ import ( "path" ) -var ( - defaultV2AuthPrefix = "/v2/auth" -) +var defaultV2AuthPrefix = "/v2/auth" type User struct { User string `json:"user"` @@ -76,11 +74,11 @@ type httpAuthAPI struct { } func (s *httpAuthAPI) Enable(ctx context.Context) error { - return s.enableDisable(ctx, &authAPIAction{"PUT"}) + return s.enableDisable(ctx, &authAPIAction{http.MethodPut}) } func (s *httpAuthAPI) Disable(ctx context.Context) error { - return s.enableDisable(ctx, &authAPIAction{"DELETE"}) + return s.enableDisable(ctx, &authAPIAction{http.MethodDelete}) } func (s *httpAuthAPI) enableDisable(ctx context.Context, req httpAction) error { @@ -163,7 +161,7 @@ type authUserAPIList struct{} func (list *authUserAPIList) HTTPRequest(ep url.URL) *http.Request { u := v2AuthURL(ep, "users", "") - req, _ := http.NewRequest("GET", u.String(), nil) + req, _ := http.NewRequest(http.MethodGet, u.String(), nil) req.Header.Set("Content-Type", "application/json") return req } @@ -219,7 +217,7 @@ func (u *httpAuthUserAPI) AddUser(ctx context.Context, username string, password Password: password, } return u.addRemoveUser(ctx, &authUserAPIAction{ - verb: "PUT", + verb: http.MethodPut, username: username, user: user, }) @@ -227,7 +225,7 @@ func (u *httpAuthUserAPI) AddUser(ctx context.Context, username string, password func (u *httpAuthUserAPI) RemoveUser(ctx context.Context, username string) error { return u.addRemoveUser(ctx, &authUserAPIAction{ - verb: "DELETE", + verb: http.MethodDelete, username: username, }) } @@ -250,7 +248,7 @@ func (u *httpAuthUserAPI) addRemoveUser(ctx context.Context, req *authUserAPIAct func (u *httpAuthUserAPI) GetUser(ctx context.Context, username string) (*User, error) { return u.modUser(ctx, &authUserAPIAction{ - verb: "GET", + verb: http.MethodGet, username: username, }) } @@ -261,7 +259,7 @@ func (u *httpAuthUserAPI) GrantUser(ctx context.Context, username string, roles Grant: roles, } return u.modUser(ctx, &authUserAPIAction{ - verb: "PUT", + verb: http.MethodPut, username: username, user: user, }) @@ -273,7 +271,7 @@ func (u *httpAuthUserAPI) RevokeUser(ctx context.Context, username string, roles Revoke: roles, } return u.modUser(ctx, &authUserAPIAction{ - verb: "PUT", + verb: http.MethodPut, username: username, user: user, }) @@ -285,7 +283,7 @@ func (u *httpAuthUserAPI) ChangePassword(ctx context.Context, username string, p Password: password, } return u.modUser(ctx, &authUserAPIAction{ - verb: "PUT", + verb: http.MethodPut, username: username, user: user, }) diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/cancelreq.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/cancelreq.go similarity index 81% rename from etcd/vendor/go.etcd.io/etcd/client/v2/cancelreq.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/cancelreq.go index 76d1f04019..23e5f89f6b 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/cancelreq.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/cancelreq.go @@ -8,7 +8,7 @@ package client import "net/http" -func requestCanceler(tr CancelableTransport, req *http.Request) func() { +func requestCanceler(req *http.Request) func() { ch := make(chan struct{}) req.Cancel = ch diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/client.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/client.go similarity index 97% rename from etcd/vendor/go.etcd.io/etcd/client/v2/client.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/client.go index fda25988f6..598c2deb75 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/client.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/client.go @@ -19,7 +19,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "math/rand" "net" "net/http" @@ -41,7 +41,7 @@ var ( // oneShotCtxValue is set on a context using WithValue(&oneShotValue) so // that Do() will not retry a request - oneShotCtxValue interface{} + oneShotCtxValue any ) var DefaultRequestTimeout = 5 * time.Second @@ -365,10 +365,10 @@ func (c *httpClusterClient) Do(ctx context.Context, act httpAction) (*http.Respo resp, body, err = hc.Do(ctx, action) if err != nil { cerr.Errors = append(cerr.Errors, err) - if err == ctx.Err() { + if errors.Is(err, ctx.Err()) { return nil, nil, ctx.Err() } - if err == context.Canceled || err == context.DeadlineExceeded { + if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { return nil, nil, err } } else if resp.StatusCode/100 == 5 { @@ -542,7 +542,7 @@ func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Respon var err error isWait, err = strconv.ParseBool(ws) if err != nil { - return nil, nil, fmt.Errorf("wrong wait value %s (%v for %+v)", ws, err, req) + return nil, nil, fmt.Errorf("wrong wait value %s (%w for %+v)", ws, err, req) } } } @@ -556,7 +556,7 @@ func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Respon } defer hcancel() - reqcancel := requestCanceler(c.transport, req) + reqcancel := requestCanceler(req) rtchan := make(chan roundTripResponse, 1) go func() { @@ -601,13 +601,15 @@ func (c *simpleHTTPClient) Do(ctx context.Context, act httpAction) (*http.Respon var body []byte done := make(chan struct{}) go func() { - body, err = ioutil.ReadAll(resp.Body) + body, err = io.ReadAll(resp.Body) done <- struct{}{} }() select { case <-ctx.Done(): - resp.Body.Close() + if resp != nil { + resp.Body.Close() + } <-done return nil, nil, ctx.Err() case <-done: @@ -647,7 +649,7 @@ func (r *redirectFollowingHTTPClient) Do(ctx context.Context, act httpAction) (* if resp.StatusCode/100 == 3 { hdr := resp.Header.Get("Location") if hdr == "" { - return nil, nil, fmt.Errorf("location header not set") + return nil, nil, errors.New("location header not set") } loc, err := url.Parse(hdr) if err != nil { diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/cluster_error.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/cluster_error.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/client/v2/cluster_error.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/cluster_error.go diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/curl.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/curl.go similarity index 88% rename from etcd/vendor/go.etcd.io/etcd/client/v2/curl.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/curl.go index c8bc9fba20..5d5dc57caf 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/curl.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/curl.go @@ -17,14 +17,12 @@ package client import ( "bytes" "fmt" - "io/ioutil" + "io" "net/http" "os" ) -var ( - cURLDebug = false -) +var cURLDebug = false func EnablecURLDebug() { cURLDebug = true @@ -53,18 +51,18 @@ func printcURL(req *http.Request) error { } if req.Body != nil { - b, err = ioutil.ReadAll(req.Body) + b, err = io.ReadAll(req.Body) if err != nil { return err } command += fmt.Sprintf(" -d %q", string(b)) } - fmt.Fprintf(os.Stderr, "cURL Command: %s\n", command) + fmt.Fprintf(os.Stderr, "cURL Command: %q\n", command) // reset body body := bytes.NewBuffer(b) - req.Body = ioutil.NopCloser(body) + req.Body = io.NopCloser(body) return nil } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/discover.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/discover.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/client/v2/discover.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/discover.go diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/doc.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/doc.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/client/v2/doc.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/doc.go diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/keys.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/keys.go similarity index 97% rename from etcd/vendor/go.etcd.io/etcd/client/v2/keys.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/keys.go index e8f1664617..87783cd30e 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/keys.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/keys.go @@ -25,6 +25,8 @@ import ( "strings" "time" + kjson "sigs.k8s.io/json" + "go.etcd.io/etcd/client/pkg/v3/pathutil" ) @@ -77,9 +79,7 @@ const ( PrevNoExist = PrevExistType("false") ) -var ( - defaultV2KeysPrefix = "/v2/keys" -) +var defaultV2KeysPrefix = "/v2/keys" // NewKeysAPI builds a KeysAPI that interacts with etcd's key-value // API over HTTP. @@ -457,7 +457,7 @@ func (hw *httpWatcher) Next(ctx context.Context) (*Response, error) { resp, err := unmarshalHTTPResponse(httpresp.StatusCode, httpresp.Header, body) if err != nil { - if err == ErrEmptyBody { + if errors.Is(err, ErrEmptyBody) { continue } return nil, err @@ -504,7 +504,7 @@ func (g *getAction) HTTPRequest(ep url.URL) *http.Request { params.Set("quorum", strconv.FormatBool(g.Quorum)) u.RawQuery = params.Encode() - req, _ := http.NewRequest("GET", u.String(), nil) + req, _ := http.NewRequest(http.MethodGet, u.String(), nil) return req } @@ -524,7 +524,7 @@ func (w *waitAction) HTTPRequest(ep url.URL) *http.Request { params.Set("recursive", strconv.FormatBool(w.Recursive)) u.RawQuery = params.Encode() - req, _ := http.NewRequest("GET", u.String(), nil) + req, _ := http.NewRequest(http.MethodGet, u.String(), nil) return req } @@ -579,7 +579,7 @@ func (a *setAction) HTTPRequest(ep url.URL) *http.Request { u.RawQuery = params.Encode() body := strings.NewReader(form.Encode()) - req, _ := http.NewRequest("PUT", u.String(), body) + req, _ := http.NewRequest(http.MethodPut, u.String(), body) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") return req @@ -612,7 +612,7 @@ func (a *deleteAction) HTTPRequest(ep url.URL) *http.Request { } u.RawQuery = params.Encode() - req, _ := http.NewRequest("DELETE", u.String(), nil) + req, _ := http.NewRequest(http.MethodDelete, u.String(), nil) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") return req @@ -635,7 +635,7 @@ func (a *createInOrderAction) HTTPRequest(ep url.URL) *http.Request { } body := strings.NewReader(form.Encode()) - req, _ := http.NewRequest("POST", u.String(), body) + req, _ := http.NewRequest(http.MethodPost, u.String(), body) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") return req } @@ -653,11 +653,9 @@ func unmarshalHTTPResponse(code int, header http.Header, body []byte) (res *Resp return res, err } -var jsonIterator = caseSensitiveJsonIterator() - func unmarshalSuccessfulKeysResponse(header http.Header, body []byte) (*Response, error) { var res Response - err := jsonIterator.Unmarshal(body, &res) + err := kjson.UnmarshalCaseSensitivePreserveInts(body, &res) if err != nil { return nil, ErrInvalidJSON } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/members.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/members.go similarity index 95% rename from etcd/vendor/go.etcd.io/etcd/client/v2/members.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/members.go index 5d638487c5..f53c2dbb2f 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/members.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/members.go @@ -130,7 +130,7 @@ func (m *httpMembersAPI) List(ctx context.Context) ([]Member, error) { return nil, err } - return []Member(mCollection), nil + return mCollection, nil } func (m *httpMembersAPI) Add(ctx context.Context, peerURL string) (*Member, error) { @@ -225,7 +225,7 @@ type membersAPIActionList struct{} func (l *membersAPIActionList) HTTPRequest(ep url.URL) *http.Request { u := v2MembersURL(ep) - req, _ := http.NewRequest("GET", u.String(), nil) + req, _ := http.NewRequest(http.MethodGet, u.String(), nil) return req } @@ -236,7 +236,7 @@ type membersAPIActionRemove struct { func (d *membersAPIActionRemove) HTTPRequest(ep url.URL) *http.Request { u := v2MembersURL(ep) u.Path = path.Join(u.Path, d.memberID) - req, _ := http.NewRequest("DELETE", u.String(), nil) + req, _ := http.NewRequest(http.MethodDelete, u.String(), nil) return req } @@ -248,7 +248,7 @@ func (a *membersAPIActionAdd) HTTPRequest(ep url.URL) *http.Request { u := v2MembersURL(ep) m := memberCreateOrUpdateRequest{PeerURLs: a.peerURLs} b, _ := json.Marshal(&m) - req, _ := http.NewRequest("POST", u.String(), bytes.NewReader(b)) + req, _ := http.NewRequest(http.MethodPost, u.String(), bytes.NewReader(b)) req.Header.Set("Content-Type", "application/json") return req } @@ -263,7 +263,7 @@ func (a *membersAPIActionUpdate) HTTPRequest(ep url.URL) *http.Request { m := memberCreateOrUpdateRequest{PeerURLs: a.peerURLs} u.Path = path.Join(u.Path, a.memberID) b, _ := json.Marshal(&m) - req, _ := http.NewRequest("PUT", u.String(), bytes.NewReader(b)) + req, _ := http.NewRequest(http.MethodPut, u.String(), bytes.NewReader(b)) req.Header.Set("Content-Type", "application/json") return req } @@ -282,7 +282,7 @@ type membersAPIActionLeader struct{} func (l *membersAPIActionLeader) HTTPRequest(ep url.URL) *http.Request { u := v2MembersURL(ep) u.Path = path.Join(u.Path, defaultLeaderSuffix) - req, _ := http.NewRequest("GET", u.String(), nil) + req, _ := http.NewRequest(http.MethodGet, u.String(), nil) return req } diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/util.go similarity index 80% rename from etcd/vendor/go.etcd.io/etcd/client/v2/util.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/util.go index 15a8babff4..76e4132c06 100644 --- a/etcd/vendor/go.etcd.io/etcd/client/v2/util.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/internal/clientv2/util.go @@ -15,6 +15,7 @@ package client import ( + "errors" "regexp" ) @@ -30,24 +31,18 @@ func init() { // IsKeyNotFound returns true if the error code is ErrorCodeKeyNotFound. func IsKeyNotFound(err error) bool { - if cErr, ok := err.(Error); ok { - return cErr.Code == ErrorCodeKeyNotFound - } - return false + var cErr Error + return errors.As(err, &cErr) && cErr.Code == ErrorCodeKeyNotFound } // IsRoleNotFound returns true if the error means role not found of v2 API. func IsRoleNotFound(err error) bool { - if ae, ok := err.(authError); ok { - return roleNotFoundRegExp.MatchString(ae.Message) - } - return false + var ae authError + return errors.As(err, &ae) && roleNotFoundRegExp.MatchString(ae.Message) } // IsUserNotFound returns true if the error means user not found of v2 API. func IsUserNotFound(err error) bool { - if ae, ok := err.(authError); ok { - return userNotFoundRegExp.MatchString(ae.Message) - } - return false + var ae authError + return errors.As(err, &ae) && userNotFoundRegExp.MatchString(ae.Message) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lease.go b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lease.go new file mode 100644 index 0000000000..8f194c9803 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lease.go @@ -0,0 +1,135 @@ +// Copyright 2022 The etcd 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 lease + +import ( + "math" + "sync" + "time" + + "go.etcd.io/etcd/server/v3/lease/leasepb" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" +) + +type Lease struct { + ID LeaseID + ttl int64 // time to live of the lease in seconds + remainingTTL int64 // remaining time to live in seconds, if zero valued it is considered unset and the full ttl should be used + // expiryMu protects concurrent accesses to expiry + expiryMu sync.RWMutex + // expiry is time when lease should expire. no expiration when expiry.IsZero() is true + expiry time.Time + + // mu protects concurrent accesses to itemSet + mu sync.RWMutex + itemSet map[LeaseItem]struct{} + revokec chan struct{} +} + +func NewLease(id LeaseID, ttl int64) *Lease { + return &Lease{ + ID: id, + ttl: ttl, + itemSet: make(map[LeaseItem]struct{}), + revokec: make(chan struct{}), + } +} + +func (l *Lease) expired() bool { + return l.Remaining() <= 0 +} + +func (l *Lease) persistTo(b backend.Backend) { + lpb := leasepb.Lease{ID: int64(l.ID), TTL: l.ttl, RemainingTTL: l.remainingTTL} + tx := b.BatchTx() + tx.LockInsideApply() + defer tx.Unlock() + schema.MustUnsafePutLease(tx, &lpb) +} + +// TTL returns the TTL of the Lease. +func (l *Lease) TTL() int64 { + return l.ttl +} + +// SetLeaseItem sets the given lease item, this func is thread-safe +func (l *Lease) SetLeaseItem(item LeaseItem) { + l.mu.Lock() + defer l.mu.Unlock() + l.itemSet[item] = struct{}{} +} + +// getRemainingTTL returns the last checkpointed remaining TTL of the lease. +func (l *Lease) getRemainingTTL() int64 { + if l.remainingTTL > 0 { + return l.remainingTTL + } + return l.ttl +} + +// refresh refreshes the expiry of the lease. +func (l *Lease) refresh(extend time.Duration) { + newExpiry := time.Now().Add(extend + time.Duration(l.getRemainingTTL())*time.Second) + l.expiryMu.Lock() + defer l.expiryMu.Unlock() + l.expiry = newExpiry +} + +// forever sets the expiry of lease to be forever. +func (l *Lease) forever() { + l.expiryMu.Lock() + defer l.expiryMu.Unlock() + l.expiry = forever +} + +// Demoted returns true if the lease's expiry has been reset to forever. +func (l *Lease) Demoted() bool { + l.expiryMu.RLock() + defer l.expiryMu.RUnlock() + return l.expiry == forever +} + +// Keys returns all the keys attached to the lease. +func (l *Lease) Keys() []string { + l.mu.RLock() + keys := make([]string, 0, len(l.itemSet)) + for k := range l.itemSet { + keys = append(keys, k.Key) + } + l.mu.RUnlock() + return keys +} + +// Remaining returns the remaining time of the lease. +func (l *Lease) Remaining() time.Duration { + l.expiryMu.RLock() + defer l.expiryMu.RUnlock() + if l.expiry.IsZero() { + return time.Duration(math.MaxInt64) + } + return time.Until(l.expiry) +} + +type LeaseItem struct { + Key string +} + +// leasesByExpiry implements the sort.Interface. +type leasesByExpiry []*Lease + +func (le leasesByExpiry) Len() int { return len(le) } +func (le leasesByExpiry) Less(i, j int) bool { return le[i].Remaining() < le[j].Remaining() } +func (le leasesByExpiry) Swap(i, j int) { le[i], le[j] = le[j], le[i] } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lease_queue.go b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lease_queue.go index ffb7285ec0..74ffee5c69 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lease_queue.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lease_queue.go @@ -42,14 +42,14 @@ func (pq LeaseQueue) Swap(i, j int) { pq[j].index = j } -func (pq *LeaseQueue) Push(x interface{}) { +func (pq *LeaseQueue) Push(x any) { n := len(*pq) item := x.(*LeaseWithTime) item.index = n *pq = append(*pq, item) } -func (pq *LeaseQueue) Pop() interface{} { +func (pq *LeaseQueue) Pop() any { old := *pq n := len(old) item := old[n-1] @@ -96,7 +96,7 @@ func (mq *LeaseExpiredNotifier) Unregister() *LeaseWithTime { return item } -func (mq *LeaseExpiredNotifier) Poll() *LeaseWithTime { +func (mq *LeaseExpiredNotifier) Peek() *LeaseWithTime { if mq.Len() == 0 { return nil } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasehttp/http.go b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasehttp/http.go index 9c815cbaec..d5572c3aaf 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasehttp/http.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasehttp/http.go @@ -19,7 +19,7 @@ import ( "context" "errors" "fmt" - "io/ioutil" + "io" "net/http" "time" @@ -47,13 +47,13 @@ type leaseHandler struct { } func (h *leaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if r.Method != "POST" { + if r.Method != http.MethodPost { http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } defer r.Body.Close() - b, err := ioutil.ReadAll(r.Body) + b, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "error reading body", http.StatusBadRequest) return @@ -75,7 +75,7 @@ func (h *leaseHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } ttl, rerr := h.l.Renew(lease.LeaseID(lreq.ID)) if rerr != nil { - if rerr == lease.ErrLeaseNotFound { + if errors.Is(rerr, lease.ErrLeaseNotFound) { http.Error(w, rerr.Error(), http.StatusNotFound) return } @@ -167,7 +167,7 @@ func RenewHTTP(ctx context.Context, id lease.LeaseID, url string, rt http.RoundT return http.ErrUseLastResponse }, } - req, err := http.NewRequest("POST", url, bytes.NewReader(lreq)) + req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(lreq)) if err != nil { return -1, err } @@ -192,12 +192,12 @@ func RenewHTTP(ctx context.Context, id lease.LeaseID, url string, rt http.RoundT } if resp.StatusCode != http.StatusOK { - return -1, fmt.Errorf("lease: unknown error(%s)", string(b)) + return -1, fmt.Errorf("lease: unknown error(%s)", b) } lresp := &pb.LeaseKeepAliveResponse{} if err := lresp.Unmarshal(b); err != nil { - return -1, fmt.Errorf(`lease: %v. data = "%s"`, err, string(b)) + return -1, fmt.Errorf(`lease: %w. data = "%s"`, err, b) } if lresp.ID != int64(id) { return -1, fmt.Errorf("lease: renew id mismatch") @@ -218,7 +218,7 @@ func TimeToLiveHTTP(ctx context.Context, id lease.LeaseID, keys bool, url string return nil, err } - req, err := http.NewRequest("POST", url, bytes.NewReader(lreq)) + req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(lreq)) if err != nil { return nil, err } @@ -254,16 +254,16 @@ func TimeToLiveHTTP(ctx context.Context, id lease.LeaseID, keys bool, url string lresp := &leasepb.LeaseInternalResponse{} if err := lresp.Unmarshal(b); err != nil { - return nil, fmt.Errorf(`lease: %v. data = "%s"`, err, string(b)) + return nil, fmt.Errorf(`lease: %w. data = "%s"`, err, string(b)) } if lresp.LeaseTimeToLiveResponse.ID != int64(id) { - return nil, fmt.Errorf("lease: renew id mismatch") + return nil, fmt.Errorf("lease: TTL id mismatch") } return lresp, nil } func readResponse(resp *http.Response) (b []byte, err error) { - b, err = ioutil.ReadAll(resp.Body) + b, err = io.ReadAll(resp.Body) httputil.GracefulClose(resp) return } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.pb.go b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.pb.go index 8a1c54922f..ee833d31a7 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.pb.go @@ -156,7 +156,7 @@ func init() { func init() { proto.RegisterFile("lease.proto", fileDescriptor_3dd57e402472b33a) } var fileDescriptor_3dd57e402472b33a = []byte{ - // 256 bytes of a gzipped FileDescriptorProto + // 283 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xce, 0x49, 0x4d, 0x2c, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x07, 0x73, 0x0a, 0x92, 0xa4, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x62, 0xfa, 0x20, 0x16, 0x44, 0x5a, 0x4a, 0x3e, 0xb5, 0x24, 0x39, 0x45, @@ -170,9 +170,11 @@ var fileDescriptor_3dd57e402472b33a = []byte{ 0x54, 0xa8, 0x0c, 0xd8, 0x46, 0x6e, 0x23, 0x15, 0x3d, 0x64, 0xf7, 0xe9, 0x61, 0x57, 0x1b, 0x84, 0xc3, 0x0c, 0xa5, 0x0a, 0x2e, 0x51, 0x34, 0x5b, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85, 0xe2, 0xb9, 0xc4, 0x31, 0xb4, 0x40, 0xa4, 0xa0, 0xf6, 0xaa, 0x12, 0xb0, 0x17, 0xa2, 0x38, 0x08, 0x97, - 0x29, 0x4e, 0x12, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0x70, 0xe2, 0x91, 0x1c, 0xe3, - 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0xce, 0x78, 0x2c, 0xc7, 0x90, 0xc4, 0x06, 0x0e, - 0x5f, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x8a, 0x94, 0xb9, 0xae, 0x01, 0x00, 0x00, + 0x29, 0x4e, 0x9e, 0x27, 0x1e, 0xca, 0x31, 0x5c, 0x78, 0x28, 0xc7, 0x70, 0xe2, 0x91, 0x1c, 0xe3, + 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0xce, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x9f, 0x9e, + 0x0f, 0x36, 0x5b, 0x2f, 0x33, 0x1f, 0x1c, 0xf6, 0xfa, 0x10, 0x4b, 0xf4, 0xcb, 0x8c, 0xf5, 0xc1, + 0x51, 0xa6, 0x0f, 0x8d, 0x38, 0x6b, 0x28, 0x9d, 0xc4, 0x06, 0x8e, 0x10, 0x63, 0x40, 0x00, 0x00, + 0x00, 0xff, 0xff, 0x0e, 0x16, 0x3b, 0xc4, 0xdf, 0x01, 0x00, 0x00, } func (m *Lease) Marshal() (dAtA []byte, err error) { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.proto b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.proto index 5b40e3b17b..d631797548 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.proto +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/leasepb/lease.proto @@ -4,6 +4,8 @@ package leasepb; import "gogoproto/gogo.proto"; import "etcd/api/etcdserverpb/rpc.proto"; +option go_package = "go.etcd.io/etcd/server/v3/lease/leasepb;leasepb"; + option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; option (gogoproto.unmarshaler_all) = true; diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lessor.go b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lessor.go index 99a4daf60d..b13974c9c9 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lessor.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/lessor.go @@ -17,9 +17,7 @@ package lease import ( "container/heap" "context" - "encoding/binary" "errors" - "fmt" "math" "sort" "sync" @@ -29,9 +27,10 @@ import ( "go.uber.org/zap" pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/version" "go.etcd.io/etcd/server/v3/lease/leasepb" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" ) // NoLease is a special LeaseID representing the absence of a lease. @@ -40,8 +39,6 @@ const NoLease = LeaseID(0) // MaxLeaseTTL is the maximum lease TTL value const MaxLeaseTTL = 9000000000 -var v3_6 = semver.Version{Major: 3, Minor: 6} - var ( forever = time.Time{} @@ -334,6 +331,7 @@ func (le *lessor) Revoke(id LeaseID) error { le.mu.Unlock() return ErrLeaseNotFound } + defer close(l.revokec) // unlock before doing external work le.mu.Unlock() @@ -358,7 +356,7 @@ func (le *lessor) Revoke(id LeaseID) error { // lease deletion needs to be in the same backend transaction with the // kv deletion. Or we might end up with not executing the revoke or not // deleting the keys if etcdserver fails in between. - le.b.BatchTx().UnsafeDelete(buckets.Lease, int64ToBytes(int64(l.ID))) + schema.UnsafeDeleteLease(le.b.BatchTx(), &leasepb.Lease{ID: int64(l.ID)}) txn.End() @@ -386,11 +384,11 @@ func (le *lessor) Checkpoint(id LeaseID, remainingTTL int64) error { func (le *lessor) shouldPersistCheckpoints() bool { cv := le.cluster.Version() - return le.checkpointPersist || (cv != nil && greaterOrEqual(*cv, v3_6)) + return le.checkpointPersist || (cv != nil && greaterOrEqual(*cv, version.V3_6)) } func greaterOrEqual(first, second semver.Version) bool { - return !first.LessThan(second) + return !version.LessThan(first, second) } // Renew renews an existing lease. If the given lease does not exist or @@ -430,6 +428,8 @@ func (le *lessor) Renew(id LeaseID) (int64, error) { } } + // gofail: var beforeCheckpointInLeaseRenew struct{} + // Clear remaining TTL when we renew if it is set // By applying a RAFT entry only when the remainingTTL is already set, we limit the number // of RAFT entries written per lease to a max of 2 per checkpoint interval. @@ -440,6 +440,12 @@ func (le *lessor) Renew(id LeaseID) (int64, error) { } le.mu.Lock() + // Re-check in case the lease was revoked immediately after the previous check + l = le.leaseMap[id] + if l == nil { + le.mu.Unlock() + return -1, ErrLeaseNotFound + } l.refresh(0) item := &LeaseWithTime{id: l.ID, time: l.expiry} le.leaseExpiredNotifier.RegisterOrUpdate(item) @@ -525,12 +531,6 @@ func (le *lessor) Promote(extend time.Duration) { } } -type leasesByExpiry []*Lease - -func (le leasesByExpiry) Len() int { return len(le) } -func (le leasesByExpiry) Less(i, j int) bool { return le[i].Remaining() < le[j].Remaining() } -func (le leasesByExpiry) Swap(i, j int) { le[i], le[j] = le[j], le[i] } - func (le *lessor) Demote() { le.mu.Lock() defer le.mu.Unlock() @@ -620,12 +620,15 @@ func (le *lessor) Stop() { func (le *lessor) runLoop() { defer close(le.doneC) + delayTicker := time.NewTicker(500 * time.Millisecond) + defer delayTicker.Stop() + for { le.revokeExpiredLeases() le.checkpointScheduledLeases() select { - case <-time.After(500 * time.Millisecond): + case <-delayTicker.C: case <-le.stopC: return } @@ -665,6 +668,7 @@ func (le *lessor) checkpointScheduledLeases() { // rate limit for i := 0; i < leaseCheckpointRate/2; i++ { var cps []*pb.LeaseCheckpoint + le.mu.Lock() if le.isPrimary() { cps = le.findDueScheduledCheckpoints(maxLeaseCheckpointBatchSize) @@ -690,33 +694,33 @@ func (le *lessor) clearLeaseExpiredNotifier() { le.leaseExpiredNotifier = newLeaseExpiredNotifier() } -// expireExists returns true if expiry items exist. +// expireExists returns "l" which is not nil if expiry items exist. // It pops only when expiry item exists. // "next" is true, to indicate that it may exist in next attempt. -func (le *lessor) expireExists() (l *Lease, ok bool, next bool) { +func (le *lessor) expireExists() (l *Lease, next bool) { if le.leaseExpiredNotifier.Len() == 0 { - return nil, false, false + return nil, false } - item := le.leaseExpiredNotifier.Poll() + item := le.leaseExpiredNotifier.Peek() l = le.leaseMap[item.id] if l == nil { // lease has expired or been revoked // no need to revoke (nothing is expiry) le.leaseExpiredNotifier.Unregister() // O(log N) - return nil, false, true + return nil, true } now := time.Now() if now.Before(item.time) /* item.time: expiration time */ { // Candidate expirations are caught up, reinsert this item // and no need to revoke (nothing is expiry) - return l, false, false + return nil, false } // recheck if revoke is complete after retry interval item.time = now.Add(le.expiredLeaseRetryInterval) le.leaseExpiredNotifier.RegisterOrUpdate(item) - return l, true, false + return l, false } // findExpiredLeases loops leases in the leaseMap until reaching expired limit @@ -725,13 +729,10 @@ func (le *lessor) findExpiredLeases(limit int) []*Lease { leases := make([]*Lease, 0, 16) for { - l, ok, next := le.expireExists() - if !ok && !next { + l, next := le.expireExists() + if l == nil && !next { break } - if !ok { - continue - } if next { continue } @@ -754,7 +755,7 @@ func (le *lessor) scheduleCheckpointIfNeeded(lease *Lease) { return } - if lease.RemainingTTL() > int64(le.checkpointInterval.Seconds()) { + if lease.getRemainingTTL() > int64(le.checkpointInterval.Seconds()) { if le.lg != nil { le.lg.Debug("Scheduling lease checkpoint", zap.Int64("leaseID", int64(lease.ID)), @@ -774,7 +775,7 @@ func (le *lessor) findDueScheduledCheckpoints(checkpointLimit int) []*pb.LeaseCh } now := time.Now() - cps := []*pb.LeaseCheckpoint{} + var cps []*pb.LeaseCheckpoint for le.leaseCheckpointHeap.Len() > 0 && len(cps) < checkpointLimit { lt := le.leaseCheckpointHeap[0] if lt.time.After(now) /* lt.time: next checkpoint time */ { @@ -806,10 +807,10 @@ func (le *lessor) findDueScheduledCheckpoints(checkpointLimit int) []*pb.LeaseCh func (le *lessor) initAndRecover() { tx := le.b.BatchTx() - tx.LockOutsideApply() - tx.UnsafeCreateBucket(buckets.Lease) - lpbs := unsafeGetAllLeases(tx) + tx.LockOutsideApply() + schema.UnsafeCreateLeaseBucket(tx) + lpbs := schema.MustUnsafeGetAllLeases(tx) tx.Unlock() for _, lpb := range lpbs { ID := LeaseID(lpb.ID) @@ -833,155 +834,20 @@ func (le *lessor) initAndRecover() { le.b.ForceCommit() } -type Lease struct { - ID LeaseID - ttl int64 // time to live of the lease in seconds - remainingTTL int64 // remaining time to live in seconds, if zero valued it is considered unset and the full ttl should be used - // expiryMu protects concurrent accesses to expiry - expiryMu sync.RWMutex - // expiry is time when lease should expire. no expiration when expiry.IsZero() is true - expiry time.Time - - // mu protects concurrent accesses to itemSet - mu sync.RWMutex - itemSet map[LeaseItem]struct{} - revokec chan struct{} -} - -func NewLease(id LeaseID, ttl int64) *Lease { - return &Lease{ - ID: id, - ttl: ttl, - itemSet: make(map[LeaseItem]struct{}), - revokec: make(chan struct{}), - } -} - -func (l *Lease) expired() bool { - return l.Remaining() <= 0 -} - -func (l *Lease) persistTo(b backend.Backend) { - key := int64ToBytes(int64(l.ID)) - - lpb := leasepb.Lease{ID: int64(l.ID), TTL: l.ttl, RemainingTTL: l.remainingTTL} - val, err := lpb.Marshal() - if err != nil { - panic("failed to marshal lease proto item") - } - - b.BatchTx().LockInsideApply() - b.BatchTx().UnsafePut(buckets.Lease, key, val) - b.BatchTx().Unlock() -} - -// TTL returns the TTL of the Lease. -func (l *Lease) TTL() int64 { - return l.ttl -} - -// SetLeaseItem sets the given lease item, this func is thread-safe -func (l *Lease) SetLeaseItem(item LeaseItem) { - l.mu.Lock() - defer l.mu.Unlock() - l.itemSet[item] = struct{}{} -} - -// RemainingTTL returns the last checkpointed remaining TTL of the lease. -// TODO(jpbetz): do not expose this utility method -func (l *Lease) RemainingTTL() int64 { - if l.remainingTTL > 0 { - return l.remainingTTL - } - return l.ttl -} - -// refresh refreshes the expiry of the lease. -func (l *Lease) refresh(extend time.Duration) { - newExpiry := time.Now().Add(extend + time.Duration(l.RemainingTTL())*time.Second) - l.expiryMu.Lock() - defer l.expiryMu.Unlock() - l.expiry = newExpiry -} - -// forever sets the expiry of lease to be forever. -func (l *Lease) forever() { - l.expiryMu.Lock() - defer l.expiryMu.Unlock() - l.expiry = forever -} - -// Demoted returns true if the lease's expiry has been reset to forever. -func (l *Lease) Demoted() bool { - l.expiryMu.RLock() - defer l.expiryMu.RUnlock() - return l.expiry == forever -} - -// Keys returns all the keys attached to the lease. -func (l *Lease) Keys() []string { - l.mu.RLock() - keys := make([]string, 0, len(l.itemSet)) - for k := range l.itemSet { - keys = append(keys, k.Key) - } - l.mu.RUnlock() - return keys -} - -// Remaining returns the remaining time of the lease. -func (l *Lease) Remaining() time.Duration { - l.expiryMu.RLock() - defer l.expiryMu.RUnlock() - if l.expiry.IsZero() { - return time.Duration(math.MaxInt64) - } - return time.Until(l.expiry) -} - -type LeaseItem struct { - Key string -} - -func int64ToBytes(n int64) []byte { - bytes := make([]byte, 8) - binary.BigEndian.PutUint64(bytes, uint64(n)) - return bytes -} - -func bytesToLeaseID(bytes []byte) int64 { - if len(bytes) != 8 { - panic(fmt.Errorf("lease ID must be 8-byte")) - } - return int64(binary.BigEndian.Uint64(bytes)) -} - -func unsafeGetAllLeases(tx backend.ReadTx) []*leasepb.Lease { - ls := make([]*leasepb.Lease, 0) - err := tx.UnsafeForEach(buckets.Lease, func(k, v []byte) error { - var lpb leasepb.Lease - err := lpb.Unmarshal(v) - if err != nil { - return fmt.Errorf("failed to Unmarshal lease proto item; lease ID=%016x", bytesToLeaseID(k)) - } - ls = append(ls, &lpb) - return nil - }) - if err != nil { - panic(err) - } - return ls -} - // FakeLessor is a fake implementation of Lessor interface. // Used for testing only. -type FakeLessor struct{} +type FakeLessor struct { + LeaseSet map[LeaseID]struct{} +} func (fl *FakeLessor) SetRangeDeleter(dr RangeDeleter) {} func (fl *FakeLessor) SetCheckpointer(cp Checkpointer) {} -func (fl *FakeLessor) Grant(id LeaseID, ttl int64) (*Lease, error) { return nil, nil } +func (fl *FakeLessor) Grant(id LeaseID, ttl int64) (*Lease, error) { + fl.LeaseSet[id] = struct{}{} + return nil, nil +} func (fl *FakeLessor) Revoke(id LeaseID) error { return nil } @@ -998,7 +864,12 @@ func (fl *FakeLessor) Demote() {} func (fl *FakeLessor) Renew(id LeaseID) (int64, error) { return 10, nil } -func (fl *FakeLessor) Lookup(id LeaseID) *Lease { return nil } +func (fl *FakeLessor) Lookup(id LeaseID) *Lease { + if _, ok := fl.LeaseSet[id]; ok { + return &Lease{ID: id} + } + return nil +} func (fl *FakeLessor) Leases() []*Lease { return nil } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/metrics.go index 06f8b58015..e38105e86f 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/lease/metrics.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/lease/metrics.go @@ -48,7 +48,8 @@ var ( Help: "Bucketed histogram of lease TTLs.", // 1 second -> 3 months Buckets: prometheus.ExponentialBuckets(1, 2, 24), - }) + }, + ) ) func init() { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/verify.go b/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/verify.go deleted file mode 100644 index a6a0b8675e..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/verify.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2022 The etcd 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 backend - -import ( - "os" - "runtime/debug" - "strings" - - "go.uber.org/zap" -) - -const ( - ENV_VERIFY = "ETCD_VERIFY" - ENV_VERIFY_ALL_VALUE = "all" - ENV_VERIFY_LOCK = "lock" -) - -func ValidateCalledInsideApply(lg *zap.Logger) { - if !verifyLockEnabled() { - return - } - if !insideApply() { - lg.Panic("Called outside of APPLY!", zap.Stack("stacktrace")) - } -} - -func ValidateCalledOutSideApply(lg *zap.Logger) { - if !verifyLockEnabled() { - return - } - if insideApply() { - lg.Panic("Called inside of APPLY!", zap.Stack("stacktrace")) - } -} - -func ValidateCalledInsideUnittest(lg *zap.Logger) { - if !verifyLockEnabled() { - return - } - if !insideUnittest() { - lg.Fatal("Lock called outside of unit test!", zap.Stack("stacktrace")) - } -} - -func verifyLockEnabled() bool { - return os.Getenv(ENV_VERIFY) == ENV_VERIFY_ALL_VALUE || os.Getenv(ENV_VERIFY) == ENV_VERIFY_LOCK -} - -func insideApply() bool { - stackTraceStr := string(debug.Stack()) - return strings.Contains(stackTraceStr, ".applyEntries") -} - -func insideUnittest() bool { - stackTraceStr := string(debug.Stack()) - return strings.Contains(stackTraceStr, "_test.go") && !strings.Contains(stackTraceStr, "tests/") -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/revision.go b/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/revision.go deleted file mode 100644 index d6213866f2..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/revision.go +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2015 The etcd 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 mvcc - -import "encoding/binary" - -// revBytesLen is the byte length of a normal revision. -// First 8 bytes is the revision.main in big-endian format. The 9th byte -// is a '_'. The last 8 bytes is the revision.sub in big-endian format. -const revBytesLen = 8 + 1 + 8 - -// A revision indicates modification of the key-value space. -// The set of changes that share same main revision changes the key-value space atomically. -type revision struct { - // main is the main revision of a set of changes that happen atomically. - main int64 - - // sub is the sub revision of a change in a set of changes that happen - // atomically. Each change has different increasing sub revision in that - // set. - sub int64 -} - -func (a revision) GreaterThan(b revision) bool { - if a.main > b.main { - return true - } - if a.main < b.main { - return false - } - return a.sub > b.sub -} - -func newRevBytes() []byte { - return make([]byte, revBytesLen, markedRevBytesLen) -} - -func revToBytes(rev revision, bytes []byte) { - binary.BigEndian.PutUint64(bytes, uint64(rev.main)) - bytes[8] = '_' - binary.BigEndian.PutUint64(bytes[9:], uint64(rev.sub)) -} - -func bytesToRev(bytes []byte) revision { - return revision{ - main: int64(binary.BigEndian.Uint64(bytes[0:8])), - sub: int64(binary.BigEndian.Uint64(bytes[9:])), - } -} - -type revisions []revision - -func (a revisions) Len() int { return len(a) } -func (a revisions) Less(i, j int) bool { return a[j].GreaterThan(a[i]) } -func (a revisions) Swap(i, j int) { a[i], a[j] = a[j], a[i] } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/util.go deleted file mode 100644 index ea3111267b..0000000000 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/util.go +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2016 The etcd 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 mvcc - -import ( - "fmt" - - "go.etcd.io/etcd/api/v3/mvccpb" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" -) - -func WriteKV(be backend.Backend, kv mvccpb.KeyValue) { - ibytes := newRevBytes() - revToBytes(revision{main: kv.ModRevision}, ibytes) - - d, err := kv.Marshal() - if err != nil { - panic(fmt.Errorf("cannot marshal event: %v", err)) - } - - be.BatchTx().LockOutsideApply() - be.BatchTx().UnsafePut(buckets.Key, ibytes, d) - be.BatchTx().Unlock() -} - -func UnsafeSetScheduledCompact(tx backend.BatchTx, value int64) { - rbytes := newRevBytes() - revToBytes(revision{main: value}, rbytes) - tx.UnsafePut(buckets.Meta, scheduledCompactKeyName, rbytes) -} - -func UnsafeReadFinishedCompact(tx backend.ReadTx) (int64, bool) { - _, finishedCompactBytes := tx.UnsafeRange(buckets.Meta, finishedCompactKeyName, nil, 0) - if len(finishedCompactBytes) != 0 { - return bytesToRev(finishedCompactBytes[0]).main, true - } - return 0, false -} - -func UnsafeReadScheduledCompact(tx backend.ReadTx) (int64, bool) { - _, scheduledCompactBytes := tx.UnsafeRange(buckets.Meta, scheduledCompactKeyName, nil, 0) - if len(scheduledCompactBytes) != 0 { - return bytesToRev(scheduledCompactBytes[0]).main, true - } - return 0, false -} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/auth_client_adapter.go b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/auth_client_adapter.go index 140212b962..0baa10c5f1 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/auth_client_adapter.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/auth_client_adapter.go @@ -17,9 +17,9 @@ package adapter import ( "context" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - grpc "google.golang.org/grpc" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) type as2ac struct{ as pb.AuthServer } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/chan_stream.go b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/chan_stream.go index 1af514b1fd..802c841d3d 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/chan_stream.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/chan_stream.go @@ -16,6 +16,7 @@ package adapter import ( "context" + "maps" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -38,9 +39,7 @@ func (ss *chanServerStream) SendHeader(md metadata.MD) error { } outmd := make(map[string][]string) for _, h := range append(ss.headers, md) { - for k, v := range h { - outmd[k] = v - } + maps.Copy(outmd, h) } select { case ss.headerc <- outmd: @@ -96,15 +95,15 @@ func (cs *chanClientStream) CloseSend() error { // chanStream implements grpc.Stream using channels type chanStream struct { - recvc <-chan interface{} - sendc chan<- interface{} + recvc <-chan any + sendc chan<- any ctx context.Context cancel context.CancelFunc } func (s *chanStream) Context() context.Context { return s.ctx } -func (s *chanStream) SendMsg(m interface{}) error { +func (s *chanStream) SendMsg(m any) error { select { case s.sendc <- m: if err, ok := m.(error); ok { @@ -116,8 +115,8 @@ func (s *chanStream) SendMsg(m interface{}) error { return s.ctx.Err() } -func (s *chanStream) RecvMsg(m interface{}) error { - v := m.(*interface{}) +func (s *chanStream) RecvMsg(m any) error { + v := m.(*any) for { select { case msg, ok := <-s.recvc: @@ -141,7 +140,7 @@ func (s *chanStream) RecvMsg(m interface{}) error { func newPipeStream(ctx context.Context, ssHandler func(chanServerStream) error) chanClientStream { // ch1 is buffered so server can send error on close - ch1, ch2 := make(chan interface{}, 1), make(chan interface{}) + ch1, ch2 := make(chan any, 1), make(chan any) headerc, trailerc := make(chan metadata.MD, 1), make(chan metadata.MD, 1) cctx, ccancel := context.WithCancel(ctx) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/cluster_client_adapter.go b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/cluster_client_adapter.go index c1fff054de..4c9fbbb082 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/cluster_client_adapter.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/cluster_client_adapter.go @@ -17,9 +17,9 @@ package adapter import ( "context" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "google.golang.org/grpc" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) type cls2clc struct{ cls pb.ClusterServer } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/election_client_adapter.go b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/election_client_adapter.go index 81d7434474..c7edaf70a4 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/election_client_adapter.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/election_client_adapter.go @@ -17,9 +17,9 @@ package adapter import ( "context" - "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb" - "google.golang.org/grpc" + + "go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb" ) type es2ec struct{ es v3electionpb.ElectionServer } @@ -60,8 +60,9 @@ type es2ecServerStream struct{ chanServerStream } func (s *es2ecClientStream) Send(rr *v3electionpb.LeaderRequest) error { return s.SendMsg(rr) } + func (s *es2ecClientStream) Recv() (*v3electionpb.LeaderResponse, error) { - var v interface{} + var v any if err := s.RecvMsg(&v); err != nil { return nil, err } @@ -71,8 +72,9 @@ func (s *es2ecClientStream) Recv() (*v3electionpb.LeaderResponse, error) { func (s *es2ecServerStream) Send(rr *v3electionpb.LeaderResponse) error { return s.SendMsg(rr) } + func (s *es2ecServerStream) Recv() (*v3electionpb.LeaderRequest, error) { - var v interface{} + var v any if err := s.RecvMsg(&v); err != nil { return nil, err } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/kv_client_adapter.go b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/kv_client_adapter.go index ddb6ada473..69e3a113c4 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/kv_client_adapter.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/kv_client_adapter.go @@ -17,9 +17,9 @@ package adapter import ( "context" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - grpc "google.golang.org/grpc" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) type kvs2kvc struct{ kvs pb.KVServer } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lease_client_adapter.go b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lease_client_adapter.go index 6640d1d39e..bf76a5563e 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lease_client_adapter.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lease_client_adapter.go @@ -17,9 +17,9 @@ package adapter import ( "context" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "google.golang.org/grpc" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) type ls2lc struct { @@ -62,8 +62,9 @@ type ls2lcServerStream struct{ chanServerStream } func (s *ls2lcClientStream) Send(rr *pb.LeaseKeepAliveRequest) error { return s.SendMsg(rr) } + func (s *ls2lcClientStream) Recv() (*pb.LeaseKeepAliveResponse, error) { - var v interface{} + var v any if err := s.RecvMsg(&v); err != nil { return nil, err } @@ -73,8 +74,9 @@ func (s *ls2lcClientStream) Recv() (*pb.LeaseKeepAliveResponse, error) { func (s *ls2lcServerStream) Send(rr *pb.LeaseKeepAliveResponse) error { return s.SendMsg(rr) } + func (s *ls2lcServerStream) Recv() (*pb.LeaseKeepAliveRequest, error) { - var v interface{} + var v any if err := s.RecvMsg(&v); err != nil { return nil, err } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lock_client_adapter.go b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lock_client_adapter.go index a3ceaf26da..de5ba049e1 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lock_client_adapter.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/lock_client_adapter.go @@ -17,9 +17,9 @@ package adapter import ( "context" - "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb" - "google.golang.org/grpc" + + "go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb" ) type ls2lsc struct{ ls v3lockpb.LockServer } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/maintenance_client_adapter.go b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/maintenance_client_adapter.go index 6369a16d8b..7b20445168 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/maintenance_client_adapter.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/maintenance_client_adapter.go @@ -17,9 +17,9 @@ package adapter import ( "context" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "google.golang.org/grpc" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) type mts2mtc struct{ mts pb.MaintenanceServer } @@ -72,8 +72,9 @@ type ss2scServerStream struct{ chanServerStream } func (s *ss2scClientStream) Send(rr *pb.SnapshotRequest) error { return s.SendMsg(rr) } + func (s *ss2scClientStream) Recv() (*pb.SnapshotResponse, error) { - var v interface{} + var v any if err := s.RecvMsg(&v); err != nil { return nil, err } @@ -83,8 +84,9 @@ func (s *ss2scClientStream) Recv() (*pb.SnapshotResponse, error) { func (s *ss2scServerStream) Send(rr *pb.SnapshotResponse) error { return s.SendMsg(rr) } + func (s *ss2scServerStream) Recv() (*pb.SnapshotRequest, error) { - var v interface{} + var v any if err := s.RecvMsg(&v); err != nil { return nil, err } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/watch_client_adapter.go b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/watch_client_adapter.go index fbc09f6ff6..828ed1b7e6 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/watch_client_adapter.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter/watch_client_adapter.go @@ -18,8 +18,9 @@ import ( "context" "errors" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" "google.golang.org/grpc" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" ) var errAlreadySentHeader = errors.New("adapter: already sent header") @@ -46,8 +47,9 @@ type ws2wcServerStream struct{ chanServerStream } func (s *ws2wcClientStream) Send(wr *pb.WatchRequest) error { return s.SendMsg(wr) } + func (s *ws2wcClientStream) Recv() (*pb.WatchResponse, error) { - var v interface{} + var v any if err := s.RecvMsg(&v); err != nil { return nil, err } @@ -57,8 +59,9 @@ func (s *ws2wcClientStream) Recv() (*pb.WatchResponse, error) { func (s *ws2wcServerStream) Send(wr *pb.WatchResponse) error { return s.SendMsg(wr) } + func (s *ws2wcServerStream) Recv() (*pb.WatchRequest, error) { - var v interface{} + var v any if err := s.RecvMsg(&v); err != nil { return nil, err } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/revbump/revbump.go b/etcd/vendor/go.etcd.io/etcd/server/v3/revbump/revbump.go index ce4ff823b3..7c3f0a7a87 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/revbump/revbump.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/revbump/revbump.go @@ -1,9 +1,9 @@ package revbump import ( - "go.etcd.io/etcd/server/v3/mvcc" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/mvcc" + "go.etcd.io/etcd/server/v3/storage/schema" "go.uber.org/zap" ) @@ -36,7 +36,7 @@ func unsafeBumpRevision(lg *zap.Logger, tx backend.BatchTx, latest revision, amo latest.sub = 0 k := make([]byte, revBytesLen) revToBytes(k, latest) - tx.UnsafePut(buckets.Key, k, []byte{}) + tx.UnsafePut(schema.Key, k, []byte{}) return latest } @@ -52,7 +52,7 @@ func unsafeMarkRevisionCompacted(lg *zap.Logger, tx backend.BatchTx, latest revi func unsafeGetLatestRevision(tx backend.BatchTx) (revision, error) { var latest revision - err := tx.UnsafeForEach(buckets.Key, func(k, _ []byte) (err error) { + err := tx.UnsafeForEach(schema.Key, func(k, _ []byte) (err error) { rev := bytesToRev(k) if rev.GreaterThan(latest) { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/backend.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend.go similarity index 69% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/backend.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend.go index 2beef57634..7db61f9fae 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/backend.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend.go @@ -12,24 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -package etcdserver +package storage import ( "fmt" "os" "time" - "go.etcd.io/etcd/raft/v3/raftpb" + "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/config" "go.etcd.io/etcd/server/v3/etcdserver/api/snap" - "go.etcd.io/etcd/server/v3/etcdserver/cindex" - "go.etcd.io/etcd/server/v3/mvcc/backend" - - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" + "go.etcd.io/raft/v3/raftpb" ) func newBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend { - bcfg := backend.DefaultBackendConfig() + bcfg := backend.DefaultBackendConfig(cfg.Logger) bcfg.Path = cfg.BackendPath() bcfg.UnsafeNoFsync = cfg.UnsafeNoFsync if cfg.BackendBatchLimit != 0 { @@ -50,25 +50,25 @@ func newBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend { // permit 10% excess over quota for disarm bcfg.MmapSize = uint64(cfg.QuotaBackendBytes + cfg.QuotaBackendBytes/10) } - bcfg.Mlock = cfg.ExperimentalMemoryMlock + bcfg.Mlock = cfg.MemoryMlock bcfg.Hooks = hooks return backend.New(bcfg) } -// openSnapshotBackend renames a snapshot db to the current etcd db and opens it. -func openSnapshotBackend(cfg config.ServerConfig, ss *snap.Snapshotter, snapshot raftpb.Snapshot, hooks backend.Hooks) (backend.Backend, error) { +// OpenSnapshotBackend renames a snapshot db to the current etcd db and opens it. +func OpenSnapshotBackend(cfg config.ServerConfig, ss *snap.Snapshotter, snapshot raftpb.Snapshot, hooks *BackendHooks) (backend.Backend, error) { snapPath, err := ss.DBFilePath(snapshot.Metadata.Index) if err != nil { - return nil, fmt.Errorf("failed to find database snapshot file (%v)", err) + return nil, fmt.Errorf("failed to find database snapshot file (%w)", err) } if err := os.Rename(snapPath, cfg.BackendPath()); err != nil { - return nil, fmt.Errorf("failed to rename database snapshot file (%v)", err) + return nil, fmt.Errorf("failed to rename database snapshot file (%w)", err) } - return openBackend(cfg, hooks), nil + return OpenBackend(cfg, hooks), nil } -// openBackend returns a backend using the current etcd db. -func openBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend { +// OpenBackend returns a backend using the current etcd db. +func OpenBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend { fn := cfg.BackendPath() now, beOpened := time.Now(), make(chan backend.Backend) @@ -76,9 +76,12 @@ func openBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend { beOpened <- newBackend(cfg, hooks) }() + defer func() { + cfg.Logger.Info("opened backend db", zap.String("path", fn), zap.Duration("took", time.Since(now))) + }() + select { case be := <-beOpened: - cfg.Logger.Info("opened backend db", zap.String("path", fn), zap.Duration("took", time.Since(now))) return be case <-time.After(10 * time.Second): @@ -92,18 +95,20 @@ func openBackend(cfg config.ServerConfig, hooks backend.Hooks) backend.Backend { return <-beOpened } -// recoverBackendSnapshot recovers the DB from a snapshot in case etcd crashes +// RecoverSnapshotBackend recovers the DB from a snapshot in case etcd crashes // before updating the backend db after persisting raft snapshot to disk, // violating the invariant snapshot.Metadata.Index < db.consistentIndex. In this // case, replace the db with the snapshot db sent by the leader. -func recoverSnapshotBackend(cfg config.ServerConfig, oldbe backend.Backend, snapshot raftpb.Snapshot, beExist bool, hooks backend.Hooks) (backend.Backend, error) { +func RecoverSnapshotBackend(cfg config.ServerConfig, oldbe backend.Backend, snapshot raftpb.Snapshot, beExist bool, hooks *BackendHooks) (backend.Backend, error) { consistentIndex := uint64(0) if beExist { - consistentIndex, _ = cindex.ReadConsistentIndex(oldbe.ReadTx()) + consistentIndex, _ = schema.ReadConsistentIndex(oldbe.ReadTx()) } if snapshot.Metadata.Index <= consistentIndex { + cfg.Logger.Info("Skipping snapshot backend", zap.Uint64("consistent-index", consistentIndex), zap.Uint64("snapshot-index", snapshot.Metadata.Index)) return oldbe, nil } + cfg.Logger.Info("Recovering from snapshot backend", zap.Uint64("consistent-index", consistentIndex), zap.Uint64("snapshot-index", snapshot.Metadata.Index)) oldbe.Close() - return openSnapshotBackend(cfg, snap.New(cfg.Logger, cfg.SnapDir()), snapshot, hooks) + return OpenSnapshotBackend(cfg, snap.New(cfg.Logger, cfg.SnapDir()), snapshot, hooks) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/backend.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/backend.go similarity index 88% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/backend.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/backend.go index 10c4275954..275064f083 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/backend.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/backend.go @@ -18,7 +18,6 @@ import ( "fmt" "hash/crc32" "io" - "io/ioutil" "os" "path/filepath" "sync" @@ -26,8 +25,10 @@ import ( "time" humanize "github.com/dustin/go-humanize" - bolt "go.etcd.io/bbolt" "go.uber.org/zap" + + bolt "go.etcd.io/bbolt" + "go.etcd.io/etcd/client/pkg/v3/verify" ) var ( @@ -153,11 +154,12 @@ type BackendConfig struct { type BackendConfigOption func(*BackendConfig) -func DefaultBackendConfig() BackendConfig { +func DefaultBackendConfig(lg *zap.Logger) BackendConfig { return BackendConfig{ BatchInterval: defaultBatchInterval, BatchLimit: defaultBatchLimit, MmapSize: InitialMmapSize, + Logger: lg, } } @@ -171,8 +173,8 @@ func WithMmapSize(size uint64) BackendConfigOption { } } -func NewDefaultBackend(path string, opts ...BackendConfigOption) Backend { - bcfg := DefaultBackendConfig() +func NewDefaultBackend(lg *zap.Logger, path string, opts ...BackendConfigOption) Backend { + bcfg := DefaultBackendConfig(lg) bcfg.Path = path for _, opt := range opts { opt(&bcfg) @@ -182,21 +184,23 @@ func NewDefaultBackend(path string, opts ...BackendConfigOption) Backend { } func newBackend(bcfg BackendConfig) *backend { - if bcfg.Logger == nil { - bcfg.Logger = zap.NewNop() - } - bopts := &bolt.Options{} if boltOpenOptions != nil { *bopts = *boltOpenOptions } + + if bcfg.Logger == nil { + bcfg.Logger = zap.NewNop() + } + bopts.InitialMmapSize = bcfg.mmapSize() bopts.FreelistType = bcfg.BackendFreelistType bopts.NoSync = bcfg.UnsafeNoFsync bopts.NoGrowSync = bcfg.UnsafeNoFsync bopts.Mlock = bcfg.Mlock + bopts.Logger = newBoltLoggerZap(bcfg) - db, err := bolt.Open(bcfg.Path, 0600, bopts) + db, err := bolt.Open(bcfg.Path, 0o600, bopts) if err != nil { bcfg.Logger.Panic("failed to open database", zap.String("path", bcfg.Path), zap.Error(err)) } @@ -396,7 +400,7 @@ func (b *backend) Hash(ignores func(bucketName, keyName []byte) bool) (uint32, e for next, _ := c.First(); next != nil; next, _ = c.Next() { b := tx.Bucket(next) if b == nil { - return fmt.Errorf("cannot get hash of bucket %s", string(next)) + return fmt.Errorf("cannot get hash of bucket %s", next) } h.Write(next) b.ForEach(func(k, v []byte) error { @@ -409,7 +413,6 @@ func (b *backend) Hash(ignores func(bucketName, keyName []byte) bool) (uint32, e } return nil }) - if err != nil { return 0, err } @@ -446,6 +449,8 @@ func (b *backend) run() { func (b *backend) Close() error { close(b.stopc) <-b.donec + b.mu.Lock() + defer b.mu.Unlock() return b.db.Close() } @@ -459,6 +464,7 @@ func (b *backend) Defrag() error { } func (b *backend) defrag() error { + verify.Assert(b.lg != nil, "the logger should not be nil") now := time.Now() isDefragActive.Set(1) defer isDefragActive.Set(0) @@ -480,7 +486,7 @@ func (b *backend) defrag() error { // Create a temporary file to ensure we start with a clean slate. // Snapshotter.cleanupSnapdir cleans up any of these that are found during startup. dir := filepath.Dir(b.db.Path()) - temp, err := ioutil.TempFile(dir, "db.tmp.*") + temp, err := os.CreateTemp(dir, "db.tmp.*") if err != nil { return err } @@ -497,10 +503,10 @@ func (b *backend) defrag() error { // Don't load tmp db into memory regardless of opening options options.Mlock = false tdbp := temp.Name() - tmpdb, err := bolt.Open(tdbp, 0600, &options) + tmpdb, err := bolt.Open(tdbp, 0o600, &options) if err != nil { temp.Close() - if rmErr := os.Remove(temp.Name()); rmErr != nil && b.lg != nil { + if rmErr := os.Remove(temp.Name()); rmErr != nil { b.lg.Error( "failed to remove temporary file", zap.String("path", temp.Name()), @@ -513,16 +519,24 @@ func (b *backend) defrag() error { dbp := b.db.Path() size1, sizeInUse1 := b.Size(), b.SizeInUse() - if b.lg != nil { - b.lg.Info( - "defragmenting", - zap.String("path", dbp), - zap.Int64("current-db-size-bytes", size1), - zap.String("current-db-size", humanize.Bytes(uint64(size1))), - zap.Int64("current-db-size-in-use-bytes", sizeInUse1), - zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse1))), - ) - } + b.lg.Info( + "defragmenting", + zap.String("path", dbp), + zap.Int64("current-db-size-bytes", size1), + zap.String("current-db-size", humanize.Bytes(uint64(size1))), + zap.Int64("current-db-size-in-use-bytes", sizeInUse1), + zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse1))), + ) + + defer func() { + // NOTE: We should exit as soon as possible because that tx + // might be closed. The inflight request might use invalid + // tx and then panic as well. The real panic reason might be + // shadowed by new panic. So, we should fatal here with lock. + if rerr := recover(); rerr != nil { + b.lg.Fatal("unexpected panic during defrag", zap.Any("panic", rerr)) + } + }() // Commit/stop and then reset current transactions (including the readTx) b.batchTx.unsafeCommit(true) @@ -557,7 +571,7 @@ func (b *backend) defrag() error { b.lg.Fatal("failed to rename tmp database", zap.Error(err)) } - b.db, err = bolt.Open(dbp, 0600, b.bopts) + b.db, err = bolt.Open(dbp, 0o600, b.bopts) if err != nil { b.lg.Fatal("failed to open database", zap.String("path", dbp), zap.Error(err)) } @@ -575,19 +589,17 @@ func (b *backend) defrag() error { defragSec.Observe(took.Seconds()) size2, sizeInUse2 := b.Size(), b.SizeInUse() - if b.lg != nil { - b.lg.Info( - "finished defragmenting directory", - zap.String("path", dbp), - zap.Int64("current-db-size-bytes-diff", size2-size1), - zap.Int64("current-db-size-bytes", size2), - zap.String("current-db-size", humanize.Bytes(uint64(size2))), - zap.Int64("current-db-size-in-use-bytes-diff", sizeInUse2-sizeInUse1), - zap.Int64("current-db-size-in-use-bytes", sizeInUse2), - zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse2))), - zap.Duration("took", took), - ) - } + b.lg.Info( + "finished defragmenting directory", + zap.String("path", dbp), + zap.Int64("current-db-size-bytes-diff", size2-size1), + zap.Int64("current-db-size-bytes", size2), + zap.String("current-db-size", humanize.Bytes(uint64(size2))), + zap.Int64("current-db-size-in-use-bytes-diff", sizeInUse2-sizeInUse1), + zap.Int64("current-db-size-in-use-bytes", sizeInUse2), + zap.String("current-db-size-in-use", humanize.Bytes(uint64(sizeInUse2))), + zap.Duration("took", took), + ) return nil } @@ -619,7 +631,7 @@ func defragdb(odb, tmpdb *bolt.DB, limit int) error { for next, _ := c.First(); next != nil; next, _ = c.Next() { b := tx.Bucket(next) if b == nil { - return fmt.Errorf("backend: cannot defrag bucket %s", string(next)) + return fmt.Errorf("backend: cannot defrag bucket %s", next) } tmpb, berr := tmptx.CreateBucketIfNotExists(next) @@ -693,3 +705,20 @@ func (s *snapshot) Close() error { <-s.donec return s.Tx.Rollback() } + +func newBoltLoggerZap(bcfg BackendConfig) bolt.Logger { + lg := bcfg.Logger.Named("bbolt") + return &zapBoltLogger{lg.WithOptions(zap.AddCallerSkip(1)).Sugar()} +} + +type zapBoltLogger struct { + *zap.SugaredLogger +} + +func (zl *zapBoltLogger) Warning(args ...any) { + zl.SugaredLogger.Warn(args...) +} + +func (zl *zapBoltLogger) Warningf(format string, args ...any) { + zl.SugaredLogger.Warnf(format, args...) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/batch_tx.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/batch_tx.go similarity index 95% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/batch_tx.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/batch_tx.go index 4ba60408e4..5af557cb42 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/batch_tx.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/batch_tx.go @@ -16,13 +16,16 @@ package backend import ( "bytes" + "errors" "math" "sync" "sync/atomic" "time" - bolt "go.etcd.io/bbolt" "go.uber.org/zap" + + bolt "go.etcd.io/bbolt" + bolterrors "go.etcd.io/bbolt/errors" ) type BucketID int @@ -43,18 +46,28 @@ type Bucket interface { } type BatchTx interface { - ReadTx - UnsafeCreateBucket(bucket Bucket) - UnsafeDeleteBucket(bucket Bucket) - UnsafePut(bucket Bucket, key []byte, value []byte) - UnsafeSeqPut(bucket Bucket, key []byte, value []byte) - UnsafeDelete(bucket Bucket, key []byte) + Lock() + Unlock() // Commit commits a previous tx and begins a new writable one. Commit() // CommitAndStop commits the previous tx and does not create a new one. CommitAndStop() LockInsideApply() LockOutsideApply() + UnsafeReadWriter +} + +type UnsafeReadWriter interface { + UnsafeReader + UnsafeWriter +} + +type UnsafeWriter interface { + UnsafeCreateBucket(bucket Bucket) + UnsafeDeleteBucket(bucket Bucket) + UnsafePut(bucket Bucket, key []byte, value []byte) + UnsafeSeqPut(bucket Bucket, key []byte, value []byte) + UnsafeDelete(bucket Bucket, key []byte) } type batchTx struct { @@ -100,21 +113,8 @@ func (t *batchTx) Unlock() { t.Mutex.Unlock() } -// BatchTx interface embeds ReadTx interface. But RLock() and RUnlock() do not -// have appropriate semantics in BatchTx interface. Therefore should not be called. -// TODO: might want to decouple ReadTx and BatchTx - -func (t *batchTx) RLock() { - panic("unexpected RLock") -} - -func (t *batchTx) RUnlock() { - panic("unexpected RUnlock") -} - func (t *batchTx) UnsafeCreateBucket(bucket Bucket) { - _, err := t.tx.CreateBucket(bucket.Name()) - if err != nil && err != bolt.ErrBucketExists { + if _, err := t.tx.CreateBucketIfNotExists(bucket.Name()); err != nil { t.backend.lg.Fatal( "failed to create a bucket", zap.Stringer("bucket-name", bucket), @@ -126,7 +126,7 @@ func (t *batchTx) UnsafeCreateBucket(bucket Bucket) { func (t *batchTx) UnsafeDeleteBucket(bucket Bucket) { err := t.tx.DeleteBucket(bucket.Name()) - if err != nil && err != bolt.ErrBucketNotFound { + if err != nil && !errors.Is(err, bolterrors.ErrBucketNotFound) { t.backend.lg.Fatal( "failed to delete a bucket", zap.Stringer("bucket-name", bucket), @@ -364,6 +364,7 @@ func (t *batchTxBuffered) unsafeCommit(stop bool) { t.backend.hooks.OnPreCommitUnsafe(t) // gofail: var commitAfterPreCommitHook struct{} } + if t.backend.readTx.tx != nil { // wait all store read transactions using the current boltdb tx to finish, // then close the boltdb tx diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_default.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/config_default.go similarity index 96% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_default.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/config_default.go index 847bd10fd7..fd57c7ca84 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_default.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/config_default.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build !linux && !windows -// +build !linux,!windows package backend diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_linux.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/config_linux.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_linux.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/config_linux.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_windows.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/config_windows.go similarity index 98% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_windows.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/config_windows.go index ba6e5a1284..7bb42f3a28 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/config_windows.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/config_windows.go @@ -13,7 +13,6 @@ // limitations under the License. //go:build windows -// +build windows package backend diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/doc.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/doc.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/doc.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/doc.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/hooks.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/hooks.go similarity index 88% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/hooks.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/hooks.go index 9750828ef7..817d0c5eb5 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/hooks.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/hooks.go @@ -14,20 +14,20 @@ package backend -type HookFunc func(tx BatchTx) +type HookFunc func(tx UnsafeReadWriter) // Hooks allow to add additional logic executed during transaction lifetime. type Hooks interface { // OnPreCommitUnsafe is executed before Commit of transactions. // The given transaction is already locked. - OnPreCommitUnsafe(tx BatchTx) + OnPreCommitUnsafe(tx UnsafeReadWriter) } type hooks struct { onPreCommitUnsafe HookFunc } -func (h hooks) OnPreCommitUnsafe(tx BatchTx) { +func (h hooks) OnPreCommitUnsafe(tx UnsafeReadWriter) { h.onPreCommitUnsafe(tx) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/metrics.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/metrics.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/metrics.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/read_tx.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/read_tx.go similarity index 98% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/read_tx.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/read_tx.go index 56327d52ae..4ca2621411 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/read_tx.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/read_tx.go @@ -26,11 +26,12 @@ import ( // is known to never overwrite any key so range is safe. type ReadTx interface { - Lock() - Unlock() RLock() RUnlock() + UnsafeReader +} +type UnsafeReader interface { UnsafeRange(bucket Bucket, key, endKey []byte, limit int64) (keys [][]byte, vals [][]byte) UnsafeForEach(bucket Bucket, visitor func(k, v []byte) error) error } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/tx_buffer.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/tx_buffer.go similarity index 83% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/tx_buffer.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/tx_buffer.go index 6674002483..821b300bfe 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/backend/tx_buffer.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/tx_buffer.go @@ -16,7 +16,11 @@ package backend import ( "bytes" + "encoding/hex" + "fmt" "sort" + + "go.etcd.io/etcd/client/pkg/v3/verify" ) const bucketBufferInitialSize = 512 @@ -50,7 +54,20 @@ func (txw *txWriteBuffer) put(bucket Bucket, k, v []byte) { } func (txw *txWriteBuffer) putSeq(bucket Bucket, k, v []byte) { - // TODO: Add (in tests?) verification whether k>b[len(b)] + // putSeq is only be called for the data in the Key bucket. The keys + // in the Key bucket should be monotonically increasing revisions. + verify.Verify(func() { + b, ok := txw.buckets[bucket.ID()] + if !ok || b.used == 0 { + return + } + + existingMaxKey := b.buf[b.used-1].key + if bytes.Compare(k, existingMaxKey) <= 0 { + panic(fmt.Sprintf("Broke the rule of monotonically increasing, existingMaxKey: %s, currentKey: %s", + hex.EncodeToString(existingMaxKey), hex.EncodeToString(k))) + } + }) txw.putInternal(bucket, k, v) } @@ -80,6 +97,9 @@ func (txw *txWriteBuffer) writeback(txr *txReadBuffer) { rb, ok := txr.buckets[k] if !ok { delete(txw.buckets, k) + if seq, ok := txw.bucket2seq[k]; ok && !seq { + wb.dedupe() + } txr.buckets[k] = wb continue } @@ -124,7 +144,7 @@ func (txr *txReadBuffer) unsafeCopy() txReadBuffer { bufVersion: 0, } for bucketName, bucket := range txr.txBuffer.buckets { - txrCopy.txBuffer.buckets[bucketName] = bucket.Copy() + txrCopy.txBuffer.buckets[bucketName] = bucket.CopyUsed() } return txrCopy } @@ -148,7 +168,7 @@ func newBucketBuffer() *bucketBuffer { func (bb *bucketBuffer) Range(key, endKey []byte, limit int64) (keys [][]byte, vals [][]byte) { f := func(i int) bool { return bytes.Compare(bb.buf[i].key, key) >= 0 } idx := sort.Search(bb.used, f) - if idx < 0 { + if idx < 0 || idx >= bb.used { return nil, nil } if len(endKey) == 0 { @@ -201,10 +221,15 @@ func (bb *bucketBuffer) merge(bbsrc *bucketBuffer) { if bytes.Compare(bb.buf[(bb.used-bbsrc.used)-1].key, bbsrc.buf[0].key) < 0 { return } + bb.dedupe() +} +// dedupe removes duplicates, using only newest update +func (bb *bucketBuffer) dedupe() { + if bb.used <= 1 { + return + } sort.Stable(bb) - - // remove duplicates, using only newest update widx := 0 for ridx := 1; ridx < bb.used; ridx++ { if !bytes.Equal(bb.buf[ridx].key, bb.buf[widx].key) { @@ -221,11 +246,13 @@ func (bb *bucketBuffer) Less(i, j int) bool { } func (bb *bucketBuffer) Swap(i, j int) { bb.buf[i], bb.buf[j] = bb.buf[j], bb.buf[i] } -func (bb *bucketBuffer) Copy() *bucketBuffer { +func (bb *bucketBuffer) CopyUsed() *bucketBuffer { + verify.Assert(bb.used <= len(bb.buf), + "used (%d) should never be bigger than the length of buf (%d)", bb.used, len(bb.buf)) bbCopy := bucketBuffer{ - buf: make([]kv, len(bb.buf)), + buf: make([]kv, bb.used), used: bb.used, } - copy(bbCopy.buf, bb.buf) + copy(bbCopy.buf, bb.buf[:bb.used]) return &bbCopy } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/verify.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/verify.go new file mode 100644 index 0000000000..206a8a41d7 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/backend/verify.go @@ -0,0 +1,117 @@ +// Copyright 2022 The etcd 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 backend + +import ( + "fmt" + "runtime/debug" + "strings" + + "github.com/google/go-cmp/cmp" + "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/verify" +) + +const ( + EnvVerifyValueLock verify.VerificationType = "lock" +) + +func ValidateCalledInsideApply(lg *zap.Logger) { + if !verifyLockEnabled() { + return + } + if !insideApply() { + lg.Panic("Called outside of APPLY!", zap.Stack("stacktrace")) + } +} + +func ValidateCalledOutSideApply(lg *zap.Logger) { + if !verifyLockEnabled() { + return + } + if insideApply() { + lg.Panic("Called inside of APPLY!", zap.Stack("stacktrace")) + } +} + +func ValidateCalledInsideUnittest(lg *zap.Logger) { + if !verifyLockEnabled() { + return + } + if !insideUnittest() { + lg.Fatal("Lock called outside of unit test!", zap.Stack("stacktrace")) + } +} + +func verifyLockEnabled() bool { + return verify.IsVerificationEnabled(EnvVerifyValueLock) +} + +func insideApply() bool { + stackTraceStr := string(debug.Stack()) + + // Exclude the case of `MustHackySaveMemberToBackend`, which is + // used to workaround the situations which are already affected + // by https://github.com/etcd-io/etcd/issues/19557. + if strings.Contains(stackTraceStr, "MustHackySaveMemberToBackend") { + return false + } + + return strings.Contains(stackTraceStr, ".applyEntries") +} + +func insideUnittest() bool { + stackTraceStr := string(debug.Stack()) + return strings.Contains(stackTraceStr, "_test.go") && !strings.Contains(stackTraceStr, "tests/") +} + +// VerifyBackendConsistency verifies data in ReadTx and BatchTx are consistent. +func VerifyBackendConsistency(b Backend, lg *zap.Logger, skipSafeRangeBucket bool, bucket ...Bucket) { + verify.Verify(func() { + if b == nil { + return + } + if lg != nil { + lg.Debug("verifyBackendConsistency", zap.Bool("skipSafeRangeBucket", skipSafeRangeBucket)) + } + b.BatchTx().LockOutsideApply() + defer b.BatchTx().Unlock() + b.ReadTx().RLock() + defer b.ReadTx().RUnlock() + for _, bkt := range bucket { + if skipSafeRangeBucket && bkt.IsSafeRangeBucket() { + continue + } + unsafeVerifyTxConsistency(b, bkt) + } + }) +} + +func unsafeVerifyTxConsistency(b Backend, bucket Bucket) { + dataFromWriteTxn := map[string]string{} + b.BatchTx().UnsafeForEach(bucket, func(k, v []byte) error { + dataFromWriteTxn[string(k)] = string(v) + return nil + }) + dataFromReadTxn := map[string]string{} + b.ReadTx().UnsafeForEach(bucket, func(k, v []byte) error { + dataFromReadTxn[string(k)] = string(v) + return nil + }) + if diff := cmp.Diff(dataFromWriteTxn, dataFromReadTxn); diff != "" { + panic(fmt.Sprintf("bucket %s data mismatch\nwrite TXN: %v\nread TXN: %v\ndiff: %s", bucket.String(), dataFromWriteTxn, dataFromReadTxn, diff)) + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/datadir/datadir.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/datadir/datadir.go similarity index 84% rename from etcd/vendor/go.etcd.io/etcd/server/v3/datadir/datadir.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/datadir/datadir.go index fa4c51ad1a..ced7d767fe 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/datadir/datadir.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/datadir/datadir.go @@ -31,7 +31,16 @@ func ToSnapDir(dataDir string) string { return filepath.Join(ToMemberDir(dataDir), snapDirSegment) } +// ToWalDir returns the directory path for the member's WAL. +// +// Deprecated: use ToWALDir instead. +// +//revive:disable-next-line:var-naming func ToWalDir(dataDir string) string { + return ToWALDir(dataDir) +} + +func ToWALDir(dataDir string) string { return filepath.Join(ToMemberDir(dataDir), walDirSegment) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/datadir/doc.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/datadir/doc.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/datadir/doc.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/datadir/doc.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/hooks.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/hooks.go new file mode 100644 index 0000000000..ffec71c0bc --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/hooks.go @@ -0,0 +1,60 @@ +// Copyright 2021 The etcd 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 storage + +import ( + "sync" + + "go.uber.org/zap" + + "go.etcd.io/etcd/server/v3/etcdserver/cindex" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" + "go.etcd.io/raft/v3/raftpb" +) + +type BackendHooks struct { + indexer cindex.ConsistentIndexer + lg *zap.Logger + + // confState to Be written in the next submitted Backend transaction (if dirty) + confState raftpb.ConfState + // first write changes it to 'dirty'. false by default, so + // not initialized `confState` is meaningless. + confStateDirty bool + confStateLock sync.Mutex +} + +func NewBackendHooks(lg *zap.Logger, indexer cindex.ConsistentIndexer) *BackendHooks { + return &BackendHooks{lg: lg, indexer: indexer} +} + +func (bh *BackendHooks) OnPreCommitUnsafe(tx backend.UnsafeReadWriter) { + bh.indexer.UnsafeSave(tx) + bh.confStateLock.Lock() + defer bh.confStateLock.Unlock() + if bh.confStateDirty { + schema.MustUnsafeSaveConfStateToBackend(bh.lg, tx, &bh.confState) + // save bh.confState + bh.confStateDirty = false + } +} + +func (bh *BackendHooks) SetConfState(confState *raftpb.ConfState) { + bh.confStateLock.Lock() + defer bh.confStateLock.Unlock() + bh.confState = *confState + bh.confStateDirty = true +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/metrics.go new file mode 100644 index 0000000000..cb7f87057f --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/metrics.go @@ -0,0 +1,30 @@ +// Copyright 2021 The etcd 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 storage + +import ( + "github.com/prometheus/client_golang/prometheus" +) + +var quotaBackendBytes = prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "server", + Name: "quota_backend_bytes", + Help: "Current backend storage quota size in bytes.", +}) + +func init() { + prometheus.MustRegister(quotaBackendBytes) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/doc.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/doc.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/doc.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/doc.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/hash.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/hash.go similarity index 76% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/hash.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/hash.go index 8af5d90a46..21618535da 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/hash.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/hash.go @@ -20,18 +20,19 @@ import ( "sort" "sync" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" "go.uber.org/zap" + + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" ) const ( hashStorageMaxSize = 10 ) -func unsafeHashByRev(tx backend.ReadTx, compactRevision, revision int64, keep map[revision]struct{}) (KeyValueHash, error) { +func unsafeHashByRev(tx backend.UnsafeReader, compactRevision, revision int64, keep map[Revision]struct{}) (KeyValueHash, error) { h := newKVHasher(compactRevision, revision, keep) - err := tx.UnsafeForEach(buckets.Key, func(k, v []byte) error { + err := tx.UnsafeForEach(schema.Key, func(k, v []byte) error { h.WriteKeyValue(k, v) return nil }) @@ -42,12 +43,12 @@ type kvHasher struct { hash hash.Hash32 compactRevision int64 revision int64 - keep map[revision]struct{} + keep map[Revision]struct{} } -func newKVHasher(compactRev, rev int64, keep map[revision]struct{}) kvHasher { +func newKVHasher(compactRev, rev int64, keep map[Revision]struct{}) kvHasher { h := crc32.New(crc32.MakeTable(crc32.Castagnoli)) - h.Write(buckets.Key.Name()) + h.Write(schema.Key.Name()) return kvHasher{ hash: h, compactRevision: compactRev, @@ -57,15 +58,15 @@ func newKVHasher(compactRev, rev int64, keep map[revision]struct{}) kvHasher { } func (h *kvHasher) WriteKeyValue(k, v []byte) { - kr := bytesToRev(k) - upper := revision{main: h.revision + 1} + kr := BytesToRev(k) + upper := Revision{Main: h.revision + 1} if !upper.GreaterThan(kr) { return } - isTombstoneRev := isTombstone(k) + isTombstone := BytesToBucketKey(k).tombstone - lower := revision{main: h.compactRevision + 1} + lower := Revision{Main: h.compactRevision + 1} // skip revisions that are scheduled for deletion // due to compacting; don't skip if there isn't one. if lower.GreaterThan(kr) && len(h.keep) > 0 { @@ -80,7 +81,7 @@ func (h *kvHasher) WriteKeyValue(k, v []byte) { // delete it. So we should skip the tombstone in such cases when // computing the hash to ensure that both older and newer versions // can always generate the same hash values. - if kr.main == h.compactRevision && isTombstoneRev { + if kr.Main == h.compactRevision && isTombstone { return } @@ -99,13 +100,18 @@ type KeyValueHash struct { } type HashStorage interface { - // Hash computes the hash of the KV's backend. + // Hash computes the hash of the whole backend keyspace, + // including key, lease, and other buckets in storage. + // This is designed for testing ONLY! + // Do not rely on this in production with ongoing transactions, + // since Hash operation does not hold MVCC locks. + // Use "HashByRev" method instead for "key" bucket consistency checks. Hash() (hash uint32, revision int64, err error) // HashByRev computes the hash of all MVCC revisions up to a given revision. HashByRev(rev int64) (hash KeyValueHash, currentRev int64, err error) - // Store adds hash value in local cache, allowing it can be returned by HashByRev. + // Store adds hash value in local cache, allowing it to be returned by HashByRev. Store(valueHash KeyValueHash) // Hashes returns list of up to `hashStorageMaxSize` newest previously stored hashes. @@ -119,7 +125,7 @@ type hashStorage struct { lg *zap.Logger } -func newHashStorage(lg *zap.Logger, s *store) *hashStorage { +func NewHashStorage(lg *zap.Logger, s *store) HashStorage { return &hashStorage{ store: s, lg: lg, @@ -168,9 +174,7 @@ func (s *hashStorage) Hashes() []KeyValueHash { s.hashMu.RLock() // Copy out hashes under lock just to be safe hashes := make([]KeyValueHash, 0, len(s.hashes)) - for _, hash := range s.hashes { - hashes = append(hashes, hash) - } + hashes = append(hashes, s.hashes...) s.hashMu.RUnlock() return hashes } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/index.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/index.go similarity index 54% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/index.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/index.go index 0a5cb00516..f300831b29 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/index.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/index.go @@ -15,7 +15,6 @@ package mvcc import ( - "sort" "sync" "github.com/google/btree" @@ -23,15 +22,14 @@ import ( ) type index interface { - Get(key []byte, atRev int64) (rev, created revision, ver int64, err error) - Range(key, end []byte, atRev int64) ([][]byte, []revision) - Revisions(key, end []byte, atRev int64, limit int) ([]revision, int) + Get(key []byte, atRev int64) (rev, created Revision, ver int64, err error) + Range(key, end []byte, atRev int64) ([][]byte, []Revision) + Revisions(key, end []byte, atRev int64, limit int) ([]Revision, int) CountRevisions(key, end []byte, atRev int64) int - Put(key []byte, rev revision) - Tombstone(key []byte, rev revision) error - RangeSince(key, end []byte, rev int64) []revision - Compact(rev int64) map[revision]struct{} - Keep(rev int64) map[revision]struct{} + Put(key []byte, rev Revision) + Tombstone(key []byte, rev Revision) error + Compact(rev int64) map[Revision]struct{} + Keep(rev int64) map[Revision]struct{} Equal(b index) bool Insert(ki *keyIndex) @@ -40,38 +38,43 @@ type index interface { type treeIndex struct { sync.RWMutex - tree *btree.BTree + tree *btree.BTreeG[*keyIndex] lg *zap.Logger } func newTreeIndex(lg *zap.Logger) index { return &treeIndex{ - tree: btree.New(32), - lg: lg, + tree: btree.NewG(32, func(aki *keyIndex, bki *keyIndex) bool { + return aki.Less(bki) + }), + lg: lg, } } -func (ti *treeIndex) Put(key []byte, rev revision) { +func (ti *treeIndex) Put(key []byte, rev Revision) { keyi := &keyIndex{key: key} ti.Lock() defer ti.Unlock() - item := ti.tree.Get(keyi) - if item == nil { - keyi.put(ti.lg, rev.main, rev.sub) + okeyi, ok := ti.tree.Get(keyi) + if !ok { + keyi.put(ti.lg, rev.Main, rev.Sub) ti.tree.ReplaceOrInsert(keyi) return } - okeyi := item.(*keyIndex) - okeyi.put(ti.lg, rev.main, rev.sub) + okeyi.put(ti.lg, rev.Main, rev.Sub) } -func (ti *treeIndex) Get(key []byte, atRev int64) (modified, created revision, ver int64, err error) { - keyi := &keyIndex{key: key} +func (ti *treeIndex) Get(key []byte, atRev int64) (modified, created Revision, ver int64, err error) { ti.RLock() defer ti.RUnlock() + return ti.unsafeGet(key, atRev) +} + +func (ti *treeIndex) unsafeGet(key []byte, atRev int64) (modified, created Revision, ver int64, err error) { + keyi := &keyIndex{key: key} if keyi = ti.keyIndex(keyi); keyi == nil { - return revision{}, revision{}, 0, ErrRevisionNotFound + return Revision{}, Revision{}, 0, ErrRevisionNotFound } return keyi.get(ti.lg, atRev) } @@ -83,38 +86,41 @@ func (ti *treeIndex) KeyIndex(keyi *keyIndex) *keyIndex { } func (ti *treeIndex) keyIndex(keyi *keyIndex) *keyIndex { - if item := ti.tree.Get(keyi); item != nil { - return item.(*keyIndex) + if ki, ok := ti.tree.Get(keyi); ok { + return ki } return nil } -func (ti *treeIndex) visit(key, end []byte, f func(ki *keyIndex) bool) { +func (ti *treeIndex) unsafeVisit(key, end []byte, f func(ki *keyIndex) bool) { keyi, endi := &keyIndex{key: key}, &keyIndex{key: end} - ti.RLock() - defer ti.RUnlock() - - ti.tree.AscendGreaterOrEqual(keyi, func(item btree.Item) bool { + ti.tree.AscendGreaterOrEqual(keyi, func(item *keyIndex) bool { if len(endi.key) > 0 && !item.Less(endi) { return false } - if !f(item.(*keyIndex)) { + if !f(item) { return false } return true }) } -func (ti *treeIndex) Revisions(key, end []byte, atRev int64, limit int) (revs []revision, total int) { +// Revisions returns limited number of revisions from key(included) to end(excluded) +// at the given rev. The returned slice is sorted in the order of key. There is no limit if limit <= 0. +// The second return parameter isn't capped by the limit and reflects the total number of revisions. +func (ti *treeIndex) Revisions(key, end []byte, atRev int64, limit int) (revs []Revision, total int) { + ti.RLock() + defer ti.RUnlock() + if end == nil { - rev, _, _, err := ti.Get(key, atRev) + rev, _, _, err := ti.unsafeGet(key, atRev) if err != nil { return nil, 0 } - return []revision{rev}, 1 + return []Revision{rev}, 1 } - ti.visit(key, end, func(ki *keyIndex) bool { + ti.unsafeVisit(key, end, func(ki *keyIndex) bool { if rev, _, _, err := ki.get(ti.lg, atRev); err == nil { if limit <= 0 || len(revs) < limit { revs = append(revs, rev) @@ -126,16 +132,21 @@ func (ti *treeIndex) Revisions(key, end []byte, atRev int64, limit int) (revs [] return revs, total } +// CountRevisions returns the number of revisions +// from key(included) to end(excluded) at the given rev. func (ti *treeIndex) CountRevisions(key, end []byte, atRev int64) int { + ti.RLock() + defer ti.RUnlock() + if end == nil { - _, _, _, err := ti.Get(key, atRev) + _, _, _, err := ti.unsafeGet(key, atRev) if err != nil { return 0 } return 1 } total := 0 - ti.visit(key, end, func(ki *keyIndex) bool { + ti.unsafeVisit(key, end, func(ki *keyIndex) bool { if _, _, _, err := ki.get(ti.lg, atRev); err == nil { total++ } @@ -144,15 +155,18 @@ func (ti *treeIndex) CountRevisions(key, end []byte, atRev int64) int { return total } -func (ti *treeIndex) Range(key, end []byte, atRev int64) (keys [][]byte, revs []revision) { +func (ti *treeIndex) Range(key, end []byte, atRev int64) (keys [][]byte, revs []Revision) { + ti.RLock() + defer ti.RUnlock() + if end == nil { - rev, _, _, err := ti.Get(key, atRev) + rev, _, _, err := ti.unsafeGet(key, atRev) if err != nil { return nil, nil } - return [][]byte{key}, []revision{rev} + return [][]byte{key}, []Revision{rev} } - ti.visit(key, end, func(ki *keyIndex) bool { + ti.unsafeVisit(key, end, func(ki *keyIndex) bool { if rev, _, _, err := ki.get(ti.lg, atRev); err == nil { revs = append(revs, rev) keys = append(keys, ki.key) @@ -162,69 +176,34 @@ func (ti *treeIndex) Range(key, end []byte, atRev int64) (keys [][]byte, revs [] return keys, revs } -func (ti *treeIndex) Tombstone(key []byte, rev revision) error { +func (ti *treeIndex) Tombstone(key []byte, rev Revision) error { keyi := &keyIndex{key: key} ti.Lock() defer ti.Unlock() - item := ti.tree.Get(keyi) - if item == nil { + ki, ok := ti.tree.Get(keyi) + if !ok { return ErrRevisionNotFound } - ki := item.(*keyIndex) - return ki.tombstone(ti.lg, rev.main, rev.sub) -} - -// RangeSince returns all revisions from key(including) to end(excluding) -// at or after the given rev. The returned slice is sorted in the order -// of revision. -func (ti *treeIndex) RangeSince(key, end []byte, rev int64) []revision { - keyi := &keyIndex{key: key} - - ti.RLock() - defer ti.RUnlock() - - if end == nil { - item := ti.tree.Get(keyi) - if item == nil { - return nil - } - keyi = item.(*keyIndex) - return keyi.since(ti.lg, rev) - } - - endi := &keyIndex{key: end} - var revs []revision - ti.tree.AscendGreaterOrEqual(keyi, func(item btree.Item) bool { - if len(endi.key) > 0 && !item.Less(endi) { - return false - } - curKeyi := item.(*keyIndex) - revs = append(revs, curKeyi.since(ti.lg, rev)...) - return true - }) - sort.Sort(revisions(revs)) - - return revs + return ki.tombstone(ti.lg, rev.Main, rev.Sub) } -func (ti *treeIndex) Compact(rev int64) map[revision]struct{} { - available := make(map[revision]struct{}) +func (ti *treeIndex) Compact(rev int64) map[Revision]struct{} { + available := make(map[Revision]struct{}) ti.lg.Info("compact tree index", zap.Int64("revision", rev)) ti.Lock() clone := ti.tree.Clone() ti.Unlock() - clone.Ascend(func(item btree.Item) bool { - keyi := item.(*keyIndex) - //Lock is needed here to prevent modification to the keyIndex while - //compaction is going on or revision added to empty before deletion + clone.Ascend(func(keyi *keyIndex) bool { + // Lock is needed here to prevent modification to the keyIndex while + // compaction is going on or revision added to empty before deletion ti.Lock() keyi.compact(ti.lg, rev, available) if keyi.isEmpty() { - item := ti.tree.Delete(keyi) - if item == nil { + _, ok := ti.tree.Delete(keyi) + if !ok { ti.lg.Panic("failed to delete during compaction") } } @@ -235,12 +214,11 @@ func (ti *treeIndex) Compact(rev int64) map[revision]struct{} { } // Keep finds all revisions to be kept for a Compaction at the given rev. -func (ti *treeIndex) Keep(rev int64) map[revision]struct{} { - available := make(map[revision]struct{}) +func (ti *treeIndex) Keep(rev int64) map[Revision]struct{} { + available := make(map[Revision]struct{}) ti.RLock() defer ti.RUnlock() - ti.tree.Ascend(func(i btree.Item) bool { - keyi := i.(*keyIndex) + ti.tree.Ascend(func(keyi *keyIndex) bool { keyi.keep(rev, available) return true }) @@ -256,9 +234,8 @@ func (ti *treeIndex) Equal(bi index) bool { equal := true - ti.tree.Ascend(func(item btree.Item) bool { - aki := item.(*keyIndex) - bki := b.tree.Get(item).(*keyIndex) + ti.tree.Ascend(func(aki *keyIndex) bool { + bki, _ := b.tree.Get(aki) if !aki.equal(bki) { equal = false return false diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/key_index.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/key_index.go similarity index 83% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/key_index.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/key_index.go index dfb5dcbee2..1403519741 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/key_index.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/key_index.go @@ -19,25 +19,22 @@ import ( "errors" "fmt" - "github.com/google/btree" "go.uber.org/zap" ) -var ( - ErrRevisionNotFound = errors.New("mvcc: revision not found") -) +var ErrRevisionNotFound = errors.New("mvcc: revision not found") // keyIndex stores the revisions of a key in the backend. // Each keyIndex has at least one key generation. // Each generation might have several key versions. -// Tombstone on a key appends an tombstone version at the end +// Tombstone on a key appends a tombstone version at the end // of the current generation and creates a new empty generation. // Each version of a key has an index pointing to the backend. // // For example: put(1.0);put(2.0);tombstone(3.0);put(4.0);tombstone(5.0) on key "foo" // generate a keyIndex: // key: "foo" -// rev: 5 +// modified: 5 // generations: // // {empty} @@ -75,21 +72,21 @@ var ( // {empty} -> key SHOULD be removed. type keyIndex struct { key []byte - modified revision // the main rev of the last modification + modified Revision // the main rev of the last modification generations []generation } // put puts a revision to the keyIndex. func (ki *keyIndex) put(lg *zap.Logger, main int64, sub int64) { - rev := revision{main: main, sub: sub} + rev := Revision{Main: main, Sub: sub} if !rev.GreaterThan(ki.modified) { lg.Panic( "'put' with an unexpected smaller revision", - zap.Int64("given-revision-main", rev.main), - zap.Int64("given-revision-sub", rev.sub), - zap.Int64("modified-revision-main", ki.modified.main), - zap.Int64("modified-revision-sub", ki.modified.sub), + zap.Int64("given-revision-main", rev.Main), + zap.Int64("given-revision-sub", rev.Sub), + zap.Int64("modified-revision-main", ki.modified.Main), + zap.Int64("modified-revision-sub", ki.modified.Sub), ) } if len(ki.generations) == 0 { @@ -105,7 +102,7 @@ func (ki *keyIndex) put(lg *zap.Logger, main int64, sub int64) { ki.modified = rev } -func (ki *keyIndex) restore(lg *zap.Logger, created, modified revision, ver int64) { +func (ki *keyIndex) restore(lg *zap.Logger, created, modified Revision, ver int64) { if len(ki.generations) != 0 { lg.Panic( "'restore' got an unexpected non-empty generations", @@ -114,7 +111,7 @@ func (ki *keyIndex) restore(lg *zap.Logger, created, modified revision, ver int6 } ki.modified = modified - g := generation{created: created, ver: ver, revs: []revision{modified}} + g := generation{created: created, ver: ver, revs: []Revision{modified}} ki.generations = append(ki.generations, g) keysGauge.Inc() } @@ -123,7 +120,7 @@ func (ki *keyIndex) restore(lg *zap.Logger, created, modified revision, ver int6 // revision so far for a key. We don't know the creating revision (i.e. already // compacted) of the key, so set it empty. func (ki *keyIndex) restoreTombstone(lg *zap.Logger, main, sub int64) { - ki.restore(lg, revision{}, revision{main, sub}, 1) + ki.restore(lg, Revision{}, Revision{main, sub}, 1) ki.generations = append(ki.generations, generation{}) keysGauge.Dec() } @@ -148,8 +145,8 @@ func (ki *keyIndex) tombstone(lg *zap.Logger, main int64, sub int64) error { } // get gets the modified, created revision and version of the key that satisfies the given atRev. -// Rev must be higher than or equal to the given atRev. -func (ki *keyIndex) get(lg *zap.Logger, atRev int64) (modified, created revision, ver int64, err error) { +// Rev must be smaller than or equal to the given atRev. +func (ki *keyIndex) get(lg *zap.Logger, atRev int64) (modified, created Revision, ver int64, err error) { if ki.isEmpty() { lg.Panic( "'get' got an unexpected empty keyIndex", @@ -158,28 +155,28 @@ func (ki *keyIndex) get(lg *zap.Logger, atRev int64) (modified, created revision } g := ki.findGeneration(atRev) if g.isEmpty() { - return revision{}, revision{}, 0, ErrRevisionNotFound + return Revision{}, Revision{}, 0, ErrRevisionNotFound } - n := g.walk(func(rev revision) bool { return rev.main > atRev }) + n := g.walk(func(rev Revision) bool { return rev.Main > atRev }) if n != -1 { return g.revs[n], g.created, g.ver - int64(len(g.revs)-n-1), nil } - return revision{}, revision{}, 0, ErrRevisionNotFound + return Revision{}, Revision{}, 0, ErrRevisionNotFound } // since returns revisions since the given rev. Only the revision with the // largest sub revision will be returned if multiple revisions have the same // main revision. -func (ki *keyIndex) since(lg *zap.Logger, rev int64) []revision { +func (ki *keyIndex) since(lg *zap.Logger, rev int64) []Revision { if ki.isEmpty() { lg.Panic( "'since' got an unexpected empty keyIndex", zap.String("key", string(ki.key)), ) } - since := revision{rev, 0} + since := Revision{Main: rev} var gi int // find the generations to start checking for gi = len(ki.generations) - 1; gi > 0; gi-- { @@ -192,21 +189,21 @@ func (ki *keyIndex) since(lg *zap.Logger, rev int64) []revision { } } - var revs []revision + var revs []Revision var last int64 for ; gi < len(ki.generations); gi++ { for _, r := range ki.generations[gi].revs { if since.GreaterThan(r) { continue } - if r.main == last { + if r.Main == last { // replace the revision with a new one that has higher sub value, // because the original one should not be seen by external revs[len(revs)-1] = r continue } revs = append(revs, r) - last = r.main + last = r.Main } } return revs @@ -215,7 +212,7 @@ func (ki *keyIndex) since(lg *zap.Logger, rev int64) []revision { // compact compacts a keyIndex by removing the versions with smaller or equal // revision than the given atRev except the largest one. // If a generation becomes empty during compaction, it will be removed. -func (ki *keyIndex) compact(lg *zap.Logger, atRev int64, available map[revision]struct{}) { +func (ki *keyIndex) compact(lg *zap.Logger, atRev int64, available map[Revision]struct{}) { if ki.isEmpty() { lg.Panic( "'compact' got an unexpected empty keyIndex", @@ -238,7 +235,7 @@ func (ki *keyIndex) compact(lg *zap.Logger, atRev int64, available map[revision] } // keep finds the revision to be kept if compact is called at given atRev. -func (ki *keyIndex) keep(atRev int64, available map[revision]struct{}) { +func (ki *keyIndex) keep(atRev int64, available map[Revision]struct{}) { if ki.isEmpty() { return } @@ -258,11 +255,11 @@ func (ki *keyIndex) keep(atRev int64, available map[revision]struct{}) { } } -func (ki *keyIndex) doCompact(atRev int64, available map[revision]struct{}) (genIdx int, revIndex int) { +func (ki *keyIndex) doCompact(atRev int64, available map[Revision]struct{}) (genIdx int, revIndex int) { // walk until reaching the first revision smaller or equal to "atRev", // and add the revision to the available map - f := func(rev revision) bool { - if rev.main <= atRev { + f := func(rev Revision) bool { + if rev.Main <= atRev { available[rev] = struct{}{} return false } @@ -272,7 +269,7 @@ func (ki *keyIndex) doCompact(atRev int64, available map[revision]struct{}) (gen genIdx, g := 0, &ki.generations[0] // find first generation includes atRev or created after atRev for genIdx < len(ki.generations)-1 { - if tomb := g.revs[len(g.revs)-1].main; tomb >= atRev { + if tomb := g.revs[len(g.revs)-1].Main; tomb >= atRev { break } genIdx++ @@ -302,11 +299,11 @@ func (ki *keyIndex) findGeneration(rev int64) *generation { } g := ki.generations[cg] if cg != lastg { - if tomb := g.revs[len(g.revs)-1].main; tomb <= rev { + if tomb := g.revs[len(g.revs)-1].Main; tomb <= rev { return nil } } - if g.revs[0].main <= rev { + if g.revs[0].Main <= rev { return &ki.generations[cg] } cg-- @@ -314,8 +311,8 @@ func (ki *keyIndex) findGeneration(rev int64) *generation { return nil } -func (ki *keyIndex) Less(b btree.Item) bool { - return bytes.Compare(ki.key, b.(*keyIndex).key) == -1 +func (ki *keyIndex) Less(bki *keyIndex) bool { + return bytes.Compare(ki.key, bki.key) == -1 } func (ki *keyIndex) equal(b *keyIndex) bool { @@ -348,8 +345,8 @@ func (ki *keyIndex) String() string { // generation contains multiple revisions of a key. type generation struct { ver int64 - created revision // when the generation is created (put in first revision). - revs []revision + created Revision // when the generation is created (put in first revision). + revs []Revision } func (g *generation) isEmpty() bool { return g == nil || len(g.revs) == 0 } @@ -359,7 +356,7 @@ func (g *generation) isEmpty() bool { return g == nil || len(g.revs) == 0 } // walk returns until: 1. it finishes walking all pairs 2. the function returns false. // walk returns the position at where it stopped. If it stopped after // finishing walking, -1 will be returned. -func (g *generation) walk(f func(rev revision) bool) int { +func (g *generation) walk(f func(rev Revision) bool) int { l := len(g.revs) for i := range g.revs { ok := f(g.revs[l-i-1]) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kv.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kv.go similarity index 99% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kv.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kv.go index 109b0d7ccb..6250bb9119 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kv.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kv.go @@ -20,7 +20,7 @@ import ( "go.etcd.io/etcd/api/v3/mvccpb" "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/server/v3/lease" - "go.etcd.io/etcd/server/v3/mvcc/backend" + "go.etcd.io/etcd/server/v3/storage/backend" ) type RangeOptions struct { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kv_view.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kv_view.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kv_view.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kv_view.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kvstore.go similarity index 81% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kvstore.go index 323abd4f8d..77c5022625 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kvstore.go @@ -22,37 +22,28 @@ import ( "sync" "time" + "go.uber.org/zap" + "go.etcd.io/etcd/api/v3/mvccpb" + "go.etcd.io/etcd/client/pkg/v3/verify" "go.etcd.io/etcd/pkg/v3/schedule" "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/server/v3/lease" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" - - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" ) var ( - scheduledCompactKeyName = []byte("scheduledCompactRev") - finishedCompactKeyName = []byte("finishedCompactRev") - ErrCompacted = errors.New("mvcc: required revision has been compacted") ErrFutureRev = errors.New("mvcc: required revision is a future revision") ) -const ( - // markedRevBytesLen is the byte length of marked revision. - // The first `revBytesLen` bytes represents a normal revision. The last - // one byte is the mark. - markedRevBytesLen = revBytesLen + 1 - markBytePosition = markedRevBytesLen - 1 - markTombstone byte = 't' +var ( + restoreChunkKeys = 10000 // non-const for testing + defaultCompactionBatchLimit = 1000 + defaultCompactionSleepInterval = 10 * time.Millisecond ) -var restoreChunkKeys = 10000 // non-const for testing -var defaultCompactionBatchLimit = 1000 -var defaultCompactionSleepInterval = 10 * time.Millisecond - type StoreConfig struct { CompactionBatchLimit int CompactionSleepInterval time.Duration @@ -91,6 +82,7 @@ type store struct { // NewStore returns a new store. It is useful to create a store inside // mvcc pkg. It should only be used for testing externally. +// revive:disable-next-line:unexported-return this is used internally in the mvcc pkg func NewStore(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfig) *store { if lg == nil { lg = zap.NewNop() @@ -111,13 +103,13 @@ func NewStore(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfi currentRev: 1, compactMainRev: -1, - fifoSched: schedule.NewFIFOScheduler(), + fifoSched: schedule.NewFIFOScheduler(lg), stopc: make(chan struct{}), lg: lg, } - s.hashes = newHashStorage(lg, s) + s.hashes = NewHashStorage(lg, s) s.ReadView = &readView{s} s.WriteView = &writeView{s} if s.le != nil { @@ -126,8 +118,8 @@ func NewStore(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfi tx := s.b.BatchTx() tx.LockOutsideApply() - tx.UnsafeCreateBucket(buckets.Key) - tx.UnsafeCreateBucket(buckets.Meta) + tx.UnsafeCreateBucket(schema.Key) + schema.UnsafeCreateMetaBucket(tx) tx.Unlock() s.b.ForceCommit() @@ -146,12 +138,12 @@ func (s *store) compactBarrier(ctx context.Context, ch chan struct{}) { select { case <-s.stopc: default: - // fix deadlock in mvcc,for more information, please refer to pr 11817. + // fix deadlock in mvcc, for more information, please refer to pr 11817. // s.stopc is only updated in restore operation, which is called by apply // snapshot call, compaction and apply snapshot requests are serialized by // raft, and do not happen at the same time. s.mu.Lock() - f := func(ctx context.Context) { s.compactBarrier(ctx, ch) } + f := schedule.NewJob("kvstore_compactBarrier", func(ctx context.Context) { s.compactBarrier(ctx, ch) }) s.fifoSched.Schedule(f) s.mu.Unlock() } @@ -165,7 +157,7 @@ func (s *store) hash() (hash uint32, revision int64, err error) { start := time.Now() s.b.ForceCommit() - h, err := s.b.Hash(buckets.DefaultIgnores) + h, err := s.b.Hash(schema.DefaultIgnores) hashSec.Observe(time.Since(start).Seconds()) return h, s.currentRev, err @@ -205,7 +197,7 @@ func (s *store) updateCompactRev(rev int64) (<-chan struct{}, int64, error) { s.revMu.Lock() if rev <= s.compactMainRev { ch := make(chan struct{}) - f := func(ctx context.Context) { s.compactBarrier(ctx, ch) } + f := schedule.NewJob("kvstore_updateCompactRev_compactBarrier", func(ctx context.Context) { s.compactBarrier(ctx, ch) }) s.fifoSched.Schedule(f) s.revMu.Unlock() return ch, 0, ErrCompacted @@ -217,13 +209,7 @@ func (s *store) updateCompactRev(rev int64) (<-chan struct{}, int64, error) { compactMainRev := s.compactMainRev s.compactMainRev = rev - rbytes := newRevBytes() - revToBytes(revision{main: rev}, rbytes) - - tx := s.b.BatchTx() - tx.LockInsideApply() - tx.UnsafePut(buckets.Meta, scheduledCompactKeyName, rbytes) - tx.Unlock() + SetScheduledCompact(s.b.BatchTx(), rev) // ensure that desired compaction is persisted // gofail: var compactBeforeCommitScheduledCompact struct{} s.b.ForceCommit() @@ -237,8 +223,8 @@ func (s *store) updateCompactRev(rev int64) (<-chan struct{}, int64, error) { // checkPrevCompactionCompleted checks whether the previous scheduled compaction is completed. func (s *store) checkPrevCompactionCompleted() bool { tx := s.b.ReadTx() - tx.Lock() - defer tx.Unlock() + tx.RLock() + defer tx.RUnlock() scheduledCompact, scheduledCompactFound := UnsafeReadScheduledCompact(tx) finishedCompact, finishedCompactFound := UnsafeReadFinishedCompact(tx) return scheduledCompact == finishedCompact && scheduledCompactFound == finishedCompactFound @@ -246,7 +232,7 @@ func (s *store) checkPrevCompactionCompleted() bool { func (s *store) compact(trace *traceutil.Trace, rev, prevCompactRev int64, prevCompactionCompleted bool) <-chan struct{} { ch := make(chan struct{}) - var j = func(ctx context.Context) { + j := schedule.NewJob("kvstore_compact", func(ctx context.Context) { if ctx.Err() != nil { s.compactBarrier(ctx, ch) return @@ -265,7 +251,7 @@ func (s *store) compact(trace *traceutil.Trace, rev, prevCompactRev int64, prevC s.lg.Info("previous compaction was interrupted, skip storing compaction hash value") } close(ch) - } + }) s.fifoSched.Schedule(j) trace.Step("schedule compaction") @@ -284,7 +270,6 @@ func (s *store) compactLockfree(rev int64) (<-chan struct{}, error) { func (s *store) Compact(trace *traceutil.Trace, rev int64) (<-chan struct{}, error) { s.mu.Lock() - prevCompactionCompleted := s.checkPrevCompactionCompleted() ch, prevCompactRev, err := s.updateCompactRev(rev) trace.Step("check and update compact revision") @@ -321,24 +306,25 @@ func (s *store) Restore(b backend.Backend) error { s.revMu.Unlock() } - s.fifoSched = schedule.NewFIFOScheduler() + s.fifoSched = schedule.NewFIFOScheduler(s.lg) s.stopc = make(chan struct{}) return s.restore() } +//nolint:unparam func (s *store) restore() error { s.setupMetricsReporter() - min, max := newRevBytes(), newRevBytes() - revToBytes(revision{main: 1}, min) - revToBytes(revision{main: math.MaxInt64, sub: math.MaxInt64}, max) + min, max := NewRevBytes(), NewRevBytes() + min = RevToBytes(Revision{Main: 1}, min) + max = RevToBytes(Revision{Main: math.MaxInt64, Sub: math.MaxInt64}, max) keyToLease := make(map[string]lease.LeaseID) // restore index tx := s.b.ReadTx() - tx.Lock() + tx.RLock() finishedCompact, found := UnsafeReadFinishedCompact(tx) if found { @@ -347,19 +333,17 @@ func (s *store) restore() error { s.lg.Info( "restored last compact revision", - zap.Stringer("meta-bucket-name", buckets.Meta), - zap.String("meta-bucket-name-key", string(finishedCompactKeyName)), + zap.String("meta-bucket-name-key", string(schema.FinishedCompactKeyName)), zap.Int64("restored-compact-revision", s.compactMainRev), ) s.revMu.Unlock() } scheduledCompact, _ := UnsafeReadScheduledCompact(tx) - // index keys concurrently as they're loaded in from tx keysGauge.Set(0) rkvc, revc := restoreIntoIndex(s.lg, s.kvindex) for { - keys, vals := tx.UnsafeRange(buckets.Key, min, max, int64(restoreChunkKeys)) + keys, vals := tx.UnsafeRange(schema.Key, min, max, int64(restoreChunkKeys)) if len(keys) == 0 { break } @@ -371,9 +355,9 @@ func (s *store) restore() error { break } // next set begins after where this one ended - newMin := bytesToRev(keys[len(keys)-1][:revBytesLen]) - newMin.sub++ - revToBytes(newMin, min) + newMin := BytesToRev(keys[len(keys)-1][:revBytesLen]) + newMin.Sub++ + min = RevToBytes(newMin, min) } close(rkvc) @@ -407,7 +391,7 @@ func (s *store) restore() error { for key, lid := range keyToLease { if s.le == nil { - tx.Unlock() + tx.RUnlock() panic("no lessor to attach lease") } err := s.le.Attach(lid, []lease.LeaseItem{{Key: key}}) @@ -419,8 +403,7 @@ func (s *store) restore() error { ) } } - - tx.Unlock() + tx.RUnlock() s.lg.Info("kvstore restored", zap.Int64("current-rev", s.currentRev)) @@ -433,8 +416,6 @@ func (s *store) restore() error { } else { s.lg.Info( "resume scheduled compaction", - zap.Stringer("meta-bucket-name", buckets.Meta), - zap.String("meta-bucket-name-key", string(scheduledCompactKeyName)), zap.Int64("scheduled-compact-revision", scheduledCompact), ) } @@ -476,21 +457,28 @@ func restoreIntoIndex(lg *zap.Logger, idx index) (chan<- revKeyValue, <-chan int ok = true } } - rev := bytesToRev(rkv.key) - currentRev = rev.main + + rev := BytesToRev(rkv.key) + verify.Verify(func() { + if rev.Main < currentRev { + panic(fmt.Errorf("revision %d shouldn't be less than the previous revision %d", rev.Main, currentRev)) + } + }) + currentRev = rev.Main + if ok { if isTombstone(rkv.key) { - if err := ki.tombstone(lg, rev.main, rev.sub); err != nil { + if err := ki.tombstone(lg, rev.Main, rev.Sub); err != nil { lg.Warn("tombstone encountered error", zap.Error(err)) } continue } - ki.put(lg, rev.main, rev.sub) + ki.put(lg, rev.Main, rev.Sub) } else { if isTombstone(rkv.key) { - ki.restoreTombstone(lg, rev.main, rev.sub) + ki.restoreTombstone(lg, rev.Main, rev.Sub) } else { - ki.restore(lg, revision{rkv.kv.CreateRevision, 0}, rev, rkv.kv.Version) + ki.restore(lg, Revision{Main: rkv.kv.CreateRevision}, rev, rkv.kv.Version) } idx.Insert(ki) kiCache[rkv.kstr] = ki @@ -529,9 +517,6 @@ func (s *store) setupMetricsReporter() { reportDbTotalSizeInBytesMu.Lock() reportDbTotalSizeInBytes = func() float64 { return float64(b.Size()) } reportDbTotalSizeInBytesMu.Unlock() - reportDbTotalSizeInBytesDebugMu.Lock() - reportDbTotalSizeInBytesDebug = func() float64 { return float64(b.Size()) } - reportDbTotalSizeInBytesDebugMu.Unlock() reportDbTotalSizeInUseInBytesMu.Lock() reportDbTotalSizeInUseInBytes = func() float64 { return float64(b.SizeInUse()) } reportDbTotalSizeInUseInBytesMu.Unlock() @@ -554,23 +539,6 @@ func (s *store) setupMetricsReporter() { reportCompactRevMu.Unlock() } -// appendMarkTombstone appends tombstone mark to normal revision bytes. -func appendMarkTombstone(lg *zap.Logger, b []byte) []byte { - if len(b) != revBytesLen { - lg.Panic( - "cannot append tombstone mark to non-normal revision bytes", - zap.Int("expected-revision-bytes-size", revBytesLen), - zap.Int("given-revision-bytes-size", len(b)), - ) - } - return append(b, markTombstone) -} - -// isTombstone checks whether the revision bytes is a tombstone. -func isTombstone(b []byte) bool { - return len(b) == markedRevBytesLen && b[markBytePosition] == markTombstone -} - func (s *store) HashStorage() HashStorage { return s.hashes } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_compaction.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kvstore_compaction.go similarity index 87% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_compaction.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kvstore_compaction.go index 72ca7c3d96..a052c93943 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_compaction.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kvstore_compaction.go @@ -20,8 +20,9 @@ import ( "time" humanize "github.com/dustin/go-humanize" - "go.etcd.io/etcd/server/v3/mvcc/buckets" "go.uber.org/zap" + + "go.etcd.io/etcd/server/v3/storage/schema" ) func (s *store) scheduleCompaction(compactMainRev, prevCompactRev int64) (KeyValueHash, error) { @@ -41,19 +42,18 @@ func (s *store) scheduleCompaction(compactMainRev, prevCompactRev int64) (KeyVal batchNum := s.cfg.CompactionBatchLimit h := newKVHasher(prevCompactRev, compactMainRev, keep) last := make([]byte, 8+1+8) - for { - var rev revision + var rev Revision start := time.Now() tx := s.b.BatchTx() tx.LockOutsideApply() - keys, values := tx.UnsafeRange(buckets.Key, last, end, int64(batchNum)) + keys, values := tx.UnsafeRange(schema.Key, last, end, int64(batchNum)) for i := range keys { - rev = bytesToRev(keys[i]) + rev = BytesToRev(keys[i]) if _, ok := keep[rev]; !ok { - tx.UnsafeDelete(buckets.Key, keys[i]) + tx.UnsafeDelete(schema.Key, keys[i]) keyCompactions++ } h.WriteKeyValue(keys[i], values[i]) @@ -61,10 +61,9 @@ func (s *store) scheduleCompaction(compactMainRev, prevCompactRev int64) (KeyVal if len(keys) < batchNum { // gofail: var compactBeforeSetFinishedCompact struct{} - rbytes := make([]byte, 8+1+8) - revToBytes(revision{main: compactMainRev}, rbytes) - tx.UnsafePut(buckets.Meta, finishedCompactKeyName, rbytes) + UnsafeSetFinishedCompact(tx, compactMainRev) tx.Unlock() + dbCompactionPauseMs.Observe(float64(time.Since(start) / time.Millisecond)) // gofail: var compactAfterSetFinishedCompact struct{} hash := h.Hash() size, sizeInUse := s.b.Size(), s.b.SizeInUse() @@ -81,9 +80,9 @@ func (s *store) scheduleCompaction(compactMainRev, prevCompactRev int64) (KeyVal return hash, nil } - // update last - revToBytes(revision{main: rev.main, sub: rev.sub + 1}, last) tx.Unlock() + // update last + last = RevToBytes(Revision{Main: rev.Main, Sub: rev.Sub + 1}, last) // Immediately commit the compaction deletes instead of letting them accumulate in the write buffer // gofail: var compactBeforeCommitBatch struct{} s.b.ForceCommit() diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_txn.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kvstore_txn.go similarity index 80% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_txn.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kvstore_txn.go index 855ededddb..c44a2cb3d9 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/kvstore_txn.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/kvstore_txn.go @@ -18,17 +18,23 @@ import ( "context" "fmt" + "go.uber.org/zap" + "go.etcd.io/etcd/api/v3/mvccpb" "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/server/v3/lease" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" ) type storeTxnRead struct { - s *store + storeTxnCommon tx backend.ReadTx +} + +type storeTxnCommon struct { + s *store + tx backend.UnsafeReader firstRev int64 rev int64 @@ -53,23 +59,85 @@ func (s *store) Read(mode ReadTxMode, trace *traceutil.Trace) TxnRead { tx.RLock() // RLock is no-op. concurrentReadTx does not need to be locked after it is created. firstRev, rev := s.compactMainRev, s.currentRev s.revMu.RUnlock() - return newMetricsTxnRead(&storeTxnRead{s, tx, firstRev, rev, trace}) + return newMetricsTxnRead(&storeTxnRead{storeTxnCommon{s, tx, firstRev, rev, trace}, tx}) } -func (tr *storeTxnRead) FirstRev() int64 { return tr.firstRev } -func (tr *storeTxnRead) Rev() int64 { return tr.rev } +func (tr *storeTxnCommon) FirstRev() int64 { return tr.firstRev } +func (tr *storeTxnCommon) Rev() int64 { return tr.rev } -func (tr *storeTxnRead) Range(ctx context.Context, key, end []byte, ro RangeOptions) (r *RangeResult, err error) { +func (tr *storeTxnCommon) Range(ctx context.Context, key, end []byte, ro RangeOptions) (r *RangeResult, err error) { return tr.rangeKeys(ctx, key, end, tr.Rev(), ro) } +func (tr *storeTxnCommon) rangeKeys(ctx context.Context, key, end []byte, curRev int64, ro RangeOptions) (*RangeResult, error) { + rev := ro.Rev + if rev > curRev { + return &RangeResult{KVs: nil, Count: -1, Rev: curRev}, ErrFutureRev + } + if rev <= 0 { + rev = curRev + } + if rev < tr.s.compactMainRev { + return &RangeResult{KVs: nil, Count: -1, Rev: 0}, ErrCompacted + } + if ro.Count { + total := tr.s.kvindex.CountRevisions(key, end, rev) + tr.trace.Step("count revisions from in-memory index tree") + return &RangeResult{KVs: nil, Count: total, Rev: curRev}, nil + } + revpairs, total := tr.s.kvindex.Revisions(key, end, rev, int(ro.Limit)) + tr.trace.Step("range keys from in-memory index tree") + if len(revpairs) == 0 { + return &RangeResult{KVs: nil, Count: total, Rev: curRev}, nil + } + + limit := int(ro.Limit) + if limit <= 0 || limit > len(revpairs) { + limit = len(revpairs) + } + + kvs := make([]mvccpb.KeyValue, limit) + revBytes := NewRevBytes() + for i, revpair := range revpairs[:len(kvs)] { + select { + case <-ctx.Done(): + return nil, fmt.Errorf("rangeKeys: context cancelled: %w", ctx.Err()) + default: + } + revBytes = RevToBytes(revpair, revBytes) + _, vs := tr.tx.UnsafeRange(schema.Key, revBytes, nil, 0) + if len(vs) != 1 { + tr.s.lg.Fatal( + "range failed to find revision pair", + zap.Int64("revision-main", revpair.Main), + zap.Int64("revision-sub", revpair.Sub), + zap.Int64("revision-current", curRev), + zap.Int64("range-option-rev", ro.Rev), + zap.Int64("range-option-limit", ro.Limit), + zap.Binary("key", key), + zap.Binary("end", end), + zap.Int("len-revpairs", len(revpairs)), + zap.Int("len-values", len(vs)), + ) + } + if err := kvs[i].Unmarshal(vs[0]); err != nil { + tr.s.lg.Fatal( + "failed to unmarshal mvccpb.KeyValue", + zap.Error(err), + ) + } + } + tr.trace.Step("range keys from bolt db") + return &RangeResult{KVs: kvs, Count: total, Rev: curRev}, nil +} + func (tr *storeTxnRead) End() { tr.tx.RUnlock() // RUnlock signals the end of concurrentReadTx. tr.s.mu.RUnlock() } type storeTxnWrite struct { - storeTxnRead + storeTxnCommon tx backend.BatchTx // beginRev is the revision where the txn begins; it will write to the next revision. beginRev int64 @@ -81,10 +149,10 @@ func (s *store) Write(trace *traceutil.Trace) TxnWrite { tx := s.b.BatchTx() tx.LockInsideApply() tw := &storeTxnWrite{ - storeTxnRead: storeTxnRead{s, tx, 0, 0, trace}, - tx: tx, - beginRev: s.currentRev, - changes: make([]mvccpb.KeyValue, 0, 4), + storeTxnCommon: storeTxnCommon{s, tx, 0, 0, trace}, + tx: tx, + beginRev: s.currentRev, + changes: make([]mvccpb.KeyValue, 0, 4), } return newMetricsTxnWrite(tw) } @@ -125,68 +193,6 @@ func (tw *storeTxnWrite) End() { tw.s.mu.RUnlock() } -func (tr *storeTxnRead) rangeKeys(ctx context.Context, key, end []byte, curRev int64, ro RangeOptions) (*RangeResult, error) { - rev := ro.Rev - if rev > curRev { - return &RangeResult{KVs: nil, Count: -1, Rev: curRev}, ErrFutureRev - } - if rev <= 0 { - rev = curRev - } - if rev < tr.s.compactMainRev { - return &RangeResult{KVs: nil, Count: -1, Rev: 0}, ErrCompacted - } - if ro.Count { - total := tr.s.kvindex.CountRevisions(key, end, rev) - tr.trace.Step("count revisions from in-memory index tree") - return &RangeResult{KVs: nil, Count: total, Rev: curRev}, nil - } - revpairs, total := tr.s.kvindex.Revisions(key, end, rev, int(ro.Limit)) - tr.trace.Step("range keys from in-memory index tree") - if len(revpairs) == 0 { - return &RangeResult{KVs: nil, Count: total, Rev: curRev}, nil - } - - limit := int(ro.Limit) - if limit <= 0 || limit > len(revpairs) { - limit = len(revpairs) - } - - kvs := make([]mvccpb.KeyValue, limit) - revBytes := newRevBytes() - for i, revpair := range revpairs[:len(kvs)] { - select { - case <-ctx.Done(): - return nil, fmt.Errorf("rangeKeys: context cancelled: %w", ctx.Err()) - default: - } - revToBytes(revpair, revBytes) - _, vs := tr.tx.UnsafeRange(buckets.Key, revBytes, nil, 0) - if len(vs) != 1 { - tr.s.lg.Fatal( - "range failed to find revision pair", - zap.Int64("revision-main", revpair.main), - zap.Int64("revision-sub", revpair.sub), - zap.Int64("revision-current", curRev), - zap.Int64("range-option-rev", ro.Rev), - zap.Int64("range-option-limit", ro.Limit), - zap.Binary("key", key), - zap.Binary("end", end), - zap.Int("len-revpairs", len(revpairs)), - zap.Int("len-values", len(vs)), - ) - } - if err := kvs[i].Unmarshal(vs[0]); err != nil { - tr.s.lg.Fatal( - "failed to unmarshal mvccpb.KeyValue", - zap.Error(err), - ) - } - } - tr.trace.Step("range keys from bolt db") - return &RangeResult{KVs: kvs, Count: total, Rev: curRev}, nil -} - func (tw *storeTxnWrite) put(key, value []byte, leaseID lease.LeaseID) { rev := tw.beginRev + 1 c := rev @@ -196,13 +202,13 @@ func (tw *storeTxnWrite) put(key, value []byte, leaseID lease.LeaseID) { // get its previous leaseID _, created, ver, err := tw.s.kvindex.Get(key, rev) if err == nil { - c = created.main + c = created.Main oldLease = tw.s.le.GetLease(lease.LeaseItem{Key: string(key)}) tw.trace.Step("get key's previous created_revision and leaseID") } - ibytes := newRevBytes() - idxRev := revision{main: rev, sub: int64(len(tw.changes))} - revToBytes(idxRev, ibytes) + ibytes := NewRevBytes() + idxRev := Revision{Main: rev, Sub: int64(len(tw.changes))} + ibytes = RevToBytes(idxRev, ibytes) ver = ver + 1 kv := mvccpb.KeyValue{ @@ -216,25 +222,30 @@ func (tw *storeTxnWrite) put(key, value []byte, leaseID lease.LeaseID) { d, err := kv.Marshal() if err != nil { - tw.storeTxnRead.s.lg.Fatal( + tw.storeTxnCommon.s.lg.Fatal( "failed to marshal mvccpb.KeyValue", zap.Error(err), ) } tw.trace.Step("marshal mvccpb.KeyValue") - tw.tx.UnsafeSeqPut(buckets.Key, ibytes, d) + tw.tx.UnsafeSeqPut(schema.Key, ibytes, d) tw.s.kvindex.Put(key, idxRev) tw.changes = append(tw.changes, kv) tw.trace.Step("store kv pair into bolt db") + if oldLease == leaseID { + tw.trace.Step("attach lease to kv pair") + return + } + if oldLease != lease.NoLease { if tw.s.le == nil { panic("no lessor to detach lease") } err = tw.s.le.Detach(oldLease, []lease.LeaseItem{{Key: string(key)}}) if err != nil { - tw.storeTxnRead.s.lg.Error( + tw.storeTxnCommon.s.lg.Error( "failed to detach old lease from a key", zap.Error(err), ) @@ -268,26 +279,24 @@ func (tw *storeTxnWrite) deleteRange(key, end []byte) int64 { } func (tw *storeTxnWrite) delete(key []byte) { - ibytes := newRevBytes() - idxRev := revision{main: tw.beginRev + 1, sub: int64(len(tw.changes))} - revToBytes(idxRev, ibytes) - - ibytes = appendMarkTombstone(tw.storeTxnRead.s.lg, ibytes) + ibytes := NewRevBytes() + idxRev := newBucketKey(tw.beginRev+1, int64(len(tw.changes)), true) + ibytes = BucketKeyToBytes(idxRev, ibytes) kv := mvccpb.KeyValue{Key: key} d, err := kv.Marshal() if err != nil { - tw.storeTxnRead.s.lg.Fatal( + tw.storeTxnCommon.s.lg.Fatal( "failed to marshal mvccpb.KeyValue", zap.Error(err), ) } - tw.tx.UnsafeSeqPut(buckets.Key, ibytes, d) - err = tw.s.kvindex.Tombstone(key, idxRev) + tw.tx.UnsafeSeqPut(schema.Key, ibytes, d) + err = tw.s.kvindex.Tombstone(key, idxRev.Revision) if err != nil { - tw.storeTxnRead.s.lg.Fatal( + tw.storeTxnCommon.s.lg.Fatal( "failed to tombstone an existing key", zap.String("key", string(key)), zap.Error(err), @@ -301,7 +310,7 @@ func (tw *storeTxnWrite) delete(key []byte) { if leaseID != lease.NoLease { err = tw.s.le.Detach(leaseID, []lease.LeaseItem{item}) if err != nil { - tw.storeTxnRead.s.lg.Error( + tw.storeTxnCommon.s.lg.Error( "failed to detach old lease from a key", zap.Error(err), ) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/metrics.go similarity index 86% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/metrics.go index f28d114e2b..e060884780 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/metrics.go @@ -27,14 +27,8 @@ var ( Subsystem: "mvcc", Name: "range_total", Help: "Total number of ranges seen by this member.", - }) - rangeCounterDebug = prometheus.NewCounter( - prometheus.CounterOpts{ - Namespace: "etcd_debugging", - Subsystem: "mvcc", - Name: "range_total", - Help: "Total number of ranges seen by this member.", - }) + }, + ) putCounter = prometheus.NewCounter( prometheus.CounterOpts{ @@ -42,7 +36,8 @@ var ( Subsystem: "mvcc", Name: "put_total", Help: "Total number of puts seen by this member.", - }) + }, + ) deleteCounter = prometheus.NewCounter( prometheus.CounterOpts{ @@ -50,7 +45,8 @@ var ( Subsystem: "mvcc", Name: "delete_total", Help: "Total number of deletes seen by this member.", - }) + }, + ) txnCounter = prometheus.NewCounter( prometheus.CounterOpts{ @@ -58,7 +54,8 @@ var ( Subsystem: "mvcc", Name: "txn_total", Help: "Total number of txns seen by this member.", - }) + }, + ) keysGauge = prometheus.NewGauge( prometheus.GaugeOpts{ @@ -66,7 +63,8 @@ var ( Subsystem: "mvcc", Name: "keys_total", Help: "Total number of keys.", - }) + }, + ) watchStreamGauge = prometheus.NewGauge( prometheus.GaugeOpts{ @@ -74,7 +72,8 @@ var ( Subsystem: "mvcc", Name: "watch_stream_total", Help: "Total number of watch streams.", - }) + }, + ) watcherGauge = prometheus.NewGauge( prometheus.GaugeOpts{ @@ -82,7 +81,8 @@ var ( Subsystem: "mvcc", Name: "watcher_total", Help: "Total number of watchers.", - }) + }, + ) slowWatcherGauge = prometheus.NewGauge( prometheus.GaugeOpts{ @@ -90,7 +90,8 @@ var ( Subsystem: "mvcc", Name: "slow_watcher_total", Help: "Total number of unsynced slow watchers.", - }) + }, + ) totalEventsCounter = prometheus.NewCounter( prometheus.CounterOpts{ @@ -98,7 +99,8 @@ var ( Subsystem: "mvcc", Name: "events_total", Help: "Total number of events sent by this member.", - }) + }, + ) pendingEventsGauge = prometheus.NewGauge( prometheus.GaugeOpts{ @@ -106,7 +108,8 @@ var ( Subsystem: "mvcc", Name: "pending_events_total", Help: "Total number of pending events to be sent.", - }) + }, + ) indexCompactionPauseMs = prometheus.NewHistogram( prometheus.HistogramOpts{ @@ -118,7 +121,8 @@ var ( // lowest bucket start of upper bound 0.5 ms with factor 2 // highest bucket start of 0.5 ms * 2^13 == 4.096 sec Buckets: prometheus.ExponentialBuckets(0.5, 2, 14), - }) + }, + ) dbCompactionPauseMs = prometheus.NewHistogram( prometheus.HistogramOpts{ @@ -130,7 +134,8 @@ var ( // lowest bucket start of upper bound 1 ms with factor 2 // highest bucket start of 1 ms * 2^12 == 4.096 sec Buckets: prometheus.ExponentialBuckets(1, 2, 13), - }) + }, + ) dbCompactionTotalMs = prometheus.NewHistogram( prometheus.HistogramOpts{ @@ -142,7 +147,8 @@ var ( // lowest bucket start of upper bound 100 ms with factor 2 // highest bucket start of 100 ms * 2^13 == 8.192 sec Buckets: prometheus.ExponentialBuckets(100, 2, 14), - }) + }, + ) dbCompactionLast = prometheus.NewGauge( prometheus.GaugeOpts{ @@ -150,7 +156,8 @@ var ( Subsystem: "mvcc", Name: "db_compaction_last", Help: "The unix time of the last db compaction. Resets to 0 on start.", - }) + }, + ) dbCompactionKeysCounter = prometheus.NewCounter( prometheus.CounterOpts{ @@ -158,14 +165,16 @@ var ( Subsystem: "mvcc", Name: "db_compaction_keys_total", Help: "Total number of db keys compacted.", - }) + }, + ) - dbTotalSize = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "mvcc", - Name: "db_total_size_in_bytes", - Help: "Total size of the underlying database physically allocated in bytes.", - }, + dbTotalSize = prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "mvcc", + Name: "db_total_size_in_bytes", + Help: "Total size of the underlying database physically allocated in bytes.", + }, func() float64 { reportDbTotalSizeInBytesMu.RLock() defer reportDbTotalSizeInBytesMu.RUnlock() @@ -176,16 +185,13 @@ var ( reportDbTotalSizeInBytesMu sync.RWMutex reportDbTotalSizeInBytes = func() float64 { return 0 } - // overridden by mvcc initialization - reportDbTotalSizeInBytesDebugMu sync.RWMutex - reportDbTotalSizeInBytesDebug = func() float64 { return 0 } - - dbTotalSizeInUse = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "mvcc", - Name: "db_total_size_in_use_in_bytes", - Help: "Total size of the underlying database logically in use in bytes.", - }, + dbTotalSizeInUse = prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "mvcc", + Name: "db_total_size_in_use_in_bytes", + Help: "Total size of the underlying database logically in use in bytes.", + }, func() float64 { reportDbTotalSizeInUseInBytesMu.RLock() defer reportDbTotalSizeInUseInBytesMu.RUnlock() @@ -196,12 +202,13 @@ var ( reportDbTotalSizeInUseInBytesMu sync.RWMutex reportDbTotalSizeInUseInBytes = func() float64 { return 0 } - dbOpenReadTxN = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ - Namespace: "etcd", - Subsystem: "mvcc", - Name: "db_open_read_transactions", - Help: "The number of currently open read transactions", - }, + dbOpenReadTxN = prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: "etcd", + Subsystem: "mvcc", + Name: "db_open_read_transactions", + Help: "The number of currently open read transactions", + }, func() float64 { reportDbOpenReadTxNMu.RLock() @@ -237,12 +244,13 @@ var ( Buckets: prometheus.ExponentialBuckets(.01, 2, 15), }) - currentRev = prometheus.NewGaugeFunc(prometheus.GaugeOpts{ - Namespace: "etcd_debugging", - Subsystem: "mvcc", - Name: "current_revision", - Help: "The current revision of store.", - }, + currentRev = prometheus.NewGaugeFunc( + prometheus.GaugeOpts{ + Namespace: "etcd_debugging", + Subsystem: "mvcc", + Name: "current_revision", + Help: "The current revision of store.", + }, func() float64 { reportCurrentRevMu.RLock() defer reportCurrentRevMu.RUnlock() @@ -280,7 +288,6 @@ var ( func init() { prometheus.MustRegister(rangeCounter) - prometheus.MustRegister(rangeCounterDebug) prometheus.MustRegister(putCounter) prometheus.MustRegister(deleteCounter) prometheus.MustRegister(txnCounter) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics_txn.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/metrics_txn.go similarity index 96% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics_txn.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/metrics_txn.go index af844f8468..aef877a1c1 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/metrics_txn.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/metrics_txn.go @@ -61,7 +61,6 @@ func (tw *metricsTxnWrite) End() { ranges := float64(tw.ranges) rangeCounter.Add(ranges) - rangeCounterDebug.Add(ranges) // TODO: remove in 3.5 release puts := float64(tw.puts) putCounter.Add(puts) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/revision.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/revision.go new file mode 100644 index 0000000000..7d1addf264 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/revision.go @@ -0,0 +1,126 @@ +// Copyright 2015 The etcd 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 mvcc + +import ( + "encoding/binary" + "fmt" +) + +const ( + // revBytesLen is the byte length of a normal revision. + // First 8 bytes is the revision.main in big-endian format. The 9th byte + // is a '_'. The last 8 bytes is the revision.sub in big-endian format. + revBytesLen = 8 + 1 + 8 + // markedRevBytesLen is the byte length of marked revision. + // The first `revBytesLen` bytes represents a normal revision. The last + // one byte is the mark. + markedRevBytesLen = revBytesLen + 1 + markBytePosition = markedRevBytesLen - 1 + markTombstone byte = 't' +) + +type Revision struct { + // Main is the main revision of a set of changes that happen atomically. + Main int64 + // Sub is the sub revision of a change in a set of changes that happen + // atomically. Each change has different increasing sub revision in that + // set. + Sub int64 +} + +func (a Revision) GreaterThan(b Revision) bool { + if a.Main > b.Main { + return true + } + if a.Main < b.Main { + return false + } + return a.Sub > b.Sub +} + +func RevToBytes(rev Revision, bytes []byte) []byte { + return BucketKeyToBytes(newBucketKey(rev.Main, rev.Sub, false), bytes) +} + +func BytesToRev(bytes []byte) Revision { + return BytesToBucketKey(bytes).Revision +} + +// BucketKey indicates modification of the key-value space. +// The set of changes that share same main revision changes the key-value space atomically. +type BucketKey struct { + Revision + tombstone bool +} + +func newBucketKey(main, sub int64, isTombstone bool) BucketKey { + return BucketKey{ + Revision: Revision{ + Main: main, + Sub: sub, + }, + tombstone: isTombstone, + } +} + +func NewRevBytes() []byte { + return make([]byte, revBytesLen, markedRevBytesLen) +} + +func BucketKeyToBytes(rev BucketKey, bytes []byte) []byte { + binary.BigEndian.PutUint64(bytes, uint64(rev.Main)) + bytes[8] = '_' + binary.BigEndian.PutUint64(bytes[9:], uint64(rev.Sub)) + if rev.tombstone { + switch len(bytes) { + case revBytesLen: + bytes = append(bytes, markTombstone) + case markedRevBytesLen: + bytes[markBytePosition] = markTombstone + } + } + return bytes +} + +func BytesToBucketKey(bytes []byte) BucketKey { + if (len(bytes) != revBytesLen) && (len(bytes) != markedRevBytesLen) { + panic(fmt.Sprintf("invalid revision length: %d", len(bytes))) + } + if bytes[8] != '_' { + panic(fmt.Sprintf("invalid separator in bucket key: %q", bytes[8])) + } + main := int64(binary.BigEndian.Uint64(bytes[0:8])) + sub := int64(binary.BigEndian.Uint64(bytes[9:])) + if main < 0 || sub < 0 { + panic(fmt.Sprintf("negative revision: main=%d sub=%d", main, sub)) + } + return BucketKey{ + Revision: Revision{ + Main: main, + Sub: sub, + }, + tombstone: isTombstone(bytes), + } +} + +// isTombstone checks whether the revision bytes is a tombstone. +func isTombstone(b []byte) bool { + return len(b) == markedRevBytesLen && b[markBytePosition] == markTombstone +} + +func IsTombstone(b []byte) bool { + return isTombstone(b) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/store.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/store.go new file mode 100644 index 0000000000..523b8cd8f2 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/store.go @@ -0,0 +1,60 @@ +// Copyright 2015 The etcd 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 mvcc + +import ( + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" +) + +func UnsafeReadFinishedCompact(tx backend.UnsafeReader) (int64, bool) { + _, finishedCompactBytes := tx.UnsafeRange(schema.Meta, schema.FinishedCompactKeyName, nil, 0) + if len(finishedCompactBytes) != 0 { + return BytesToRev(finishedCompactBytes[0]).Main, true + } + return 0, false +} + +func UnsafeReadScheduledCompact(tx backend.UnsafeReader) (int64, bool) { + _, scheduledCompactBytes := tx.UnsafeRange(schema.Meta, schema.ScheduledCompactKeyName, nil, 0) + if len(scheduledCompactBytes) != 0 { + return BytesToRev(scheduledCompactBytes[0]).Main, true + } + return 0, false +} + +func SetScheduledCompact(tx backend.BatchTx, value int64) { + tx.LockInsideApply() + defer tx.Unlock() + UnsafeSetScheduledCompact(tx, value) +} + +func UnsafeSetScheduledCompact(tx backend.UnsafeWriter, value int64) { + rbytes := NewRevBytes() + rbytes = RevToBytes(Revision{Main: value}, rbytes) + tx.UnsafePut(schema.Meta, schema.ScheduledCompactKeyName, rbytes) +} + +func SetFinishedCompact(tx backend.BatchTx, value int64) { + tx.LockInsideApply() + defer tx.Unlock() + UnsafeSetFinishedCompact(tx, value) +} + +func UnsafeSetFinishedCompact(tx backend.UnsafeWriter, value int64) { + rbytes := NewRevBytes() + rbytes = RevToBytes(Revision{Main: value}, rbytes) + tx.UnsafePut(schema.Meta, schema.FinishedCompactKeyName, rbytes) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watchable_store.go similarity index 80% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watchable_store.go index cdac20ad5e..67b2d7f2d3 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watchable_store.go @@ -15,17 +15,19 @@ package mvcc import ( + "fmt" "sync" "time" + "go.uber.org/zap" + "go.etcd.io/etcd/api/v3/mvccpb" + "go.etcd.io/etcd/client/pkg/v3/verify" clientv3 "go.etcd.io/etcd/client/v3" "go.etcd.io/etcd/pkg/v3/traceutil" "go.etcd.io/etcd/server/v3/lease" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" - - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/schema" ) // non-const so modifiable by tests @@ -37,8 +39,13 @@ var ( // maxWatchersPerSync is the number of watchers to sync in a single batch maxWatchersPerSync = 512 + + // maxResyncPeriod is the period of executing resync. + watchResyncPeriod = 100 * time.Millisecond ) +func ChanBufLen() int { return chanBufLen } + type watchable interface { watch(key, end []byte, startRev int64, id WatchID, ch chan<- WatchResponse, fcs ...FilterFunc) (*watcher, cancelFunc) progress(w *watcher) @@ -68,12 +75,18 @@ type watchableStore struct { wg sync.WaitGroup } +var _ WatchableKV = (*watchableStore)(nil) + // cancelFunc updates unsynced and synced maps when running // cancel operations. type cancelFunc func() func New(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfig) WatchableKV { - return newWatchableStore(lg, b, le, cfg) + s := newWatchableStore(lg, b, le, cfg) + s.wg.Add(2) + go s.syncWatchersLoop() + go s.syncVictimsLoop() + return s } func newWatchableStore(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg StoreConfig) *watchableStore { @@ -93,9 +106,6 @@ func newWatchableStore(lg *zap.Logger, b backend.Backend, le lease.Lessor, cfg S // use this store as the deleter so revokes trigger watch events s.le.SetRangeDeleter(func() lease.TxnDelete { return s.Write(traceutil.TODO()) }) } - s.wg.Add(2) - go s.syncWatchersLoop() - go s.syncVictimsLoop() return s } @@ -117,12 +127,13 @@ func (s *watchableStore) NewWatchStream() WatchStream { func (s *watchableStore) watch(key, end []byte, startRev int64, id WatchID, ch chan<- WatchResponse, fcs ...FilterFunc) (*watcher, cancelFunc) { wa := &watcher{ - key: key, - end: end, - minRev: startRev, - id: id, - ch: ch, - fcs: fcs, + key: key, + end: end, + startRev: startRev, + minRev: startRev, + id: id, + ch: ch, + fcs: fcs, } s.mu.Lock() @@ -157,12 +168,12 @@ func (s *watchableStore) cancelWatcher(wa *watcher) { } else if s.synced.delete(wa) { watcherGauge.Dec() break - } else if wa.compacted { - watcherGauge.Dec() - break } else if wa.ch == nil { // already canceled (e.g., cancel/close race) break + } else if wa.compacted { + watcherGauge.Dec() + break } if !wa.victim { @@ -213,6 +224,10 @@ func (s *watchableStore) Restore(b backend.Backend) error { func (s *watchableStore) syncWatchersLoop() { defer s.wg.Done() + delayTicker := time.NewTicker(watchResyncPeriod) + defer delayTicker.Stop() + var evs []mvccpb.Event + for { s.mu.RLock() st := time.Now() @@ -221,19 +236,19 @@ func (s *watchableStore) syncWatchersLoop() { unsyncedWatchers := 0 if lastUnsyncedWatchers > 0 { - unsyncedWatchers = s.syncWatchers() + unsyncedWatchers, evs = s.syncWatchers(evs) } syncDuration := time.Since(st) - waitDuration := 100 * time.Millisecond + delayTicker.Reset(watchResyncPeriod) // more work pending? if unsyncedWatchers != 0 && lastUnsyncedWatchers > unsyncedWatchers { // be fair to other store operations by yielding time taken - waitDuration = syncDuration + delayTicker.Reset(syncDuration) } select { - case <-time.After(waitDuration): + case <-delayTicker.C: case <-s.stopc: return } @@ -280,15 +295,14 @@ func (s *watchableStore) moveVictims() (moved int) { for w, eb := range wb { // watcher has observed the store up to, but not including, w.minRev rev := w.minRev - 1 - if w.send(WatchResponse{WatchID: w.id, Events: eb.evs, Revision: rev}) { - pendingEventsGauge.Add(float64(len(eb.evs))) - } else { + if !w.send(WatchResponse{WatchID: w.id, Events: eb.evs, Revision: rev}) { if newVictim == nil { newVictim = make(watcherBatch) } newVictim[w] = eb continue } + pendingEventsGauge.Add(float64(len(eb.evs))) moved++ } @@ -330,12 +344,12 @@ func (s *watchableStore) moveVictims() (moved int) { // 2. iterate over the set to get the minimum revision and remove compacted watchers // 3. use minimum revision to get all key-value pairs and send those events to watchers // 4. remove synced watchers in set from unsynced group and move to synced group -func (s *watchableStore) syncWatchers() int { +func (s *watchableStore) syncWatchers(evs []mvccpb.Event) (int, []mvccpb.Event) { s.mu.Lock() defer s.mu.Unlock() if s.unsynced.size() == 0 { - return 0 + return 0, []mvccpb.Event{} } s.store.revMu.RLock() @@ -348,22 +362,9 @@ func (s *watchableStore) syncWatchers() int { compactionRev := s.store.compactMainRev wg, minRev := s.unsynced.choose(maxWatchersPerSync, curRev, compactionRev) - minBytes, maxBytes := newRevBytes(), newRevBytes() - revToBytes(revision{main: minRev}, minBytes) - revToBytes(revision{main: curRev + 1}, maxBytes) - - // UnsafeRange returns keys and values. And in boltdb, keys are revisions. - // values are actual key-value pairs in backend. - tx := s.store.b.ReadTx() - tx.RLock() - revs, vs := tx.UnsafeRange(buckets.Key, minBytes, maxBytes, 0) - evs := kvsToEvents(s.store.lg, wg, revs, vs) - // Must unlock after kvsToEvents, because vs (come from boltdb memory) is not deep copy. - // We can only unlock after Unmarshal, which will do deep copy. - // Otherwise we will trigger SIGSEGV during boltdb re-mmap. - tx.RUnlock() + evs = rangeEventsWithReuse(s.store.lg, s.store.b, evs, minRev, curRev+1) - var victims watcherBatch + victims := make(watcherBatch) wb := newWatcherBatch(wg, evs) for w := range wg.watchers { if w.minRev < compactionRev { @@ -371,7 +372,7 @@ func (s *watchableStore) syncWatchers() int { // Next retry of syncWatchers would try to resend the compacted watch response to w.ch continue } - w.minRev = curRev + 1 + w.minRev = max(curRev+1, w.minRev) eb, ok := wb[w] if !ok { @@ -388,9 +389,6 @@ func (s *watchableStore) syncWatchers() int { if w.send(WatchResponse{WatchID: w.id, Events: eb.evs, Revision: curRev}) { pendingEventsGauge.Add(float64(len(eb.evs))) } else { - if victims == nil { - victims = make(watcherBatch) - } w.victim = true } @@ -413,26 +411,73 @@ func (s *watchableStore) syncWatchers() int { } slowWatcherGauge.Set(float64(s.unsynced.size() + vsz)) - return s.unsynced.size() + return s.unsynced.size(), evs +} + +// rangeEventsWithReuse returns events in range [minRev, maxRev), while reusing already provided events. +func rangeEventsWithReuse(lg *zap.Logger, b backend.Backend, evs []mvccpb.Event, minRev, maxRev int64) []mvccpb.Event { + if len(evs) == 0 { + return rangeEvents(lg, b, minRev, maxRev) + } + // append from left + if evs[0].Kv.ModRevision > minRev { + evs = append(rangeEvents(lg, b, minRev, evs[0].Kv.ModRevision), evs...) + } + // cut from left + prefixIndex := 0 + for prefixIndex < len(evs) && evs[prefixIndex].Kv.ModRevision < minRev { + prefixIndex++ + } + evs = evs[prefixIndex:] + + if len(evs) == 0 { + return rangeEvents(lg, b, minRev, maxRev) + } + // append from right + if evs[len(evs)-1].Kv.ModRevision+1 < maxRev { + evs = append(evs, rangeEvents(lg, b, evs[len(evs)-1].Kv.ModRevision+1, maxRev)...) + } + // cut from right + suffixIndex := len(evs) - 1 + for suffixIndex >= 0 && evs[suffixIndex].Kv.ModRevision >= maxRev { + suffixIndex-- + } + evs = evs[:suffixIndex+1] + return evs +} + +// rangeEvents returns events in range [minRev, maxRev). +func rangeEvents(lg *zap.Logger, b backend.Backend, minRev, maxRev int64) []mvccpb.Event { + minBytes, maxBytes := NewRevBytes(), NewRevBytes() + minBytes = RevToBytes(Revision{Main: minRev}, minBytes) + maxBytes = RevToBytes(Revision{Main: maxRev}, maxBytes) + + // UnsafeRange returns keys and values. And in boltdb, keys are revisions. + // values are actual key-value pairs in backend. + tx := b.ReadTx() + tx.RLock() + revs, vs := tx.UnsafeRange(schema.Key, minBytes, maxBytes, 0) + evs := kvsToEvents(lg, revs, vs) + // Must unlock after kvsToEvents, because vs (come from boltdb memory) is not deep copy. + // We can only unlock after Unmarshal, which will do deep copy. + // Otherwise we will trigger SIGSEGV during boltdb re-mmap. + tx.RUnlock() + return evs } // kvsToEvents gets all events for the watchers from all key-value pairs -func kvsToEvents(lg *zap.Logger, wg *watcherGroup, revs, vals [][]byte) (evs []mvccpb.Event) { +func kvsToEvents(lg *zap.Logger, revs, vals [][]byte) (evs []mvccpb.Event) { for i, v := range vals { var kv mvccpb.KeyValue if err := kv.Unmarshal(v); err != nil { lg.Panic("failed to unmarshal mvccpb.KeyValue", zap.Error(err)) } - if !wg.contains(string(kv.Key)) { - continue - } - ty := mvccpb.PUT if isTombstone(revs[i]) { ty = mvccpb.DELETE // patch in mod revision so watchers won't skip - kv.ModRevision = bytesToRev(revs[i]).main + kv.ModRevision = BytesToRev(revs[i]).Main } evs = append(evs, mvccpb.Event{Kv: &kv, Type: ty}) } @@ -442,7 +487,7 @@ func kvsToEvents(lg *zap.Logger, wg *watcherGroup, revs, vals [][]byte) (evs []m // notify notifies the fact that given event at the given rev just happened to // watchers that watch on the key of the event. func (s *watchableStore) notify(rev int64, evs []mvccpb.Event) { - var victim watcherBatch + victim := make(watcherBatch) for w, eb := range newWatcherBatch(&s.synced, evs) { if eb.revs != 1 { s.store.lg.Panic( @@ -454,9 +499,6 @@ func (s *watchableStore) notify(rev int64, evs []mvccpb.Event) { pendingEventsGauge.Add(float64(len(eb.evs))) } else { // move slow watcher to victims - if victim == nil { - victim = make(watcherBatch) - } w.victim = true victim[w] = eb s.synced.delete(w) @@ -471,7 +513,7 @@ func (s *watchableStore) notify(rev int64, evs []mvccpb.Event) { } func (s *watchableStore) addVictim(victim watcherBatch) { - if victim == nil { + if len(victim) == 0 { return } s.victims = append(s.victims, victim) @@ -495,11 +537,15 @@ func (s *watchableStore) progressIfSync(watchers map[WatchID]*watcher, responseW s.mu.RLock() defer s.mu.RUnlock() + rev := s.rev() // Any watcher unsynced? for _, w := range watchers { if _, ok := s.synced.watchers[w]; !ok { return false } + if rev < w.startRev { + return false + } } // If all watchers are synchronised, send out progress @@ -508,7 +554,7 @@ func (s *watchableStore) progressIfSync(watchers map[WatchID]*watcher, responseW // notification will be broadcasted client-side if required // (see dispatchEvent in client/v3/watch.go) for _, w := range watchers { - w.send(WatchResponse{WatchID: responseWatchID, Revision: s.rev()}) + w.send(WatchResponse{WatchID: responseWatchID, Revision: rev}) return true } return true @@ -535,6 +581,7 @@ type watcher struct { // except when the watcher were to be moved from "synced" watcher group restore bool + startRev int64 // minRev is the minimum revision update the watcher will accept minRev int64 id WatchID @@ -565,6 +612,16 @@ func (w *watcher) send(wr WatchResponse) bool { wr.Events = ne } + verify.Verify(func() { + if w.startRev > 0 { + for _, ev := range wr.Events { + if ev.Kv.ModRevision < w.startRev { + panic(fmt.Sprintf("Event.ModRevision(%d) is less than the w.startRev(%d) for watchID: %d", ev.Kv.ModRevision, w.startRev, w.id)) + } + } + } + }) + // if all events are filtered out, we should send nothing. if !progressEvent && len(wr.Events) == 0 { return true diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store_txn.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watchable_store_txn.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watchable_store_txn.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watchable_store_txn.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watcher.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watcher.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher_group.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watcher_group.go similarity index 97% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher_group.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watcher_group.go index 356b49e641..c9db0e2bd9 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/watcher_group.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/mvcc/watcher_group.go @@ -22,12 +22,10 @@ import ( "go.etcd.io/etcd/pkg/v3/adt" ) -var ( - // watchBatchMaxRevs is the maximum distinct revisions that - // may be sent to an unsynced watcher at a time. Declared as - // var instead of const for testing purposes. - watchBatchMaxRevs = 1000 -) +// watchBatchMaxRevs is the maximum distinct revisions that +// may be sent to an unsynced watcher at a time. Declared as +// var instead of const for testing purposes. +var watchBatchMaxRevs = 1000 type eventBatch struct { // evs is a batch of revision-ordered events diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/quota.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/quota.go similarity index 72% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/quota.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/quota.go index c5fadc4b1e..f9ff72d7e8 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/quota.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/quota.go @@ -12,15 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -package etcdserver +package storage import ( "sync" - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - humanize "github.com/dustin/go-humanize" "go.uber.org/zap" + + pb "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/server/v3/storage/backend" ) const ( @@ -37,28 +38,28 @@ const ( // too few resources available within the quota to apply the request. type Quota interface { // Available judges whether the given request fits within the quota. - Available(req interface{}) bool + Available(req any) bool // Cost computes the charge against the quota for a given request. - Cost(req interface{}) int + Cost(req any) int // Remaining is the amount of charge left for the quota. Remaining() int64 } type passthroughQuota struct{} -func (*passthroughQuota) Available(interface{}) bool { return true } -func (*passthroughQuota) Cost(interface{}) int { return 0 } -func (*passthroughQuota) Remaining() int64 { return 1 } +func (*passthroughQuota) Available(any) bool { return true } +func (*passthroughQuota) Cost(any) int { return 0 } +func (*passthroughQuota) Remaining() int64 { return 1 } -type backendQuota struct { - s *EtcdServer +type BackendQuota struct { + be backend.Backend maxBackendBytes int64 } const ( // leaseOverhead is an estimate for the cost of storing a lease leaseOverhead = 64 - // kvOverhead is an estimate for the cost of storing a key's metadata + // kvOverhead is an estimate for the cost of storing a key's Metadata kvOverhead = 256 ) @@ -71,23 +72,21 @@ var ( ) // NewBackendQuota creates a quota layer with the given storage limit. -func NewBackendQuota(s *EtcdServer, name string) Quota { - lg := s.Logger() - quotaBackendBytes.Set(float64(s.Cfg.QuotaBackendBytes)) - - if s.Cfg.QuotaBackendBytes < 0 { +func NewBackendQuota(lg *zap.Logger, quotaBackendBytesCfg int64, be backend.Backend, name string) Quota { + quotaBackendBytes.Set(float64(quotaBackendBytesCfg)) + if quotaBackendBytesCfg < 0 { // disable quotas if negative quotaLogOnce.Do(func() { lg.Info( "disabled backend quota", zap.String("quota-name", name), - zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes), + zap.Int64("quota-size-bytes", quotaBackendBytesCfg), ) }) return &passthroughQuota{} } - if s.Cfg.QuotaBackendBytes == 0 { + if quotaBackendBytesCfg == 0 { // use default size if no quota size given quotaLogOnce.Do(func() { if lg != nil { @@ -100,16 +99,16 @@ func NewBackendQuota(s *EtcdServer, name string) Quota { } }) quotaBackendBytes.Set(float64(DefaultQuotaBytes)) - return &backendQuota{s, DefaultQuotaBytes} + return &BackendQuota{be, DefaultQuotaBytes} } quotaLogOnce.Do(func() { - if s.Cfg.QuotaBackendBytes > MaxQuotaBytes { + if quotaBackendBytesCfg > MaxQuotaBytes { lg.Warn( "quota exceeds the maximum value", zap.String("quota-name", name), - zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes), - zap.String("quota-size", humanize.Bytes(uint64(s.Cfg.QuotaBackendBytes))), + zap.Int64("quota-size-bytes", quotaBackendBytesCfg), + zap.String("quota-size", humanize.Bytes(uint64(quotaBackendBytesCfg))), zap.Int64("quota-maximum-size-bytes", MaxQuotaBytes), zap.String("quota-maximum-size", maxQuotaSize), ) @@ -117,24 +116,24 @@ func NewBackendQuota(s *EtcdServer, name string) Quota { lg.Info( "enabled backend quota", zap.String("quota-name", name), - zap.Int64("quota-size-bytes", s.Cfg.QuotaBackendBytes), - zap.String("quota-size", humanize.Bytes(uint64(s.Cfg.QuotaBackendBytes))), + zap.Int64("quota-size-bytes", quotaBackendBytesCfg), + zap.String("quota-size", humanize.Bytes(uint64(quotaBackendBytesCfg))), ) }) - return &backendQuota{s, s.Cfg.QuotaBackendBytes} + return &BackendQuota{be, quotaBackendBytesCfg} } -func (b *backendQuota) Available(v interface{}) bool { +func (b *BackendQuota) Available(v any) bool { cost := b.Cost(v) // if there are no mutating requests, it's safe to pass through if cost == 0 { return true } - // TODO: maybe optimize backend.Size() - return b.s.Backend().Size()+int64(cost) < b.maxBackendBytes + // TODO: maybe optimize Backend.Size() + return b.be.Size()+int64(cost) < b.maxBackendBytes } -func (b *backendQuota) Cost(v interface{}) int { +func (b *BackendQuota) Cost(v any) int { switch r := v.(type) { case *pb.PutRequest: return costPut(r) @@ -172,6 +171,6 @@ func costTxn(r *pb.TxnRequest) int { return sizeSuccess } -func (b *backendQuota) Remaining() int64 { - return b.maxBackendBytes - b.s.Backend().Size() +func (b *BackendQuota) Remaining() int64 { + return b.maxBackendBytes - b.be.Size() } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/actions.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/actions.go new file mode 100644 index 0000000000..8d18cee863 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/actions.go @@ -0,0 +1,93 @@ +// Copyright 2021 The etcd 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 schema + +import ( + "go.uber.org/zap" + + "go.etcd.io/etcd/server/v3/storage/backend" +) + +type action interface { + // unsafeDo executes the action and returns revert action, when executed + // should restore the state from before. + unsafeDo(tx backend.UnsafeReadWriter) (revert action, err error) +} + +type setKeyAction struct { + Bucket backend.Bucket + FieldName []byte + FieldValue []byte +} + +func (a setKeyAction) unsafeDo(tx backend.UnsafeReadWriter) (action, error) { + revert := restoreFieldValueAction(tx, a.Bucket, a.FieldName) + tx.UnsafePut(a.Bucket, a.FieldName, a.FieldValue) + return revert, nil +} + +type deleteKeyAction struct { + Bucket backend.Bucket + FieldName []byte +} + +func (a deleteKeyAction) unsafeDo(tx backend.UnsafeReadWriter) (action, error) { + revert := restoreFieldValueAction(tx, a.Bucket, a.FieldName) + tx.UnsafeDelete(a.Bucket, a.FieldName) + return revert, nil +} + +func restoreFieldValueAction(tx backend.UnsafeReader, bucket backend.Bucket, fieldName []byte) action { + _, vs := tx.UnsafeRange(bucket, fieldName, nil, 1) + if len(vs) == 1 { + return &setKeyAction{ + Bucket: bucket, + FieldName: fieldName, + FieldValue: vs[0], + } + } + return &deleteKeyAction{ + Bucket: bucket, + FieldName: fieldName, + } +} + +type ActionList []action + +// unsafeExecute executes actions one by one. If one of actions returns error, +// it will revert them. +func (as ActionList) unsafeExecute(lg *zap.Logger, tx backend.UnsafeReadWriter) error { + revertActions := make(ActionList, 0, len(as)) + for _, a := range as { + revert, err := a.unsafeDo(tx) + if err != nil { + revertActions.unsafeExecuteInReversedOrder(lg, tx) + return err + } + revertActions = append(revertActions, revert) + } + return nil +} + +// unsafeExecuteInReversedOrder executes actions in revered order. Will panic on +// action error. Should be used when reverting. +func (as ActionList) unsafeExecuteInReversedOrder(lg *zap.Logger, tx backend.UnsafeReadWriter) { + for j := len(as) - 1; j >= 0; j-- { + _, err := as[j].unsafeDo(tx) + if err != nil { + lg.Panic("Cannot recover from revert error", zap.Error(err)) + } + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/alarm.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/alarm.go new file mode 100644 index 0000000000..929fbd4ceb --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/alarm.go @@ -0,0 +1,105 @@ +// Copyright 2021 The etcd 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 schema + +import ( + "go.uber.org/zap" + + "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/server/v3/storage/backend" +) + +type AlarmBackend interface { + CreateAlarmBucket() + MustPutAlarm(member *etcdserverpb.AlarmMember) + MustDeleteAlarm(alarm *etcdserverpb.AlarmMember) + GetAllAlarms() ([]*etcdserverpb.AlarmMember, error) + ForceCommit() +} + +type alarmBackend struct { + lg *zap.Logger + be backend.Backend +} + +func NewAlarmBackend(lg *zap.Logger, be backend.Backend) AlarmBackend { + return &alarmBackend{ + lg: lg, + be: be, + } +} + +func (s *alarmBackend) CreateAlarmBucket() { + tx := s.be.BatchTx() + tx.LockOutsideApply() + defer tx.Unlock() + tx.UnsafeCreateBucket(Alarm) +} + +func (s *alarmBackend) MustPutAlarm(alarm *etcdserverpb.AlarmMember) { + tx := s.be.BatchTx() + tx.LockInsideApply() + defer tx.Unlock() + s.mustUnsafePutAlarm(tx, alarm) +} + +func (s *alarmBackend) mustUnsafePutAlarm(tx backend.UnsafeWriter, alarm *etcdserverpb.AlarmMember) { + v, err := alarm.Marshal() + if err != nil { + s.lg.Panic("failed to marshal alarm member", zap.Error(err)) + } + + tx.UnsafePut(Alarm, v, nil) +} + +func (s *alarmBackend) MustDeleteAlarm(alarm *etcdserverpb.AlarmMember) { + tx := s.be.BatchTx() + tx.LockInsideApply() + defer tx.Unlock() + s.mustUnsafeDeleteAlarm(tx, alarm) +} + +func (s *alarmBackend) mustUnsafeDeleteAlarm(tx backend.UnsafeWriter, alarm *etcdserverpb.AlarmMember) { + v, err := alarm.Marshal() + if err != nil { + s.lg.Panic("failed to marshal alarm member", zap.Error(err)) + } + + tx.UnsafeDelete(Alarm, v) +} + +func (s *alarmBackend) GetAllAlarms() ([]*etcdserverpb.AlarmMember, error) { + tx := s.be.ReadTx() + tx.RLock() + defer tx.RUnlock() + return s.unsafeGetAllAlarms(tx) +} + +func (s *alarmBackend) unsafeGetAllAlarms(tx backend.UnsafeReader) ([]*etcdserverpb.AlarmMember, error) { + var ms []*etcdserverpb.AlarmMember + err := tx.UnsafeForEach(Alarm, func(k, v []byte) error { + var m etcdserverpb.AlarmMember + if err := m.Unmarshal(k); err != nil { + return err + } + ms = append(ms, &m) + return nil + }) + return ms, err +} + +func (s alarmBackend) ForceCommit() { + s.be.ForceCommit() +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth.go new file mode 100644 index 0000000000..b91b6eb6ac --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth.go @@ -0,0 +1,152 @@ +// Copyright 2021 The etcd 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 schema + +import ( + "bytes" + "encoding/binary" + + "go.uber.org/zap" + + "go.etcd.io/etcd/server/v3/auth" + "go.etcd.io/etcd/server/v3/storage/backend" +) + +const ( + revBytesLen = 8 +) + +var ( + authEnabled = []byte{1} + authDisabled = []byte{0} +) + +type authBackend struct { + be backend.Backend + lg *zap.Logger +} + +var _ auth.AuthBackend = (*authBackend)(nil) + +func NewAuthBackend(lg *zap.Logger, be backend.Backend) auth.AuthBackend { + return &authBackend{ + be: be, + lg: lg, + } +} + +func (abe *authBackend) CreateAuthBuckets() { + tx := abe.be.BatchTx() + tx.LockOutsideApply() + defer tx.Unlock() + tx.UnsafeCreateBucket(Auth) + tx.UnsafeCreateBucket(AuthUsers) + tx.UnsafeCreateBucket(AuthRoles) +} + +func (abe *authBackend) ForceCommit() { + abe.be.ForceCommit() +} + +func (abe *authBackend) ReadTx() auth.AuthReadTx { + return &authReadTx{tx: abe.be.ReadTx(), lg: abe.lg} +} + +func (abe *authBackend) BatchTx() auth.AuthBatchTx { + return &authBatchTx{tx: abe.be.BatchTx(), lg: abe.lg} +} + +type authReadTx struct { + tx backend.ReadTx + lg *zap.Logger +} + +type authBatchTx struct { + tx backend.BatchTx + lg *zap.Logger +} + +var ( + _ auth.AuthReadTx = (*authReadTx)(nil) + _ auth.AuthBatchTx = (*authBatchTx)(nil) +) + +func (atx *authBatchTx) UnsafeSaveAuthEnabled(enabled bool) { + if enabled { + atx.tx.UnsafePut(Auth, AuthEnabledKeyName, authEnabled) + } else { + atx.tx.UnsafePut(Auth, AuthEnabledKeyName, authDisabled) + } +} + +func (atx *authBatchTx) UnsafeSaveAuthRevision(rev uint64) { + revBytes := make([]byte, revBytesLen) + binary.BigEndian.PutUint64(revBytes, rev) + atx.tx.UnsafePut(Auth, AuthRevisionKeyName, revBytes) +} + +func (atx *authBatchTx) UnsafeReadAuthEnabled() bool { + return unsafeReadAuthEnabled(atx.tx) +} + +func (atx *authBatchTx) UnsafeReadAuthRevision() uint64 { + return unsafeReadAuthRevision(atx.tx) +} + +func (atx *authBatchTx) Lock() { + atx.tx.LockInsideApply() +} + +func (atx *authBatchTx) Unlock() { + atx.tx.Unlock() + // Calling Commit() for defensive purpose. If the number of pending writes doesn't exceed batchLimit, + // ReadTx can miss some writes issued by its predecessor BatchTx. + atx.tx.Commit() +} + +func (atx *authReadTx) UnsafeReadAuthEnabled() bool { + return unsafeReadAuthEnabled(atx.tx) +} + +func unsafeReadAuthEnabled(tx backend.UnsafeReader) bool { + _, vs := tx.UnsafeRange(Auth, AuthEnabledKeyName, nil, 0) + if len(vs) == 1 { + if bytes.Equal(vs[0], authEnabled) { + return true + } + } + return false +} + +func (atx *authReadTx) UnsafeReadAuthRevision() uint64 { + return unsafeReadAuthRevision(atx.tx) +} + +func unsafeReadAuthRevision(tx backend.UnsafeReader) uint64 { + _, vs := tx.UnsafeRange(Auth, AuthRevisionKeyName, nil, 0) + if len(vs) != 1 { + // this can happen in the initialization phase + return 0 + } + return binary.BigEndian.Uint64(vs[0]) +} + +func (atx *authReadTx) RLock() { + atx.tx.RLock() +} + +func (atx *authReadTx) RUnlock() { + atx.tx.RUnlock() +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth_roles.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth_roles.go new file mode 100644 index 0000000000..6161a0885a --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth_roles.go @@ -0,0 +1,105 @@ +// Copyright 2021 The etcd 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 schema + +import ( + "go.uber.org/zap" + + "go.etcd.io/etcd/api/v3/authpb" + "go.etcd.io/etcd/server/v3/storage/backend" +) + +func UnsafeCreateAuthRolesBucket(tx backend.UnsafeWriter) { + tx.UnsafeCreateBucket(AuthRoles) +} + +func (abe *authBackend) GetRole(roleName string) *authpb.Role { + tx := abe.ReadTx() + tx.RLock() + defer tx.RUnlock() + return tx.UnsafeGetRole(roleName) +} + +func (atx *authBatchTx) UnsafeGetRole(roleName string) *authpb.Role { + return unsafeGetRole(atx.lg, atx.tx, roleName) +} + +func (abe *authBackend) GetAllRoles() []*authpb.Role { + tx := abe.BatchTx() + tx.Lock() + defer tx.Unlock() + return tx.UnsafeGetAllRoles() +} + +func (atx *authBatchTx) UnsafeGetAllRoles() []*authpb.Role { + return unsafeGetAllRoles(atx.lg, atx.tx) +} + +func (atx *authBatchTx) UnsafePutRole(role *authpb.Role) { + b, err := role.Marshal() + if err != nil { + atx.lg.Panic( + "failed to marshal 'authpb.Role'", + zap.String("role-name", string(role.Name)), + zap.Error(err), + ) + } + + atx.tx.UnsafePut(AuthRoles, role.Name, b) +} + +func (atx *authBatchTx) UnsafeDeleteRole(rolename string) { + atx.tx.UnsafeDelete(AuthRoles, []byte(rolename)) +} + +func (atx *authReadTx) UnsafeGetRole(roleName string) *authpb.Role { + return unsafeGetRole(atx.lg, atx.tx, roleName) +} + +func unsafeGetRole(lg *zap.Logger, tx backend.UnsafeReader, roleName string) *authpb.Role { + _, vs := tx.UnsafeRange(AuthRoles, []byte(roleName), nil, 0) + if len(vs) == 0 { + return nil + } + + role := &authpb.Role{} + err := role.Unmarshal(vs[0]) + if err != nil { + lg.Panic("failed to unmarshal 'authpb.Role'", zap.Error(err)) + } + return role +} + +func (atx *authReadTx) UnsafeGetAllRoles() []*authpb.Role { + return unsafeGetAllRoles(atx.lg, atx.tx) +} + +func unsafeGetAllRoles(lg *zap.Logger, tx backend.UnsafeReader) []*authpb.Role { + _, vs := tx.UnsafeRange(AuthRoles, []byte{0}, []byte{0xff}, -1) + if len(vs) == 0 { + return nil + } + + roles := make([]*authpb.Role, len(vs)) + for i := range vs { + role := &authpb.Role{} + err := role.Unmarshal(vs[i]) + if err != nil { + lg.Panic("failed to unmarshal 'authpb.Role'", zap.Error(err)) + } + roles[i] = role + } + return roles +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth_users.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth_users.go new file mode 100644 index 0000000000..c21fa7c16d --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/auth_users.go @@ -0,0 +1,108 @@ +// Copyright 2021 The etcd 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 schema + +import ( + "go.uber.org/zap" + + "go.etcd.io/etcd/api/v3/authpb" + "go.etcd.io/etcd/server/v3/storage/backend" +) + +func (abe *authBackend) GetUser(username string) *authpb.User { + tx := abe.ReadTx() + tx.RLock() + defer tx.RUnlock() + return tx.UnsafeGetUser(username) +} + +func (atx *authBatchTx) UnsafeGetUser(username string) *authpb.User { + return unsafeGetUser(atx.lg, atx.tx, username) +} + +func (atx *authBatchTx) UnsafeGetAllUsers() []*authpb.User { + return unsafeGetAllUsers(atx.lg, atx.tx) +} + +func (atx *authBatchTx) UnsafePutUser(user *authpb.User) { + b, err := user.Marshal() + if err != nil { + atx.lg.Panic("failed to unmarshal 'authpb.User'", zap.Error(err)) + } + atx.tx.UnsafePut(AuthUsers, user.Name, b) +} + +func (atx *authBatchTx) UnsafeDeleteUser(username string) { + atx.tx.UnsafeDelete(AuthUsers, []byte(username)) +} + +func (atx *authReadTx) UnsafeGetUser(username string) *authpb.User { + return unsafeGetUser(atx.lg, atx.tx, username) +} + +func unsafeGetUser(lg *zap.Logger, tx backend.UnsafeReader, username string) *authpb.User { + _, vs := tx.UnsafeRange(AuthUsers, []byte(username), nil, 0) + if len(vs) == 0 { + return nil + } + + user := &authpb.User{} + err := user.Unmarshal(vs[0]) + if err != nil { + lg.Panic( + "failed to unmarshal 'authpb.User'", + zap.String("user-name", username), + zap.Error(err), + ) + } + return user +} + +func (abe *authBackend) GetAllUsers() []*authpb.User { + tx := abe.ReadTx() + tx.RLock() + defer tx.RUnlock() + return tx.UnsafeGetAllUsers() +} + +func (atx *authReadTx) UnsafeGetAllUsers() []*authpb.User { + return unsafeGetAllUsers(atx.lg, atx.tx) +} + +func unsafeGetAllUsers(lg *zap.Logger, tx backend.UnsafeReader) []*authpb.User { + var vs [][]byte + err := tx.UnsafeForEach(AuthUsers, func(k []byte, v []byte) error { + vs = append(vs, v) + return nil + }) + if err != nil { + lg.Panic("failed to get users", + zap.Error(err)) + } + if len(vs) == 0 { + return nil + } + + users := make([]*authpb.User, len(vs)) + for i := range vs { + user := &authpb.User{} + err := user.Unmarshal(vs[i]) + if err != nil { + lg.Panic("failed to unmarshal 'authpb.User'", zap.Error(err)) + } + users[i] = user + } + return users +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/buckets/bucket.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/bucket.go similarity index 70% rename from etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/buckets/bucket.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/bucket.go index 9214f72f25..06da660df5 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/mvcc/buckets/bucket.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/bucket.go @@ -12,12 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -package buckets +package schema import ( "bytes" - "go.etcd.io/etcd/server/v3/mvcc/backend" + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/server/v3/storage/backend" ) var ( @@ -53,6 +54,8 @@ var ( AuthRoles = backend.Bucket(bucket{id: 22, name: authRolesBucketName, safeRangeBucket: false}) Test = backend.Bucket(bucket{id: 100, name: testBucketName, safeRangeBucket: false}) + + AllBuckets = []backend.Bucket{Key, Meta, Lease, Alarm, Cluster, Members, MembersRemoved, Auth, AuthUsers, AuthRoles} ) type bucket struct { @@ -67,14 +70,31 @@ func (b bucket) String() string { return string(b.Name()) } func (b bucket) IsSafeRangeBucket() bool { return b.safeRangeBucket } var ( + // Pre v3.5 + ScheduledCompactKeyName = []byte("scheduledCompactRev") + FinishedCompactKeyName = []byte("finishedCompactRev") MetaConsistentIndexKeyName = []byte("consistent_index") - MetaTermKeyName = []byte("term") + AuthEnabledKeyName = []byte("authEnabled") + AuthRevisionKeyName = []byte("authRevision") + // Since v3.5 + MetaTermKeyName = []byte("term") + MetaConfStateName = []byte("confState") + ClusterClusterVersionKeyName = []byte("clusterVersion") + ClusterDowngradeKeyName = []byte("downgrade") + // Since v3.6 + MetaStorageVersionName = []byte("storageVersion") + // Before adding new meta key please update server/etcdserver/version ) // DefaultIgnores defines buckets & keys to ignore in hash checking. func DefaultIgnores(bucket, key []byte) bool { // consistent index & term might be changed due to v2 internal sync, which // is not controllable by the user. - return bytes.Compare(bucket, Meta.Name()) == 0 && - (bytes.Compare(key, MetaTermKeyName) == 0 || bytes.Compare(key, MetaConsistentIndexKeyName) == 0) + // storage version might change after wal snapshot and is not controller by user. + return bytes.Equal(bucket, Meta.Name()) && + (bytes.Equal(key, MetaTermKeyName) || bytes.Equal(key, MetaConsistentIndexKeyName) || bytes.Equal(key, MetaStorageVersionName)) +} + +func BackendMemberKey(id types.ID) []byte { + return []byte(id.String()) } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/changes.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/changes.go new file mode 100644 index 0000000000..6eb0b75120 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/changes.go @@ -0,0 +1,50 @@ +// Copyright 2021 The etcd 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 schema + +import "go.etcd.io/etcd/server/v3/storage/backend" + +type schemaChange interface { + upgradeAction() action + downgradeAction() action +} + +// addNewField represents adding new field when upgrading. Downgrade will remove the field. +func addNewField(bucket backend.Bucket, fieldName []byte, fieldValue []byte) schemaChange { + return simpleSchemaChange{ + upgrade: setKeyAction{ + Bucket: bucket, + FieldName: fieldName, + FieldValue: fieldValue, + }, + downgrade: deleteKeyAction{ + Bucket: bucket, + FieldName: fieldName, + }, + } +} + +type simpleSchemaChange struct { + upgrade action + downgrade action +} + +func (c simpleSchemaChange) upgradeAction() action { + return c.upgrade +} + +func (c simpleSchemaChange) downgradeAction() action { + return c.downgrade +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/cindex.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/cindex.go new file mode 100644 index 0000000000..cdf938d346 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/cindex.go @@ -0,0 +1,95 @@ +// Copyright 2021 The etcd 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 schema + +import ( + "encoding/binary" + "fmt" + + "go.etcd.io/etcd/client/pkg/v3/verify" + "go.etcd.io/etcd/server/v3/storage/backend" +) + +// UnsafeCreateMetaBucket creates the `meta` bucket (if it does not exist yet). +func UnsafeCreateMetaBucket(tx backend.UnsafeWriter) { + tx.UnsafeCreateBucket(Meta) +} + +// CreateMetaBucket creates the `meta` bucket (if it does not exist yet). +func CreateMetaBucket(tx backend.BatchTx) { + tx.LockOutsideApply() + defer tx.Unlock() + tx.UnsafeCreateBucket(Meta) +} + +// UnsafeReadConsistentIndex loads consistent index & term from given transaction. +// returns 0,0 if the data are not found. +// Term is persisted since v3.5. +func UnsafeReadConsistentIndex(tx backend.UnsafeReader) (uint64, uint64) { + _, vs := tx.UnsafeRange(Meta, MetaConsistentIndexKeyName, nil, 0) + if len(vs) == 0 { + return 0, 0 + } + v := binary.BigEndian.Uint64(vs[0]) + _, ts := tx.UnsafeRange(Meta, MetaTermKeyName, nil, 0) + if len(ts) == 0 { + return v, 0 + } + t := binary.BigEndian.Uint64(ts[0]) + return v, t +} + +// ReadConsistentIndex loads consistent index and term from given transaction. +// returns 0 if the data are not found. +func ReadConsistentIndex(tx backend.ReadTx) (uint64, uint64) { + tx.RLock() + defer tx.RUnlock() + return UnsafeReadConsistentIndex(tx) +} + +func UnsafeUpdateConsistentIndexForce(tx backend.UnsafeReadWriter, index uint64, term uint64) { + unsafeUpdateConsistentIndex(tx, index, term, true) +} + +func UnsafeUpdateConsistentIndex(tx backend.UnsafeReadWriter, index uint64, term uint64) { + unsafeUpdateConsistentIndex(tx, index, term, false) +} + +func unsafeUpdateConsistentIndex(tx backend.UnsafeReadWriter, index uint64, term uint64, allowDecreasing bool) { + if index == 0 { + // Never save 0 as it means that we didn't load the real index yet. + return + } + bs1 := make([]byte, 8) + binary.BigEndian.PutUint64(bs1, index) + + if !allowDecreasing { + verify.Verify(func() { + previousIndex, _ := UnsafeReadConsistentIndex(tx) + if index < previousIndex { + panic(fmt.Errorf("update of consistent index not advancing: previous: %v new: %v", previousIndex, index)) + } + }) + } + + // put the index into the underlying backend + // tx has been locked in TxnBegin, so there is no need to lock it again + tx.UnsafePut(Meta, MetaConsistentIndexKeyName, bs1) + if term > 0 { + bs2 := make([]byte, 8) + binary.BigEndian.PutUint64(bs2, term) + tx.UnsafePut(Meta, MetaTermKeyName, bs2) + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/confstate.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/confstate.go similarity index 73% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/confstate.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/confstate.go index 3aa8c649b2..c2bcb54013 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/api/membership/confstate.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/confstate.go @@ -12,44 +12,40 @@ // See the License for the specific language governing permissions and // limitations under the License. -package membership +package schema import ( "encoding/json" "log" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/mvcc/backend" - "go.etcd.io/etcd/server/v3/mvcc/buckets" "go.uber.org/zap" -) -var ( - confStateKey = []byte("confState") + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/raft/v3/raftpb" ) // MustUnsafeSaveConfStateToBackend persists confState using given transaction (tx). // confState in backend is persisted since etcd v3.5. -func MustUnsafeSaveConfStateToBackend(lg *zap.Logger, tx backend.BatchTx, confState *raftpb.ConfState) { +func MustUnsafeSaveConfStateToBackend(lg *zap.Logger, tx backend.UnsafeWriter, confState *raftpb.ConfState) { confStateBytes, err := json.Marshal(confState) if err != nil { lg.Panic("Cannot marshal raftpb.ConfState", zap.Stringer("conf-state", confState), zap.Error(err)) } - tx.UnsafePut(buckets.Meta, confStateKey, confStateBytes) + tx.UnsafePut(Meta, MetaConfStateName, confStateBytes) } // UnsafeConfStateFromBackend retrieves ConfState from the backend. -// Returns nil if confState in backend is not persisted (e.g. backend writen by = 3.6, so we don't need to use any other + // fields to identify the etcd's storage version. + _, term := UnsafeReadConsistentIndex(tx) + if term == 0 { + return v, fmt.Errorf("missing term information") + } + return version.V3_5, nil +} + +func schemaChangesForVersion(v semver.Version, isUpgrade bool) ([]schemaChange, error) { + // changes should be taken from higher version + higherV := v + if isUpgrade { + higherV = semver.Version{Major: v.Major, Minor: v.Minor + 1} + } + + actions, found := schemaChanges[higherV] + if !found { + if isUpgrade { + return nil, fmt.Errorf("version %q is not supported", higherV.String()) + } + return nil, fmt.Errorf("version %q is not supported", v.String()) + } + return actions, nil +} + +var ( + // schemaChanges list changes that were introduced in a particular version. + // schema was introduced in v3.6 as so its changes were not tracked before. + schemaChanges = map[semver.Version][]schemaChange{ + version.V3_6: { + addNewField(Meta, MetaStorageVersionName, emptyStorageVersion), + }, + } + // emptyStorageVersion is used for v3.6 Step for the first time, in all other version StoragetVersion should be set by migrator. + // Adding a addNewField for StorageVersion we can reuse logic to remove it when downgrading to v3.5 + emptyStorageVersion = []byte("") +) diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/version.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/version.go new file mode 100644 index 0000000000..83984e6b5f --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/schema/version.go @@ -0,0 +1,67 @@ +// Copyright 2021 The etcd 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 schema + +import ( + "github.com/coreos/go-semver/semver" + + "go.etcd.io/bbolt" + "go.etcd.io/etcd/server/v3/storage/backend" +) + +// ReadStorageVersion loads storage version from given backend transaction. +// Populated since v3.6 +func ReadStorageVersion(tx backend.ReadTx) *semver.Version { + tx.RLock() + defer tx.RUnlock() + return UnsafeReadStorageVersion(tx) +} + +// UnsafeReadStorageVersion loads storage version from given backend transaction. +// Populated since v3.6 +func UnsafeReadStorageVersion(tx backend.UnsafeReader) *semver.Version { + _, vs := tx.UnsafeRange(Meta, MetaStorageVersionName, nil, 1) + if len(vs) == 0 { + return nil + } + v, err := semver.NewVersion(string(vs[0])) + if err != nil { + return nil + } + return v +} + +// ReadStorageVersionFromSnapshot loads storage version from given bbolt transaction. +// Populated since v3.6 +func ReadStorageVersionFromSnapshot(tx *bbolt.Tx) *semver.Version { + v := tx.Bucket(Meta.Name()).Get(MetaStorageVersionName) + version, err := semver.NewVersion(string(v)) + if err != nil { + return nil + } + return version +} + +// UnsafeSetStorageVersion updates etcd storage version in backend. +// Populated since v3.6 +func UnsafeSetStorageVersion(tx backend.UnsafeWriter, v *semver.Version) { + sv := semver.Version{Major: v.Major, Minor: v.Minor} + tx.UnsafePut(Meta, MetaStorageVersionName, []byte(sv.String())) +} + +// UnsafeClearStorageVersion removes etcd storage version in backend. +func UnsafeClearStorageVersion(tx backend.UnsafeWriter) { + tx.UnsafeDelete(Meta, MetaStorageVersionName) +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/storage.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/storage.go similarity index 54% rename from etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/storage.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/storage.go index 64fc862c0c..99a37a23d0 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/etcdserver/storage.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/storage.go @@ -12,21 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -package etcdserver +package storage import ( "errors" - "io" - - pb "go.etcd.io/etcd/api/v3/etcdserverpb" - "go.etcd.io/etcd/client/pkg/v3/types" - "go.etcd.io/etcd/pkg/v3/pbutil" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/etcdserver/api/snap" - "go.etcd.io/etcd/server/v3/wal" - "go.etcd.io/etcd/server/v3/wal/walpb" + "sync" + "github.com/coreos/go-semver/semver" "go.uber.org/zap" + + "go.etcd.io/etcd/server/v3/etcdserver/api/snap" + "go.etcd.io/etcd/server/v3/storage/wal" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" + "go.etcd.io/raft/v3/raftpb" ) type Storage interface { @@ -41,19 +39,27 @@ type Storage interface { Release(snap raftpb.Snapshot) error // Sync WAL Sync() error + // MinimalEtcdVersion returns minimal etcd storage able to interpret WAL log. + MinimalEtcdVersion() *semver.Version } type storage struct { - *wal.WAL - *snap.Snapshotter + lg *zap.Logger + s *snap.Snapshotter + + // Mutex protected variables + mux sync.RWMutex + w *wal.WAL } -func NewStorage(w *wal.WAL, s *snap.Snapshotter) Storage { - return &storage{w, s} +func NewStorage(lg *zap.Logger, w *wal.WAL, s *snap.Snapshotter) Storage { + return &storage{lg: lg, w: w, s: s} } // SaveSnap saves the snapshot file to disk and writes the WAL snapshot entry. func (st *storage) SaveSnap(snap raftpb.Snapshot) error { + st.mux.RLock() + defer st.mux.RUnlock() walsnap := walpb.Snapshot{ Index: snap.Metadata.Index, Term: snap.Metadata.Term, @@ -62,61 +68,68 @@ func (st *storage) SaveSnap(snap raftpb.Snapshot) error { // save the snapshot file before writing the snapshot to the wal. // This makes it possible for the snapshot file to become orphaned, but prevents // a WAL snapshot entry from having no corresponding snapshot file. - err := st.Snapshotter.SaveSnap(snap) + err := st.s.SaveSnap(snap) if err != nil { return err } // gofail: var raftBeforeWALSaveSnaphot struct{} - return st.WAL.SaveSnapshot(walsnap) + return st.w.SaveSnapshot(walsnap) } // Release releases resources older than the given snap and are no longer needed: // - releases the locks to the wal files that are older than the provided wal for the given snap. // - deletes any .snap.db files that are older than the given snap. func (st *storage) Release(snap raftpb.Snapshot) error { - if err := st.WAL.ReleaseLockTo(snap.Metadata.Index); err != nil { + st.mux.RLock() + defer st.mux.RUnlock() + if err := st.w.ReleaseLockTo(snap.Metadata.Index); err != nil { return err } - return st.Snapshotter.ReleaseSnapDBs(snap) + return st.s.ReleaseSnapDBs(snap) +} + +func (st *storage) Save(s raftpb.HardState, ents []raftpb.Entry) error { + st.mux.RLock() + defer st.mux.RUnlock() + return st.w.Save(s, ents) +} + +func (st *storage) Close() error { + st.mux.Lock() + defer st.mux.Unlock() + return st.w.Close() } -// readWAL reads the WAL at the given snap and returns the wal, its latest HardState and cluster ID, and all entries that appear -// after the position of the given snap in the WAL. -// The snap must have been previously saved to the WAL, or this call will panic. -func readWAL(lg *zap.Logger, waldir string, snap walpb.Snapshot, unsafeNoFsync bool) (w *wal.WAL, id, cid types.ID, st raftpb.HardState, ents []raftpb.Entry) { - var ( - err error - wmetadata []byte - ) - - repaired := false - for { - if w, err = wal.Open(lg, waldir, snap); err != nil { - lg.Fatal("failed to open WAL", zap.Error(err)) - } - if unsafeNoFsync { - w.SetUnsafeNoFsync() - } - if wmetadata, st, ents, err = w.ReadAll(); err != nil { - w.Close() - // we can only repair ErrUnexpectedEOF and we never repair twice. - if repaired || !errors.Is(err, io.ErrUnexpectedEOF) { - lg.Fatal("failed to read WAL, cannot be repaired", zap.Error(err)) - } - if !wal.Repair(lg, waldir) { - lg.Fatal("failed to repair WAL", zap.Error(err)) - } else { - lg.Info("repaired WAL", zap.Error(err)) - repaired = true - } - continue - } - break +func (st *storage) Sync() error { + st.mux.RLock() + defer st.mux.RUnlock() + return st.w.Sync() +} + +func (st *storage) MinimalEtcdVersion() *semver.Version { + st.mux.Lock() + defer st.mux.Unlock() + walsnap := walpb.Snapshot{} + + sn, err := st.s.Load() + if err != nil && !errors.Is(err, snap.ErrNoSnapshot) { + panic(err) + } + if sn != nil { + walsnap.Index = sn.Metadata.Index + walsnap.Term = sn.Metadata.Term + walsnap.ConfState = &sn.Metadata.ConfState + } + w, err := st.w.Reopen(st.lg, walsnap) + if err != nil { + panic(err) + } + _, _, ents, err := w.ReadAll() + if err != nil { + panic(err) } - var metadata pb.Metadata - pbutil.MustUnmarshal(&metadata, wmetadata) - id = types.ID(metadata.NodeID) - cid = types.ID(metadata.ClusterID) - return w, id, cid, st, ents + v := wal.MinimalEtcdVersion(ents) + st.w = w + return v } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/util.go new file mode 100644 index 0000000000..0dc7f1c6d3 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/util.go @@ -0,0 +1,160 @@ +// Copyright 2021 The etcd 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 storage + +import ( + "encoding/json" + "fmt" + "sort" + + "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/types" + "go.etcd.io/etcd/pkg/v3/pbutil" + "go.etcd.io/etcd/server/v3/config" + "go.etcd.io/etcd/server/v3/etcdserver/api/membership" + "go.etcd.io/etcd/server/v3/etcdserver/api/v2store" + "go.etcd.io/raft/v3/raftpb" +) + +// AssertNoV2StoreContent -> depending on the deprecation stage, warns or report an error +// if the v2store contains custom content. +func AssertNoV2StoreContent(lg *zap.Logger, st v2store.Store, deprecationStage config.V2DeprecationEnum) error { + metaOnly, err := membership.IsMetaStoreOnly(st) + if err != nil { + return err + } + if metaOnly { + return nil + } + if deprecationStage.IsAtLeast(config.V2Depr1WriteOnly) { + return fmt.Errorf("detected disallowed custom content in v2store for stage --v2-deprecation=%s", deprecationStage) + } + lg.Warn("detected custom v2store content. Etcd v3.5 is the last version allowing to access it using API v2. Please remove the content.") + return nil +} + +// CreateConfigChangeEnts creates a series of Raft entries (i.e. +// EntryConfChange) to remove the set of given IDs from the cluster. The ID +// `self` is _not_ removed, even if present in the set. +// If `self` is not inside the given ids, it creates a Raft entry to add a +// default member with the given `self`. +func CreateConfigChangeEnts(lg *zap.Logger, ids []uint64, self uint64, term, index uint64) []raftpb.Entry { + found := false + for _, id := range ids { + if id == self { + found = true + } + } + + var ents []raftpb.Entry + next := index + 1 + + // NB: always add self first, then remove other nodes. Raft will panic if the + // set of voters ever becomes empty. + if !found { + m := membership.Member{ + ID: types.ID(self), + RaftAttributes: membership.RaftAttributes{PeerURLs: []string{"http://localhost:2380"}}, + } + ctx, err := json.Marshal(m) + if err != nil { + lg.Panic("failed to marshal member", zap.Error(err)) + } + cc := &raftpb.ConfChange{ + Type: raftpb.ConfChangeAddNode, + NodeID: self, + Context: ctx, + } + e := raftpb.Entry{ + Type: raftpb.EntryConfChange, + Data: pbutil.MustMarshal(cc), + Term: term, + Index: next, + } + ents = append(ents, e) + next++ + } + + for _, id := range ids { + if id == self { + continue + } + cc := &raftpb.ConfChange{ + Type: raftpb.ConfChangeRemoveNode, + NodeID: id, + } + e := raftpb.Entry{ + Type: raftpb.EntryConfChange, + Data: pbutil.MustMarshal(cc), + Term: term, + Index: next, + } + ents = append(ents, e) + next++ + } + + return ents +} + +// GetEffectiveNodeIdsFromWalEntries returns an ordered set of IDs included in the given snapshot and +// the entries. +// +// Deprecated: use GetEffectiveNodeIDsFromWALEntries instead. +// +//revive:disable-next-line:var-naming +func GetEffectiveNodeIdsFromWalEntries(lg *zap.Logger, snap *raftpb.Snapshot, ents []raftpb.Entry) []uint64 { + return GetEffectiveNodeIDsFromWALEntries(lg, snap, ents) +} + +// GetEffectiveNodeIDsFromWALEntries returns an ordered set of IDs included in the given snapshot and +// the entries. The given snapshot/entries can contain three kinds of +// ID-related entry: +// - ConfChangeAddNode, in which case the contained ID will Be added into the set. +// - ConfChangeRemoveNode, in which case the contained ID will Be removed from the set. +// - ConfChangeAddLearnerNode, in which the contained ID will Be added into the set. +func GetEffectiveNodeIDsFromWALEntries(lg *zap.Logger, snap *raftpb.Snapshot, ents []raftpb.Entry) []uint64 { + ids := make(map[uint64]bool) + if snap != nil { + for _, id := range snap.Metadata.ConfState.Voters { + ids[id] = true + } + } + for _, e := range ents { + if e.Type != raftpb.EntryConfChange { + continue + } + var cc raftpb.ConfChange + pbutil.MustUnmarshal(&cc, e.Data) + switch cc.Type { + case raftpb.ConfChangeAddLearnerNode: + ids[cc.NodeID] = true + case raftpb.ConfChangeAddNode: + ids[cc.NodeID] = true + case raftpb.ConfChangeRemoveNode: + delete(ids, cc.NodeID) + case raftpb.ConfChangeUpdateNode: + // do nothing + default: + lg.Panic("unknown ConfChange Type", zap.String("type", cc.Type.String())) + } + } + sids := make(types.Uint64Slice, 0, len(ids)) + for id := range ids { + sids = append(sids, id) + } + sort.Sort(sids) + return sids +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/decoder.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/decoder.go similarity index 66% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/decoder.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/decoder.go index b8c68bef6d..bdd4962e97 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/decoder.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/decoder.go @@ -16,6 +16,7 @@ package wal import ( "encoding/binary" + "errors" "fmt" "hash" "io" @@ -24,8 +25,8 @@ import ( "go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/pkg/v3/crc" "go.etcd.io/etcd/pkg/v3/pbutil" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/wal/walpb" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" + "go.etcd.io/raft/v3/raftpb" ) const minSectorSize = 512 @@ -33,6 +34,13 @@ const minSectorSize = 512 // frameSizeBytes is frame size in bytes, including record size and padding size. const frameSizeBytes = 8 +type Decoder interface { + Decode(rec *walpb.Record) error + LastOffset() int64 + LastCRC() uint32 + UpdateCRC(prevCrc uint32) +} + type decoder struct { mu sync.Mutex brs []*fileutil.FileBufReader @@ -40,20 +48,35 @@ type decoder struct { // lastValidOff file offset following the last valid decoded record lastValidOff int64 crc hash.Hash32 + + // continueOnCrcError - causes the decoder to continue working even in case of crc mismatch. + // This is a desired mode for tools performing inspection of the corrupted WAL logs. + // See comments on 'Decode' method for semantic. + continueOnCrcError bool } -func newDecoder(r ...fileutil.FileReader) *decoder { +func NewDecoderAdvanced(continueOnCrcError bool, r ...fileutil.FileReader) Decoder { readers := make([]*fileutil.FileBufReader, len(r)) for i := range r { readers[i] = fileutil.NewFileBufReader(r[i]) } return &decoder{ - brs: readers, - crc: crc.New(0, crcTable), + brs: readers, + crc: crc.New(0, crcTable), + continueOnCrcError: continueOnCrcError, } } -func (d *decoder) decode(rec *walpb.Record) error { +func NewDecoder(r ...fileutil.FileReader) Decoder { + return NewDecoderAdvanced(false, r...) +} + +// Decode reads the next record out of the file. +// In the success path, fills 'rec' and returns nil. +// When it fails, it returns err and usually resets 'rec' to the defaults. +// When continueOnCrcError is set, the method may return ErrUnexpectedEOF or ErrCRCMismatch, but preserve the read +// (potentially corrupted) record content. +func (d *decoder) Decode(rec *walpb.Record) error { rec.Reset() d.mu.Lock() defer d.mu.Unlock() @@ -67,7 +90,7 @@ func (d *decoder) decodeRecord(rec *walpb.Record) error { fileBufReader := d.brs[0] l, err := readInt64(fileBufReader) - if err == io.EOF || (err == nil && l == 0) { + if errors.Is(err, io.EOF) || (err == nil && l == 0) { // hit end of file or preallocated space d.brs = d.brs[1:] if len(d.brs) == 0 { @@ -84,7 +107,7 @@ func (d *decoder) decodeRecord(rec *walpb.Record) error { // The length of current WAL entry must be less than the remaining file size. maxEntryLimit := fileBufReader.FileInfo().Size() - d.lastValidOff - padBytes if recBytes > maxEntryLimit { - return fmt.Errorf("%w: [wal] max entry size limit exceeded when decoding %q, recBytes: %d, fileSize(%d) - offset(%d) - padBytes(%d) = entryLimit(%d)", + return fmt.Errorf("%w: [wal] max entry size limit exceeded when reading %q, recBytes: %d, fileSize(%d) - offset(%d) - padBytes(%d) = entryLimit(%d)", io.ErrUnexpectedEOF, fileBufReader.FileInfo().Name(), recBytes, fileBufReader.FileInfo().Size(), d.lastValidOff, padBytes, maxEntryLimit) } @@ -92,7 +115,7 @@ func (d *decoder) decodeRecord(rec *walpb.Record) error { if _, err = io.ReadFull(fileBufReader, data); err != nil { // ReadFull returns io.EOF only if no bytes were read // the decoder should treat this as an ErrUnexpectedEOF instead. - if err == io.EOF { + if errors.Is(err, io.EOF) { err = io.ErrUnexpectedEOF } return err @@ -104,14 +127,24 @@ func (d *decoder) decodeRecord(rec *walpb.Record) error { return err } - // skip crc checking if the record type is crcType - if rec.Type != crcType { - d.crc.Write(rec.Data) + // skip crc checking if the record type is CrcType + if rec.Type != CrcType { + _, err := d.crc.Write(rec.Data) + if err != nil { + return err + } if err := rec.Validate(d.crc.Sum32()); err != nil { + if !d.continueOnCrcError { + rec.Reset() + } else { + // If we continue, we want to update lastValidOff, such that following errors are consistent + defer func() { d.lastValidOff += frameSizeBytes + recBytes + padBytes }() + } + if d.isTornEntry(data) { - return io.ErrUnexpectedEOF + return fmt.Errorf("%w: in file '%s' at position: %d", io.ErrUnexpectedEOF, fileBufReader.FileInfo().Name(), d.lastValidOff) } - return err + return fmt.Errorf("%w: in file '%s' at position: %d", err, fileBufReader.FileInfo().Name(), d.lastValidOff) } } // record decoded as valid; point last valid offset to end of record @@ -139,7 +172,7 @@ func (d *decoder) isTornEntry(data []byte) bool { fileOff := d.lastValidOff + frameSizeBytes curOff := 0 - chunks := [][]byte{} + var chunks [][]byte // split data on sector boundaries for curOff < len(data) { chunkLen := int(minSectorSize - (fileOff % minSectorSize)) @@ -167,23 +200,23 @@ func (d *decoder) isTornEntry(data []byte) bool { return false } -func (d *decoder) updateCRC(prevCrc uint32) { +func (d *decoder) UpdateCRC(prevCrc uint32) { d.crc = crc.New(prevCrc, crcTable) } -func (d *decoder) lastCRC() uint32 { +func (d *decoder) LastCRC() uint32 { return d.crc.Sum32() } -func (d *decoder) lastOffset() int64 { return d.lastValidOff } +func (d *decoder) LastOffset() int64 { return d.lastValidOff } -func mustUnmarshalEntry(d []byte) raftpb.Entry { +func MustUnmarshalEntry(d []byte) raftpb.Entry { var e raftpb.Entry pbutil.MustUnmarshal(&e, d) return e } -func mustUnmarshalState(d []byte) raftpb.HardState { +func MustUnmarshalState(d []byte) raftpb.HardState { var s raftpb.HardState pbutil.MustUnmarshal(&s, d) return s diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/doc.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/doc.go similarity index 85% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/doc.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/doc.go index 4288495461..0f7ef8527b 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/doc.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/doc.go @@ -13,11 +13,11 @@ // limitations under the License. /* -Package wal provides an implementation of a write ahead log that is used by +Package wal provides an implementation of write ahead log that is used by etcd. A WAL is created at a particular directory and is made up of a number of -segmented WAL files. Inside of each file the raft state and entries are appended +segmented WAL files. Inside each file the raft state and entries are appended to it with the Save method: metadata := []byte{} @@ -41,18 +41,18 @@ protobuf. The record protobuf contains a CRC, a type, and a data payload. The le record is 8-byte aligned so that the length field is never torn. The CRC contains the CRC32 value of all record protobufs preceding the current record. -WAL files are placed inside of the directory in the following format: +WAL files are placed inside the directory in the following format: $seq-$index.wal The first WAL file to be created will be 0000000000000000-0000000000000000.wal indicating an initial sequence of 0 and an initial raft index of 0. The first entry written to WAL MUST have raft index 0. -WAL will cut its current tail wal file if its size exceeds 64MB. This will increment an internal +WAL will cut its current tail wal file if its size exceeds 64 MB. This will increment an internal sequence number and cause a new file to be created. If the last raft index saved was 0x20 and this is the first time cut has been called on this WAL then the sequence will increment from 0x0 to 0x1. The new file will be: 0000000000000001-0000000000000021.wal. -If a second cut issues 0x10 entries with incremental index later then the file will be called: +If a second cut issues 0x10 entries with incremental index later, then the file will be called: 0000000000000002-0000000000000031.wal. At a later time a WAL can be opened at a particular snapshot. If there is no @@ -63,7 +63,7 @@ snapshot, an empty snapshot should be passed in. The snapshot must have been written to the WAL. -Additional items cannot be Saved to this WAL until all of the items from the given +Additional items cannot be Saved to this WAL until all the items from the given snapshot to the end of the WAL are read first: metadata, state, ents, err := w.ReadAll() diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/encoder.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/encoder.go similarity index 96% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/encoder.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/encoder.go index 2642e156c8..5944ba7b12 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/encoder.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/encoder.go @@ -24,7 +24,7 @@ import ( "go.etcd.io/etcd/pkg/v3/crc" "go.etcd.io/etcd/pkg/v3/ioutil" - "go.etcd.io/etcd/server/v3/wal/walpb" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" ) // walPageBytes is the alignment for flushing records to the backing Writer. @@ -102,10 +102,8 @@ func encodeFrameSize(dataBytes int) (lenField uint64, padBytes int) { func (e *encoder) flush() error { e.mu.Lock() - n, err := e.bw.FlushN() - e.mu.Unlock() - walWriteBytes.Add(float64(n)) - return err + defer e.mu.Unlock() + return e.bw.Flush() } func prepareDataWithPadding(data []byte) ([]byte, uint64) { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/file_pipeline.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/file_pipeline.go similarity index 94% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/file_pipeline.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/file_pipeline.go index c2feba6c1d..c8ee4cce42 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/file_pipeline.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/file_pipeline.go @@ -19,9 +19,9 @@ import ( "os" "path/filepath" - "go.etcd.io/etcd/client/pkg/v3/fileutil" - "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/fileutil" ) // filePipeline pipelines allocating disk space @@ -58,6 +58,7 @@ func newFilePipeline(lg *zap.Logger, dir string, fileSize int64) *filePipeline { // Open returns a fresh file for writing. Rename the file before calling // Open again or there will be file collisions. +// it will 'block' if the tmp file lock is already taken. func (fp *filePipeline) Open() (f *fileutil.LockedFile, err error) { select { case f = <-fp.filec: @@ -74,7 +75,7 @@ func (fp *filePipeline) Close() error { func (fp *filePipeline) alloc() (f *fileutil.LockedFile, err error) { // count % 2 so this file isn't the same as the one last published fpath := filepath.Join(fp.dir, fmt.Sprintf("%d.tmp", fp.count%2)) - if f, err = fileutil.LockFile(fpath, os.O_CREATE|os.O_WRONLY, fileutil.PrivateFileMode); err != nil { + if f, err = createNewWALFile[*fileutil.LockedFile](fpath, false); err != nil { return nil, err } if err = fileutil.Preallocate(f.File, fp.size, true); err != nil { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/metrics.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/metrics.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/metrics.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/metrics.go diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/repair.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/repair.go similarity index 83% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/repair.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/repair.go index dec2fa240b..16277540f3 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/repair.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/repair.go @@ -21,9 +21,10 @@ import ( "path/filepath" "time" - "go.etcd.io/etcd/client/pkg/v3/fileutil" - "go.etcd.io/etcd/server/v3/wal/walpb" "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/fileutil" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" ) // Repair tries to repair ErrUnexpectedEOF in the @@ -41,22 +42,22 @@ func Repair(lg *zap.Logger, dirpath string) bool { lg.Info("repairing", zap.String("path", f.Name())) rec := &walpb.Record{} - decoder := newDecoder(fileutil.NewFileReader(f.File)) + decoder := NewDecoder(fileutil.NewFileReader(f.File)) for { - lastOffset := decoder.lastOffset() - err := decoder.decode(rec) + lastOffset := decoder.LastOffset() + err := decoder.Decode(rec) switch { case err == nil: // update crc of the decoder when necessary switch rec.Type { - case crcType: - crc := decoder.crc.Sum32() + case CrcType: + crc := decoder.LastCRC() // current crc of decoder must match the crc of the record. // do no need to match 0 crc, since the decoder is a new one at this case. if crc != 0 && rec.Validate(crc) != nil { return false } - decoder.updateCRC(rec.Crc) + decoder.UpdateCRC(rec.Crc) } continue @@ -65,9 +66,10 @@ func Repair(lg *zap.Logger, dirpath string) bool { return true case errors.Is(err, io.ErrUnexpectedEOF): - bf, bferr := os.Create(f.Name() + ".broken") + brokenName := f.Name() + ".broken" + bf, bferr := createNewWALFile[*os.File](brokenName, true) if bferr != nil { - lg.Warn("failed to create backup file", zap.String("path", f.Name()+".broken"), zap.Error(bferr)) + lg.Warn("failed to create backup file", zap.String("path", brokenName), zap.Error(bferr)) return false } defer bf.Close() @@ -78,7 +80,7 @@ func Repair(lg *zap.Logger, dirpath string) bool { } if _, err = io.Copy(bf, f); err != nil { - lg.Warn("failed to copy", zap.String("from", f.Name()+".broken"), zap.String("to", f.Name()), zap.Error(err)) + lg.Warn("failed to copy", zap.String("from", f.Name()), zap.String("to", brokenName), zap.Error(err)) return false } diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/util.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/util.go similarity index 94% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/util.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/util.go index 4a21ae6182..8dec85c15d 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/util.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/util.go @@ -19,9 +19,9 @@ import ( "fmt" "strings" - "go.etcd.io/etcd/client/pkg/v3/fileutil" - "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/fileutil" ) var errBadWALName = errors.New("bad wal name") @@ -72,16 +72,16 @@ func isValidSeq(lg *zap.Logger, names []string) bool { func readWALNames(lg *zap.Logger, dirpath string) ([]string, error) { names, err := fileutil.ReadDir(dirpath) if err != nil { - return nil, err + return nil, fmt.Errorf("[readWALNames] fileutil.ReadDir failed: %w", err) } - wnames := checkWalNames(lg, names) + wnames := checkWALNames(lg, names) if len(wnames) == 0 { return nil, ErrFileNotFound } return wnames, nil } -func checkWalNames(lg *zap.Logger, names []string) []string { +func checkWALNames(lg *zap.Logger, names []string) []string { wnames := make([]string, 0) for _, name := range names { if _, _, err := parseWALName(name); err != nil { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/version.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/version.go new file mode 100644 index 0000000000..b592fd2ee8 --- /dev/null +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/version.go @@ -0,0 +1,288 @@ +// Copyright 2021 The etcd 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 wal + +import ( + "fmt" + "strings" + + "github.com/coreos/go-semver/semver" + "github.com/golang/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" + + "go.etcd.io/etcd/api/v3/etcdserverpb" + "go.etcd.io/etcd/api/v3/version" + "go.etcd.io/etcd/pkg/v3/pbutil" + "go.etcd.io/raft/v3/raftpb" +) + +// Version defines the wal version interface. +type Version interface { + // MinimalEtcdVersion returns minimal etcd version able to interpret WAL log. + MinimalEtcdVersion() *semver.Version +} + +// ReadWALVersion reads remaining entries from opened WAL and returns struct +// that implements schema.WAL interface. +func ReadWALVersion(w *WAL) (Version, error) { + _, _, ents, err := w.ReadAll() + if err != nil { + return nil, err + } + return &walVersion{entries: ents}, nil +} + +type walVersion struct { + entries []raftpb.Entry +} + +// MinimalEtcdVersion returns minimal etcd able to interpret entries from WAL log, +func (w *walVersion) MinimalEtcdVersion() *semver.Version { + return MinimalEtcdVersion(w.entries) +} + +// MinimalEtcdVersion returns minimal etcd able to interpret entries from WAL log, +// determined by looking at entries since the last snapshot and returning the highest +// etcd version annotation from used messages, fields, enums and their values. +func MinimalEtcdVersion(ents []raftpb.Entry) *semver.Version { + var maxVer *semver.Version + for _, ent := range ents { + err := visitEntry(ent, func(path protoreflect.FullName, ver *semver.Version) error { + maxVer = maxVersion(maxVer, ver) + return nil + }) + if err != nil { + panic(err) + } + } + return maxVer +} + +type Visitor func(path protoreflect.FullName, ver *semver.Version) error + +// VisitFileDescriptor calls visitor on each field and enum value with etcd version read from proto definition. +// If field/enum value is not annotated, visitor will be called with nil. +// Upon encountering invalid annotation, will immediately exit with error. +func VisitFileDescriptor(file protoreflect.FileDescriptor, visitor Visitor) error { + msgs := file.Messages() + for i := 0; i < msgs.Len(); i++ { + err := visitMessageDescriptor(msgs.Get(i), visitor) + if err != nil { + return err + } + } + enums := file.Enums() + for i := 0; i < enums.Len(); i++ { + err := visitEnumDescriptor(enums.Get(i), visitor) + if err != nil { + return err + } + } + return nil +} + +func visitEntry(ent raftpb.Entry, visitor Visitor) error { + err := visitMessage(proto.MessageReflect(&ent), visitor) + if err != nil { + return err + } + return visitEntryData(ent.Type, ent.Data, visitor) +} + +func visitEntryData(entryType raftpb.EntryType, data []byte, visitor Visitor) error { + var msg protoreflect.Message + switch entryType { + case raftpb.EntryNormal: + var raftReq etcdserverpb.InternalRaftRequest + if err := pbutil.Unmarshaler(&raftReq).Unmarshal(data); err != nil { + // try V2 Request + var r etcdserverpb.Request + if pbutil.Unmarshaler(&r).Unmarshal(data) != nil { + // return original error + return err + } + msg = proto.MessageReflect(&r) + break + } + msg = proto.MessageReflect(&raftReq) + if raftReq.DowngradeVersionTest != nil { + ver, err := semver.NewVersion(raftReq.DowngradeVersionTest.Ver) + if err != nil { + return err + } + err = visitor(msg.Descriptor().FullName(), ver) + if err != nil { + return err + } + } + case raftpb.EntryConfChange: + var confChange raftpb.ConfChange + err := pbutil.Unmarshaler(&confChange).Unmarshal(data) + if err != nil { + return nil + } + msg = proto.MessageReflect(&confChange) + return visitor(msg.Descriptor().FullName(), &version.V3_0) + case raftpb.EntryConfChangeV2: + var confChange raftpb.ConfChangeV2 + err := pbutil.Unmarshaler(&confChange).Unmarshal(data) + if err != nil { + return nil + } + msg = proto.MessageReflect(&confChange) + return visitor(msg.Descriptor().FullName(), &version.V3_4) + default: + panic("unhandled") + } + return visitMessage(msg, visitor) +} + +func visitMessageDescriptor(md protoreflect.MessageDescriptor, visitor Visitor) error { + err := visitDescriptor(md, visitor) + if err != nil { + return err + } + fields := md.Fields() + for i := 0; i < fields.Len(); i++ { + fd := fields.Get(i) + err = visitDescriptor(fd, visitor) + if err != nil { + return err + } + } + + enums := md.Enums() + for i := 0; i < enums.Len(); i++ { + err = visitEnumDescriptor(enums.Get(i), visitor) + if err != nil { + return err + } + } + return err +} + +func visitMessage(m protoreflect.Message, visitor Visitor) error { + md := m.Descriptor() + err := visitDescriptor(md, visitor) + if err != nil { + return err + } + m.Range(func(field protoreflect.FieldDescriptor, value protoreflect.Value) bool { + fd := md.Fields().Get(field.Index()) + err = visitDescriptor(fd, visitor) + if err != nil { + return false + } + + switch m := value.Interface().(type) { + case protoreflect.Message: + err = visitMessage(m, visitor) + case protoreflect.EnumNumber: + err = visitEnumNumber(fd.Enum(), m, visitor) + } + return err == nil + }) + return err +} + +func visitEnumDescriptor(enum protoreflect.EnumDescriptor, visitor Visitor) error { + err := visitDescriptor(enum, visitor) + if err != nil { + return err + } + fields := enum.Values() + for i := 0; i < fields.Len(); i++ { + fd := fields.Get(i) + err = visitDescriptor(fd, visitor) + if err != nil { + return err + } + } + return err +} + +func visitEnumNumber(enum protoreflect.EnumDescriptor, number protoreflect.EnumNumber, visitor Visitor) error { + err := visitDescriptor(enum, visitor) + if err != nil { + return err + } + intNumber := int(number) + fields := enum.Values() + if intNumber >= fields.Len() || intNumber < 0 { + return fmt.Errorf("could not visit EnumNumber [%d]", intNumber) + } + return visitEnumValue(fields.Get(intNumber), visitor) +} + +func visitEnumValue(enum protoreflect.EnumValueDescriptor, visitor Visitor) error { + valueOpts := enum.Options().(*descriptorpb.EnumValueOptions) + if valueOpts != nil { + ver, _ := etcdVersionFromOptionsString(valueOpts.String()) + err := visitor(enum.FullName(), ver) + if err != nil { + return err + } + } + return nil +} + +func visitDescriptor(md protoreflect.Descriptor, visitor Visitor) error { + opts, ok := md.Options().(fmt.Stringer) + if !ok { + return nil + } + ver, err := etcdVersionFromOptionsString(opts.String()) + if err != nil { + return fmt.Errorf("%s: %w", md.FullName(), err) + } + return visitor(md.FullName(), ver) +} + +func maxVersion(a *semver.Version, b *semver.Version) *semver.Version { + if a != nil && (b == nil || b.LessThan(*a)) { + return a + } + return b +} + +func etcdVersionFromOptionsString(opts string) (*semver.Version, error) { + // TODO: Use proto.GetExtention when gogo/protobuf is usable with protoreflect + msgs := []string{"[versionpb.etcd_version_msg]:", "[versionpb.etcd_version_field]:", "[versionpb.etcd_version_enum]:", "[versionpb.etcd_version_enum_value]:"} + var end, index int + for _, msg := range msgs { + index = strings.Index(opts, msg) + end = index + len(msg) + if index != -1 { + break + } + } + if index == -1 { + return nil, nil + } + var verStr string + _, err := fmt.Sscanf(opts[end:], "%q", &verStr) + if err != nil { + return nil, err + } + if strings.Count(verStr, ".") == 1 { + verStr = verStr + ".0" + } + ver, err := semver.NewVersion(verStr) + if err != nil { + return nil, err + } + return ver, nil +} diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/wal.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/wal.go similarity index 85% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/wal.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/wal.go index 69011025fa..7886c52fcc 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/wal.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/wal.go @@ -27,21 +27,21 @@ import ( "sync" "time" + "go.uber.org/zap" + "go.etcd.io/etcd/client/pkg/v3/fileutil" "go.etcd.io/etcd/pkg/v3/pbutil" - "go.etcd.io/etcd/raft/v3" - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/wal/walpb" - - "go.uber.org/zap" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" + "go.etcd.io/raft/v3" + "go.etcd.io/raft/v3/raftpb" ) const ( - metadataType int64 = iota + 1 - entryType - stateType - crcType - snapshotType + MetadataType int64 = iota + 1 + EntryType + StateType + CrcType + SnapshotType // warnSyncDuration is the amount of time allotted to an fsync before // logging a warning @@ -57,7 +57,7 @@ var ( ErrMetadataConflict = errors.New("wal: conflicting metadata found") ErrFileNotFound = errors.New("wal: file not found") - ErrCRCMismatch = errors.New("wal: crc mismatch") + ErrCRCMismatch = walpb.ErrCRCMismatch ErrSnapshotMismatch = errors.New("wal: snapshot mismatch") ErrSnapshotNotFound = errors.New("wal: snapshot not found") ErrSliceOutOfRange = errors.New("wal: slice bounds out of range") @@ -82,8 +82,8 @@ type WAL struct { state raftpb.HardState // hardstate recorded at the head of WAL start walpb.Snapshot // snapshot to start reading - decoder *decoder // decoder to decode records - readClose func() error // closer for decode reader + decoder Decoder // decoder to Decode records + readClose func() error // closer for Decode reader unsafeNoSync bool // if set, do not fsync @@ -129,7 +129,7 @@ func Create(lg *zap.Logger, dirpath string, metadata []byte) (*WAL, error) { } p := filepath.Join(tmpdirpath, walName(0, 0)) - f, err := fileutil.LockFile(p, os.O_WRONLY|os.O_CREATE, fileutil.PrivateFileMode) + f, err := createNewWALFile[*fileutil.LockedFile](p, false) if err != nil { lg.Warn( "failed to flock an initial WAL file", @@ -169,7 +169,7 @@ func Create(lg *zap.Logger, dirpath string, metadata []byte) (*WAL, error) { if err = w.saveCrc(0); err != nil { return nil, err } - if err = w.encoder.encode(&walpb.Record{Type: metadataType, Data: metadata}); err != nil { + if err = w.encoder.encode(&walpb.Record{Type: MetadataType, Data: metadata}); err != nil { return nil, err } if err = w.SaveSnapshot(walpb.Snapshot{}); err != nil { @@ -236,6 +236,39 @@ func Create(lg *zap.Logger, dirpath string, metadata []byte) (*WAL, error) { return w, nil } +// createNewWALFile creates a WAL file. +// To create a locked file, use *fileutil.LockedFile type parameter. +// To create a standard file, use *os.File type parameter. +// If forceNew is true, the file will be truncated if it already exists. +func createNewWALFile[T *os.File | *fileutil.LockedFile](path string, forceNew bool) (T, error) { + flag := os.O_WRONLY | os.O_CREATE + if forceNew { + flag |= os.O_TRUNC + } + + if _, isLockedFile := any(T(nil)).(*fileutil.LockedFile); isLockedFile { + lockedFile, err := fileutil.LockFile(path, flag, fileutil.PrivateFileMode) + if err != nil { + return nil, err + } + return any(lockedFile).(T), nil + } + + file, err := os.OpenFile(path, flag, fileutil.PrivateFileMode) + if err != nil { + return nil, err + } + return any(file).(T), nil +} + +func (w *WAL) Reopen(lg *zap.Logger, snap walpb.Snapshot) (*WAL, error) { + err := w.Close() + if err != nil { + lg.Panic("failed to close WAL during reopen", zap.Error(err)) + } + return Open(lg, w.dir, snap) +} + func (w *WAL) SetUnsafeNoFsync() { w.unsafeNoSync = true } @@ -267,7 +300,8 @@ func (w *WAL) renameWAL(tmpdirpath string) (*WAL, error) { // but there is a window between the fork and the exec where another // process holds the lock. if err := os.Rename(tmpdirpath, w.dir); err != nil { - if _, ok := err.(*os.LinkError); ok { + var linkErr *os.LinkError + if errors.As(err, &linkErr) { return w.renameWALUnlock(tmpdirpath) } return nil, err @@ -313,10 +347,10 @@ func (w *WAL) renameWALUnlock(tmpdirpath string) (*WAL, error) { func Open(lg *zap.Logger, dirpath string, snap walpb.Snapshot) (*WAL, error) { w, err := openAtIndex(lg, dirpath, snap, true) if err != nil { - return nil, err + return nil, fmt.Errorf("openAtIndex failed: %w", err) } if w.dirFile, err = fileutil.OpenDir(w.dir); err != nil { - return nil, err + return nil, fmt.Errorf("fileutil.OpenDir failed: %w", err) } return w, nil } @@ -333,12 +367,12 @@ func openAtIndex(lg *zap.Logger, dirpath string, snap walpb.Snapshot, write bool } names, nameIndex, err := selectWALFiles(lg, dirpath, snap) if err != nil { - return nil, err + return nil, fmt.Errorf("[openAtIndex] selectWALFiles failed: %w", err) } rs, ls, closer, err := openWALFiles(lg, dirpath, names, nameIndex, write) if err != nil { - return nil, err + return nil, fmt.Errorf("[openAtIndex] openWALFiles failed: %w", err) } // create a WAL ready for reading @@ -346,7 +380,7 @@ func openAtIndex(lg *zap.Logger, dirpath string, snap walpb.Snapshot, write bool lg: lg, dir: dirpath, start: snap, - decoder: newDecoder(rs...), + decoder: NewDecoder(rs...), readClose: closer, locks: ls, } @@ -357,7 +391,7 @@ func openAtIndex(lg *zap.Logger, dirpath string, snap walpb.Snapshot, write bool w.readClose = nil if _, _, err := parseWALName(filepath.Base(w.tail().Name())); err != nil { closer() - return nil, err + return nil, fmt.Errorf("[openAtIndex] parseWALName failed: %w", err) } w.fp = newFilePipeline(lg, w.dir, SegmentSizeBytes) } @@ -368,13 +402,16 @@ func openAtIndex(lg *zap.Logger, dirpath string, snap walpb.Snapshot, write bool func selectWALFiles(lg *zap.Logger, dirpath string, snap walpb.Snapshot) ([]string, int, error) { names, err := readWALNames(lg, dirpath) if err != nil { - return nil, -1, err + return nil, -1, fmt.Errorf("readWALNames failed: %w", err) } nameIndex, ok := searchIndex(lg, names, snap.Index) - if !ok || !isValidSeq(lg, names[nameIndex:]) { - err = ErrFileNotFound - return nil, -1, err + if !ok { + return nil, -1, fmt.Errorf("wal: file not found which matches the snapshot index '%d'", snap.Index) + } + + if !isValidSeq(lg, names[nameIndex:]) { + return nil, -1, fmt.Errorf("wal: file sequence numbers (starting from %d) do not increase continuously", nameIndex) } return names, nameIndex, nil @@ -391,7 +428,7 @@ func openWALFiles(lg *zap.Logger, dirpath string, names []string, nameIndex int, l, err := fileutil.TryLockFile(p, os.O_RDWR, fileutil.PrivateFileMode) if err != nil { closeAll(lg, rcs...) - return nil, nil, nil, err + return nil, nil, nil, fmt.Errorf("[openWALFiles] fileutil.TryLockFile failed: %w", err) } ls = append(ls, l) rcs = append(rcs, l) @@ -400,7 +437,7 @@ func openWALFiles(lg *zap.Logger, dirpath string, names []string, nameIndex int, rf, err := os.OpenFile(p, os.O_RDONLY, fileutil.PrivateFileMode) if err != nil { closeAll(lg, rcs...) - return nil, nil, nil, err + return nil, nil, nil, fmt.Errorf("[openWALFiles] os.OpenFile failed (%q): %w", p, err) } ls = append(ls, nil) rcs = append(rcs, rf) @@ -430,7 +467,7 @@ func openWALFiles(lg *zap.Logger, dirpath string, names []string, nameIndex int, // exists in the log). Such a situation can happen in cases described in figure 7. of the // RAFT paper (http://web.stanford.edu/~ouster/cgi-bin/papers/raft-atc14.pdf). // -// ReadAll may return uncommitted yet entries, that are subject to be overriden. +// ReadAll may return uncommitted yet entries, that are subject to be overridden. // Do not apply entries that have index > state.commit, as they are subject to change. func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb.Entry, err error) { w.mu.Lock() @@ -444,44 +481,47 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb. decoder := w.decoder var match bool - for err = decoder.decode(rec); err == nil; err = decoder.decode(rec) { + for err = decoder.Decode(rec); err == nil; err = decoder.Decode(rec) { switch rec.Type { - case entryType: - e := mustUnmarshalEntry(rec.Data) + case EntryType: + e := MustUnmarshalEntry(rec.Data) // 0 <= e.Index-w.start.Index - 1 < len(ents) if e.Index > w.start.Index { // prevent "panic: runtime error: slice bounds out of range [:13038096702221461992] with capacity 0" - up := e.Index - w.start.Index - 1 - if up > uint64(len(ents)) { - // return error before append call causes runtime panic - return nil, state, nil, ErrSliceOutOfRange + offset := e.Index - w.start.Index - 1 + if offset > uint64(len(ents)) { + // return error before append call causes runtime panic. + // We still return the continuous WAL entries that have already been read. + // Refer to https://github.com/etcd-io/etcd/pull/19038#issuecomment-2557414292. + return nil, state, ents, fmt.Errorf("%w, snapshot[Index: %d, Term: %d], current entry[Index: %d, Term: %d], len(ents): %d", + ErrSliceOutOfRange, w.start.Index, w.start.Term, e.Index, e.Term, len(ents)) } // The line below is potentially overriding some 'uncommitted' entries. - ents = append(ents[:up], e) + ents = append(ents[:offset], e) } w.enti = e.Index - case stateType: - state = mustUnmarshalState(rec.Data) + case StateType: + state = MustUnmarshalState(rec.Data) - case metadataType: + case MetadataType: if metadata != nil && !bytes.Equal(metadata, rec.Data) { state.Reset() return nil, state, nil, ErrMetadataConflict } metadata = rec.Data - case crcType: - crc := decoder.crc.Sum32() + case CrcType: + crc := decoder.LastCRC() // current crc of decoder must match the crc of the record. // do no need to match 0 crc, since the decoder is a new one at this case. if crc != 0 && rec.Validate(crc) != nil { state.Reset() return nil, state, nil, ErrCRCMismatch } - decoder.updateCRC(rec.Crc) + decoder.UpdateCRC(rec.Crc) - case snapshotType: + case SnapshotType: var snap walpb.Snapshot pbutil.MustUnmarshal(&snap, rec.Data) if snap.Index == w.start.Index { @@ -502,7 +542,7 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb. case nil: // We do not have to read out all entries in read mode. // The last record maybe a partial written one, so - // ErrunexpectedEOF might be returned. + // `io.ErrUnexpectedEOF` might be returned. if !errors.Is(err, io.EOF) && !errors.Is(err, io.ErrUnexpectedEOF) { state.Reset() return nil, state, nil, err @@ -519,7 +559,7 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb. // not all, will cause CRC errors on WAL open. Since the records // were never fully synced to disk in the first place, it's safe // to zero them out to avoid any CRC errors from new writes. - if _, err = w.tail().Seek(w.decoder.lastOffset(), io.SeekStart); err != nil { + if _, err = w.tail().Seek(w.decoder.LastOffset(), io.SeekStart); err != nil { return nil, state, nil, err } if err = fileutil.ZeroToEnd(w.tail().File); err != nil { @@ -543,9 +583,9 @@ func (w *WAL) ReadAll() (metadata []byte, state raftpb.HardState, ents []raftpb. if w.tail() != nil { // create encoder (chain crc with the decoder), enable appending - w.encoder, err = newFileEncoder(w.tail().File, w.decoder.lastCRC()) + w.encoder, err = newFileEncoder(w.tail().File, w.decoder.LastCRC()) if err != nil { - return + return nil, state, nil, err } } w.decoder = nil @@ -579,24 +619,24 @@ func ValidSnapshotEntries(lg *zap.Logger, walDir string) ([]walpb.Snapshot, erro }() // create a new decoder from the readers on the WAL files - decoder := newDecoder(rs...) + decoder := NewDecoder(rs...) - for err = decoder.decode(rec); err == nil; err = decoder.decode(rec) { + for err = decoder.Decode(rec); err == nil; err = decoder.Decode(rec) { switch rec.Type { - case snapshotType: + case SnapshotType: var loadedSnap walpb.Snapshot pbutil.MustUnmarshal(&loadedSnap, rec.Data) snaps = append(snaps, loadedSnap) - case stateType: - state = mustUnmarshalState(rec.Data) - case crcType: - crc := decoder.crc.Sum32() + case StateType: + state = MustUnmarshalState(rec.Data) + case CrcType: + crc := decoder.LastCRC() // current crc of decoder must match the crc of the record. // do no need to match 0 crc, since the decoder is a new one at this case. if crc != 0 && rec.Validate(crc) != nil { return nil, ErrCRCMismatch } - decoder.updateCRC(rec.Crc) + decoder.UpdateCRC(rec.Crc) } } // We do not have to read out all the WAL entries @@ -653,24 +693,24 @@ func Verify(lg *zap.Logger, walDir string, snap walpb.Snapshot) (*raftpb.HardSta }() // create a new decoder from the readers on the WAL files - decoder := newDecoder(rs...) + decoder := NewDecoder(rs...) - for err = decoder.decode(rec); err == nil; err = decoder.decode(rec) { + for err = decoder.Decode(rec); err == nil; err = decoder.Decode(rec) { switch rec.Type { - case metadataType: + case MetadataType: if metadata != nil && !bytes.Equal(metadata, rec.Data) { return nil, ErrMetadataConflict } metadata = rec.Data - case crcType: - crc := decoder.crc.Sum32() + case CrcType: + crc := decoder.LastCRC() // Current crc of decoder must match the crc of the record. // We need not match 0 crc, since the decoder is a new one at this point. if crc != 0 && rec.Validate(crc) != nil { return nil, ErrCRCMismatch } - decoder.updateCRC(rec.Crc) - case snapshotType: + decoder.UpdateCRC(rec.Crc) + case SnapshotType: var loadedSnap walpb.Snapshot pbutil.MustUnmarshal(&loadedSnap, rec.Data) if loadedSnap.Index == snap.Index { @@ -681,8 +721,8 @@ func Verify(lg *zap.Logger, walDir string, snap walpb.Snapshot) (*raftpb.HardSta } // We ignore all entry and state type records as these // are not necessary for validating the WAL contents - case entryType: - case stateType: + case EntryType: + case StateType: pbutil.MustUnmarshal(&state, rec.Data) default: return nil, fmt.Errorf("unexpected block type %d", rec.Type) @@ -740,7 +780,7 @@ func (w *WAL) cut() error { return err } - if err = w.encoder.encode(&walpb.Record{Type: metadataType, Data: w.metadata}); err != nil { + if err = w.encoder.encode(&walpb.Record{Type: MetadataType, Data: w.metadata}); err != nil { return err } @@ -911,7 +951,7 @@ func (w *WAL) Close() error { func (w *WAL) saveEntry(e *raftpb.Entry) error { // TODO: add MustMarshalTo to reduce one allocation. b := pbutil.MustMarshal(e) - rec := &walpb.Record{Type: entryType, Data: b} + rec := &walpb.Record{Type: EntryType, Data: b} if err := w.encoder.encode(rec); err != nil { return err } @@ -925,7 +965,7 @@ func (w *WAL) saveState(s *raftpb.HardState) error { } w.state = *s b := pbutil.MustMarshal(s) - rec := &walpb.Record{Type: stateType, Data: b} + rec := &walpb.Record{Type: StateType, Data: b} return w.encoder.encode(rec) } @@ -977,7 +1017,7 @@ func (w *WAL) SaveSnapshot(e walpb.Snapshot) error { w.mu.Lock() defer w.mu.Unlock() - rec := &walpb.Record{Type: snapshotType, Data: b} + rec := &walpb.Record{Type: SnapshotType, Data: b} if err := w.encoder.encode(rec); err != nil { return err } @@ -989,7 +1029,7 @@ func (w *WAL) SaveSnapshot(e walpb.Snapshot) error { } func (w *WAL) saveCrc(prevCrc uint32) error { - return w.encoder.encode(&walpb.Record{Type: crcType, Crc: prevCrc}) + return w.encoder.encode(&walpb.Record{Type: CrcType, Crc: prevCrc}) } func (w *WAL) tail() *fileutil.LockedFile { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/walpb/record.go similarity index 87% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/walpb/record.go index e2070fbba3..30e6c06136 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/walpb/record.go @@ -14,18 +14,18 @@ package walpb -import "errors" - -var ( - ErrCRCMismatch = errors.New("walpb: crc mismatch") +import ( + "errors" + "fmt" ) +var ErrCRCMismatch = errors.New("walpb: crc mismatch") + func (rec *Record) Validate(crc uint32) error { if rec.Crc == crc { return nil } - rec.Reset() - return ErrCRCMismatch + return fmt.Errorf("%w: expected: %x computed: %x", ErrCRCMismatch, rec.Crc, crc) } // ValidateSnapshotForWrite ensures the Snapshot the newly written snapshot is valid. diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.pb.go b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/walpb/record.pb.go similarity index 89% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.pb.go rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/walpb/record.pb.go index 654d82636c..5605fbdaa3 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.pb.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/walpb/record.pb.go @@ -11,7 +11,7 @@ import ( _ "github.com/gogo/protobuf/gogoproto" proto "github.com/golang/protobuf/proto" - raftpb "go.etcd.io/etcd/raft/v3/raftpb" + raftpb "go.etcd.io/raft/v3/raftpb" ) // Reference imports to suppress errors if they are not otherwise used. @@ -119,22 +119,24 @@ func init() { func init() { proto.RegisterFile("record.proto", fileDescriptor_bf94fd919e302a1d) } var fileDescriptor_bf94fd919e302a1d = []byte{ - // 234 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0x8e, 0x41, 0x4e, 0xc3, 0x30, - 0x10, 0x45, 0x63, 0xe2, 0x22, 0x18, 0xca, 0x02, 0xab, 0xaa, 0xa2, 0x2c, 0x4c, 0xd4, 0x55, 0x56, - 0x29, 0xe2, 0x08, 0x65, 0xcf, 0x22, 0x3d, 0x00, 0x72, 0x1d, 0xa7, 0x20, 0xd1, 0x8c, 0x35, 0xb5, - 0x04, 0xdc, 0x84, 0x23, 0x65, 0xc9, 0x09, 0x10, 0x84, 0x8b, 0xa0, 0x8c, 0x03, 0x1b, 0xfb, 0xeb, - 0x7d, 0xf9, 0x7d, 0xc3, 0x9c, 0x9c, 0x45, 0x6a, 0x2a, 0x4f, 0x18, 0x50, 0xcd, 0x5e, 0xcc, 0xb3, - 0xdf, 0xe5, 0x8b, 0x3d, 0xee, 0x91, 0xc9, 0x7a, 0x4c, 0xb1, 0xcc, 0x97, 0x64, 0xda, 0xb0, 0x1e, - 0x0f, 0xbf, 0xe3, 0x2b, 0xf2, 0xd5, 0x3d, 0x9c, 0xd6, 0x2c, 0x51, 0x19, 0xc8, 0xf0, 0xe6, 0x5d, - 0x26, 0x0a, 0x51, 0xa6, 0x1b, 0xd9, 0x7f, 0x5e, 0x27, 0x35, 0x13, 0xb5, 0x84, 0xd4, 0x92, 0xcd, - 0x4e, 0x0a, 0x51, 0x5e, 0x4e, 0xc5, 0x08, 0x94, 0x02, 0xd9, 0x98, 0x60, 0xb2, 0xb4, 0x10, 0xe5, - 0xbc, 0xe6, 0xbc, 0x22, 0x38, 0xdb, 0x76, 0xc6, 0x1f, 0x1f, 0x31, 0xa8, 0x1c, 0x66, 0x4f, 0x5d, - 0xe3, 0x5e, 0x59, 0x29, 0xa7, 0x97, 0x11, 0xf1, 0x9a, 0xa3, 0x03, 0x4b, 0xe5, 0xff, 0x9a, 0xa3, - 0x83, 0xba, 0x01, 0xb0, 0xd8, 0xb5, 0x0f, 0xc7, 0x60, 0x82, 0x63, 0xf7, 0xc5, 0xed, 0x55, 0x15, - 0x7f, 0x5e, 0xdd, 0x61, 0xd7, 0x6e, 0xc7, 0xa2, 0x3e, 0xb7, 0x7f, 0x71, 0xb3, 0xe8, 0xbf, 0x75, - 0xd2, 0x0f, 0x5a, 0x7c, 0x0c, 0x5a, 0x7c, 0x0d, 0x5a, 0xbc, 0xff, 0xe8, 0xe4, 0x37, 0x00, 0x00, - 0xff, 0xff, 0xc3, 0x36, 0x0c, 0xad, 0x1d, 0x01, 0x00, 0x00, + // 266 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0x90, 0x41, 0x4e, 0xc3, 0x30, + 0x14, 0x44, 0x63, 0x92, 0x22, 0x30, 0x65, 0x51, 0x0b, 0xa1, 0x28, 0x8b, 0x10, 0x75, 0x15, 0x09, + 0x29, 0x46, 0x70, 0x02, 0xca, 0x9e, 0x45, 0xba, 0x63, 0x83, 0x5c, 0xe7, 0x27, 0x54, 0x6a, 0xf3, + 0xad, 0x1f, 0xab, 0x85, 0x9b, 0x70, 0xa4, 0x2c, 0x39, 0x01, 0x82, 0x70, 0x11, 0x64, 0xa7, 0xb0, + 0xfa, 0xa3, 0x37, 0x9a, 0x19, 0xcb, 0x7c, 0x4a, 0xa0, 0x91, 0xaa, 0xc2, 0x10, 0x5a, 0x14, 0x93, + 0xbd, 0xda, 0x98, 0x55, 0x72, 0xd1, 0x60, 0x83, 0x9e, 0x48, 0xa7, 0x46, 0x33, 0x99, 0x91, 0xaa, + 0xad, 0x59, 0x49, 0x77, 0x46, 0x34, 0x7f, 0xe4, 0xc7, 0xa5, 0xcf, 0x8b, 0x98, 0x47, 0xf6, 0xcd, + 0x40, 0xcc, 0x32, 0x96, 0x87, 0x8b, 0xa8, 0xff, 0xbc, 0x0a, 0x4a, 0x4f, 0xc4, 0x25, 0x0f, 0x35, + 0xe9, 0xf8, 0x28, 0x63, 0xf9, 0xf9, 0xc1, 0x70, 0x40, 0x08, 0x1e, 0x55, 0xca, 0xaa, 0x38, 0xcc, + 0x58, 0x3e, 0x2d, 0xbd, 0x9e, 0x13, 0x3f, 0x59, 0xb6, 0xca, 0x74, 0x2f, 0x68, 0x45, 0xc2, 0x27, + 0xeb, 0xb6, 0x82, 0x57, 0x5f, 0x19, 0x1d, 0x92, 0x23, 0xf2, 0x6b, 0x40, 0x5b, 0x5f, 0x1a, 0xfd, + 0xaf, 0x01, 0x6d, 0xc5, 0x0d, 0xe7, 0x1a, 0xdb, 0xfa, 0xb9, 0xb3, 0xca, 0x82, 0xef, 0x3e, 0xbb, + 0x9d, 0x15, 0xe3, 0xcb, 0x8b, 0x07, 0x6c, 0xeb, 0xa5, 0x33, 0xca, 0x53, 0xfd, 0x27, 0x17, 0xf7, + 0xfd, 0x77, 0x1a, 0xf4, 0x43, 0xca, 0x3e, 0x86, 0x94, 0x7d, 0x0d, 0x29, 0x7b, 0xff, 0x49, 0x83, + 0xa7, 0xeb, 0x06, 0x0b, 0xb0, 0xba, 0x2a, 0xd6, 0x28, 0xdd, 0x95, 0x1d, 0xd0, 0x0e, 0x48, 0xee, + 0xee, 0x64, 0x67, 0x91, 0x54, 0x03, 0x72, 0xaf, 0x36, 0xd2, 0xff, 0xd7, 0x6f, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xcf, 0xa9, 0xf0, 0x02, 0x45, 0x01, 0x00, 0x00, } func (m *Record) Marshal() (dAtA []byte, err error) { diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.proto b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/walpb/record.proto similarity index 87% rename from etcd/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.proto rename to etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/walpb/record.proto index 536fa6c19c..e1050fde48 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/wal/walpb/record.proto +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/storage/wal/walpb/record.proto @@ -2,7 +2,9 @@ syntax = "proto2"; package walpb; import "gogoproto/gogo.proto"; -import "raft/raftpb/raft.proto"; +import "raftpb/raft.proto"; + +option go_package = "go.etcd.io/etcd/server/v3/storage/wal/walpb"; option (gogoproto.marshaler_all) = true; option (gogoproto.sizer_all) = true; diff --git a/etcd/vendor/go.etcd.io/etcd/server/v3/verify/verify.go b/etcd/vendor/go.etcd.io/etcd/server/v3/verify/verify.go index 64fb34af53..0dc99afc81 100644 --- a/etcd/vendor/go.etcd.io/etcd/server/v3/verify/verify.go +++ b/etcd/vendor/go.etcd.io/etcd/server/v3/verify/verify.go @@ -16,19 +16,20 @@ package verify import ( "fmt" - "os" - - "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/server/v3/datadir" - "go.etcd.io/etcd/server/v3/etcdserver/cindex" - "go.etcd.io/etcd/server/v3/mvcc/backend" - wal2 "go.etcd.io/etcd/server/v3/wal" - "go.etcd.io/etcd/server/v3/wal/walpb" + "go.uber.org/zap" + + "go.etcd.io/etcd/client/pkg/v3/fileutil" + "go.etcd.io/etcd/client/pkg/v3/verify" + "go.etcd.io/etcd/server/v3/storage/backend" + "go.etcd.io/etcd/server/v3/storage/datadir" + "go.etcd.io/etcd/server/v3/storage/schema" + wal2 "go.etcd.io/etcd/server/v3/storage/wal" + "go.etcd.io/etcd/server/v3/storage/wal/walpb" + "go.etcd.io/raft/v3/raftpb" ) -const ENV_VERIFY = "ETCD_VERIFY" -const ENV_VERIFY_ALL_VALUE = "all" +const envVerifyValueStorageWAL verify.VerificationType = "storage_wal" type Config struct { // DataDir is a root directory where the data being verified are stored. @@ -47,19 +48,23 @@ type Config struct { // the function can also panic. // The function is expected to work on not-in-use data model, i.e. // no file-locks should be taken. Verify does not modified the data. -func Verify(cfg Config) error { +func Verify(cfg Config) (retErr error) { lg := cfg.Logger if lg == nil { lg = zap.NewNop() } - var err error + if !fileutil.Exist(datadir.ToBackendFileName(cfg.DataDir)) { + lg.Info("verification skipped due to non exist db file") + return nil + } + lg.Info("verification of persisted state", zap.String("data-dir", cfg.DataDir)) defer func() { - if err != nil { + if retErr != nil { lg.Error("verification of persisted state failed", zap.String("data-dir", cfg.DataDir), - zap.Error(err)) + zap.Error(retErr)) } else if r := recover(); r != nil { lg.Error("verification of persisted state failed", zap.String("data-dir", cfg.DataDir)) @@ -69,14 +74,10 @@ func Verify(cfg Config) error { } }() - beConfig := backend.DefaultBackendConfig() - beConfig.Path = datadir.ToBackendFileName(cfg.DataDir) - beConfig.Logger = cfg.Logger - - be := backend.New(beConfig) + be := backend.NewDefaultBackend(lg, datadir.ToBackendFileName(cfg.DataDir)) defer be.Close() - snapshot, hardstate, err := validateWal(cfg) + snapshot, hardstate, err := validateWAL(cfg) if err != nil { return err } @@ -90,37 +91,12 @@ func Verify(cfg Config) error { // VerifyIfEnabled performs verification according to ETCD_VERIFY env settings. // See Verify for more information. func VerifyIfEnabled(cfg Config) error { - if VerifyEnabled() { + if verify.IsVerificationEnabled(envVerifyValueStorageWAL) { return Verify(cfg) } return nil } -// VerifyEnabled returns `true` if verification is enabled. -func VerifyEnabled() bool { - return os.Getenv(ENV_VERIFY) == ENV_VERIFY_ALL_VALUE -} - -// EnableVerification enables the verification and returns a function that -// can be used to bring the original settings. -func EnableVerification() func() { - previousEnv := os.Getenv(ENV_VERIFY) - os.Setenv(ENV_VERIFY, ENV_VERIFY_ALL_VALUE) - return func() { - os.Setenv(ENV_VERIFY, previousEnv) - } -} - -// DisableVerification disables the verification and returns a function that -// can be used to bring the original settings. -func DisableVerification() func() { - previousEnv := os.Getenv(ENV_VERIFY) - os.Unsetenv(ENV_VERIFY) - return func() { - os.Setenv(ENV_VERIFY, previousEnv) - } -} - // MustVerifyIfEnabled performs verification according to ETCD_VERIFY env settings // and exits in case of found problems. // See Verify for more information. @@ -133,7 +109,7 @@ func MustVerifyIfEnabled(cfg Config) { } func validateConsistentIndex(cfg Config, hardstate *raftpb.HardState, snapshot *walpb.Snapshot, be backend.Backend) error { - index, term := cindex.ReadConsistentIndex(be.ReadTx()) + index, term := schema.ReadConsistentIndex(be.ReadTx()) if cfg.ExactIndex && index != hardstate.Commit { return fmt.Errorf("backend.ConsistentIndex (%v) expected == WAL.HardState.commit (%v)", index, hardstate.Commit) } @@ -155,8 +131,8 @@ func validateConsistentIndex(cfg Config, hardstate *raftpb.HardState, snapshot * return nil } -func validateWal(cfg Config) (*walpb.Snapshot, *raftpb.HardState, error) { - walDir := datadir.ToWalDir(cfg.DataDir) +func validateWAL(cfg Config) (*walpb.Snapshot, *raftpb.HardState, error) { + walDir := datadir.ToWALDir(cfg.DataDir) walSnaps, err := wal2.ValidSnapshotEntries(cfg.Logger, walDir) if err != nil { diff --git a/etcd/vendor/go.etcd.io/raft/v3/.gitignore b/etcd/vendor/go.etcd.io/raft/v3/.gitignore new file mode 100644 index 0000000000..485dee64bc --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/etcd/vendor/go.etcd.io/raft/v3/.go-version b/etcd/vendor/go.etcd.io/raft/v3/.go-version new file mode 100644 index 0000000000..d8c40e539c --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/.go-version @@ -0,0 +1 @@ +1.23.6 diff --git a/etcd/vendor/go.etcd.io/raft/v3/.golangci.yaml b/etcd/vendor/go.etcd.io/raft/v3/.golangci.yaml new file mode 100644 index 0000000000..d169aa4e7f --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/.golangci.yaml @@ -0,0 +1,41 @@ +run: + timeout: 30m + skip-files: + - "^zz_generated.*" + +issues: + max-same-issues: 0 + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + # exclude ineffassing linter for generated files for conversion + - path: conversion\.go + linters: + - ineffassign + +linters: + disable-all: true + enable: # please keep this alphabetized + # Don't use soon to deprecated[1] linters that lead to false + # https://github.com/golangci/golangci-lint/issues/1841 + # - deadcode + # - structcheck + # - varcheck + - goimports + - ineffassign + - revive + - staticcheck + - stylecheck + - unused + - unconvert # Remove unnecessary type conversions + +linters-settings: # please keep this alphabetized + goimports: + local-prefixes: go.etcd.io # Put imports beginning with prefix after 3rd-party packages. + staticcheck: + checks: + - "all" + - "-SA1019" # TODO(fix) Using a deprecated function, variable, constant or field + - "-SA2002" # TODO(fix) Called testing.T.FailNow or SkipNow in a goroutine, which isn’t allowed + stylecheck: + checks: + - "ST1019" # Importing the same package multiple times. diff --git a/etcd/vendor/go.etcd.io/etcd/client/v2/LICENSE b/etcd/vendor/go.etcd.io/raft/v3/LICENSE similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/client/v2/LICENSE rename to etcd/vendor/go.etcd.io/raft/v3/LICENSE diff --git a/etcd/vendor/go.etcd.io/raft/v3/Makefile b/etcd/vendor/go.etcd.io/raft/v3/Makefile new file mode 100644 index 0000000000..3ae9d6a3c2 --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/Makefile @@ -0,0 +1,28 @@ +GO_TEST_FLAGS?= + +.PHONY: verify +verify: verify-gofmt verify-dep verify-lint verify-mod-tidy verify-genproto + +.PHONY: verify-gofmt +verify-gofmt: + PASSES="gofmt" ./scripts/test.sh + +.PHONY: verify-dep +verify-dep: + PASSES="dep" ./scripts/test.sh + +.PHONY: verify-lint +verify-lint: + golangci-lint run + +.PHONY: verify-mod-tidy +verify-mod-tidy: + PASSES="mod_tidy" ./scripts/test.sh + +.PHONY: verify-genproto +verify-genproto: + PASSES="genproto" ./scripts/test.sh + +.PHONY: test +test: + PASSES="unit" ./scripts/test.sh $(GO_TEST_FLAGS) diff --git a/etcd/vendor/go.etcd.io/raft/v3/OWNERS b/etcd/vendor/go.etcd.io/raft/v3/OWNERS new file mode 100644 index 0000000000..288f19949d --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/OWNERS @@ -0,0 +1,11 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +approvers: + - ahrtr # Benjamin Wang + - serathius # Marek Siarkowicz + - ptabor # Piotr Tabor + - spzala # Sahdev Zala +reviewers: + - pav-kv # Pavel Kalinnikov +emeritus_approvers: + - tbg # Tobias Grieger diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/README.md b/etcd/vendor/go.etcd.io/raft/v3/README.md similarity index 97% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/README.md rename to etcd/vendor/go.etcd.io/raft/v3/README.md index fbd8b4d49b..6527fd9cf5 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/README.md +++ b/etcd/vendor/go.etcd.io/raft/v3/README.md @@ -67,9 +67,9 @@ To start a three-node cluster MaxSizePerMsg: 4096, MaxInflightMsgs: 256, } - // Set peer list to the other nodes in the cluster. - // Note that they need to be started separately as well. - n := raft.StartNode(c, []raft.Peer{{ID: 0x02}, {ID: 0x03}}) + // Set peer list to all nodes in the cluster. + // Note that other nodes in the cluster, apart from this node, need to be started separately. + n := raft.StartNode(c, []raft.Peer{{ID: 0x01}, {ID: 0x02}, {ID: 0x03}}) ``` Start a single node cluster, like so: @@ -198,4 +198,4 @@ This approach introduces a problem when removing a member from a two-member clus ## Go docs -More detailed development documentation can be found in go docs: https://pkg.go.dev/go.etcd.io/etcd/raft/v3. \ No newline at end of file +More detailed development documentation can be found in go docs: https://pkg.go.dev/go.etcd.io/raft/v3. \ No newline at end of file diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/bootstrap.go b/etcd/vendor/go.etcd.io/raft/v3/bootstrap.go similarity index 98% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/bootstrap.go rename to etcd/vendor/go.etcd.io/raft/v3/bootstrap.go index 824bd5f51b..2a61aa23e4 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/bootstrap.go +++ b/etcd/vendor/go.etcd.io/raft/v3/bootstrap.go @@ -17,7 +17,7 @@ package raft import ( "errors" - pb "go.etcd.io/etcd/raft/v3/raftpb" + pb "go.etcd.io/raft/v3/raftpb" ) // Bootstrap initializes the RawNode for first use by appending configuration diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/confchange/confchange.go b/etcd/vendor/go.etcd.io/raft/v3/confchange/confchange.go similarity index 87% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/confchange/confchange.go rename to etcd/vendor/go.etcd.io/raft/v3/confchange/confchange.go index dddbcc9d9b..a73d5609aa 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/confchange/confchange.go +++ b/etcd/vendor/go.etcd.io/raft/v3/confchange/confchange.go @@ -19,9 +19,9 @@ import ( "fmt" "strings" - "go.etcd.io/etcd/raft/v3/quorum" - pb "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/raft/v3/tracker" + "go.etcd.io/raft/v3/quorum" + pb "go.etcd.io/raft/v3/raftpb" + "go.etcd.io/raft/v3/tracker" ) // Changer facilitates configuration changes. It exposes methods to handle @@ -49,7 +49,7 @@ type Changer struct { // // [1]: https://github.com/ongardie/dissertation/blob/master/online-trim.pdf func (c Changer) EnterJoint(autoLeave bool, ccs ...pb.ConfChangeSingle) (tracker.Config, tracker.ProgressMap, error) { - cfg, prs, err := c.checkAndCopy() + cfg, trk, err := c.checkAndCopy() if err != nil { return c.err(err) } @@ -70,11 +70,11 @@ func (c Changer) EnterJoint(autoLeave bool, ccs ...pb.ConfChangeSingle) (tracker outgoing(cfg.Voters)[id] = struct{}{} } - if err := c.apply(&cfg, prs, ccs...); err != nil { + if err := c.apply(&cfg, trk, ccs...); err != nil { return c.err(err) } cfg.AutoLeave = autoLeave - return checkAndReturn(cfg, prs) + return checkAndReturn(cfg, trk) } // LeaveJoint transitions out of a joint configuration. It is an error to call @@ -92,7 +92,7 @@ func (c Changer) EnterJoint(autoLeave bool, ccs ...pb.ConfChangeSingle) (tracker // // [1]: https://github.com/ongardie/dissertation/blob/master/online-trim.pdf func (c Changer) LeaveJoint() (tracker.Config, tracker.ProgressMap, error) { - cfg, prs, err := c.checkAndCopy() + cfg, trk, err := c.checkAndCopy() if err != nil { return c.err(err) } @@ -100,13 +100,9 @@ func (c Changer) LeaveJoint() (tracker.Config, tracker.ProgressMap, error) { err := errors.New("can't leave a non-joint config") return c.err(err) } - if len(outgoing(cfg.Voters)) == 0 { - err := fmt.Errorf("configuration is not joint: %v", cfg) - return c.err(err) - } for id := range cfg.LearnersNext { nilAwareAdd(&cfg.Learners, id) - prs[id].IsLearner = true + trk[id].IsLearner = true } cfg.LearnersNext = nil @@ -115,13 +111,13 @@ func (c Changer) LeaveJoint() (tracker.Config, tracker.ProgressMap, error) { _, isLearner := cfg.Learners[id] if !isVoter && !isLearner { - delete(prs, id) + delete(trk, id) } } *outgoingPtr(&cfg.Voters) = nil cfg.AutoLeave = false - return checkAndReturn(cfg, prs) + return checkAndReturn(cfg, trk) } // Simple carries out a series of configuration changes that (in aggregate) @@ -130,7 +126,7 @@ func (c Changer) LeaveJoint() (tracker.Config, tracker.ProgressMap, error) { // zero, or if the configuration is in a joint state (i.e. if there is an // outgoing configuration). func (c Changer) Simple(ccs ...pb.ConfChangeSingle) (tracker.Config, tracker.ProgressMap, error) { - cfg, prs, err := c.checkAndCopy() + cfg, trk, err := c.checkAndCopy() if err != nil { return c.err(err) } @@ -138,20 +134,20 @@ func (c Changer) Simple(ccs ...pb.ConfChangeSingle) (tracker.Config, tracker.Pro err := errors.New("can't apply simple config change in joint config") return c.err(err) } - if err := c.apply(&cfg, prs, ccs...); err != nil { + if err := c.apply(&cfg, trk, ccs...); err != nil { return c.err(err) } if n := symdiff(incoming(c.Tracker.Voters), incoming(cfg.Voters)); n > 1 { return tracker.Config{}, nil, errors.New("more than one voter changed without entering joint config") } - return checkAndReturn(cfg, prs) + return checkAndReturn(cfg, trk) } // apply a change to the configuration. By convention, changes to voters are // always made to the incoming majority config Voters[0]. Voters[1] is either // empty or preserves the outgoing majority configuration while in a joint state. -func (c Changer) apply(cfg *tracker.Config, prs tracker.ProgressMap, ccs ...pb.ConfChangeSingle) error { +func (c Changer) apply(cfg *tracker.Config, trk tracker.ProgressMap, ccs ...pb.ConfChangeSingle) error { for _, cc := range ccs { if cc.NodeID == 0 { // etcd replaces the NodeID with zero if it decides (downstream of @@ -161,11 +157,11 @@ func (c Changer) apply(cfg *tracker.Config, prs tracker.ProgressMap, ccs ...pb.C } switch cc.Type { case pb.ConfChangeAddNode: - c.makeVoter(cfg, prs, cc.NodeID) + c.makeVoter(cfg, trk, cc.NodeID) case pb.ConfChangeAddLearnerNode: - c.makeLearner(cfg, prs, cc.NodeID) + c.makeLearner(cfg, trk, cc.NodeID) case pb.ConfChangeRemoveNode: - c.remove(cfg, prs, cc.NodeID) + c.remove(cfg, trk, cc.NodeID) case pb.ConfChangeUpdateNode: default: return fmt.Errorf("unexpected conf type %d", cc.Type) @@ -179,10 +175,10 @@ func (c Changer) apply(cfg *tracker.Config, prs tracker.ProgressMap, ccs ...pb.C // makeVoter adds or promotes the given ID to be a voter in the incoming // majority config. -func (c Changer) makeVoter(cfg *tracker.Config, prs tracker.ProgressMap, id uint64) { - pr := prs[id] +func (c Changer) makeVoter(cfg *tracker.Config, trk tracker.ProgressMap, id uint64) { + pr := trk[id] if pr == nil { - c.initProgress(cfg, prs, id, false /* isLearner */) + c.initProgress(cfg, trk, id, false /* isLearner */) return } @@ -205,19 +201,19 @@ func (c Changer) makeVoter(cfg *tracker.Config, prs tracker.ProgressMap, id uint // simultaneously. Instead, we add the learner to LearnersNext, so that it will // be added to Learners the moment the outgoing config is removed by // LeaveJoint(). -func (c Changer) makeLearner(cfg *tracker.Config, prs tracker.ProgressMap, id uint64) { - pr := prs[id] +func (c Changer) makeLearner(cfg *tracker.Config, trk tracker.ProgressMap, id uint64) { + pr := trk[id] if pr == nil { - c.initProgress(cfg, prs, id, true /* isLearner */) + c.initProgress(cfg, trk, id, true /* isLearner */) return } if pr.IsLearner { return } // Remove any existing voter in the incoming config... - c.remove(cfg, prs, id) + c.remove(cfg, trk, id) // ... but save the Progress. - prs[id] = pr + trk[id] = pr // Use LearnersNext if we can't add the learner to Learners directly, i.e. // if the peer is still tracked as a voter in the outgoing config. It will // be turned into a learner in LeaveJoint(). @@ -232,8 +228,8 @@ func (c Changer) makeLearner(cfg *tracker.Config, prs tracker.ProgressMap, id ui } // remove this peer as a voter or learner from the incoming config. -func (c Changer) remove(cfg *tracker.Config, prs tracker.ProgressMap, id uint64) { - if _, ok := prs[id]; !ok { +func (c Changer) remove(cfg *tracker.Config, trk tracker.ProgressMap, id uint64) { + if _, ok := trk[id]; !ok { return } @@ -243,18 +239,18 @@ func (c Changer) remove(cfg *tracker.Config, prs tracker.ProgressMap, id uint64) // If the peer is still a voter in the outgoing config, keep the Progress. if _, onRight := outgoing(cfg.Voters)[id]; !onRight { - delete(prs, id) + delete(trk, id) } } // initProgress initializes a new progress for the given node or learner. -func (c Changer) initProgress(cfg *tracker.Config, prs tracker.ProgressMap, id uint64, isLearner bool) { +func (c Changer) initProgress(cfg *tracker.Config, trk tracker.ProgressMap, id uint64, isLearner bool) { if !isLearner { incoming(cfg.Voters)[id] = struct{}{} } else { nilAwareAdd(&cfg.Learners, id) } - prs[id] = &tracker.Progress{ + trk[id] = &tracker.Progress{ // Initializing the Progress with the last index means that the follower // can be probed (with the last index). // @@ -263,9 +259,9 @@ func (c Changer) initProgress(cfg *tracker.Config, prs tracker.ProgressMap, id u // at all (and will thus likely need a snapshot), though the app may // have applied a snapshot out of band before adding the replica (thus // making the first index the better choice). - Next: c.LastIndex, Match: 0, - Inflights: tracker.NewInflights(c.Tracker.MaxInflight), + Next: max(c.LastIndex, 1), // invariant: Match < Next + Inflights: tracker.NewInflights(c.Tracker.MaxInflight, c.Tracker.MaxInflightBytes), IsLearner: isLearner, // When a node is first added, we should mark it as recently active. // Otherwise, CheckQuorum may cause us to step down if it is invoked @@ -277,7 +273,7 @@ func (c Changer) initProgress(cfg *tracker.Config, prs tracker.ProgressMap, id u // checkInvariants makes sure that the config and progress are compatible with // each other. This is used to check both what the Changer is initialized with, // as well as what it returns. -func checkInvariants(cfg tracker.Config, prs tracker.ProgressMap) error { +func checkInvariants(cfg tracker.Config, trk tracker.ProgressMap) error { // NB: intentionally allow the empty config. In production we'll never see a // non-empty config (we prevent it from being created) but we will need to // be able to *create* an initial config, for example during bootstrap (or @@ -290,7 +286,7 @@ func checkInvariants(cfg tracker.Config, prs tracker.ProgressMap) error { cfg.LearnersNext, } { for id := range ids { - if _, ok := prs[id]; !ok { + if _, ok := trk[id]; !ok { return fmt.Errorf("no progress for %d", id) } } @@ -302,7 +298,7 @@ func checkInvariants(cfg tracker.Config, prs tracker.ProgressMap) error { if _, ok := outgoing(cfg.Voters)[id]; !ok { return fmt.Errorf("%d is in LearnersNext, but not Voters[1]", id) } - if prs[id].IsLearner { + if trk[id].IsLearner { return fmt.Errorf("%d is in LearnersNext, but is already marked as learner", id) } } @@ -314,7 +310,7 @@ func checkInvariants(cfg tracker.Config, prs tracker.ProgressMap) error { if _, ok := incoming(cfg.Voters)[id]; ok { return fmt.Errorf("%d is in Learners and Voters[0]", id) } - if !prs[id].IsLearner { + if !trk[id].IsLearner { return fmt.Errorf("%d is in Learners, but is not marked as learner", id) } } @@ -340,23 +336,23 @@ func checkInvariants(cfg tracker.Config, prs tracker.ProgressMap) error { // if checkInvariants does. func (c Changer) checkAndCopy() (tracker.Config, tracker.ProgressMap, error) { cfg := c.Tracker.Config.Clone() - prs := tracker.ProgressMap{} + trk := tracker.ProgressMap{} for id, pr := range c.Tracker.Progress { // A shallow copy is enough because we only mutate the Learner field. ppr := *pr - prs[id] = &ppr + trk[id] = &ppr } - return checkAndReturn(cfg, prs) + return checkAndReturn(cfg, trk) } // checkAndReturn calls checkInvariants on the input and returns either the // resulting error or the input. -func checkAndReturn(cfg tracker.Config, prs tracker.ProgressMap) (tracker.Config, tracker.ProgressMap, error) { - if err := checkInvariants(cfg, prs); err != nil { +func checkAndReturn(cfg tracker.Config, trk tracker.ProgressMap) (tracker.Config, tracker.ProgressMap, error) { + if err := checkInvariants(cfg, trk); err != nil { return tracker.Config{}, tracker.ProgressMap{}, err } - return cfg, prs, nil + return cfg, trk, nil } // err returns zero values and an error. diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/confchange/restore.go b/etcd/vendor/go.etcd.io/raft/v3/confchange/restore.go similarity index 97% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/confchange/restore.go rename to etcd/vendor/go.etcd.io/raft/v3/confchange/restore.go index ea317fc289..68ef029a9c 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/confchange/restore.go +++ b/etcd/vendor/go.etcd.io/raft/v3/confchange/restore.go @@ -15,8 +15,8 @@ package confchange import ( - pb "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/raft/v3/tracker" + pb "go.etcd.io/raft/v3/raftpb" + "go.etcd.io/raft/v3/tracker" ) // toConfChangeSingle translates a conf state into 1) a slice of operations creating @@ -98,12 +98,12 @@ func toConfChangeSingle(cs pb.ConfState) (out []pb.ConfChangeSingle, in []pb.Con func chain(chg Changer, ops ...func(Changer) (tracker.Config, tracker.ProgressMap, error)) (tracker.Config, tracker.ProgressMap, error) { for _, op := range ops { - cfg, prs, err := op(chg) + cfg, trk, err := op(chg) if err != nil { return tracker.Config{}, nil, err } chg.Tracker.Config = cfg - chg.Tracker.Progress = prs + chg.Tracker.Progress = trk } return chg.Tracker.Config, chg.Tracker.Progress, nil } diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/design.md b/etcd/vendor/go.etcd.io/raft/v3/design.md similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/design.md rename to etcd/vendor/go.etcd.io/raft/v3/design.md diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/doc.go b/etcd/vendor/go.etcd.io/raft/v3/doc.go similarity index 79% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/doc.go rename to etcd/vendor/go.etcd.io/raft/v3/doc.go index 4febfe6084..06253f4e12 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/doc.go +++ b/etcd/vendor/go.etcd.io/raft/v3/doc.go @@ -169,6 +169,94 @@ given ID MUST be used only once even if the old node has been removed. This means that for example IP addresses make poor node IDs since they may be reused. Node IDs must be non-zero. +# Usage with Asynchronous Storage Writes + +The library can be configured with an alternate interface for local storage +writes that can provide better performance in the presence of high proposal +concurrency by minimizing interference between proposals. This feature is called +AsynchronousStorageWrites, and can be enabled using the flag on the Config +struct with the same name. + +When Asynchronous Storage Writes is enabled, the responsibility of code using +the library is different from what was presented above. Users still read from +the Node.Ready() channel. However, they process the updates it contains in a +different manner. Users no longer consult the HardState, Entries, and Snapshot +fields (steps 1 and 3 above). They also no longer call Node.Advance() to +indicate that they have processed all entries in the Ready (step 4 above). +Instead, all local storage operations are also communicated through messages +present in the Ready.Message slice. + +The local storage messages come in two flavors. The first flavor is log append +messages, which target a LocalAppendThread and carry Entries, HardState, and a +Snapshot. The second flavor is entry application messages, which target a +LocalApplyThread and carry CommittedEntries. Messages to the same target must be +reliably processed in order. Messages to different targets can be processed in +any order. + +Each local storage message carries a slice of response messages that must +delivered after the corresponding storage write has been completed. These +responses may target the same node or may target other nodes. + +With Asynchronous Storage Writes enabled, the total state machine handling loop +will look something like this: + + for { + select { + case <-s.Ticker: + n.Tick() + case rd := <-s.Node.Ready(): + for _, m := range rd.Messages { + switch m.To { + case raft.LocalAppendThread: + toAppend <- m + case raft.LocalApplyThread: + toApply <-m + default: + sendOverNetwork(m) + } + } + case <-s.done: + return + } + } + +Usage of Asynchronous Storage Writes will typically also contain a pair of +storage handler threads, one for log writes (append) and one for entry +application to the local state machine (apply). Those will look something like: + + // append thread + go func() { + for { + select { + case m := <-toAppend: + saveToStorage(m.State, m.Entries, m.Snapshot) + send(m.Responses) + case <-s.done: + return + } + } + } + + // apply thread + go func() { + for { + select { + case m := <-toApply: + for _, entry := range m.CommittedEntries { + process(entry) + if entry.Type == raftpb.EntryConfChange { + var cc raftpb.ConfChange + cc.Unmarshal(entry.Data) + s.Node.ApplyConfChange(cc) + } + } + send(m.Responses) + case <-s.done: + return + } + } + } + # Implementation notes This implementation is up to date with the final Raft thesis @@ -295,5 +383,17 @@ stale log entries: that the follower that sent this 'MsgUnreachable' is not reachable, often indicating 'MsgApp' is lost. When follower's progress state is replicate, the leader sets it back to probe. + + 'MsgStorageAppend' is a message from a node to its local append storage + thread to write entries, hard state, and/or a snapshot to stable storage. + The message will carry one or more responses, one of which will be a + 'MsgStorageAppendResp' back to itself. The responses can also contain + 'MsgAppResp', 'MsgVoteResp', and 'MsgPreVoteResp' messages. Used with + AsynchronousStorageWrites. + + 'MsgStorageApply' is a message from a node to its local apply storage + thread to apply committed entries. The message will carry one response, + which will be a 'MsgStorageApplyResp' back to itself. Used with + AsynchronousStorageWrites. */ package raft diff --git a/etcd/vendor/go.etcd.io/raft/v3/log.go b/etcd/vendor/go.etcd.io/raft/v3/log.go new file mode 100644 index 0000000000..bd7c2febb6 --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/log.go @@ -0,0 +1,574 @@ +// Copyright 2015 The etcd 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 raft + +import ( + "fmt" + + pb "go.etcd.io/raft/v3/raftpb" +) + +type raftLog struct { + // storage contains all stable entries since the last snapshot. + storage Storage + + // unstable contains all unstable entries and snapshot. + // they will be saved into storage. + unstable unstable + + // committed is the highest log position that is known to be in + // stable storage on a quorum of nodes. + committed uint64 + // applying is the highest log position that the application has + // been instructed to apply to its state machine. Some of these + // entries may be in the process of applying and have not yet + // reached applied. + // Use: The field is incremented when accepting a Ready struct. + // Invariant: applied <= applying && applying <= committed + applying uint64 + // applied is the highest log position that the application has + // successfully applied to its state machine. + // Use: The field is incremented when advancing after the committed + // entries in a Ready struct have been applied (either synchronously + // or asynchronously). + // Invariant: applied <= committed + applied uint64 + + logger Logger + + // maxApplyingEntsSize limits the outstanding byte size of the messages + // returned from calls to nextCommittedEnts that have not been acknowledged + // by a call to appliedTo. + maxApplyingEntsSize entryEncodingSize + // applyingEntsSize is the current outstanding byte size of the messages + // returned from calls to nextCommittedEnts that have not been acknowledged + // by a call to appliedTo. + applyingEntsSize entryEncodingSize + // applyingEntsPaused is true when entry application has been paused until + // enough progress is acknowledged. + applyingEntsPaused bool +} + +// newLog returns log using the given storage and default options. It +// recovers the log to the state that it just commits and applies the +// latest snapshot. +func newLog(storage Storage, logger Logger) *raftLog { + return newLogWithSize(storage, logger, noLimit) +} + +// newLogWithSize returns a log using the given storage and max +// message size. +func newLogWithSize(storage Storage, logger Logger, maxApplyingEntsSize entryEncodingSize) *raftLog { + firstIndex, err := storage.FirstIndex() + if err != nil { + panic(err) // TODO(bdarnell) + } + lastIndex, err := storage.LastIndex() + if err != nil { + panic(err) // TODO(bdarnell) + } + return &raftLog{ + storage: storage, + unstable: unstable{ + offset: lastIndex + 1, + offsetInProgress: lastIndex + 1, + logger: logger, + }, + maxApplyingEntsSize: maxApplyingEntsSize, + + // Initialize our committed and applied pointers to the time of the last compaction. + committed: firstIndex - 1, + applying: firstIndex - 1, + applied: firstIndex - 1, + + logger: logger, + } +} + +func (l *raftLog) String() string { + return fmt.Sprintf("committed=%d, applied=%d, applying=%d, unstable.offset=%d, unstable.offsetInProgress=%d, len(unstable.Entries)=%d", + l.committed, l.applied, l.applying, l.unstable.offset, l.unstable.offsetInProgress, len(l.unstable.entries)) +} + +// maybeAppend returns (0, false) if the entries cannot be appended. Otherwise, +// it returns (last index of new entries, true). +func (l *raftLog) maybeAppend(a logSlice, committed uint64) (lastnewi uint64, ok bool) { + if !l.matchTerm(a.prev) { + return 0, false + } + // TODO(pav-kv): propagate logSlice down the stack. It will be used all the + // way down in unstable, for safety checks, and for useful bookkeeping. + + lastnewi = a.prev.index + uint64(len(a.entries)) + ci := l.findConflict(a.entries) + switch { + case ci == 0: + case ci <= l.committed: + l.logger.Panicf("entry %d conflict with committed entry [committed(%d)]", ci, l.committed) + default: + offset := a.prev.index + 1 + if ci-offset > uint64(len(a.entries)) { + l.logger.Panicf("index, %d, is out of range [%d]", ci-offset, len(a.entries)) + } + l.append(a.entries[ci-offset:]...) + } + l.commitTo(min(committed, lastnewi)) + return lastnewi, true +} + +func (l *raftLog) append(ents ...pb.Entry) uint64 { + if len(ents) == 0 { + return l.lastIndex() + } + if after := ents[0].Index - 1; after < l.committed { + l.logger.Panicf("after(%d) is out of range [committed(%d)]", after, l.committed) + } + l.unstable.truncateAndAppend(ents) + return l.lastIndex() +} + +// findConflict finds the index of the conflict. +// It returns the first pair of conflicting entries between the existing +// entries and the given entries, if there are any. +// If there is no conflicting entries, and the existing entries contains +// all the given entries, zero will be returned. +// If there is no conflicting entries, but the given entries contains new +// entries, the index of the first new entry will be returned. +// An entry is considered to be conflicting if it has the same index but +// a different term. +// The index of the given entries MUST be continuously increasing. +func (l *raftLog) findConflict(ents []pb.Entry) uint64 { + for i := range ents { + if id := pbEntryID(&ents[i]); !l.matchTerm(id) { + if id.index <= l.lastIndex() { + // TODO(pav-kv): can simply print %+v of the id. This will change the + // log format though. + l.logger.Infof("found conflict at index %d [existing term: %d, conflicting term: %d]", + id.index, l.zeroTermOnOutOfBounds(l.term(id.index)), id.term) + } + return id.index + } + } + return 0 +} + +// findConflictByTerm returns a best guess on where this log ends matching +// another log, given that the only information known about the other log is the +// (index, term) of its single entry. +// +// Specifically, the first returned value is the max guessIndex <= index, such +// that term(guessIndex) <= term or term(guessIndex) is not known (because this +// index is compacted or not yet stored). +// +// The second returned value is the term(guessIndex), or 0 if it is unknown. +// +// This function is used by a follower and leader to resolve log conflicts after +// an unsuccessful append to a follower, and ultimately restore the steady flow +// of appends. +func (l *raftLog) findConflictByTerm(index uint64, term uint64) (uint64, uint64) { + for ; index > 0; index-- { + // If there is an error (likely ErrCompacted or ErrUnavailable), we don't + // know whether it's a match or not, so assume a possible match and return + // the index, with 0 term indicating an unknown term. + if ourTerm, err := l.term(index); err != nil { + return index, 0 + } else if ourTerm <= term { + return index, ourTerm + } + } + return 0, 0 +} + +// nextUnstableEnts returns all entries that are available to be written to the +// local stable log and are not already in-progress. +func (l *raftLog) nextUnstableEnts() []pb.Entry { + return l.unstable.nextEntries() +} + +// hasNextUnstableEnts returns if there are any entries that are available to be +// written to the local stable log and are not already in-progress. +func (l *raftLog) hasNextUnstableEnts() bool { + return len(l.nextUnstableEnts()) > 0 +} + +// hasNextOrInProgressUnstableEnts returns if there are any entries that are +// available to be written to the local stable log or in the process of being +// written to the local stable log. +func (l *raftLog) hasNextOrInProgressUnstableEnts() bool { + return len(l.unstable.entries) > 0 +} + +// nextCommittedEnts returns all the available entries for execution. +// Entries can be committed even when the local raft instance has not durably +// appended them to the local raft log yet. If allowUnstable is true, committed +// entries from the unstable log may be returned; otherwise, only entries known +// to reside locally on stable storage will be returned. +func (l *raftLog) nextCommittedEnts(allowUnstable bool) (ents []pb.Entry) { + if l.applyingEntsPaused { + // Entry application outstanding size limit reached. + return nil + } + if l.hasNextOrInProgressSnapshot() { + // See comment in hasNextCommittedEnts. + return nil + } + lo, hi := l.applying+1, l.maxAppliableIndex(allowUnstable)+1 // [lo, hi) + if lo >= hi { + // Nothing to apply. + return nil + } + maxSize := l.maxApplyingEntsSize - l.applyingEntsSize + if maxSize <= 0 { + l.logger.Panicf("applying entry size (%d-%d)=%d not positive", + l.maxApplyingEntsSize, l.applyingEntsSize, maxSize) + } + ents, err := l.slice(lo, hi, maxSize) + if err != nil { + l.logger.Panicf("unexpected error when getting unapplied entries (%v)", err) + } + return ents +} + +// hasNextCommittedEnts returns if there is any available entries for execution. +// This is a fast check without heavy raftLog.slice() in nextCommittedEnts(). +func (l *raftLog) hasNextCommittedEnts(allowUnstable bool) bool { + if l.applyingEntsPaused { + // Entry application outstanding size limit reached. + return false + } + if l.hasNextOrInProgressSnapshot() { + // If we have a snapshot to apply, don't also return any committed + // entries. Doing so raises questions about what should be applied + // first. + return false + } + lo, hi := l.applying+1, l.maxAppliableIndex(allowUnstable)+1 // [lo, hi) + return lo < hi +} + +// maxAppliableIndex returns the maximum committed index that can be applied. +// If allowUnstable is true, committed entries from the unstable log can be +// applied; otherwise, only entries known to reside locally on stable storage +// can be applied. +func (l *raftLog) maxAppliableIndex(allowUnstable bool) uint64 { + hi := l.committed + if !allowUnstable { + hi = min(hi, l.unstable.offset-1) + } + return hi +} + +// nextUnstableSnapshot returns the snapshot, if present, that is available to +// be applied to the local storage and is not already in-progress. +func (l *raftLog) nextUnstableSnapshot() *pb.Snapshot { + return l.unstable.nextSnapshot() +} + +// hasNextUnstableSnapshot returns if there is a snapshot that is available to +// be applied to the local storage and is not already in-progress. +func (l *raftLog) hasNextUnstableSnapshot() bool { + return l.unstable.nextSnapshot() != nil +} + +// hasNextOrInProgressSnapshot returns if there is pending snapshot waiting for +// applying or in the process of being applied. +func (l *raftLog) hasNextOrInProgressSnapshot() bool { + return l.unstable.snapshot != nil +} + +func (l *raftLog) snapshot() (pb.Snapshot, error) { + if l.unstable.snapshot != nil { + return *l.unstable.snapshot, nil + } + return l.storage.Snapshot() +} + +func (l *raftLog) firstIndex() uint64 { + if i, ok := l.unstable.maybeFirstIndex(); ok { + return i + } + index, err := l.storage.FirstIndex() + if err != nil { + panic(err) // TODO(bdarnell) + } + return index +} + +func (l *raftLog) lastIndex() uint64 { + if i, ok := l.unstable.maybeLastIndex(); ok { + return i + } + i, err := l.storage.LastIndex() + if err != nil { + panic(err) // TODO(bdarnell) + } + return i +} + +func (l *raftLog) commitTo(tocommit uint64) { + // never decrease commit + if l.committed < tocommit { + if l.lastIndex() < tocommit { + l.logger.Panicf("tocommit(%d) is out of range [lastIndex(%d)]. Was the raft log corrupted, truncated, or lost?", tocommit, l.lastIndex()) + } + l.committed = tocommit + } +} + +func (l *raftLog) appliedTo(i uint64, size entryEncodingSize) { + if l.committed < i || i < l.applied { + l.logger.Panicf("applied(%d) is out of range [prevApplied(%d), committed(%d)]", i, l.applied, l.committed) + } + l.applied = i + l.applying = max(l.applying, i) + if l.applyingEntsSize > size { + l.applyingEntsSize -= size + } else { + // Defense against underflow. + l.applyingEntsSize = 0 + } + l.applyingEntsPaused = l.applyingEntsSize >= l.maxApplyingEntsSize +} + +func (l *raftLog) acceptApplying(i uint64, size entryEncodingSize, allowUnstable bool) { + if l.committed < i { + l.logger.Panicf("applying(%d) is out of range [prevApplying(%d), committed(%d)]", i, l.applying, l.committed) + } + l.applying = i + l.applyingEntsSize += size + // Determine whether to pause entry application until some progress is + // acknowledged. We pause in two cases: + // 1. the outstanding entry size equals or exceeds the maximum size. + // 2. the outstanding entry size does not equal or exceed the maximum size, + // but we determine that the next entry in the log will push us over the + // limit. We determine this by comparing the last entry returned from + // raftLog.nextCommittedEnts to the maximum entry that the method was + // allowed to return had there been no size limit. If these indexes are + // not equal, then the returned entries slice must have been truncated to + // adhere to the memory limit. + l.applyingEntsPaused = l.applyingEntsSize >= l.maxApplyingEntsSize || + i < l.maxAppliableIndex(allowUnstable) +} + +func (l *raftLog) stableTo(id entryID) { l.unstable.stableTo(id) } + +func (l *raftLog) stableSnapTo(i uint64) { l.unstable.stableSnapTo(i) } + +// acceptUnstable indicates that the application has started persisting the +// unstable entries in storage, and that the current unstable entries are thus +// to be marked as being in-progress, to avoid returning them with future calls +// to Ready(). +func (l *raftLog) acceptUnstable() { l.unstable.acceptInProgress() } + +// lastEntryID returns the ID of the last entry in the log. +func (l *raftLog) lastEntryID() entryID { + index := l.lastIndex() + t, err := l.term(index) + if err != nil { + l.logger.Panicf("unexpected error when getting the last term at %d: %v", index, err) + } + return entryID{term: t, index: index} +} + +func (l *raftLog) term(i uint64) (uint64, error) { + // Check the unstable log first, even before computing the valid term range, + // which may need to access stable Storage. If we find the entry's term in + // the unstable log, we know it was in the valid range. + if t, ok := l.unstable.maybeTerm(i); ok { + return t, nil + } + + // The valid term range is [firstIndex-1, lastIndex]. Even though the entry at + // firstIndex-1 is compacted away, its term is available for matching purposes + // when doing log appends. + if i+1 < l.firstIndex() { + return 0, ErrCompacted + } + if i > l.lastIndex() { + return 0, ErrUnavailable + } + + t, err := l.storage.Term(i) + if err == nil { + return t, nil + } + if err == ErrCompacted || err == ErrUnavailable { + return 0, err + } + panic(err) // TODO(bdarnell) +} + +func (l *raftLog) entries(i uint64, maxSize entryEncodingSize) ([]pb.Entry, error) { + if i > l.lastIndex() { + return nil, nil + } + return l.slice(i, l.lastIndex()+1, maxSize) +} + +// allEntries returns all entries in the log. +func (l *raftLog) allEntries() []pb.Entry { + ents, err := l.entries(l.firstIndex(), noLimit) + if err == nil { + return ents + } + if err == ErrCompacted { // try again if there was a racing compaction + return l.allEntries() + } + // TODO (xiangli): handle error? + panic(err) +} + +// isUpToDate determines if a log with the given last entry is more up-to-date +// by comparing the index and term of the last entries in the existing logs. +// +// If the logs have last entries with different terms, then the log with the +// later term is more up-to-date. If the logs end with the same term, then +// whichever log has the larger lastIndex is more up-to-date. If the logs are +// the same, the given log is up-to-date. +func (l *raftLog) isUpToDate(their entryID) bool { + our := l.lastEntryID() + return their.term > our.term || their.term == our.term && their.index >= our.index +} + +func (l *raftLog) matchTerm(id entryID) bool { + t, err := l.term(id.index) + if err != nil { + return false + } + return t == id.term +} + +func (l *raftLog) maybeCommit(at entryID) bool { + // NB: term should never be 0 on a commit because the leader campaigned at + // least at term 1. But if it is 0 for some reason, we don't consider this a + // term match. + if at.term != 0 && at.index > l.committed && l.matchTerm(at) { + l.commitTo(at.index) + return true + } + return false +} + +func (l *raftLog) restore(s pb.Snapshot) { + l.logger.Infof("log [%s] starts to restore snapshot [index: %d, term: %d]", l, s.Metadata.Index, s.Metadata.Term) + l.committed = s.Metadata.Index + l.unstable.restore(s) +} + +// scan visits all log entries in the [lo, hi) range, returning them via the +// given callback. The callback can be invoked multiple times, with consecutive +// sub-ranges of the requested range. Returns up to pageSize bytes worth of +// entries at a time. May return more if a single entry size exceeds the limit. +// +// The entries in [lo, hi) must exist, otherwise scan() eventually returns an +// error (possibly after passing some entries through the callback). +// +// If the callback returns an error, scan terminates and returns this error +// immediately. This can be used to stop the scan early ("break" the loop). +func (l *raftLog) scan(lo, hi uint64, pageSize entryEncodingSize, v func([]pb.Entry) error) error { + for lo < hi { + ents, err := l.slice(lo, hi, pageSize) + if err != nil { + return err + } else if len(ents) == 0 { + return fmt.Errorf("got 0 entries in [%d, %d)", lo, hi) + } + if err := v(ents); err != nil { + return err + } + lo += uint64(len(ents)) + } + return nil +} + +// slice returns a slice of log entries from lo through hi-1, inclusive. +func (l *raftLog) slice(lo, hi uint64, maxSize entryEncodingSize) ([]pb.Entry, error) { + if err := l.mustCheckOutOfBounds(lo, hi); err != nil { + return nil, err + } + if lo == hi { + return nil, nil + } + if lo >= l.unstable.offset { + ents := limitSize(l.unstable.slice(lo, hi), maxSize) + // NB: use the full slice expression to protect the unstable slice from + // appends to the returned ents slice. + return ents[:len(ents):len(ents)], nil + } + + cut := min(hi, l.unstable.offset) + ents, err := l.storage.Entries(lo, cut, uint64(maxSize)) + if err == ErrCompacted { + return nil, err + } else if err == ErrUnavailable { + l.logger.Panicf("entries[%d:%d) is unavailable from storage", lo, cut) + } else if err != nil { + panic(err) // TODO(pavelkalinnikov): handle errors uniformly + } + if hi <= l.unstable.offset { + return ents, nil + } + + // Fast path to check if ents has reached the size limitation. Either the + // returned slice is shorter than requested (which means the next entry would + // bring it over the limit), or a single entry reaches the limit. + if uint64(len(ents)) < cut-lo { + return ents, nil + } + // Slow path computes the actual total size, so that unstable entries are cut + // optimally before being copied to ents slice. + size := entsSize(ents) + if size >= maxSize { + return ents, nil + } + + unstable := limitSize(l.unstable.slice(l.unstable.offset, hi), maxSize-size) + // Total size of unstable may exceed maxSize-size only if len(unstable) == 1. + // If this happens, ignore this extra entry. + if len(unstable) == 1 && size+entsSize(unstable) > maxSize { + return ents, nil + } + // Otherwise, total size of unstable does not exceed maxSize-size, so total + // size of ents+unstable does not exceed maxSize. Simply concatenate them. + return extend(ents, unstable), nil +} + +// l.firstIndex <= lo <= hi <= l.firstIndex + len(l.entries) +func (l *raftLog) mustCheckOutOfBounds(lo, hi uint64) error { + if lo > hi { + l.logger.Panicf("invalid slice %d > %d", lo, hi) + } + fi := l.firstIndex() + if lo < fi { + return ErrCompacted + } + + length := l.lastIndex() + 1 - fi + if hi > fi+length { + l.logger.Panicf("slice[%d,%d) out of bound [%d,%d]", lo, hi, fi, l.lastIndex()) + } + return nil +} + +func (l *raftLog) zeroTermOnOutOfBounds(t uint64, err error) uint64 { + if err == nil { + return t + } + if err == ErrCompacted || err == ErrUnavailable { + return 0 + } + l.logger.Panicf("unexpected error (%v)", err) + return 0 +} diff --git a/etcd/vendor/go.etcd.io/raft/v3/log_unstable.go b/etcd/vendor/go.etcd.io/raft/v3/log_unstable.go new file mode 100644 index 0000000000..2629aae86b --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/log_unstable.go @@ -0,0 +1,245 @@ +// Copyright 2015 The etcd 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 raft + +import pb "go.etcd.io/raft/v3/raftpb" + +// unstable contains "unstable" log entries and snapshot state that has +// not yet been written to Storage. The type serves two roles. First, it +// holds on to new log entries and an optional snapshot until they are +// handed to a Ready struct for persistence. Second, it continues to +// hold on to this state after it has been handed off to provide raftLog +// with a view of the in-progress log entries and snapshot until their +// writes have been stabilized and are guaranteed to be reflected in +// queries of Storage. After this point, the corresponding log entries +// and/or snapshot can be cleared from unstable. +// +// unstable.entries[i] has raft log position i+unstable.offset. +// Note that unstable.offset may be less than the highest log +// position in storage; this means that the next write to storage +// might need to truncate the log before persisting unstable.entries. +type unstable struct { + // the incoming unstable snapshot, if any. + snapshot *pb.Snapshot + // all entries that have not yet been written to storage. + entries []pb.Entry + // entries[i] has raft log position i+offset. + offset uint64 + + // if true, snapshot is being written to storage. + snapshotInProgress bool + // entries[:offsetInProgress-offset] are being written to storage. + // Like offset, offsetInProgress is exclusive, meaning that it + // contains the index following the largest in-progress entry. + // Invariant: offset <= offsetInProgress + offsetInProgress uint64 + + logger Logger +} + +// maybeFirstIndex returns the index of the first possible entry in entries +// if it has a snapshot. +func (u *unstable) maybeFirstIndex() (uint64, bool) { + if u.snapshot != nil { + return u.snapshot.Metadata.Index + 1, true + } + return 0, false +} + +// maybeLastIndex returns the last index if it has at least one +// unstable entry or snapshot. +func (u *unstable) maybeLastIndex() (uint64, bool) { + if l := len(u.entries); l != 0 { + return u.offset + uint64(l) - 1, true + } + if u.snapshot != nil { + return u.snapshot.Metadata.Index, true + } + return 0, false +} + +// maybeTerm returns the term of the entry at index i, if there +// is any. +func (u *unstable) maybeTerm(i uint64) (uint64, bool) { + if i < u.offset { + if u.snapshot != nil && u.snapshot.Metadata.Index == i { + return u.snapshot.Metadata.Term, true + } + return 0, false + } + + last, ok := u.maybeLastIndex() + if !ok { + return 0, false + } + if i > last { + return 0, false + } + + return u.entries[i-u.offset].Term, true +} + +// nextEntries returns the unstable entries that are not already in the process +// of being written to storage. +func (u *unstable) nextEntries() []pb.Entry { + inProgress := int(u.offsetInProgress - u.offset) + if len(u.entries) == inProgress { + return nil + } + return u.entries[inProgress:] +} + +// nextSnapshot returns the unstable snapshot, if one exists that is not already +// in the process of being written to storage. +func (u *unstable) nextSnapshot() *pb.Snapshot { + if u.snapshot == nil || u.snapshotInProgress { + return nil + } + return u.snapshot +} + +// acceptInProgress marks all entries and the snapshot, if any, in the unstable +// as having begun the process of being written to storage. The entries/snapshot +// will no longer be returned from nextEntries/nextSnapshot. However, new +// entries/snapshots added after a call to acceptInProgress will be returned +// from those methods, until the next call to acceptInProgress. +func (u *unstable) acceptInProgress() { + if len(u.entries) > 0 { + // NOTE: +1 because offsetInProgress is exclusive, like offset. + u.offsetInProgress = u.entries[len(u.entries)-1].Index + 1 + } + if u.snapshot != nil { + u.snapshotInProgress = true + } +} + +// stableTo marks entries up to the entry with the specified (index, term) as +// being successfully written to stable storage. +// +// The method should only be called when the caller can attest that the entries +// can not be overwritten by an in-progress log append. See the related comment +// in newStorageAppendRespMsg. +func (u *unstable) stableTo(id entryID) { + gt, ok := u.maybeTerm(id.index) + if !ok { + // Unstable entry missing. Ignore. + u.logger.Infof("entry at index %d missing from unstable log; ignoring", id.index) + return + } + if id.index < u.offset { + // Index matched unstable snapshot, not unstable entry. Ignore. + u.logger.Infof("entry at index %d matched unstable snapshot; ignoring", id.index) + return + } + if gt != id.term { + // Term mismatch between unstable entry and specified entry. Ignore. + // This is possible if part or all of the unstable log was replaced + // between that time that a set of entries started to be written to + // stable storage and when they finished. + u.logger.Infof("entry at (index,term)=(%d,%d) mismatched with "+ + "entry at (%d,%d) in unstable log; ignoring", id.index, id.term, id.index, gt) + return + } + num := int(id.index + 1 - u.offset) + u.entries = u.entries[num:] + u.offset = id.index + 1 + u.offsetInProgress = max(u.offsetInProgress, u.offset) + u.shrinkEntriesArray() +} + +// shrinkEntriesArray discards the underlying array used by the entries slice +// if most of it isn't being used. This avoids holding references to a bunch of +// potentially large entries that aren't needed anymore. Simply clearing the +// entries wouldn't be safe because clients might still be using them. +func (u *unstable) shrinkEntriesArray() { + // We replace the array if we're using less than half of the space in + // it. This number is fairly arbitrary, chosen as an attempt to balance + // memory usage vs number of allocations. It could probably be improved + // with some focused tuning. + const lenMultiple = 2 + if len(u.entries) == 0 { + u.entries = nil + } else if len(u.entries)*lenMultiple < cap(u.entries) { + newEntries := make([]pb.Entry, len(u.entries)) + copy(newEntries, u.entries) + u.entries = newEntries + } +} + +func (u *unstable) stableSnapTo(i uint64) { + if u.snapshot != nil && u.snapshot.Metadata.Index == i { + u.snapshot = nil + u.snapshotInProgress = false + } +} + +func (u *unstable) restore(s pb.Snapshot) { + u.offset = s.Metadata.Index + 1 + u.offsetInProgress = u.offset + u.entries = nil + u.snapshot = &s + u.snapshotInProgress = false +} + +func (u *unstable) truncateAndAppend(ents []pb.Entry) { + fromIndex := ents[0].Index + switch { + case fromIndex == u.offset+uint64(len(u.entries)): + // fromIndex is the next index in the u.entries, so append directly. + u.entries = append(u.entries, ents...) + case fromIndex <= u.offset: + u.logger.Infof("replace the unstable entries from index %d", fromIndex) + // The log is being truncated to before our current offset + // portion, so set the offset and replace the entries. + u.entries = ents + u.offset = fromIndex + u.offsetInProgress = u.offset + default: + // Truncate to fromIndex (exclusive), and append the new entries. + u.logger.Infof("truncate the unstable entries before index %d", fromIndex) + keep := u.slice(u.offset, fromIndex) // NB: appending to this slice is safe, + u.entries = append(keep, ents...) // and will reallocate/copy it + // Only in-progress entries before fromIndex are still considered to be + // in-progress. + u.offsetInProgress = min(u.offsetInProgress, fromIndex) + } +} + +// slice returns the entries from the unstable log with indexes in the range +// [lo, hi). The entire range must be stored in the unstable log or the method +// will panic. The returned slice can be appended to, but the entries in it must +// not be changed because they are still shared with unstable. +// +// TODO(pavelkalinnikov): this, and similar []pb.Entry slices, may bubble up all +// the way to the application code through Ready struct. Protect other slices +// similarly, and document how the client can use them. +func (u *unstable) slice(lo uint64, hi uint64) []pb.Entry { + u.mustCheckOutOfBounds(lo, hi) + // NB: use the full slice expression to limit what the caller can do with the + // returned slice. For example, an append will reallocate and copy this slice + // instead of corrupting the neighbouring u.entries. + return u.entries[lo-u.offset : hi-u.offset : hi-u.offset] +} + +// u.offset <= lo <= hi <= u.offset+len(u.entries) +func (u *unstable) mustCheckOutOfBounds(lo, hi uint64) { + if lo > hi { + u.logger.Panicf("invalid unstable.slice %d > %d", lo, hi) + } + upper := u.offset + uint64(len(u.entries)) + if lo < u.offset || hi > upper { + u.logger.Panicf("unstable.slice[%d,%d) out of bound [%d,%d]", lo, hi, u.offset, upper) + } +} diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/logger.go b/etcd/vendor/go.etcd.io/raft/v3/logger.go similarity index 97% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/logger.go rename to etcd/vendor/go.etcd.io/raft/v3/logger.go index dc73b1f210..e3cb00cc9d 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/logger.go +++ b/etcd/vendor/go.etcd.io/raft/v3/logger.go @@ -16,7 +16,7 @@ package raft import ( "fmt" - "io/ioutil" + "io" "log" "os" "sync" @@ -60,7 +60,7 @@ func getLogger() Logger { var ( defaultLogger = &DefaultLogger{Logger: log.New(os.Stderr, "raft", log.LstdFlags)} - discardLogger = &DefaultLogger{Logger: log.New(ioutil.Discard, "", 0)} + discardLogger = &DefaultLogger{Logger: log.New(io.Discard, "", 0)} raftLoggerMu sync.Mutex raftLogger = Logger(defaultLogger) ) diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/node.go b/etcd/vendor/go.etcd.io/raft/v3/node.go similarity index 79% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/node.go rename to etcd/vendor/go.etcd.io/raft/v3/node.go index dca5954f7a..e2a261cd7b 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/node.go +++ b/etcd/vendor/go.etcd.io/raft/v3/node.go @@ -18,7 +18,7 @@ import ( "context" "errors" - pb "go.etcd.io/etcd/raft/v3/raftpb" + pb "go.etcd.io/raft/v3/raftpb" ) type SnapshotStatus int @@ -57,7 +57,12 @@ type Ready struct { // The current state of a Node to be saved to stable storage BEFORE // Messages are sent. + // // HardState will be equal to empty state if there is no update. + // + // If async storage writes are enabled, this field does not need to be acted + // on immediately. It will be reflected in a MsgStorageAppend message in the + // Messages slice. pb.HardState // ReadStates can be used for node to serve linearizable read requests locally @@ -68,24 +73,44 @@ type Ready struct { // Entries specifies entries to be saved to stable storage BEFORE // Messages are sent. + // + // If async storage writes are enabled, this field does not need to be acted + // on immediately. It will be reflected in a MsgStorageAppend message in the + // Messages slice. Entries []pb.Entry // Snapshot specifies the snapshot to be saved to stable storage. + // + // If async storage writes are enabled, this field does not need to be acted + // on immediately. It will be reflected in a MsgStorageAppend message in the + // Messages slice. Snapshot pb.Snapshot // CommittedEntries specifies entries to be committed to a - // store/state-machine. These have previously been committed to stable - // store. + // store/state-machine. These have previously been appended to stable + // storage. + // + // If async storage writes are enabled, this field does not need to be acted + // on immediately. It will be reflected in a MsgStorageApply message in the + // Messages slice. CommittedEntries []pb.Entry - // Messages specifies outbound messages to be sent AFTER Entries are - // committed to stable storage. + // Messages specifies outbound messages. + // + // If async storage writes are not enabled, these messages must be sent + // AFTER Entries are appended to stable storage. + // + // If async storage writes are enabled, these messages can be sent + // immediately as the messages that have the completion of the async writes + // as a precondition are attached to the individual MsgStorage{Append,Apply} + // messages instead. + // // If it contains a MsgSnap message, the application MUST report back to raft // when the snapshot has been received or has failed by calling ReportSnapshot. Messages []pb.Message - // MustSync indicates whether the HardState and Entries must be synchronously - // written to disk or if an asynchronous write is permissible. + // MustSync indicates whether the HardState and Entries must be durably + // written to disk or if a non-durable write is permissible. MustSync bool } @@ -103,25 +128,6 @@ func IsEmptySnap(sp pb.Snapshot) bool { return sp.Metadata.Index == 0 } -func (rd Ready) containsUpdates() bool { - return rd.SoftState != nil || !IsEmptyHardState(rd.HardState) || - !IsEmptySnap(rd.Snapshot) || len(rd.Entries) > 0 || - len(rd.CommittedEntries) > 0 || len(rd.Messages) > 0 || len(rd.ReadStates) != 0 -} - -// appliedCursor extracts from the Ready the highest index the client has -// applied (once the Ready is confirmed via Advance). If no information is -// contained in the Ready, returns zero. -func (rd Ready) appliedCursor() uint64 { - if n := len(rd.CommittedEntries); n > 0 { - return rd.CommittedEntries[n-1].Index - } - if index := rd.Snapshot.Metadata.Index; index > 0 { - return index - } - return 0 -} - // Node represents a node in a raft cluster. type Node interface { // Tick increments the internal logical clock for the Node by a single tick. Election @@ -150,7 +156,8 @@ type Node interface { Step(ctx context.Context, msg pb.Message) error // Ready returns a channel that returns the current point-in-time state. - // Users of the Node must call Advance after retrieving the state returned by Ready. + // Users of the Node must call Advance after retrieving the state returned by Ready (unless + // async storage writes is enabled, in which case it should never be called). // // NOTE: No committed entries from the next Ready may be applied until all committed entries // and snapshots from the previous one have finished. @@ -165,6 +172,9 @@ type Node interface { // commands. For example. when the last Ready contains a snapshot, the application might take // a long time to apply the snapshot data. To continue receiving Ready without blocking raft // progress, it can call Advance before finishing applying the last ready. + // + // NOTE: Advance must not be called when using AsyncStorageWrites. Response messages from the + // local append and apply threads take its place. Advance() // ApplyConfChange applies a config change (previously passed to // ProposeConfChange) to the node. This must be called whenever a config @@ -179,6 +189,32 @@ type Node interface { // TransferLeadership attempts to transfer leadership to the given transferee. TransferLeadership(ctx context.Context, lead, transferee uint64) + // ForgetLeader forgets a follower's current leader, changing it to None. It + // remains a leaderless follower in the current term, without campaigning. + // + // This is useful with PreVote+CheckQuorum, where followers will normally not + // grant pre-votes if they've heard from the leader in the past election + // timeout interval. Leaderless followers can grant pre-votes immediately, so + // if a quorum of followers have strong reason to believe the leader is dead + // (for example via a side-channel or external failure detector) and forget it + // then they can elect a new leader immediately, without waiting out the + // election timeout. They will also revert to normal followers if they hear + // from the leader again, or transition to candidates on an election timeout. + // + // For example, consider a three-node cluster where 1 is the leader and 2+3 + // have just received a heartbeat from it. If 2 and 3 believe the leader has + // now died (maybe they know that an orchestration system shut down 1's VM), + // we can instruct 2 to forget the leader and 3 to campaign. 2 will then be + // able to grant 3's pre-vote and elect 3 as leader immediately (normally 2 + // would reject the vote until an election timeout passes because it has heard + // from the leader recently). However, 3 can not campaign unilaterally, a + // quorum have to agree that the leader is dead, which avoids disrupting the + // leader if individual nodes are wrong about it being dead. + // + // This does nothing with ReadOnlyLeaseBased, since it would allow a new + // leader to be elected without the old leader knowing. + ForgetLeader(ctx context.Context) error + // ReadIndex request a read state. The read state will be set in the ready. // Read state has a read index. Once the application advances further than the read // index, any linearizable read requests issued before the read request can be @@ -211,11 +247,7 @@ type Peer struct { Context []byte } -// StartNode returns a new Node given configuration and a list of raft peers. -// It appends a ConfChangeAddNode entry for each given peer to the initial log. -// -// Peers must not be zero length; call RestartNode in that case. -func StartNode(c *Config, peers []Peer) Node { +func setupNode(c *Config, peers []Peer) *node { if len(peers) == 0 { panic("no peers given; use RestartNode instead") } @@ -223,12 +255,23 @@ func StartNode(c *Config, peers []Peer) Node { if err != nil { panic(err) } - rn.Bootstrap(peers) + err = rn.Bootstrap(peers) + if err != nil { + c.Logger.Warningf("error occurred during starting a new node: %v", err) + } n := newNode(rn) + return &n +} +// StartNode returns a new Node given configuration and a list of raft peers. +// It appends a ConfChangeAddNode entry for each given peer to the initial log. +// +// Peers must not be zero length; call RestartNode in that case. +func StartNode(c *Config, peers []Peer) Node { + n := setupNode(c, peers) go n.run() - return &n + return n } // RestartNode is similar to StartNode but does not take a list of peers. @@ -308,9 +351,7 @@ func (n *node) run() { lead := None for { - if advancec != nil { - readyc = nil - } else if n.rn.HasReady() { + if advancec == nil && n.rn.HasReady() { // Populate a Ready. Note that this Ready is not guaranteed to // actually be handled. We will arm readyc, but there's no guarantee // that we will actually send on it. It's possible that we will @@ -351,12 +392,13 @@ func (n *node) run() { close(pm.result) } case m := <-n.recvc: - // filter out response message from unknown From. - if pr := r.prs.Progress[m.From]; pr != nil || !IsResponseMsg(m.Type) { - r.Step(m) + if IsResponseMsg(m.Type) && !IsLocalMsgTarget(m.From) && r.trk.Progress[m.From] == nil { + // Filter out response message from unknown From. + break } + r.Step(m) case cc := <-n.confc: - _, okBefore := r.prs.Progress[r.id] + _, okBefore := r.trk.Progress[r.id] cs := r.applyConfChange(cc) // If the node was removed, block incoming proposals. Note that we // only do this if the node was in the config before. Nodes may be @@ -367,16 +409,18 @@ func (n *node) run() { // NB: propc is reset when the leader changes, which, if we learn // about it, sort of implies that we got readded, maybe? This isn't // very sound and likely has bugs. - if _, okAfter := r.prs.Progress[r.id]; okBefore && !okAfter { + if _, okAfter := r.trk.Progress[r.id]; okBefore && !okAfter { var found bool - outer: for _, sl := range [][]uint64{cs.Voters, cs.VotersOutgoing} { for _, id := range sl { if id == r.id { found = true - break outer + break } } + if found { + break + } } if !found { propc = nil @@ -390,7 +434,12 @@ func (n *node) run() { n.rn.Tick() case readyc <- rd: n.rn.acceptReady(rd) - advancec = n.advancec + if !n.rn.asyncStorageWrites { + advancec = n.advancec + } else { + rd = Ready{} + } + readyc = nil case <-advancec: n.rn.Advance(rd) rd = Ready{} @@ -422,8 +471,8 @@ func (n *node) Propose(ctx context.Context, data []byte) error { } func (n *node) Step(ctx context.Context, m pb.Message) error { - // ignore unexpected local messages receiving over network - if IsLocalMsg(m.Type) { + // Ignore unexpected local messages receiving over network. + if IsLocalMsg(m.Type) && !IsLocalMsgTarget(m.From) { // TODO: return an error? return nil } @@ -552,39 +601,10 @@ func (n *node) TransferLeadership(ctx context.Context, lead, transferee uint64) } } -func (n *node) ReadIndex(ctx context.Context, rctx []byte) error { - return n.step(ctx, pb.Message{Type: pb.MsgReadIndex, Entries: []pb.Entry{{Data: rctx}}}) +func (n *node) ForgetLeader(ctx context.Context) error { + return n.step(ctx, pb.Message{Type: pb.MsgForgetLeader}) } -func newReady(r *raft, prevSoftSt *SoftState, prevHardSt pb.HardState) Ready { - rd := Ready{ - Entries: r.raftLog.unstableEntries(), - CommittedEntries: r.raftLog.nextEnts(), - Messages: r.msgs, - } - if softSt := r.softState(); !softSt.equal(prevSoftSt) { - rd.SoftState = softSt - } - if hardSt := r.hardState(); !isHardStateEqual(hardSt, prevHardSt) { - rd.HardState = hardSt - } - if r.raftLog.unstable.snapshot != nil { - rd.Snapshot = *r.raftLog.unstable.snapshot - } - if len(r.readStates) != 0 { - rd.ReadStates = r.readStates - } - rd.MustSync = MustSync(r.hardState(), prevHardSt, len(rd.Entries)) - return rd -} - -// MustSync returns true if the hard state and count of Raft entries indicate -// that a synchronous write to persistent storage is required. -func MustSync(st, prevst pb.HardState, entsnum int) bool { - // Persistent state on all servers: - // (Updated on stable storage before responding to RPCs) - // currentTerm - // votedFor - // log entries[] - return entsnum != 0 || st.Vote != prevst.Vote || st.Term != prevst.Term +func (n *node) ReadIndex(ctx context.Context, rctx []byte) error { + return n.step(ctx, pb.Message{Type: pb.MsgReadIndex, Entries: []pb.Entry{{Data: rctx}}}) } diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/quorum/joint.go b/etcd/vendor/go.etcd.io/raft/v3/quorum/joint.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/quorum/joint.go rename to etcd/vendor/go.etcd.io/raft/v3/quorum/joint.go diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/quorum/majority.go b/etcd/vendor/go.etcd.io/raft/v3/quorum/majority.go similarity index 85% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/quorum/majority.go rename to etcd/vendor/go.etcd.io/raft/v3/quorum/majority.go index 8858a36b63..85b296aa7a 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/quorum/majority.go +++ b/etcd/vendor/go.etcd.io/raft/v3/quorum/majority.go @@ -15,9 +15,10 @@ package quorum import ( + "cmp" "fmt" "math" - "sort" + "slices" "strings" ) @@ -29,7 +30,7 @@ func (c MajorityConfig) String() string { for id := range c { sl = append(sl, id) } - sort.Slice(sl, func(i, j int) bool { return sl[i] < sl[j] }) + slices.Sort(sl) var buf strings.Builder buf.WriteByte('(') for i := range sl { @@ -67,11 +68,11 @@ func (c MajorityConfig) Describe(l AckedIndexer) string { } // Sort by index - sort.Slice(info, func(i, j int) bool { - if info[i].idx == info[j].idx { - return info[i].id < info[j].id + slices.SortFunc(info, func(a, b tup) int { + if n := cmp.Compare(a.idx, b.idx); n != 0 { + return n } - return info[i].idx < info[j].idx + return cmp.Compare(a.id, b.id) }) // Populate .bar. @@ -82,8 +83,8 @@ func (c MajorityConfig) Describe(l AckedIndexer) string { } // Sort by ID. - sort.Slice(info, func(i, j int) bool { - return info[i].id < info[j].id + slices.SortFunc(info, func(a, b tup) int { + return cmp.Compare(a.id, b.id) }) var buf strings.Builder @@ -108,19 +109,10 @@ func (c MajorityConfig) Slice() []uint64 { for id := range c { sl = append(sl, id) } - sort.Slice(sl, func(i, j int) bool { return sl[i] < sl[j] }) + slices.Sort(sl) return sl } -func insertionSort(sl []uint64) { - a, b := 0, len(sl) - for i := a + 1; i < b; i++ { - for j := i; j > a && sl[j] < sl[j-1]; j-- { - sl[j], sl[j-1] = sl[j-1], sl[j] - } - } -} - // CommittedIndex computes the committed index from those supplied via the // provided AckedIndexer (for the active config). func (c MajorityConfig) CommittedIndex(l AckedIndexer) Index { @@ -159,10 +151,7 @@ func (c MajorityConfig) CommittedIndex(l AckedIndexer) Index { } } } - - // Sort by index. Use a bespoke algorithm (copied from the stdlib's sort - // package) to keep srt on the stack. - insertionSort(srt) + slices.Sort(srt) // The smallest index into the array for which the value is acked by a // quorum. In other words, from the end of the slice, move n/2+1 to the @@ -183,8 +172,7 @@ func (c MajorityConfig) VoteResult(votes map[uint64]bool) VoteResult { return VoteWon } - ny := [2]int{} // vote counts for no and yes, respectively - + var votedCnt int //vote counts for yes. var missing int for id := range c { v, ok := votes[id] @@ -193,17 +181,15 @@ func (c MajorityConfig) VoteResult(votes map[uint64]bool) VoteResult { continue } if v { - ny[1]++ - } else { - ny[0]++ + votedCnt++ } } q := len(c)/2 + 1 - if ny[1] >= q { + if votedCnt >= q { return VoteWon } - if ny[1]+missing >= q { + if votedCnt+missing >= q { return VotePending } return VoteLost diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/quorum/quorum.go b/etcd/vendor/go.etcd.io/raft/v3/quorum/quorum.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/quorum/quorum.go rename to etcd/vendor/go.etcd.io/raft/v3/quorum/quorum.go diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/quorum/voteresult_string.go b/etcd/vendor/go.etcd.io/raft/v3/quorum/voteresult_string.go similarity index 100% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/quorum/voteresult_string.go rename to etcd/vendor/go.etcd.io/raft/v3/quorum/voteresult_string.go diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/raft.go b/etcd/vendor/go.etcd.io/raft/v3/raft.go similarity index 63% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/raft.go rename to etcd/vendor/go.etcd.io/raft/v3/raft.go index c80262ebaf..94c2363d59 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/raft.go +++ b/etcd/vendor/go.etcd.io/raft/v3/raft.go @@ -16,24 +16,33 @@ package raft import ( "bytes" + "crypto/rand" "errors" "fmt" "math" - "math/rand" - "sort" + "math/big" + "slices" "strings" "sync" - "time" - "go.etcd.io/etcd/raft/v3/confchange" - "go.etcd.io/etcd/raft/v3/quorum" - pb "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/raft/v3/tracker" + "go.etcd.io/raft/v3/confchange" + "go.etcd.io/raft/v3/quorum" + pb "go.etcd.io/raft/v3/raftpb" + "go.etcd.io/raft/v3/tracker" ) -// None is a placeholder node ID used when there is no leader. -const None uint64 = 0 -const noLimit = math.MaxUint64 +const ( + // None is a placeholder node ID used when there is no leader. + None uint64 = 0 + // LocalAppendThread is a reference to a local thread that saves unstable + // log entries and snapshots to stable storage. The identifier is used as a + // target for MsgStorageAppend messages when AsyncStorageWrites is enabled. + LocalAppendThread uint64 = math.MaxUint64 + // LocalApplyThread is a reference to a local thread that applies committed + // log entries to the local state machine. The identifier is used as a + // target for MsgStorageApply messages when AsyncStorageWrites is enabled. + LocalApplyThread uint64 = math.MaxUint64 - 1 +) // Possible values for StateType. const ( @@ -70,6 +79,8 @@ const ( campaignTransfer CampaignType = "CampaignTransfer" ) +const noLimit = math.MaxUint64 + // ErrProposalDropped is returned when the proposal is ignored by some cases, // so that the proposer can be notified and fail fast. var ErrProposalDropped = errors.New("raft proposal dropped") @@ -78,20 +89,17 @@ var ErrProposalDropped = errors.New("raft proposal dropped") // synchronization among multiple raft groups. Only the methods needed // by the code are exposed (e.g. Intn). type lockedRand struct { - mu sync.Mutex - rand *rand.Rand + mu sync.Mutex } func (r *lockedRand) Intn(n int) int { r.mu.Lock() - v := r.rand.Intn(n) + v, _ := rand.Int(rand.Reader, big.NewInt(int64(n))) r.mu.Unlock() - return v + return int(v.Int64()) } -var globalRand = &lockedRand{ - rand: rand.New(rand.NewSource(time.Now().UnixNano())), -} +var globalRand = &lockedRand{} // CampaignType represents the type of campaigning // the reason we use the type of string instead of uint64 @@ -109,7 +117,7 @@ var stmap = [...]string{ } func (st StateType) String() string { - return stmap[uint64(st)] + return stmap[st] } // Config contains the parameters to start a raft. @@ -140,6 +148,42 @@ type Config struct { // applied entries. This is a very application dependent configuration. Applied uint64 + // AsyncStorageWrites configures the raft node to write to its local storage + // (raft log and state machine) using a request/response message passing + // interface instead of the default Ready/Advance function call interface. + // Local storage messages can be pipelined and processed asynchronously + // (with respect to Ready iteration), facilitating reduced interference + // between Raft proposals and increased batching of log appends and state + // machine application. As a result, use of asynchronous storage writes can + // reduce end-to-end commit latency and increase maximum throughput. + // + // When true, the Ready.Message slice will include MsgStorageAppend and + // MsgStorageApply messages. The messages will target a LocalAppendThread + // and a LocalApplyThread, respectively. Messages to the same target must be + // reliably processed in order. In other words, they can't be dropped (like + // messages over the network) and those targeted at the same thread can't be + // reordered. Messages to different targets can be processed in any order. + // + // MsgStorageAppend carries Raft log entries to append, election votes / + // term changes / updated commit indexes to persist, and snapshots to apply. + // All writes performed in service of a MsgStorageAppend must be durable + // before response messages are delivered. However, if the MsgStorageAppend + // carries no response messages, durability is not required. The message + // assumes the role of the Entries, HardState, and Snapshot fields in Ready. + // + // MsgStorageApply carries committed entries to apply. Writes performed in + // service of a MsgStorageApply need not be durable before response messages + // are delivered. The message assumes the role of the CommittedEntries field + // in Ready. + // + // Local messages each carry one or more response messages which should be + // delivered after the corresponding storage write has been completed. These + // responses may target the same node or may target other nodes. The storage + // threads are not responsible for understanding the response messages, only + // for delivering them to the correct target after performing the storage + // write. + AsyncStorageWrites bool + // MaxSizePerMsg limits the max byte size of each append message. Smaller // value lowers the raft recovery cost(initial probing and message lost // during normal operation). On the other side, it might affect the @@ -147,7 +191,11 @@ type Config struct { // 0 for at most one entry per message. MaxSizePerMsg uint64 // MaxCommittedSizePerReady limits the size of the committed entries which - // can be applied. + // can be applying at the same time. + // + // Despite its name (preserved for compatibility), this quota applies across + // Ready structs to encompass all outstanding entries in unacknowledged + // MsgStorageApply messages when AsyncStorageWrites is enabled. MaxCommittedSizePerReady uint64 // MaxUncommittedEntriesSize limits the aggregate byte size of the // uncommitted entries that may be appended to a leader's log. Once this @@ -160,6 +208,16 @@ type Config struct { // overflowing that sending buffer. TODO (xiangli): feedback to application to // limit the proposal rate? MaxInflightMsgs int + // MaxInflightBytes limits the number of in-flight bytes in append messages. + // Complements MaxInflightMsgs. Ignored if zero. + // + // This effectively bounds the bandwidth-delay product. Note that especially + // in high-latency deployments setting this too low can lead to a dramatic + // reduction in throughput. For example, with a peer that has a round-trip + // latency of 100ms to the leader and this setting is set to 1 MB, there is a + // throughput limit of 10 MB/s for this group. With RTT of 400ms, this drops + // to 2.5 MB/s. See Little's law to understand the maths behind. + MaxInflightBytes uint64 // CheckQuorum specifies if the leader should check quorum activity. Leader // steps down when quorum is not active for an electionTimeout. @@ -196,12 +254,47 @@ type Config struct { // logical clock from assigning the timestamp and then forwarding the data // to the leader. DisableProposalForwarding bool + + // DisableConfChangeValidation turns off propose-time verification of + // configuration changes against the currently active configuration of the + // raft instance. These checks are generally sensible (cannot leave a joint + // config unless in a joint config, et cetera) but they have false positives + // because the active configuration may not be the most recent + // configuration. This is because configurations are activated during log + // application, and even the leader can trail log application by an + // unbounded number of entries. + // Symmetrically, the mechanism has false negatives - because the check may + // not run against the "actual" config that will be the predecessor of the + // newly proposed one, the check may pass but the new config may be invalid + // when it is being applied. In other words, the checks are best-effort. + // + // Users should *not* use this option unless they have a reliable mechanism + // (above raft) that serializes and verifies configuration changes. If an + // invalid configuration change enters the log and gets applied, a panic + // will result. + // + // This option may be removed once false positives are no longer possible. + // See: https://github.com/etcd-io/raft/issues/80 + DisableConfChangeValidation bool + + // StepDownOnRemoval makes the leader step down when it is removed from the + // group or demoted to a learner. + // + // This behavior will become unconditional in the future. See: + // https://github.com/etcd-io/raft/issues/83 + StepDownOnRemoval bool + + // raft state tracer + TraceLogger TraceLogger } func (c *Config) validate() error { if c.ID == None { return errors.New("cannot use none as id") } + if IsLocalMsgTarget(c.ID) { + return errors.New("cannot use local target as id") + } if c.HeartbeatTick <= 0 { return errors.New("heartbeat tick must be greater than 0") @@ -228,6 +321,11 @@ func (c *Config) validate() error { if c.MaxInflightMsgs <= 0 { return errors.New("max inflight messages must be greater than 0") } + if c.MaxInflightBytes == 0 { + c.MaxInflightBytes = noLimit + } else if c.MaxInflightBytes < c.MaxSizePerMsg { + return errors.New("max inflight bytes must be >= max message size") + } if c.Logger == nil { c.Logger = getLogger() @@ -251,17 +349,32 @@ type raft struct { // the log raftLog *raftLog - maxMsgSize uint64 - maxUncommittedSize uint64 - // TODO(tbg): rename to trk. - prs tracker.ProgressTracker + maxMsgSize entryEncodingSize + maxUncommittedSize entryPayloadSize + + trk tracker.ProgressTracker state StateType // isLearner is true if the local raft node is a learner. isLearner bool + // msgs contains the list of messages that should be sent out immediately to + // other nodes. + // + // Messages in this list must target other nodes. msgs []pb.Message + // msgsAfterAppend contains the list of messages that should be sent after + // the accumulated unstable state (e.g. term, vote, []entry, and snapshot) + // has been persisted to durable storage. This includes waiting for any + // unstable state that is already in the process of being persisted (i.e. + // has already been handed out in a prior Ready struct) to complete. + // + // Messages in this list may target other nodes or may target this node. + // + // Messages in this list have the type MsgAppResp, MsgVoteResp, or + // MsgPreVoteResp. See the comment in raft.send for details. + msgsAfterAppend []pb.Message // the leader id lead uint64 @@ -275,10 +388,13 @@ type raft struct { // be proposed if the leader's applied index is greater than this // value. pendingConfIndex uint64 + // disableConfChangeValidation is Config.DisableConfChangeValidation, + // see there for details. + disableConfChangeValidation bool // an estimate of the size of the uncommitted tail of the Raft log. Used to // prevent unbounded log growth. Only maintained by the leader. Reset on // term changes. - uncommittedSize uint64 + uncommittedSize entryPayloadSize readOnly *readOnly @@ -302,6 +418,7 @@ type raft struct { // when raft changes its state to follower or candidate. randomizedElectionTimeout int disableProposalForwarding bool + stepDownOnRemoval bool tick func() step stepFunc @@ -313,65 +430,74 @@ type raft struct { // current term. Those will be handled as fast as first log is committed in // current term. pendingReadIndexMessages []pb.Message + + traceLogger TraceLogger } func newRaft(c *Config) *raft { if err := c.validate(); err != nil { panic(err.Error()) } - raftlog := newLogWithSize(c.Storage, c.Logger, c.MaxCommittedSizePerReady) + raftlog := newLogWithSize(c.Storage, c.Logger, entryEncodingSize(c.MaxCommittedSizePerReady)) hs, cs, err := c.Storage.InitialState() if err != nil { panic(err) // TODO(bdarnell) } r := &raft{ - id: c.ID, - lead: None, - isLearner: false, - raftLog: raftlog, - maxMsgSize: c.MaxSizePerMsg, - maxUncommittedSize: c.MaxUncommittedEntriesSize, - prs: tracker.MakeProgressTracker(c.MaxInflightMsgs), - electionTimeout: c.ElectionTick, - heartbeatTimeout: c.HeartbeatTick, - logger: c.Logger, - checkQuorum: c.CheckQuorum, - preVote: c.PreVote, - readOnly: newReadOnly(c.ReadOnlyOption), - disableProposalForwarding: c.DisableProposalForwarding, - } - - cfg, prs, err := confchange.Restore(confchange.Changer{ - Tracker: r.prs, - LastIndex: raftlog.lastIndex(), + id: c.ID, + lead: None, + isLearner: false, + raftLog: raftlog, + maxMsgSize: entryEncodingSize(c.MaxSizePerMsg), + maxUncommittedSize: entryPayloadSize(c.MaxUncommittedEntriesSize), + trk: tracker.MakeProgressTracker(c.MaxInflightMsgs, c.MaxInflightBytes), + electionTimeout: c.ElectionTick, + heartbeatTimeout: c.HeartbeatTick, + logger: c.Logger, + checkQuorum: c.CheckQuorum, + preVote: c.PreVote, + readOnly: newReadOnly(c.ReadOnlyOption), + disableProposalForwarding: c.DisableProposalForwarding, + disableConfChangeValidation: c.DisableConfChangeValidation, + stepDownOnRemoval: c.StepDownOnRemoval, + traceLogger: c.TraceLogger, + } + + traceInitState(r) + + lastID := r.raftLog.lastEntryID() + cfg, trk, err := confchange.Restore(confchange.Changer{ + Tracker: r.trk, + LastIndex: lastID.index, }, cs) if err != nil { panic(err) } - assertConfStatesEquivalent(r.logger, cs, r.switchToConfig(cfg, prs)) + assertConfStatesEquivalent(r.logger, cs, r.switchToConfig(cfg, trk)) if !IsEmptyHardState(hs) { r.loadState(hs) } if c.Applied > 0 { - raftlog.appliedTo(c.Applied) + raftlog.appliedTo(c.Applied, 0 /* size */) } r.becomeFollower(r.Term, None) var nodesStrs []string - for _, n := range r.prs.VoterNodes() { + for _, n := range r.trk.VoterNodes() { nodesStrs = append(nodesStrs, fmt.Sprintf("%x", n)) } + // TODO(pav-kv): it should be ok to simply print %+v for lastID. r.logger.Infof("newRaft %x [peers: [%s], term: %d, commit: %d, applied: %d, lastindex: %d, lastterm: %d]", - r.id, strings.Join(nodesStrs, ","), r.Term, r.raftLog.committed, r.raftLog.applied, r.raftLog.lastIndex(), r.raftLog.lastTerm()) + r.id, strings.Join(nodesStrs, ","), r.Term, r.raftLog.committed, r.raftLog.applied, lastID.index, lastID.term) return r } func (r *raft) hasLeader() bool { return r.lead != None } -func (r *raft) softState() *SoftState { return &SoftState{Lead: r.lead, RaftState: r.state} } +func (r *raft) softState() SoftState { return SoftState{Lead: r.lead, RaftState: r.state} } func (r *raft) hardState() pb.HardState { return pb.HardState{ @@ -401,11 +527,11 @@ func (r *raft) send(m pb.Message) { // - MsgPreVoteResp: m.Term is the term received in the original // MsgPreVote if the pre-vote was granted, non-zero for the // same reasons MsgPreVote is - panic(fmt.Sprintf("term should be set when sending %s", m.Type)) + r.logger.Panicf("term should be set when sending %s", m.Type) } } else { if m.Term != 0 { - panic(fmt.Sprintf("term should not be set when sending %s (was %d)", m.Type, m.Term)) + r.logger.Panicf("term should not be set when sending %s (was %d)", m.Type, m.Term) } // do not attach term to MsgProp, MsgReadIndex // proposals are a way to forward to the leader and @@ -415,7 +541,61 @@ func (r *raft) send(m pb.Message) { m.Term = r.Term } } - r.msgs = append(r.msgs, m) + if m.Type == pb.MsgAppResp || m.Type == pb.MsgVoteResp || m.Type == pb.MsgPreVoteResp { + // If async storage writes are enabled, messages added to the msgs slice + // are allowed to be sent out before unstable state (e.g. log entry + // writes and election votes) have been durably synced to the local + // disk. + // + // For most message types, this is not an issue. However, response + // messages that relate to "voting" on either leader election or log + // appends require durability before they can be sent. It would be + // incorrect to publish a vote in an election before that vote has been + // synced to stable storage locally. Similarly, it would be incorrect to + // acknowledge a log append to the leader before that entry has been + // synced to stable storage locally. + // + // Per the Raft thesis, section 3.8 Persisted state and server restarts: + // + // > Raft servers must persist enough information to stable storage to + // > survive server restarts safely. In particular, each server persists + // > its current term and vote; this is necessary to prevent the server + // > from voting twice in the same term or replacing log entries from a + // > newer leader with those from a deposed leader. Each server also + // > persists new log entries before they are counted towards the entries’ + // > commitment; this prevents committed entries from being lost or + // > “uncommitted” when servers restart + // + // To enforce this durability requirement, these response messages are + // queued to be sent out as soon as the current collection of unstable + // state (the state that the response message was predicated upon) has + // been durably persisted. This unstable state may have already been + // passed to a Ready struct whose persistence is in progress or may be + // waiting for the next Ready struct to begin being written to Storage. + // These messages must wait for all of this state to be durable before + // being published. + // + // Rejected responses (m.Reject == true) present an interesting case + // where the durability requirement is less unambiguous. A rejection may + // be predicated upon unstable state. For instance, a node may reject a + // vote for one peer because it has already begun syncing its vote for + // another peer. Or it may reject a vote from one peer because it has + // unstable log entries that indicate that the peer is behind on its + // log. In these cases, it is likely safe to send out the rejection + // response immediately without compromising safety in the presence of a + // server restart. However, because these rejections are rare and + // because the safety of such behavior has not been formally verified, + // we err on the side of safety and omit a `&& !m.Reject` condition + // above. + r.msgsAfterAppend = append(r.msgsAfterAppend, m) + traceSendMessage(r, &m) + } else { + if m.To == r.id { + r.logger.Panicf("message should not be self-addressed when sending %s", m.Type) + } + r.msgs = append(r.msgs, m) + traceSendMessage(r, &m) + } } // sendAppend sends an append RPC with new entries (if any) and the @@ -429,91 +609,108 @@ func (r *raft) sendAppend(to uint64) { // argument controls whether messages with no entries will be sent // ("empty" messages are useful to convey updated Commit indexes, but // are undesirable when we're sending multiple messages in a batch). +// +// TODO(pav-kv): make invocation of maybeSendAppend stateless. The Progress +// struct contains all the state necessary for deciding whether to send a +// message. func (r *raft) maybeSendAppend(to uint64, sendIfEmpty bool) bool { - pr := r.prs.Progress[to] + pr := r.trk.Progress[to] if pr.IsPaused() { return false } - m := pb.Message{} - m.To = to - term, errt := r.raftLog.term(pr.Next - 1) - ents, erre := r.raftLog.entries(pr.Next, r.maxMsgSize) + prevIndex := pr.Next - 1 + prevTerm, err := r.raftLog.term(prevIndex) + if err != nil { + // The log probably got truncated at >= pr.Next, so we can't catch up the + // follower log anymore. Send a snapshot instead. + return r.maybeSendSnapshot(to, pr) + } + + var ents []pb.Entry + // In a throttled StateReplicate only send empty MsgApp, to ensure progress. + // Otherwise, if we had a full Inflights and all inflight messages were in + // fact dropped, replication to that follower would stall. Instead, an empty + // MsgApp will eventually reach the follower (heartbeats responses prompt the + // leader to send an append), allowing it to be acked or rejected, both of + // which will clear out Inflights. + if pr.State != tracker.StateReplicate || !pr.Inflights.Full() { + ents, err = r.raftLog.entries(pr.Next, r.maxMsgSize) + } if len(ents) == 0 && !sendIfEmpty { return false } + // TODO(pav-kv): move this check up to where err is returned. + if err != nil { // send a snapshot if we failed to get the entries + return r.maybeSendSnapshot(to, pr) + } - if errt != nil || erre != nil { // send snapshot if we failed to get term or entries - if !pr.RecentActive { - r.logger.Debugf("ignore sending snapshot to %x since it is not recently active", to) - return false - } + // Send the actual MsgApp otherwise, and update the progress accordingly. + r.send(pb.Message{ + To: to, + Type: pb.MsgApp, + Index: prevIndex, + LogTerm: prevTerm, + Entries: ents, + Commit: r.raftLog.committed, + }) + pr.SentEntries(len(ents), uint64(payloadsSize(ents))) + pr.SentCommit(r.raftLog.committed) + return true +} - m.Type = pb.MsgSnap - snapshot, err := r.raftLog.snapshot() - if err != nil { - if err == ErrSnapshotTemporarilyUnavailable { - r.logger.Debugf("%x failed to send snapshot to %x because snapshot is temporarily unavailable", r.id, to) - return false - } - panic(err) // TODO(bdarnell) - } - if IsEmptySnap(snapshot) { - panic("need non-empty snapshot") - } - m.Snapshot = snapshot - sindex, sterm := snapshot.Metadata.Index, snapshot.Metadata.Term - r.logger.Debugf("%x [firstindex: %d, commit: %d] sent snapshot[index: %d, term: %d] to %x [%s]", - r.id, r.raftLog.firstIndex(), r.raftLog.committed, sindex, sterm, to, pr) - pr.BecomeSnapshot(sindex) - r.logger.Debugf("%x paused sending replication messages to %x [%s]", r.id, to, pr) - } else { - m.Type = pb.MsgApp - m.Index = pr.Next - 1 - m.LogTerm = term - m.Entries = ents - m.Commit = r.raftLog.committed - if n := len(m.Entries); n != 0 { - switch pr.State { - // optimistically increase the next when in StateReplicate - case tracker.StateReplicate: - last := m.Entries[n-1].Index - pr.OptimisticUpdate(last) - pr.Inflights.Add(last) - case tracker.StateProbe: - pr.ProbeSent = true - default: - r.logger.Panicf("%x is sending append in unhandled state %s", r.id, pr.State) - } +// maybeSendSnapshot fetches a snapshot from Storage, and sends it to the given +// node. Returns true iff the snapshot message has been emitted successfully. +func (r *raft) maybeSendSnapshot(to uint64, pr *tracker.Progress) bool { + if !pr.RecentActive { + r.logger.Debugf("ignore sending snapshot to %x since it is not recently active", to) + return false + } + + snapshot, err := r.raftLog.snapshot() + if err != nil { + if err == ErrSnapshotTemporarilyUnavailable { + r.logger.Debugf("%x failed to send snapshot to %x because snapshot is temporarily unavailable", r.id, to) + return false } + panic(err) // TODO(bdarnell) + } + if IsEmptySnap(snapshot) { + panic("need non-empty snapshot") } - r.send(m) + sindex, sterm := snapshot.Metadata.Index, snapshot.Metadata.Term + r.logger.Debugf("%x [firstindex: %d, commit: %d] sent snapshot[index: %d, term: %d] to %x [%s]", + r.id, r.raftLog.firstIndex(), r.raftLog.committed, sindex, sterm, to, pr) + pr.BecomeSnapshot(sindex) + r.logger.Debugf("%x paused sending replication messages to %x [%s]", r.id, to, pr) + + r.send(pb.Message{To: to, Type: pb.MsgSnap, Snapshot: &snapshot}) return true } // sendHeartbeat sends a heartbeat RPC to the given peer. func (r *raft) sendHeartbeat(to uint64, ctx []byte) { + pr := r.trk.Progress[to] // Attach the commit as min(to.matched, r.committed). // When the leader sends out heartbeat message, // the receiver(follower) might not be matched with the leader // or it might not have all the committed entries. // The leader MUST NOT forward the follower's commit to // an unmatched index. - commit := min(r.prs.Progress[to].Match, r.raftLog.committed) - m := pb.Message{ + commit := min(pr.Match, r.raftLog.committed) + r.send(pb.Message{ To: to, Type: pb.MsgHeartbeat, Commit: commit, Context: ctx, - } - - r.send(m) + }) + pr.SentCommit(commit) } // bcastAppend sends RPC, with entries to all peers that are not up-to-date -// according to the progress recorded in r.prs. +// according to the progress recorded in r.trk. func (r *raft) bcastAppend() { - r.prs.Visit(func(id uint64, _ *tracker.Progress) { + r.trk.Visit(func(id uint64, _ *tracker.Progress) { if id == r.id { return } @@ -532,7 +729,7 @@ func (r *raft) bcastHeartbeat() { } func (r *raft) bcastHeartbeatWithCtx(ctx []byte) { - r.prs.Visit(func(id uint64, _ *tracker.Progress) { + r.trk.Visit(func(id uint64, _ *tracker.Progress) { if id == r.id { return } @@ -540,51 +737,48 @@ func (r *raft) bcastHeartbeatWithCtx(ctx []byte) { }) } -func (r *raft) advance(rd Ready) { - r.reduceUncommittedSize(rd.CommittedEntries) - - // If entries were applied (or a snapshot), update our cursor for - // the next Ready. Note that if the current HardState contains a - // new Commit index, this does not mean that we're also applying - // all of the new entries due to commit pagination by size. - if newApplied := rd.appliedCursor(); newApplied > 0 { - oldApplied := r.raftLog.applied - r.raftLog.appliedTo(newApplied) - - if r.prs.Config.AutoLeave && oldApplied <= r.pendingConfIndex && newApplied >= r.pendingConfIndex && r.state == StateLeader { - // If the current (and most recent, at least for this leader's term) - // configuration should be auto-left, initiate that now. We use a - // nil Data which unmarshals into an empty ConfChangeV2 and has the - // benefit that appendEntry can never refuse it based on its size - // (which registers as zero). - ent := pb.Entry{ - Type: pb.EntryConfChangeV2, - Data: nil, - } - // There's no way in which this proposal should be able to be rejected. - if !r.appendEntry(ent) { - panic("refused un-refusable auto-leaving ConfChangeV2") - } - r.pendingConfIndex = r.raftLog.lastIndex() - r.logger.Infof("initiating automatic transition out of joint configuration %s", r.prs.Config) +func (r *raft) appliedTo(index uint64, size entryEncodingSize) { + oldApplied := r.raftLog.applied + newApplied := max(index, oldApplied) + r.raftLog.appliedTo(newApplied, size) + + if r.trk.Config.AutoLeave && newApplied >= r.pendingConfIndex && r.state == StateLeader { + // If the current (and most recent, at least for this leader's term) + // configuration should be auto-left, initiate that now. We use a + // nil Data which unmarshals into an empty ConfChangeV2 and has the + // benefit that appendEntry can never refuse it based on its size + // (which registers as zero). + m, err := confChangeToMsg(nil) + if err != nil { + panic(err) + } + // NB: this proposal can't be dropped due to size, but can be + // dropped if a leadership transfer is in progress. We'll keep + // checking this condition on each applied entry, so either the + // leadership transfer will succeed and the new leader will leave + // the joint configuration, or the leadership transfer will fail, + // and we will propose the config change on the next advance. + if err := r.Step(m); err != nil { + r.logger.Debugf("not initiating automatic transition out of joint configuration %s: %v", r.trk.Config, err) + } else { + r.logger.Infof("initiating automatic transition out of joint configuration %s", r.trk.Config) } } +} - if len(rd.Entries) > 0 { - e := rd.Entries[len(rd.Entries)-1] - r.raftLog.stableTo(e.Index, e.Term) - } - if !IsEmptySnap(rd.Snapshot) { - r.raftLog.stableSnapTo(rd.Snapshot.Metadata.Index) - } +func (r *raft) appliedSnap(snap *pb.Snapshot) { + index := snap.Metadata.Index + r.raftLog.stableSnapTo(index) + r.appliedTo(index, 0 /* size */) } -// maybeCommit attempts to advance the commit index. Returns true if -// the commit index changed (in which case the caller should call -// r.bcastAppend). +// maybeCommit attempts to advance the commit index. Returns true if the commit +// index changed (in which case the caller should call r.bcastAppend). This can +// only be called in StateLeader. func (r *raft) maybeCommit() bool { - mci := r.prs.Committed() - return r.raftLog.maybeCommit(mci, r.Term) + defer traceCommit(r) + + return r.raftLog.maybeCommit(entryID{term: r.Term, index: r.trk.Committed()}) } func (r *raft) reset(term uint64) { @@ -600,12 +794,12 @@ func (r *raft) reset(term uint64) { r.abortLeaderTransfer() - r.prs.ResetVotes() - r.prs.Visit(func(id uint64, pr *tracker.Progress) { + r.trk.ResetVotes() + r.trk.Visit(func(id uint64, pr *tracker.Progress) { *pr = tracker.Progress{ Match: 0, Next: r.raftLog.lastIndex() + 1, - Inflights: tracker.NewInflights(r.prs.MaxInflight), + Inflights: tracker.NewInflights(r.trk.MaxInflight, r.trk.MaxInflightBytes), IsLearner: pr.IsLearner, } if id == r.id { @@ -626,18 +820,29 @@ func (r *raft) appendEntry(es ...pb.Entry) (accepted bool) { } // Track the size of this uncommitted proposal. if !r.increaseUncommittedSize(es) { - r.logger.Debugf( + r.logger.Warningf( "%x appending new entries to log would exceed uncommitted entry size limit; dropping proposal", r.id, ) // Drop the proposal. return false } + + traceReplicate(r, es...) + // use latest "last" index after truncate/append li = r.raftLog.append(es...) - r.prs.Progress[r.id].MaybeUpdate(li) - // Regardless of maybeCommit's return, our caller will call bcastAppend. - r.maybeCommit() + // The leader needs to self-ack the entries just appended once they have + // been durably persisted (since it doesn't send an MsgApp to itself). This + // response message will be added to msgsAfterAppend and delivered back to + // this node after these entries have been written to stable storage. When + // handled, this is roughly equivalent to: + // + // r.trk.Progress[r.id].MaybeUpdate(e.Index) + // if r.maybeCommit() { + // r.bcastAppend() + // } + r.send(pb.Message{To: r.id, Type: pb.MsgAppResp, Index: li}) return true } @@ -647,7 +852,9 @@ func (r *raft) tickElection() { if r.promotable() && r.pastElectionTimeout() { r.electionElapsed = 0 - r.Step(pb.Message{From: r.id, Type: pb.MsgHup}) + if err := r.Step(pb.Message{From: r.id, Type: pb.MsgHup}); err != nil { + r.logger.Debugf("error occurred during election: %v", err) + } } } @@ -659,7 +866,9 @@ func (r *raft) tickHeartbeat() { if r.electionElapsed >= r.electionTimeout { r.electionElapsed = 0 if r.checkQuorum { - r.Step(pb.Message{From: r.id, Type: pb.MsgCheckQuorum}) + if err := r.Step(pb.Message{From: r.id, Type: pb.MsgCheckQuorum}); err != nil { + r.logger.Debugf("error occurred during checking sending heartbeat: %v", err) + } } // If current leader cannot transfer leadership in electionTimeout, it becomes leader again. if r.state == StateLeader && r.leadTransferee != None { @@ -673,7 +882,9 @@ func (r *raft) tickHeartbeat() { if r.heartbeatElapsed >= r.heartbeatTimeout { r.heartbeatElapsed = 0 - r.Step(pb.Message{From: r.id, Type: pb.MsgBeat}) + if err := r.Step(pb.Message{From: r.id, Type: pb.MsgBeat}); err != nil { + r.logger.Debugf("error occurred during checking sending heartbeat: %v", err) + } } } @@ -684,6 +895,8 @@ func (r *raft) becomeFollower(term uint64, lead uint64) { r.lead = lead r.state = StateFollower r.logger.Infof("%x became follower at term %d", r.id, r.Term) + + traceBecomeFollower(r) } func (r *raft) becomeCandidate() { @@ -697,6 +910,8 @@ func (r *raft) becomeCandidate() { r.Vote = r.id r.state = StateCandidate r.logger.Infof("%x became candidate at term %d", r.id, r.Term) + + traceBecomeCandidate(r) } func (r *raft) becomePreCandidate() { @@ -708,7 +923,7 @@ func (r *raft) becomePreCandidate() { // but doesn't change anything else. In particular it does not increase // r.Term or change r.Vote. r.step = stepCandidate - r.prs.ResetVotes() + r.trk.ResetVotes() r.tick = r.tickElection r.lead = None r.state = StatePreCandidate @@ -729,7 +944,11 @@ func (r *raft) becomeLeader() { // (perhaps after having received a snapshot as a result). The leader is // trivially in this state. Note that r.reset() has initialized this // progress with the last index already. - r.prs.Progress[r.id].BecomeReplicate() + pr := r.trk.Progress[r.id] + pr.BecomeReplicate() + // The leader always has RecentActive == true; MsgCheckQuorum makes sure to + // preserve this. + pr.RecentActive = true // Conservatively set the pendingConfIndex to the last index in the // log. There may or may not be a pending config change, but it's @@ -738,16 +957,16 @@ func (r *raft) becomeLeader() { // could be expensive. r.pendingConfIndex = r.raftLog.lastIndex() + traceBecomeLeader(r) emptyEnt := pb.Entry{Data: nil} if !r.appendEntry(emptyEnt) { // This won't happen because we just called reset() above. r.logger.Panic("empty entry was dropped") } - // As a special case, don't count the initial empty entry towards the - // uncommitted log quota. This is because we want to preserve the - // behavior of allowing one entry larger than quota if the current - // usage is zero. - r.reduceUncommittedSize([]pb.Entry{emptyEnt}) + // The payloadSize of an empty entry is 0 (see TestPayloadSizeOfEmptyEntry), + // so the preceding log append does not count against the uncommitted log + // quota of the new leader. In other words, after the call to appendEntry, + // r.uncommittedSize is still 0. r.logger.Infof("%x became leader at term %d", r.id, r.Term) } @@ -761,12 +980,8 @@ func (r *raft) hup(t CampaignType) { r.logger.Warningf("%x is unpromotable and can not campaign", r.id) return } - ents, err := r.raftLog.slice(r.raftLog.applied+1, r.raftLog.committed+1, noLimit) - if err != nil { - r.logger.Panicf("unexpected error getting unapplied entries (%v)", err) - } - if n := numOfPendingConf(ents); n != 0 && r.raftLog.committed > r.raftLog.applied { - r.logger.Warningf("%x cannot campaign at term %d since there are still %d pending configuration changes to apply", r.id, r.Term, n) + if r.hasUnappliedConfChanges() { + r.logger.Warningf("%x cannot campaign at term %d since there are still pending configuration changes to apply", r.id, r.Term) return } @@ -774,6 +989,37 @@ func (r *raft) hup(t CampaignType) { r.campaign(t) } +// errBreak is a sentinel error used to break a callback-based loop. +var errBreak = errors.New("break") + +func (r *raft) hasUnappliedConfChanges() bool { + if r.raftLog.applied >= r.raftLog.committed { // in fact applied == committed + return false + } + found := false + // Scan all unapplied committed entries to find a config change. Paginate the + // scan, to avoid a potentially unlimited memory spike. + lo, hi := r.raftLog.applied+1, r.raftLog.committed+1 + // Reuse the maxApplyingEntsSize limit because it is used for similar purposes + // (limiting the read of unapplied committed entries) when raft sends entries + // via the Ready struct for application. + // TODO(pavelkalinnikov): find a way to budget memory/bandwidth for this scan + // outside the raft package. + pageSize := r.raftLog.maxApplyingEntsSize + if err := r.raftLog.scan(lo, hi, pageSize, func(ents []pb.Entry) error { + for i := range ents { + if ents[i].Type == pb.EntryConfChange || ents[i].Type == pb.EntryConfChangeV2 { + found = true + return errBreak + } + } + return nil + }); err != nil && err != errBreak { + r.logger.Panicf("error scanning unapplied entries [%d, %d): %v", lo, hi, err) + } + return found +} + // campaign transitions the raft instance to candidate state. This must only be // called after verifying that this is a legitimate transition. func (r *raft) campaign(t CampaignType) { @@ -794,37 +1040,35 @@ func (r *raft) campaign(t CampaignType) { voteMsg = pb.MsgVote term = r.Term } - if _, _, res := r.poll(r.id, voteRespMsgType(voteMsg), true); res == quorum.VoteWon { - // We won the election after voting for ourselves (which must mean that - // this is a single-node cluster). Advance to the next state. - if t == campaignPreElection { - r.campaign(campaignElection) - } else { - r.becomeLeader() - } - return - } var ids []uint64 { - idMap := r.prs.Voters.IDs() + idMap := r.trk.Voters.IDs() ids = make([]uint64, 0, len(idMap)) for id := range idMap { ids = append(ids, id) } - sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] }) + slices.Sort(ids) } for _, id := range ids { if id == r.id { + // The candidate votes for itself and should account for this self + // vote once the vote has been durably persisted (since it doesn't + // send a MsgVote to itself). This response message will be added to + // msgsAfterAppend and delivered back to this node after the vote + // has been written to stable storage. + r.send(pb.Message{To: id, Term: term, Type: voteRespMsgType(voteMsg)}) continue } + // TODO(pav-kv): it should be ok to simply print %+v for the lastEntryID. + last := r.raftLog.lastEntryID() r.logger.Infof("%x [logterm: %d, index: %d] sent %s request to %x at term %d", - r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), voteMsg, id, r.Term) + r.id, last.term, last.index, voteMsg, id, r.Term) var ctx []byte if t == campaignTransfer { ctx = []byte(t) } - r.send(pb.Message{Term: term, To: id, Type: voteMsg, Index: r.raftLog.lastIndex(), LogTerm: r.raftLog.lastTerm(), Context: ctx}) + r.send(pb.Message{To: id, Term: term, Type: voteMsg, Index: last.index, LogTerm: last.term, Context: ctx}) } } @@ -834,11 +1078,13 @@ func (r *raft) poll(id uint64, t pb.MessageType, v bool) (granted int, rejected } else { r.logger.Infof("%x received %s rejection from %x at term %d", r.id, t, id, r.Term) } - r.prs.RecordVote(id, v) - return r.prs.TallyVotes() + r.trk.RecordVote(id, v) + return r.trk.TallyVotes() } func (r *raft) Step(m pb.Message) error { + traceReceiveMessage(r, &m) + // Handle the message term, which may result in our stepping down to a follower. switch { case m.Term == 0: @@ -850,8 +1096,10 @@ func (r *raft) Step(m pb.Message) error { if !force && inLease { // If a server receives a RequestVote request within the minimum election timeout // of hearing from a current leader, it does not update its term or grant its vote + last := r.raftLog.lastEntryID() + // TODO(pav-kv): it should be ok to simply print the %+v of the lastEntryID. r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] ignored %s from %x [logterm: %d, index: %d] at term %d: lease is not expired (remaining ticks: %d)", - r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term, r.electionTimeout-r.electionElapsed) + r.id, last.term, last.index, r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term, r.electionTimeout-r.electionElapsed) return nil } } @@ -902,9 +1150,26 @@ func (r *raft) Step(m pb.Message) error { // Before Pre-Vote enable, there may have candidate with higher term, // but less log. After update to Pre-Vote, the cluster may deadlock if // we drop messages with a lower term. + last := r.raftLog.lastEntryID() + // TODO(pav-kv): it should be ok to simply print %+v of the lastEntryID. r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] rejected %s from %x [logterm: %d, index: %d] at term %d", - r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term) + r.id, last.term, last.index, r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term) r.send(pb.Message{To: m.From, Term: r.Term, Type: pb.MsgPreVoteResp, Reject: true}) + } else if m.Type == pb.MsgStorageAppendResp { + if m.Index != 0 { + // Don't consider the appended log entries to be stable because + // they may have been overwritten in the unstable log during a + // later term. See the comment in newStorageAppendResp for more + // about this race. + r.logger.Infof("%x [term: %d] ignored entry appends from a %s message with lower term [term: %d]", + r.id, r.Term, m.Type, m.Term) + } + if m.Snapshot != nil { + // Even if the snapshot applied under a different term, its + // application is still valid. Snapshots carry committed + // (term-independent) state. + r.appliedSnap(m.Snapshot) + } } else { // ignore other cases r.logger.Infof("%x [term: %d] ignored a %s message with lower term from %x [term: %d]", @@ -921,6 +1186,21 @@ func (r *raft) Step(m pb.Message) error { r.hup(campaignElection) } + case pb.MsgStorageAppendResp: + if m.Index != 0 { + r.raftLog.stableTo(entryID{term: m.LogTerm, index: m.Index}) + } + if m.Snapshot != nil { + r.appliedSnap(m.Snapshot) + } + + case pb.MsgStorageApplyResp: + if len(m.Entries) > 0 { + index := m.Entries[len(m.Entries)-1].Index + r.appliedTo(index, entsSize(m.Entries)) + r.reduceUncommittedSize(payloadsSize(m.Entries)) + } + case pb.MsgVote, pb.MsgPreVote: // We can vote if this is a repeat of a vote we've already cast... canVote := r.Vote == m.From || @@ -929,7 +1209,9 @@ func (r *raft) Step(m pb.Message) error { // ...or this is a PreVote for a future term... (m.Type == pb.MsgPreVote && m.Term > r.Term) // ...and we believe the candidate is up to date. - if canVote && r.raftLog.isUpToDate(m.Index, m.LogTerm) { + lastID := r.raftLog.lastEntryID() + candLastID := entryID{term: m.LogTerm, index: m.Index} + if canVote && r.raftLog.isUpToDate(candLastID) { // Note: it turns out that that learners must be allowed to cast votes. // This seems counter- intuitive but is necessary in the situation in which // a learner has been promoted (i.e. is now a voter) but has not learned @@ -949,7 +1231,7 @@ func (r *raft) Step(m pb.Message) error { // in: // https://github.com/etcd-io/etcd/issues/7625#issuecomment-488798263. r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] cast %s for %x [logterm: %d, index: %d] at term %d", - r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term) + r.id, lastID.term, lastID.index, r.Vote, m.Type, m.From, candLastID.term, candLastID.index, r.Term) // When responding to Msg{Pre,}Vote messages we include the term // from the message, not the local term. To see why, consider the // case where a single node was previously partitioned away and @@ -967,7 +1249,7 @@ func (r *raft) Step(m pb.Message) error { } } else { r.logger.Infof("%x [logterm: %d, index: %d, vote: %x] rejected %s from %x [logterm: %d, index: %d] at term %d", - r.id, r.raftLog.lastTerm(), r.raftLog.lastIndex(), r.Vote, m.Type, m.From, m.LogTerm, m.Index, r.Term) + r.id, lastID.term, lastID.index, r.Vote, m.Type, m.From, candLastID.term, candLastID.index, r.Term) r.send(pb.Message{To: m.From, Term: r.Term, Type: voteRespMsgType(m.Type), Reject: true}) } @@ -989,22 +1271,13 @@ func stepLeader(r *raft, m pb.Message) error { r.bcastHeartbeat() return nil case pb.MsgCheckQuorum: - // The leader should always see itself as active. As a precaution, handle - // the case in which the leader isn't in the configuration any more (for - // example if it just removed itself). - // - // TODO(tbg): I added a TODO in removeNode, it doesn't seem that the - // leader steps down when removing itself. I might be missing something. - if pr := r.prs.Progress[r.id]; pr != nil { - pr.RecentActive = true - } - if !r.prs.QuorumActive() { + if !r.trk.QuorumActive() { r.logger.Warningf("%x stepped down to follower since quorum is not active", r.id) r.becomeFollower(r.Term, None) } // Mark everyone (but ourselves) as inactive in preparation for the next // CheckQuorum. - r.prs.Visit(func(id uint64, pr *tracker.Progress) { + r.trk.Visit(func(id uint64, pr *tracker.Progress) { if id != r.id { pr.RecentActive = false } @@ -1014,7 +1287,7 @@ func stepLeader(r *raft, m pb.Message) error { if len(m.Entries) == 0 { r.logger.Panicf("%x stepped empty MsgProp", r.id) } - if r.prs.Progress[r.id] == nil { + if r.trk.Progress[r.id] == nil { // If we are not currently a member of the range (i.e. this node // was removed from the configuration while serving as leader), // drop any new proposals. @@ -1043,23 +1316,24 @@ func stepLeader(r *raft, m pb.Message) error { } if cc != nil { alreadyPending := r.pendingConfIndex > r.raftLog.applied - alreadyJoint := len(r.prs.Config.Voters[1]) > 0 + alreadyJoint := len(r.trk.Config.Voters[1]) > 0 wantsLeaveJoint := len(cc.AsV2().Changes) == 0 - var refused string + var failedCheck string if alreadyPending { - refused = fmt.Sprintf("possible unapplied conf change at index %d (applied to %d)", r.pendingConfIndex, r.raftLog.applied) + failedCheck = fmt.Sprintf("possible unapplied conf change at index %d (applied to %d)", r.pendingConfIndex, r.raftLog.applied) } else if alreadyJoint && !wantsLeaveJoint { - refused = "must transition out of joint config first" + failedCheck = "must transition out of joint config first" } else if !alreadyJoint && wantsLeaveJoint { - refused = "not in joint state; refusing empty conf change" + failedCheck = "not in joint state; refusing empty conf change" } - if refused != "" { - r.logger.Infof("%x ignoring conf change %v at config %s: %s", r.id, cc, r.prs.Config, refused) + if failedCheck != "" && !r.disableConfChangeValidation { + r.logger.Infof("%x ignoring conf change %v at config %s: %s", r.id, cc, r.trk.Config, failedCheck) m.Entries[i] = pb.Entry{Type: pb.EntryNormal} } else { r.pendingConfIndex = r.raftLog.lastIndex() + uint64(i) + 1 + traceChangeConfEvent(cc, r) } } } @@ -1071,7 +1345,7 @@ func stepLeader(r *raft, m pb.Message) error { return nil case pb.MsgReadIndex: // only one voting member (the leader) in the cluster - if r.prs.IsSingleton() { + if r.trk.IsSingleton() { if resp := r.responseToReadIndexReq(m, r.raftLog.committed); resp.To != None { r.send(resp) } @@ -1088,16 +1362,21 @@ func stepLeader(r *raft, m pb.Message) error { sendMsgReadIndexResponse(r, m) return nil + case pb.MsgForgetLeader: + return nil // noop on leader } // All other message types require a progress for m.From (pr). - pr := r.prs.Progress[m.From] + pr := r.trk.Progress[m.From] if pr == nil { r.logger.Debugf("%x no progress available for %x", r.id, m.From) return nil } switch m.Type { case pb.MsgAppResp: + // NB: this code path is also hit from (*raft).advance, where the leader steps + // an MsgAppResp to acknowledge the appended entries in the last Ready. + pr.RecentActive = true if m.Reject { @@ -1148,7 +1427,7 @@ func stepLeader(r *raft, m pb.Message) error { // the rejection's log term. If a probe at one of these indexes // succeeded, its log term at that index would match the leader's, // i.e. 3 or 5 in this example. But the follower already told the - // leader that it is still at term 2 at index 9, and since the + // leader that it is still at term 2 at index 6, and since the // log term only ever goes up (within a log), this is a contradiction. // // At index 1, however, the leader can draw no such conclusion, @@ -1219,7 +1498,7 @@ func stepLeader(r *raft, m pb.Message) error { // 7, the rejection points it at the end of the follower's log // which is at a higher log term than the actually committed // log. - nextProbeIdx = r.raftLog.findConflictByTerm(m.RejectHint, m.LogTerm) + nextProbeIdx, _ = r.raftLog.findConflictByTerm(m.RejectHint, m.LogTerm) } if pr.MaybeDecrTo(m.Index, nextProbeIdx) { r.logger.Debugf("%x decreased progress of %x to [%s]", r.id, m.From, pr) @@ -1229,15 +1508,25 @@ func stepLeader(r *raft, m pb.Message) error { r.sendAppend(m.From) } } else { - oldPaused := pr.IsPaused() - if pr.MaybeUpdate(m.Index) { + // We want to update our tracking if the response updates our + // matched index or if the response can move a probing peer back + // into StateReplicate (see heartbeat_rep_recovers_from_probing.txt + // for an example of the latter case). + // NB: the same does not make sense for StateSnapshot - if `m.Index` + // equals pr.Match we know we don't m.Index+1 in our log, so moving + // back to replicating state is not useful; besides pr.PendingSnapshot + // would prevent it. + if pr.MaybeUpdate(m.Index) || (pr.Match == m.Index && pr.State == tracker.StateProbe) { switch { case pr.State == tracker.StateProbe: pr.BecomeReplicate() - case pr.State == tracker.StateSnapshot && pr.Match >= pr.PendingSnapshot: - // TODO(tbg): we should also enter this branch if a snapshot is - // received that is below pr.PendingSnapshot but which makes it - // possible to use the log again. + case pr.State == tracker.StateSnapshot && pr.Match+1 >= r.raftLog.firstIndex(): + // Note that we don't take into account PendingSnapshot to + // enter this branch. No matter at which index a snapshot + // was actually applied, as long as this allows catching up + // the follower from the log, we will accept it. This gives + // systems more flexibility in how they implement snapshots; + // see the comments on PendingSnapshot. r.logger.Debugf("%x recovered from needing snapshot, resumed sending replication messages to %x [%s]", r.id, m.From, pr) // Transition back to replicating state via probing state // (which takes the snapshot into account). If we didn't @@ -1255,9 +1544,11 @@ func stepLeader(r *raft, m pb.Message) error { // to respond to pending read index requests releasePendingReadIndexMessages(r) r.bcastAppend() - } else if oldPaused { - // If we were paused before, this node may be missing the - // latest commit index, so send it. + } else if r.id != m.From && pr.CanBumpCommit(r.raftLog.committed) { + // This node may be missing the latest commit index, so send it. + // NB: this is not strictly necessary because the periodic heartbeat + // messages deliver commit indices too. However, a message sent now + // may arrive earlier than the next heartbeat fires. r.sendAppend(m.From) } // We've updated flow control information above, which may @@ -1266,7 +1557,9 @@ func stepLeader(r *raft, m pb.Message) error { // replicate, or when freeTo() covers multiple messages). If // we have more entries to send, send as many messages as we // can (without sending empty messages for the commit index) - for r.maybeSendAppend(m.From, false) { + if r.id != m.From { + for r.maybeSendAppend(m.From, false /* sendIfEmpty */) { + } } // Transfer leadership is in progress. if m.From == r.leadTransferee && pr.Match == r.raftLog.lastIndex() { @@ -1277,13 +1570,22 @@ func stepLeader(r *raft, m pb.Message) error { } case pb.MsgHeartbeatResp: pr.RecentActive = true - pr.ProbeSent = false + pr.MsgAppFlowPaused = false - // free one slot for the full inflights window to allow progress. - if pr.State == tracker.StateReplicate && pr.Inflights.Full() { - pr.Inflights.FreeFirstOne() - } - if pr.Match < r.raftLog.lastIndex() { + // NB: if the follower is paused (full Inflights), this will still send an + // empty append, allowing it to recover from situations in which all the + // messages that filled up Inflights in the first place were dropped. Note + // also that the outgoing heartbeat already communicated the commit index. + // + // If the follower is fully caught up but also in StateProbe (as can happen + // if ReportUnreachable was called), we also want to send an append (it will + // be empty) to allow the follower to transition back to StateReplicate once + // it responds. + // + // Note that StateSnapshot typically satisfies pr.Match < lastIndex, but + // `pr.Paused()` is always true for StateSnapshot, so sendAppend is a + // no-op. + if pr.Match < r.raftLog.lastIndex() || pr.State == tracker.StateProbe { r.sendAppend(m.From) } @@ -1291,7 +1593,7 @@ func stepLeader(r *raft, m pb.Message) error { return nil } - if r.prs.Voters.VoteResult(r.readOnly.recvAck(m.From, m.Context)) != quorum.VoteWon { + if r.trk.Voters.VoteResult(r.readOnly.recvAck(m.From, m.Context)) != quorum.VoteWon { return nil } @@ -1305,10 +1607,6 @@ func stepLeader(r *raft, m pb.Message) error { if pr.State != tracker.StateSnapshot { return nil } - // TODO(tbg): this code is very similar to the snapshot handling in - // MsgAppResp above. In fact, the code there is more correct than the - // code here and should likely be updated to match (or even better, the - // logic pulled into a newly created Progress state machine handler). if !m.Reject { pr.BecomeProbe() r.logger.Debugf("%x snapshot succeeded, resumed sending replication messages to %x [%s]", r.id, m.From, pr) @@ -1322,7 +1620,7 @@ func stepLeader(r *raft, m pb.Message) error { // If snapshot finish, wait for the MsgAppResp from the remote node before sending // out the next MsgApp. // If snapshot failure, wait for a heartbeat interval before next try - pr.ProbeSent = true + pr.MsgAppFlowPaused = true case pb.MsgUnreachable: // During optimistic replication, if the remote becomes unreachable, // there is huge probability that a MsgApp is lost. @@ -1443,6 +1741,15 @@ func stepFollower(r *raft, m pb.Message) error { } m.To = r.lead r.send(m) + case pb.MsgForgetLeader: + if r.readOnly.option == ReadOnlyLeaseBased { + r.logger.Error("ignoring MsgForgetLeader due to ReadOnlyLeaseBased") + return nil + } + if r.lead != None { + r.logger.Infof("%x forgetting leader %x at term %d", r.id, r.lead, r.Term) + r.lead = None + } case pb.MsgTimeoutNow: r.logger.Infof("%x [term %d] received MsgTimeoutNow from %x and starts an election to get leadership.", r.id, r.Term, m.From) // Leadership transfers never use pre-vote even if r.preVote is true; we @@ -1466,42 +1773,58 @@ func stepFollower(r *raft, m pb.Message) error { return nil } +// logSliceFromMsgApp extracts the appended logSlice from a MsgApp message. +func logSliceFromMsgApp(m *pb.Message) logSlice { + // TODO(pav-kv): consider also validating the logSlice here. + return logSlice{ + term: m.Term, + prev: entryID{term: m.LogTerm, index: m.Index}, + entries: m.Entries, + } +} + func (r *raft) handleAppendEntries(m pb.Message) { - if m.Index < r.raftLog.committed { + // TODO(pav-kv): construct logSlice up the stack next to receiving the + // message, and validate it before taking any action (e.g. bumping term). + a := logSliceFromMsgApp(&m) + + if a.prev.index < r.raftLog.committed { r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: r.raftLog.committed}) return } - - if mlastIndex, ok := r.raftLog.maybeAppend(m.Index, m.LogTerm, m.Commit, m.Entries...); ok { + if mlastIndex, ok := r.raftLog.maybeAppend(a, m.Commit); ok { r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: mlastIndex}) - } else { - r.logger.Debugf("%x [logterm: %d, index: %d] rejected MsgApp [logterm: %d, index: %d] from %x", - r.id, r.raftLog.zeroTermOnErrCompacted(r.raftLog.term(m.Index)), m.Index, m.LogTerm, m.Index, m.From) - - // Return a hint to the leader about the maximum index and term that the - // two logs could be divergent at. Do this by searching through the - // follower's log for the maximum (index, term) pair with a term <= the - // MsgApp's LogTerm and an index <= the MsgApp's Index. This can help - // skip all indexes in the follower's uncommitted tail with terms - // greater than the MsgApp's LogTerm. - // - // See the other caller for findConflictByTerm (in stepLeader) for a much - // more detailed explanation of this mechanism. - hintIndex := min(m.Index, r.raftLog.lastIndex()) - hintIndex = r.raftLog.findConflictByTerm(hintIndex, m.LogTerm) - hintTerm, err := r.raftLog.term(hintIndex) - if err != nil { - panic(fmt.Sprintf("term(%d) must be valid, but got %v", hintIndex, err)) - } - r.send(pb.Message{ - To: m.From, - Type: pb.MsgAppResp, - Index: m.Index, - Reject: true, - RejectHint: hintIndex, - LogTerm: hintTerm, - }) + return } + r.logger.Debugf("%x [logterm: %d, index: %d] rejected MsgApp [logterm: %d, index: %d] from %x", + r.id, r.raftLog.zeroTermOnOutOfBounds(r.raftLog.term(m.Index)), m.Index, m.LogTerm, m.Index, m.From) + + // Our log does not match the leader's at index m.Index. Return a hint to the + // leader - a guess on the maximal (index, term) at which the logs match. Do + // this by searching through the follower's log for the maximum (index, term) + // pair with a term <= the MsgApp's LogTerm and an index <= the MsgApp's + // Index. This can help skip all indexes in the follower's uncommitted tail + // with terms greater than the MsgApp's LogTerm. + // + // See the other caller for findConflictByTerm (in stepLeader) for a much more + // detailed explanation of this mechanism. + + // NB: m.Index >= raftLog.committed by now (see the early return above), and + // raftLog.lastIndex() >= raftLog.committed by invariant, so min of the two is + // also >= raftLog.committed. Hence, the findConflictByTerm argument is within + // the valid interval, which then will return a valid (index, term) pair with + // a non-zero term (unless the log is empty). However, it is safe to send a zero + // LogTerm in this response in any case, so we don't verify it here. + hintIndex := min(m.Index, r.raftLog.lastIndex()) + hintIndex, hintTerm := r.raftLog.findConflictByTerm(hintIndex, m.LogTerm) + r.send(pb.Message{ + To: m.From, + Type: pb.MsgAppResp, + Index: m.Index, + Reject: true, + RejectHint: hintIndex, + LogTerm: hintTerm, + }) } func (r *raft) handleHeartbeat(m pb.Message) { @@ -1510,8 +1833,14 @@ func (r *raft) handleHeartbeat(m pb.Message) { } func (r *raft) handleSnapshot(m pb.Message) { - sindex, sterm := m.Snapshot.Metadata.Index, m.Snapshot.Metadata.Term - if r.restore(m.Snapshot) { + // MsgSnap messages should always carry a non-nil Snapshot, but err on the + // side of safety and treat a nil Snapshot as a zero-valued Snapshot. + var s pb.Snapshot + if m.Snapshot != nil { + s = *m.Snapshot + } + sindex, sterm := s.Metadata.Index, s.Metadata.Term + if r.restore(s) { r.logger.Infof("%x [commit: %d] restored snapshot [index: %d, term: %d]", r.id, r.raftLog.committed, sindex, sterm) r.send(pb.Message{To: m.From, Type: pb.MsgAppResp, Index: r.raftLog.lastIndex()}) @@ -1575,9 +1904,12 @@ func (r *raft) restore(s pb.Snapshot) bool { // Now go ahead and actually restore. - if r.raftLog.matchTerm(s.Metadata.Index, s.Metadata.Term) { + id := entryID{term: s.Metadata.Term, index: s.Metadata.Index} + if r.raftLog.matchTerm(id) { + // TODO(pav-kv): can print %+v of the id, but it will change the format. + last := r.raftLog.lastEntryID() r.logger.Infof("%x [commit: %d, lastindex: %d, lastterm: %d] fast-forwarded commit to snapshot [index: %d, term: %d]", - r.id, r.raftLog.committed, r.raftLog.lastIndex(), r.raftLog.lastTerm(), s.Metadata.Index, s.Metadata.Term) + r.id, r.raftLog.committed, last.index, last.term, id.index, id.term) r.raftLog.commitTo(s.Metadata.Index) return false } @@ -1585,9 +1917,9 @@ func (r *raft) restore(s pb.Snapshot) bool { r.raftLog.restore(s) // Reset the configuration and add the (potentially updated) peers in anew. - r.prs = tracker.MakeProgressTracker(r.prs.MaxInflight) - cfg, prs, err := confchange.Restore(confchange.Changer{ - Tracker: r.prs, + r.trk = tracker.MakeProgressTracker(r.trk.MaxInflight, r.trk.MaxInflightBytes) + cfg, trk, err := confchange.Restore(confchange.Changer{ + Tracker: r.trk, LastIndex: r.raftLog.lastIndex(), }, cs) @@ -1597,27 +1929,25 @@ func (r *raft) restore(s pb.Snapshot) bool { panic(fmt.Sprintf("unable to restore config %+v: %s", cs, err)) } - assertConfStatesEquivalent(r.logger, cs, r.switchToConfig(cfg, prs)) - - pr := r.prs.Progress[r.id] - pr.MaybeUpdate(pr.Next - 1) // TODO(tbg): this is untested and likely unneeded + assertConfStatesEquivalent(r.logger, cs, r.switchToConfig(cfg, trk)) + last := r.raftLog.lastEntryID() r.logger.Infof("%x [commit: %d, lastindex: %d, lastterm: %d] restored snapshot [index: %d, term: %d]", - r.id, r.raftLog.committed, r.raftLog.lastIndex(), r.raftLog.lastTerm(), s.Metadata.Index, s.Metadata.Term) + r.id, r.raftLog.committed, last.index, last.term, id.index, id.term) return true } // promotable indicates whether state machine can be promoted to leader, // which is true when its own id is in progress list. func (r *raft) promotable() bool { - pr := r.prs.Progress[r.id] - return pr != nil && !pr.IsLearner && !r.raftLog.hasPendingSnapshot() + pr := r.trk.Progress[r.id] + return pr != nil && !pr.IsLearner && !r.raftLog.hasNextOrInProgressSnapshot() } func (r *raft) applyConfChange(cc pb.ConfChangeV2) pb.ConfState { - cfg, prs, err := func() (tracker.Config, tracker.ProgressMap, error) { + cfg, trk, err := func() (tracker.Config, tracker.ProgressMap, error) { changer := confchange.Changer{ - Tracker: r.prs, + Tracker: r.trk, LastIndex: r.raftLog.lastIndex(), } if cc.LeaveJoint() { @@ -1633,7 +1963,7 @@ func (r *raft) applyConfChange(cc pb.ConfChangeV2) pb.ConfState { panic(err) } - return r.switchToConfig(cfg, prs) + return r.switchToConfig(cfg, trk) } // switchToConfig reconfigures this node to use the provided configuration. It @@ -1642,28 +1972,32 @@ func (r *raft) applyConfChange(cc pb.ConfChangeV2) pb.ConfState { // requirements. // // The inputs usually result from restoring a ConfState or applying a ConfChange. -func (r *raft) switchToConfig(cfg tracker.Config, prs tracker.ProgressMap) pb.ConfState { - r.prs.Config = cfg - r.prs.Progress = prs +func (r *raft) switchToConfig(cfg tracker.Config, trk tracker.ProgressMap) pb.ConfState { + traceConfChangeEvent(cfg, r) + + r.trk.Config = cfg + r.trk.Progress = trk - r.logger.Infof("%x switched to configuration %s", r.id, r.prs.Config) - cs := r.prs.ConfState() - pr, ok := r.prs.Progress[r.id] + r.logger.Infof("%x switched to configuration %s", r.id, r.trk.Config) + cs := r.trk.ConfState() + pr, ok := r.trk.Progress[r.id] // Update whether the node itself is a learner, resetting to false when the // node is removed. r.isLearner = ok && pr.IsLearner if (!ok || r.isLearner) && r.state == StateLeader { - // This node is leader and was removed or demoted. We prevent demotions - // at the time writing but hypothetically we handle them the same way as - // removing the leader: stepping down into the next Term. + // This node is leader and was removed or demoted, step down if requested. // - // TODO(tbg): step down (for sanity) and ask follower with largest Match - // to TimeoutNow (to avoid interruption). This might still drop some - // proposals but it's better than nothing. + // We prevent demotions at the time writing but hypothetically we handle + // them the same way as removing the leader. // - // TODO(tbg): test this branch. It is untested at the time of writing. + // TODO(tbg): ask follower with largest Match to TimeoutNow (to avoid + // interruption). This might still drop some proposals but it's better than + // nothing. + if r.stepDownOnRemoval { + r.becomeFollower(r.Term, None) + } return cs } @@ -1681,12 +2015,15 @@ func (r *raft) switchToConfig(cfg tracker.Config, prs tracker.ProgressMap) pb.Co // Otherwise, still probe the newly added replicas; there's no reason to // let them wait out a heartbeat interval (or the next incoming // proposal). - r.prs.Visit(func(id uint64, pr *tracker.Progress) { + r.trk.Visit(func(id uint64, _ *tracker.Progress) { + if id == r.id { + return + } r.maybeSendAppend(id, false /* sendIfEmpty */) }) } - // If the the leadTransferee was removed or demoted, abort the leadership transfer. - if _, tOK := r.prs.Config.Voters.IDs()[r.leadTransferee]; !tOK && r.leadTransferee != 0 { + // If the leadTransferee was removed or demoted, abort the leadership transfer. + if _, tOK := r.trk.Config.Voters.IDs()[r.leadTransferee]; !tOK && r.leadTransferee != 0 { r.abortLeaderTransfer() } @@ -1702,7 +2039,7 @@ func (r *raft) loadState(state pb.HardState) { r.Vote = state.Vote } -// pastElectionTimeout returns true iff r.electionElapsed is greater +// pastElectionTimeout returns true if r.electionElapsed is greater // than or equal to the randomized election timeout in // [electiontimeout, 2 * electiontimeout - 1]. func (r *raft) pastElectionTimeout() bool { @@ -1723,7 +2060,9 @@ func (r *raft) abortLeaderTransfer() { // committedEntryInCurrentTerm return true if the peer has committed an entry in its term. func (r *raft) committedEntryInCurrentTerm() bool { - return r.raftLog.zeroTermOnErrCompacted(r.raftLog.term(r.raftLog.committed)) == r.Term + // NB: r.Term is never 0 on a leader, so if zeroTermOnOutOfBounds returns 0, + // we won't see it as a match with r.Term. + return r.raftLog.zeroTermOnOutOfBounds(r.raftLog.term(r.raftLog.committed)) == r.Term } // responseToReadIndexReq constructs a response for `req`. If `req` comes from the peer @@ -1753,11 +2092,7 @@ func (r *raft) responseToReadIndexReq(req pb.Message, readIndex uint64) pb.Messa // Empty payloads are never refused. This is used both for appending an empty // entry at a new leader's term, as well as leaving a joint configuration. func (r *raft) increaseUncommittedSize(ents []pb.Entry) bool { - var s uint64 - for _, e := range ents { - s += uint64(PayloadSize(e)) - } - + s := payloadsSize(ents) if r.uncommittedSize > 0 && s > 0 && r.uncommittedSize+s > r.maxUncommittedSize { // If the uncommitted tail of the Raft log is empty, allow any size // proposal. Otherwise, limit the size of the uncommitted tail of the @@ -1774,16 +2109,7 @@ func (r *raft) increaseUncommittedSize(ents []pb.Entry) bool { // reduceUncommittedSize accounts for the newly committed entries by decreasing // the uncommitted entry size limit. -func (r *raft) reduceUncommittedSize(ents []pb.Entry) { - if r.uncommittedSize == 0 { - // Fast-path for followers, who do not track or enforce the limit. - return - } - - var s uint64 - for _, e := range ents { - s += uint64(PayloadSize(e)) - } +func (r *raft) reduceUncommittedSize(s entryPayloadSize) { if s > r.uncommittedSize { // uncommittedSize may underestimate the size of the uncommitted Raft // log tail but will never overestimate it. Saturate at 0 instead of @@ -1794,17 +2120,12 @@ func (r *raft) reduceUncommittedSize(ents []pb.Entry) { } } -func numOfPendingConf(ents []pb.Entry) int { - n := 0 - for i := range ents { - if ents[i].Type == pb.EntryConfChange || ents[i].Type == pb.EntryConfChangeV2 { - n++ - } - } - return n -} - func releasePendingReadIndexMessages(r *raft) { + if len(r.pendingReadIndexMessages) == 0 { + // Fast path for the common case to avoid a call to storage.LastIndex() + // via committedEntryInCurrentTerm. + return + } if !r.committedEntryInCurrentTerm() { r.logger.Error("pending MsgReadIndex should be released only after first commit in current term") return diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/confchange.go b/etcd/vendor/go.etcd.io/raft/v3/raftpb/confchange.go similarity index 95% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/confchange.go rename to etcd/vendor/go.etcd.io/raft/v3/raftpb/confchange.go index 47fae65dfe..a3ddff62fd 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/confchange.go +++ b/etcd/vendor/go.etcd.io/raft/v3/raftpb/confchange.go @@ -35,7 +35,13 @@ func MarshalConfChange(c ConfChangeI) (EntryType, []byte, error) { var typ EntryType var ccdata []byte var err error - if ccv1, ok := c.AsV1(); ok { + if c == nil { + // A nil data unmarshals into an empty ConfChangeV2 and has the benefit + // that appendEntry can never refuse it based on its size (which + // registers as zero). + typ = EntryConfChangeV2 + ccdata = nil + } else if ccv1, ok := c.AsV1(); ok { typ = EntryConfChange ccdata, err = ccv1.Marshal() } else { diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/confstate.go b/etcd/vendor/go.etcd.io/raft/v3/raftpb/confstate.go similarity index 94% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/confstate.go rename to etcd/vendor/go.etcd.io/raft/v3/raftpb/confstate.go index 39b9dd7000..3aedeb79bd 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/confstate.go +++ b/etcd/vendor/go.etcd.io/raft/v3/raftpb/confstate.go @@ -17,7 +17,7 @@ package raftpb import ( "fmt" "reflect" - "sort" + "slices" ) // Equivalent returns a nil error if the inputs describe the same configuration. @@ -27,7 +27,7 @@ func (cs ConfState) Equivalent(cs2 ConfState) error { orig1, orig2 := cs1, cs2 s := func(sl *[]uint64) { *sl = append([]uint64(nil), *sl...) - sort.Slice(*sl, func(i, j int) bool { return (*sl)[i] < (*sl)[j] }) + slices.Sort(*sl) } for _, cs := range []*ConfState{&cs1, &cs2} { diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.pb.go b/etcd/vendor/go.etcd.io/raft/v3/raftpb/raft.pb.go similarity index 84% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.pb.go rename to etcd/vendor/go.etcd.io/raft/v3/raftpb/raft.pb.go index 1ee77a9a45..7dcdef0cd6 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.pb.go +++ b/etcd/vendor/go.etcd.io/raft/v3/raftpb/raft.pb.go @@ -68,29 +68,34 @@ func (EntryType) EnumDescriptor() ([]byte, []int) { } // For description of different message types, see: -// https://pkg.go.dev/go.etcd.io/etcd/raft/v3#hdr-MessageType +// https://pkg.go.dev/go.etcd.io/raft/v3#hdr-MessageType type MessageType int32 const ( - MsgHup MessageType = 0 - MsgBeat MessageType = 1 - MsgProp MessageType = 2 - MsgApp MessageType = 3 - MsgAppResp MessageType = 4 - MsgVote MessageType = 5 - MsgVoteResp MessageType = 6 - MsgSnap MessageType = 7 - MsgHeartbeat MessageType = 8 - MsgHeartbeatResp MessageType = 9 - MsgUnreachable MessageType = 10 - MsgSnapStatus MessageType = 11 - MsgCheckQuorum MessageType = 12 - MsgTransferLeader MessageType = 13 - MsgTimeoutNow MessageType = 14 - MsgReadIndex MessageType = 15 - MsgReadIndexResp MessageType = 16 - MsgPreVote MessageType = 17 - MsgPreVoteResp MessageType = 18 + MsgHup MessageType = 0 + MsgBeat MessageType = 1 + MsgProp MessageType = 2 + MsgApp MessageType = 3 + MsgAppResp MessageType = 4 + MsgVote MessageType = 5 + MsgVoteResp MessageType = 6 + MsgSnap MessageType = 7 + MsgHeartbeat MessageType = 8 + MsgHeartbeatResp MessageType = 9 + MsgUnreachable MessageType = 10 + MsgSnapStatus MessageType = 11 + MsgCheckQuorum MessageType = 12 + MsgTransferLeader MessageType = 13 + MsgTimeoutNow MessageType = 14 + MsgReadIndex MessageType = 15 + MsgReadIndexResp MessageType = 16 + MsgPreVote MessageType = 17 + MsgPreVoteResp MessageType = 18 + MsgStorageAppend MessageType = 19 + MsgStorageAppendResp MessageType = 20 + MsgStorageApply MessageType = 21 + MsgStorageApplyResp MessageType = 22 + MsgForgetLeader MessageType = 23 ) var MessageType_name = map[int32]string{ @@ -113,28 +118,38 @@ var MessageType_name = map[int32]string{ 16: "MsgReadIndexResp", 17: "MsgPreVote", 18: "MsgPreVoteResp", + 19: "MsgStorageAppend", + 20: "MsgStorageAppendResp", + 21: "MsgStorageApply", + 22: "MsgStorageApplyResp", + 23: "MsgForgetLeader", } var MessageType_value = map[string]int32{ - "MsgHup": 0, - "MsgBeat": 1, - "MsgProp": 2, - "MsgApp": 3, - "MsgAppResp": 4, - "MsgVote": 5, - "MsgVoteResp": 6, - "MsgSnap": 7, - "MsgHeartbeat": 8, - "MsgHeartbeatResp": 9, - "MsgUnreachable": 10, - "MsgSnapStatus": 11, - "MsgCheckQuorum": 12, - "MsgTransferLeader": 13, - "MsgTimeoutNow": 14, - "MsgReadIndex": 15, - "MsgReadIndexResp": 16, - "MsgPreVote": 17, - "MsgPreVoteResp": 18, + "MsgHup": 0, + "MsgBeat": 1, + "MsgProp": 2, + "MsgApp": 3, + "MsgAppResp": 4, + "MsgVote": 5, + "MsgVoteResp": 6, + "MsgSnap": 7, + "MsgHeartbeat": 8, + "MsgHeartbeatResp": 9, + "MsgUnreachable": 10, + "MsgSnapStatus": 11, + "MsgCheckQuorum": 12, + "MsgTransferLeader": 13, + "MsgTimeoutNow": 14, + "MsgReadIndex": 15, + "MsgReadIndexResp": 16, + "MsgPreVote": 17, + "MsgPreVoteResp": 18, + "MsgStorageAppend": 19, + "MsgStorageAppendResp": 20, + "MsgStorageApply": 21, + "MsgStorageApplyResp": 22, + "MsgForgetLeader": 23, } func (x MessageType) Enum() *MessageType { @@ -386,18 +401,37 @@ type Message struct { From uint64 `protobuf:"varint,3,opt,name=from" json:"from"` Term uint64 `protobuf:"varint,4,opt,name=term" json:"term"` // logTerm is generally used for appending Raft logs to followers. For example, - // (type=MsgApp,index=100,logTerm=5) means leader appends entries starting at - // index=101, and the term of entry at index 100 is 5. + // (type=MsgApp,index=100,logTerm=5) means the leader appends entries starting + // at index=101, and the term of the entry at index 100 is 5. // (type=MsgAppResp,reject=true,index=100,logTerm=5) means follower rejects some // entries from its leader as it already has an entry with term 5 at index 100. - LogTerm uint64 `protobuf:"varint,5,opt,name=logTerm" json:"logTerm"` - Index uint64 `protobuf:"varint,6,opt,name=index" json:"index"` - Entries []Entry `protobuf:"bytes,7,rep,name=entries" json:"entries"` - Commit uint64 `protobuf:"varint,8,opt,name=commit" json:"commit"` - Snapshot Snapshot `protobuf:"bytes,9,opt,name=snapshot" json:"snapshot"` - Reject bool `protobuf:"varint,10,opt,name=reject" json:"reject"` - RejectHint uint64 `protobuf:"varint,11,opt,name=rejectHint" json:"rejectHint"` - Context []byte `protobuf:"bytes,12,opt,name=context" json:"context,omitempty"` + // (type=MsgStorageAppendResp,index=100,logTerm=5) means the local node wrote + // entries up to index=100 in stable storage, and the term of the entry at index + // 100 was 5. This doesn't always mean that the corresponding MsgStorageAppend + // message was the one that carried these entries, just that those entries were + // stable at the time of processing the corresponding MsgStorageAppend. + LogTerm uint64 `protobuf:"varint,5,opt,name=logTerm" json:"logTerm"` + Index uint64 `protobuf:"varint,6,opt,name=index" json:"index"` + Entries []Entry `protobuf:"bytes,7,rep,name=entries" json:"entries"` + Commit uint64 `protobuf:"varint,8,opt,name=commit" json:"commit"` + // (type=MsgStorageAppend,vote=5,term=10) means the local node is voting for + // peer 5 in term 10. For MsgStorageAppends, the term, vote, and commit fields + // will either all be set (to facilitate the construction of a HardState) if + // any of the fields have changed or will all be unset if none of the fields + // have changed. + Vote uint64 `protobuf:"varint,13,opt,name=vote" json:"vote"` + // snapshot is non-nil and non-empty for MsgSnap messages and nil for all other + // message types. However, peer nodes running older binary versions may send a + // non-nil, empty value for the snapshot field of non-MsgSnap messages. Code + // should be prepared to handle such messages. + Snapshot *Snapshot `protobuf:"bytes,9,opt,name=snapshot" json:"snapshot,omitempty"` + Reject bool `protobuf:"varint,10,opt,name=reject" json:"reject"` + RejectHint uint64 `protobuf:"varint,11,opt,name=rejectHint" json:"rejectHint"` + Context []byte `protobuf:"bytes,12,opt,name=context" json:"context,omitempty"` + // responses are populated by a raft node to instruct storage threads on how + // to respond and who to respond to when the work associated with a message + // is complete. Populated for MsgStorageAppend and MsgStorageApply messages. + Responses []Message `protobuf:"bytes,14,rep,name=responses" json:"responses"` } func (m *Message) Reset() { *m = Message{} } @@ -695,72 +729,76 @@ func init() { func init() { proto.RegisterFile("raft.proto", fileDescriptor_b042552c306ae59b) } var fileDescriptor_b042552c306ae59b = []byte{ - // 1026 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcd, 0x6e, 0xdb, 0x46, - 0x17, 0x25, 0x29, 0x5a, 0x3f, 0x57, 0xb2, 0x3c, 0xbe, 0xf1, 0x17, 0x10, 0x86, 0xc1, 0xe8, 0x53, - 0x52, 0x44, 0x70, 0x11, 0xb7, 0xd0, 0xa2, 0x28, 0xba, 0xf3, 0x4f, 0x00, 0xab, 0xb0, 0xdc, 0x54, - 0x76, 0xbc, 0x28, 0x50, 0x08, 0x63, 0x71, 0x44, 0xb3, 0x15, 0x39, 0x04, 0x39, 0x72, 0xed, 0x4d, - 0x51, 0xf4, 0x09, 0xba, 0xec, 0x26, 0xdb, 0x3e, 0x40, 0x9f, 0xc2, 0x4b, 0x03, 0xdd, 0x74, 0x15, - 0x34, 0xf6, 0x8b, 0x14, 0x33, 0x1c, 0x4a, 0x94, 0x6c, 0x64, 0xd1, 0xdd, 0xcc, 0xb9, 0x67, 0xee, - 0x9c, 0x73, 0xef, 0xe5, 0x10, 0x20, 0xa1, 0x63, 0xb1, 0x13, 0x27, 0x5c, 0x70, 0x2c, 0xcb, 0x75, - 0x7c, 0xbe, 0xb9, 0xe1, 0x73, 0x9f, 0x2b, 0xe8, 0x33, 0xb9, 0xca, 0xa2, 0xed, 0x9f, 0x61, 0xe5, - 0x75, 0x24, 0x92, 0x6b, 0x74, 0xc0, 0x3e, 0x65, 0x49, 0xe8, 0x58, 0x2d, 0xb3, 0x63, 0xef, 0xd9, - 0x37, 0xef, 0x9f, 0x19, 0x03, 0x85, 0xe0, 0x26, 0xac, 0xf4, 0x22, 0x8f, 0x5d, 0x39, 0xa5, 0x42, - 0x28, 0x83, 0xf0, 0x53, 0xb0, 0x4f, 0xaf, 0x63, 0xe6, 0x98, 0x2d, 0xb3, 0xd3, 0xec, 0xae, 0xef, - 0x64, 0x77, 0xed, 0xa8, 0x94, 0x32, 0x30, 0x4b, 0x74, 0x1d, 0x33, 0x44, 0xb0, 0x0f, 0xa8, 0xa0, - 0x8e, 0xdd, 0x32, 0x3b, 0x8d, 0x81, 0x5a, 0xb7, 0x7f, 0x31, 0x81, 0x9c, 0x44, 0x34, 0x4e, 0x2f, - 0xb8, 0xe8, 0x33, 0x41, 0x3d, 0x2a, 0x28, 0x7e, 0x01, 0x30, 0xe2, 0xd1, 0x78, 0x98, 0x0a, 0x2a, - 0xb2, 0xdc, 0xf5, 0x79, 0xee, 0x7d, 0x1e, 0x8d, 0x4f, 0x64, 0x40, 0xe7, 0xae, 0x8d, 0x72, 0x40, - 0x2a, 0x0d, 0x94, 0xd2, 0xa2, 0x89, 0x0c, 0x92, 0xfe, 0x84, 0xf4, 0x57, 0x34, 0xa1, 0x90, 0xf6, - 0x77, 0x50, 0xcd, 0x15, 0x48, 0x89, 0x52, 0x81, 0xba, 0xb3, 0x31, 0x50, 0x6b, 0xfc, 0x0a, 0xaa, - 0xa1, 0x56, 0xa6, 0x12, 0xd7, 0xbb, 0x4e, 0xae, 0x65, 0x59, 0xb9, 0xce, 0x3b, 0xe3, 0xb7, 0xdf, - 0x95, 0xa0, 0xd2, 0x67, 0x69, 0x4a, 0x7d, 0x86, 0xaf, 0xc0, 0x16, 0xf3, 0x5a, 0x3d, 0xc9, 0x73, - 0xe8, 0x70, 0xb1, 0x5a, 0x92, 0x86, 0x1b, 0x60, 0x09, 0xbe, 0xe0, 0xc4, 0x12, 0x5c, 0xda, 0x18, - 0x27, 0x7c, 0xc9, 0x86, 0x44, 0x66, 0x06, 0xed, 0x65, 0x83, 0xe8, 0x42, 0x65, 0xc2, 0x7d, 0xd5, - 0xdd, 0x95, 0x42, 0x30, 0x07, 0xe7, 0x65, 0x2b, 0x3f, 0x2c, 0xdb, 0x2b, 0xa8, 0xb0, 0x48, 0x24, - 0x01, 0x4b, 0x9d, 0x4a, 0xab, 0xd4, 0xa9, 0x77, 0x57, 0x17, 0x7a, 0x9c, 0xa7, 0xd2, 0x1c, 0xdc, - 0x82, 0xf2, 0x88, 0x87, 0x61, 0x20, 0x9c, 0x6a, 0x21, 0x97, 0xc6, 0xb0, 0x0b, 0xd5, 0x54, 0x57, - 0xcc, 0xa9, 0xa9, 0x4a, 0x92, 0xe5, 0x4a, 0xe6, 0x15, 0xcc, 0x79, 0x32, 0x63, 0xc2, 0x7e, 0x60, - 0x23, 0xe1, 0x40, 0xcb, 0xec, 0x54, 0xf3, 0x8c, 0x19, 0x86, 0x2f, 0x00, 0xb2, 0xd5, 0x61, 0x10, - 0x09, 0xa7, 0x5e, 0xb8, 0xb3, 0x80, 0xa3, 0x03, 0x95, 0x11, 0x8f, 0x04, 0xbb, 0x12, 0x4e, 0x43, - 0x35, 0x36, 0xdf, 0xb6, 0xbf, 0x87, 0xda, 0x21, 0x4d, 0xbc, 0x6c, 0x7c, 0xf2, 0x0a, 0x9a, 0x0f, - 0x2a, 0xe8, 0x80, 0x7d, 0xc9, 0x05, 0x5b, 0xfc, 0x38, 0x24, 0x52, 0x30, 0x5c, 0x7a, 0x68, 0xb8, - 0xfd, 0xa7, 0x09, 0xb5, 0xd9, 0xbc, 0xe2, 0x53, 0x28, 0xcb, 0x33, 0x49, 0xea, 0x98, 0xad, 0x52, - 0xc7, 0x1e, 0xe8, 0x1d, 0x6e, 0x42, 0x75, 0xc2, 0x68, 0x12, 0xc9, 0x88, 0xa5, 0x22, 0xb3, 0x3d, - 0xbe, 0x84, 0xb5, 0x8c, 0x35, 0xe4, 0x53, 0xe1, 0xf3, 0x20, 0xf2, 0x9d, 0x92, 0xa2, 0x34, 0x33, - 0xf8, 0x1b, 0x8d, 0xe2, 0x73, 0x58, 0xcd, 0x0f, 0x0d, 0x23, 0xe9, 0xd4, 0x56, 0xb4, 0x46, 0x0e, - 0x1e, 0xb3, 0x2b, 0x81, 0xcf, 0x01, 0xe8, 0x54, 0xf0, 0xe1, 0x84, 0xd1, 0x4b, 0xa6, 0x86, 0x21, - 0x2f, 0x68, 0x4d, 0xe2, 0x47, 0x12, 0x6e, 0xbf, 0x33, 0x01, 0xa4, 0xe8, 0xfd, 0x0b, 0x1a, 0xf9, - 0x0c, 0x3f, 0xd7, 0x63, 0x6b, 0xa9, 0xb1, 0x7d, 0x5a, 0xfc, 0x0c, 0x33, 0xc6, 0x83, 0xc9, 0x7d, - 0x09, 0x95, 0x88, 0x7b, 0x6c, 0x18, 0x78, 0xba, 0x28, 0x4d, 0x19, 0xbc, 0x7b, 0xff, 0xac, 0x7c, - 0xcc, 0x3d, 0xd6, 0x3b, 0x18, 0x94, 0x65, 0xb8, 0xe7, 0x15, 0xfb, 0x62, 0x2f, 0xf4, 0x05, 0x37, - 0xc1, 0x0a, 0x3c, 0xdd, 0x08, 0xd0, 0xa7, 0xad, 0xde, 0xc1, 0xc0, 0x0a, 0xbc, 0x76, 0x08, 0x64, - 0x7e, 0xf9, 0x49, 0x10, 0xf9, 0x93, 0xb9, 0x48, 0xf3, 0xbf, 0x88, 0xb4, 0x3e, 0x26, 0xb2, 0xfd, - 0x87, 0x09, 0x8d, 0x79, 0x9e, 0xb3, 0x2e, 0xee, 0x01, 0x88, 0x84, 0x46, 0x69, 0x20, 0x02, 0x1e, - 0xe9, 0x1b, 0xb7, 0x1e, 0xb9, 0x71, 0xc6, 0xc9, 0x27, 0x72, 0x7e, 0x0a, 0xbf, 0x84, 0xca, 0x48, - 0xb1, 0xb2, 0x8e, 0x17, 0x9e, 0x94, 0x65, 0x6b, 0xf9, 0x17, 0xa6, 0xe9, 0xc5, 0x9a, 0x95, 0x16, - 0x6a, 0xb6, 0x7d, 0x08, 0xb5, 0xd9, 0xbb, 0x8b, 0x6b, 0x50, 0x57, 0x9b, 0x63, 0x9e, 0x84, 0x74, - 0x42, 0x0c, 0x7c, 0x02, 0x6b, 0x0a, 0x98, 0xe7, 0x27, 0x26, 0xfe, 0x0f, 0xd6, 0x97, 0xc0, 0xb3, - 0x2e, 0xb1, 0xb6, 0xff, 0xb2, 0xa0, 0x5e, 0x78, 0x96, 0x10, 0xa0, 0xdc, 0x4f, 0xfd, 0xc3, 0x69, - 0x4c, 0x0c, 0xac, 0x43, 0xa5, 0x9f, 0xfa, 0x7b, 0x8c, 0x0a, 0x62, 0xea, 0xcd, 0x9b, 0x84, 0xc7, - 0xc4, 0xd2, 0xac, 0xdd, 0x38, 0x26, 0x25, 0x6c, 0x02, 0x64, 0xeb, 0x01, 0x4b, 0x63, 0x62, 0x6b, - 0xe2, 0x19, 0x17, 0x8c, 0xac, 0x48, 0x6d, 0x7a, 0xa3, 0xa2, 0x65, 0x1d, 0x95, 0x4f, 0x00, 0xa9, - 0x20, 0x81, 0x86, 0xbc, 0x8c, 0xd1, 0x44, 0x9c, 0xcb, 0x5b, 0xaa, 0xb8, 0x01, 0xa4, 0x88, 0xa8, - 0x43, 0x35, 0x44, 0x68, 0xf6, 0x53, 0xff, 0x6d, 0x94, 0x30, 0x3a, 0xba, 0xa0, 0xe7, 0x13, 0x46, - 0x00, 0xd7, 0x61, 0x55, 0x27, 0x92, 0x5f, 0xdc, 0x34, 0x25, 0x75, 0x4d, 0xdb, 0xbf, 0x60, 0xa3, - 0x1f, 0xbf, 0x9d, 0xf2, 0x64, 0x1a, 0x92, 0x86, 0xb4, 0xdd, 0x4f, 0x7d, 0xd5, 0xa0, 0x31, 0x4b, - 0x8e, 0x18, 0xf5, 0x58, 0x42, 0x56, 0xf5, 0xe9, 0xd3, 0x20, 0x64, 0x7c, 0x2a, 0x8e, 0xf9, 0x4f, - 0xa4, 0xa9, 0xc5, 0x0c, 0x18, 0xf5, 0xd4, 0xff, 0x8e, 0xac, 0x69, 0x31, 0x33, 0x44, 0x89, 0x21, - 0xda, 0xef, 0x9b, 0x84, 0x29, 0x8b, 0xeb, 0xfa, 0x56, 0xbd, 0x57, 0x1c, 0xdc, 0xfe, 0xd5, 0x84, - 0x8d, 0xc7, 0xc6, 0x03, 0xb7, 0xc0, 0x79, 0x0c, 0xdf, 0x9d, 0x0a, 0x4e, 0x0c, 0xfc, 0x04, 0xfe, - 0xff, 0x58, 0xf4, 0x6b, 0x1e, 0x44, 0xa2, 0x17, 0xc6, 0x93, 0x60, 0x14, 0xc8, 0x56, 0x7c, 0x8c, - 0xf6, 0xfa, 0x4a, 0xd3, 0xac, 0xed, 0x6b, 0x68, 0x2e, 0x7e, 0x14, 0xb2, 0x18, 0x73, 0x64, 0xd7, - 0xf3, 0xe4, 0xf8, 0x13, 0x03, 0x9d, 0xa2, 0xd8, 0x01, 0x0b, 0xf9, 0x25, 0x53, 0x11, 0x73, 0x31, - 0xf2, 0x36, 0xf6, 0xa8, 0xc8, 0x22, 0xd6, 0xa2, 0x91, 0x5d, 0xcf, 0x3b, 0xca, 0xde, 0x1e, 0x15, - 0x2d, 0xed, 0xbd, 0xb8, 0xf9, 0xe0, 0x1a, 0xb7, 0x1f, 0x5c, 0xe3, 0xe6, 0xce, 0x35, 0x6f, 0xef, - 0x5c, 0xf3, 0x9f, 0x3b, 0xd7, 0xfc, 0xed, 0xde, 0x35, 0x7e, 0xbf, 0x77, 0x8d, 0xdb, 0x7b, 0xd7, - 0xf8, 0xfb, 0xde, 0x35, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xee, 0xe3, 0x39, 0x8b, 0xbb, 0x08, - 0x00, 0x00, + // 1102 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0xcb, 0x6e, 0x23, 0x45, + 0x14, 0xed, 0x6e, 0x77, 0xfc, 0xb8, 0x76, 0x9c, 0x4a, 0xc5, 0x33, 0xd3, 0x8a, 0x22, 0x8f, 0xf1, + 0x0c, 0x1a, 0x2b, 0x68, 0x02, 0x32, 0x12, 0x42, 0xec, 0xf2, 0x18, 0x94, 0xa0, 0x38, 0x0c, 0x4e, + 0x26, 0x0b, 0x24, 0x14, 0x55, 0xdc, 0x95, 0x4e, 0x83, 0x5d, 0xd5, 0xaa, 0x2e, 0x87, 0x64, 0x83, + 0x10, 0x5f, 0xc0, 0x92, 0x0d, 0x5b, 0x3e, 0x80, 0x8f, 0x40, 0x59, 0x66, 0xc9, 0x6a, 0xc4, 0x24, + 0x7f, 0xc0, 0x17, 0xa0, 0xaa, 0xae, 0x7e, 0xd8, 0x89, 0x66, 0xc1, 0xae, 0xea, 0xdc, 0x53, 0xf7, + 0x9e, 0x7b, 0x6e, 0x57, 0x35, 0x80, 0x20, 0x67, 0x72, 0x23, 0x12, 0x5c, 0x72, 0x5c, 0x56, 0xeb, + 0xe8, 0x74, 0xb5, 0x15, 0xf0, 0x80, 0x6b, 0xe8, 0x63, 0xb5, 0x4a, 0xa2, 0xdd, 0x9f, 0x60, 0xe1, + 0x15, 0x93, 0xe2, 0x0a, 0x7b, 0xe0, 0x1e, 0x51, 0x31, 0xf1, 0x9c, 0x8e, 0xdd, 0x73, 0xb7, 0xdc, + 0xeb, 0xb7, 0x4f, 0xad, 0xa1, 0x46, 0xf0, 0x2a, 0x2c, 0xec, 0x31, 0x9f, 0x5e, 0x7a, 0xa5, 0x42, + 0x28, 0x81, 0xf0, 0x47, 0xe0, 0x1e, 0x5d, 0x45, 0xd4, 0xb3, 0x3b, 0x76, 0xaf, 0xd9, 0x5f, 0xde, + 0x48, 0x6a, 0x6d, 0xe8, 0x94, 0x2a, 0x90, 0x25, 0xba, 0x8a, 0x28, 0xc6, 0xe0, 0xee, 0x10, 0x49, + 0x3c, 0xb7, 0x63, 0xf7, 0x1a, 0x43, 0xbd, 0xee, 0xfe, 0x6c, 0x03, 0x3a, 0x64, 0x24, 0x8a, 0xcf, + 0xb9, 0x1c, 0x50, 0x49, 0x7c, 0x22, 0x09, 0xfe, 0x0c, 0x60, 0xc4, 0xd9, 0xd9, 0x49, 0x2c, 0x89, + 0x4c, 0x72, 0xd7, 0xf3, 0xdc, 0xdb, 0x9c, 0x9d, 0x1d, 0xaa, 0x80, 0xc9, 0x5d, 0x1b, 0xa5, 0x80, + 0x52, 0x1a, 0x6a, 0xa5, 0xc5, 0x26, 0x12, 0x48, 0xf5, 0x27, 0x55, 0x7f, 0xc5, 0x26, 0x34, 0xd2, + 0xfd, 0x16, 0xaa, 0xa9, 0x02, 0x25, 0x51, 0x29, 0xd0, 0x35, 0x1b, 0x43, 0xbd, 0xc6, 0x5f, 0x40, + 0x75, 0x62, 0x94, 0xe9, 0xc4, 0xf5, 0xbe, 0x97, 0x6a, 0x99, 0x57, 0x6e, 0xf2, 0x66, 0xfc, 0xee, + 0xbf, 0x25, 0xa8, 0x0c, 0x68, 0x1c, 0x93, 0x80, 0xe2, 0x97, 0xe0, 0xca, 0xdc, 0xab, 0x95, 0x34, + 0x87, 0x09, 0x17, 0xdd, 0x52, 0x34, 0xdc, 0x02, 0x47, 0xf2, 0x99, 0x4e, 0x1c, 0xc9, 0x55, 0x1b, + 0x67, 0x82, 0xcf, 0xb5, 0xa1, 0x90, 0xac, 0x41, 0x77, 0xbe, 0x41, 0xdc, 0x86, 0xca, 0x98, 0x07, + 0x7a, 0xba, 0x0b, 0x85, 0x60, 0x0a, 0xe6, 0xb6, 0x95, 0xef, 0xdb, 0xf6, 0x12, 0x2a, 0x94, 0x49, + 0x11, 0xd2, 0xd8, 0xab, 0x74, 0x4a, 0xbd, 0x7a, 0x7f, 0x71, 0x66, 0xc6, 0x69, 0x2a, 0xc3, 0xc1, + 0x6b, 0x50, 0x1e, 0xf1, 0xc9, 0x24, 0x94, 0x5e, 0xb5, 0x90, 0xcb, 0x60, 0x4a, 0xe2, 0x05, 0x97, + 0xd4, 0x5b, 0x2c, 0x4a, 0x54, 0x08, 0xee, 0x43, 0x35, 0x36, 0x5e, 0x7a, 0x35, 0xed, 0x31, 0x9a, + 0xf7, 0x58, 0xf3, 0xed, 0x61, 0xc6, 0x53, 0xb5, 0x04, 0xfd, 0x9e, 0x8e, 0xa4, 0x07, 0x1d, 0xbb, + 0x57, 0x4d, 0x6b, 0x25, 0x18, 0x7e, 0x0e, 0x90, 0xac, 0x76, 0x43, 0x26, 0xbd, 0x7a, 0xa1, 0x62, + 0x01, 0x57, 0xd6, 0x8c, 0x38, 0x93, 0xf4, 0x52, 0x7a, 0x0d, 0x35, 0x72, 0x53, 0x24, 0x05, 0xf1, + 0xa7, 0x50, 0x13, 0x34, 0x8e, 0x38, 0x8b, 0x69, 0xec, 0x35, 0xb5, 0x01, 0x4b, 0x73, 0x83, 0x4b, + 0x3f, 0xc3, 0x8c, 0xd7, 0xfd, 0x0e, 0x6a, 0xbb, 0x44, 0xf8, 0xc9, 0x37, 0x99, 0x8e, 0xc5, 0xbe, + 0x37, 0x96, 0xd4, 0x0d, 0xe7, 0x9e, 0x1b, 0xb9, 0x8b, 0xa5, 0xfb, 0x2e, 0x76, 0xff, 0xb4, 0xa1, + 0x96, 0x5d, 0x02, 0xfc, 0x18, 0xca, 0xea, 0x8c, 0x88, 0x3d, 0xbb, 0x53, 0xea, 0xb9, 0x43, 0xb3, + 0xc3, 0xab, 0x50, 0x1d, 0x53, 0x22, 0x98, 0x8a, 0x38, 0x3a, 0x92, 0xed, 0xf1, 0x0b, 0x58, 0x4a, + 0x58, 0x27, 0x7c, 0x2a, 0x03, 0x1e, 0xb2, 0xc0, 0x2b, 0x69, 0x4a, 0x33, 0x81, 0xbf, 0x36, 0x28, + 0x7e, 0x06, 0x8b, 0xe9, 0xa1, 0x13, 0xa6, 0x4c, 0x72, 0x35, 0xad, 0x91, 0x82, 0x07, 0xca, 0xa3, + 0x67, 0x00, 0x64, 0x2a, 0xf9, 0xc9, 0x98, 0x92, 0x0b, 0xaa, 0xbf, 0xb0, 0x74, 0x16, 0x35, 0x85, + 0xef, 0x2b, 0xb8, 0xfb, 0xbb, 0x0d, 0xa0, 0x44, 0x6f, 0x9f, 0x13, 0x16, 0x50, 0xfc, 0x89, 0xb9, + 0x0b, 0x8e, 0xbe, 0x0b, 0x8f, 0x8b, 0x77, 0x3b, 0x61, 0xdc, 0xbb, 0x0e, 0x2f, 0xa0, 0xc2, 0xb8, + 0x4f, 0x4f, 0x42, 0xdf, 0x98, 0xd2, 0x54, 0xc1, 0xdb, 0xb7, 0x4f, 0xcb, 0x07, 0xdc, 0xa7, 0x7b, + 0x3b, 0xc3, 0xb2, 0x0a, 0xef, 0xf9, 0xd8, 0xcb, 0x47, 0x9a, 0x3c, 0x34, 0xd9, 0x30, 0x57, 0xc1, + 0x09, 0x7d, 0x33, 0x08, 0x30, 0xa7, 0x9d, 0xbd, 0x9d, 0xa1, 0x13, 0xfa, 0xdd, 0x09, 0xa0, 0xbc, + 0xf8, 0x61, 0xc8, 0x82, 0x71, 0x2e, 0xd2, 0xfe, 0x3f, 0x22, 0x9d, 0xf7, 0x89, 0xec, 0xfe, 0x61, + 0x43, 0x23, 0xcf, 0x73, 0xdc, 0xc7, 0x5b, 0x00, 0x52, 0x10, 0x16, 0x87, 0x32, 0xe4, 0xcc, 0x54, + 0x5c, 0x7b, 0xa0, 0x62, 0xc6, 0x49, 0x3f, 0xe6, 0xfc, 0x14, 0xfe, 0x1c, 0x2a, 0x23, 0xcd, 0x4a, + 0x26, 0x5e, 0x78, 0xa7, 0xe6, 0x5b, 0x4b, 0xaf, 0xad, 0xa1, 0x17, 0x3d, 0x2b, 0xcd, 0x78, 0xb6, + 0xbe, 0x0b, 0xb5, 0xec, 0x31, 0xc7, 0x4b, 0x50, 0xd7, 0x9b, 0x03, 0x2e, 0x26, 0x64, 0x8c, 0x2c, + 0xbc, 0x02, 0x4b, 0x1a, 0xc8, 0xf3, 0x23, 0x1b, 0x3f, 0x82, 0xe5, 0x39, 0xf0, 0xb8, 0x8f, 0x9c, + 0xf5, 0xbf, 0x4a, 0x50, 0x2f, 0xbc, 0x75, 0x18, 0xa0, 0x3c, 0x88, 0x83, 0xdd, 0x69, 0x84, 0x2c, + 0x5c, 0x87, 0xca, 0x20, 0x0e, 0xb6, 0x28, 0x91, 0xc8, 0x36, 0x9b, 0xd7, 0x82, 0x47, 0xc8, 0x31, + 0xac, 0xcd, 0x28, 0x42, 0x25, 0xdc, 0x04, 0x48, 0xd6, 0x43, 0x1a, 0x47, 0xc8, 0x35, 0xc4, 0x63, + 0x2e, 0x29, 0x5a, 0x50, 0xda, 0xcc, 0x46, 0x47, 0xcb, 0x26, 0xaa, 0x5e, 0x0f, 0x54, 0xc1, 0x08, + 0x1a, 0xaa, 0x18, 0x25, 0x42, 0x9e, 0xaa, 0x2a, 0x55, 0xdc, 0x02, 0x54, 0x44, 0xf4, 0xa1, 0x1a, + 0xc6, 0xd0, 0x1c, 0xc4, 0xc1, 0x1b, 0x26, 0x28, 0x19, 0x9d, 0x93, 0xd3, 0x31, 0x45, 0x80, 0x97, + 0x61, 0xd1, 0x24, 0x52, 0x37, 0x6e, 0x1a, 0xa3, 0xba, 0xa1, 0x6d, 0x9f, 0xd3, 0xd1, 0x0f, 0xdf, + 0x4c, 0xb9, 0x98, 0x4e, 0x50, 0x43, 0xb5, 0x3d, 0x88, 0x03, 0x3d, 0xa0, 0x33, 0x2a, 0xf6, 0x29, + 0xf1, 0xa9, 0x40, 0x8b, 0xe6, 0xf4, 0x51, 0x38, 0xa1, 0x7c, 0x2a, 0x0f, 0xf8, 0x8f, 0xa8, 0x69, + 0xc4, 0x0c, 0x29, 0xf1, 0xf5, 0x4f, 0x14, 0x2d, 0x19, 0x31, 0x19, 0xa2, 0xc5, 0x20, 0xd3, 0xef, + 0x6b, 0x41, 0x75, 0x8b, 0xcb, 0xa6, 0xaa, 0xd9, 0x6b, 0x0e, 0x36, 0x27, 0x0f, 0x25, 0x17, 0x24, + 0xa0, 0x9b, 0x51, 0x44, 0x99, 0x8f, 0x56, 0xb0, 0x07, 0xad, 0x79, 0x54, 0xf3, 0x5b, 0x6a, 0x62, + 0x33, 0x91, 0xf1, 0x15, 0x7a, 0x84, 0x9f, 0xc0, 0xca, 0x1c, 0xa8, 0xd9, 0x8f, 0x0d, 0xfb, 0x4b, + 0x2e, 0x02, 0x2a, 0x4d, 0x47, 0x4f, 0xd6, 0x7f, 0xb1, 0xa1, 0xf5, 0xd0, 0x17, 0x89, 0xd7, 0xc0, + 0x7b, 0x08, 0xdf, 0x9c, 0x4a, 0x8e, 0x2c, 0xfc, 0x21, 0x7c, 0xf0, 0x50, 0xf4, 0x2b, 0x1e, 0x32, + 0xb9, 0x37, 0x89, 0xc6, 0xe1, 0x28, 0x54, 0xd3, 0x7f, 0x1f, 0xed, 0xd5, 0xa5, 0xa1, 0x39, 0xeb, + 0x57, 0xd0, 0x9c, 0xbd, 0x87, 0xca, 0xff, 0x1c, 0xd9, 0xf4, 0x7d, 0x75, 0xe3, 0x90, 0xa5, 0xac, + 0xc8, 0xe1, 0x21, 0x9d, 0xf0, 0x0b, 0xaa, 0x23, 0xf6, 0x6c, 0xe4, 0x4d, 0xe4, 0x13, 0x99, 0x44, + 0x9c, 0xd9, 0x46, 0x36, 0x7d, 0x7f, 0x3f, 0x79, 0xee, 0x74, 0xb4, 0xb4, 0xf5, 0xfc, 0xfa, 0x5d, + 0xdb, 0xba, 0x79, 0xd7, 0xb6, 0xae, 0x6f, 0xdb, 0xf6, 0xcd, 0x6d, 0xdb, 0xfe, 0xe7, 0xb6, 0x6d, + 0xff, 0x7a, 0xd7, 0xb6, 0x7e, 0xbb, 0x6b, 0x5b, 0x37, 0x77, 0x6d, 0xeb, 0xef, 0xbb, 0xb6, 0xf5, + 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x67, 0x2b, 0x47, 0x0c, 0x83, 0x09, 0x00, 0x00, } func (m *Entry) Marshal() (dAtA []byte, err error) { @@ -901,6 +939,23 @@ func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Responses) > 0 { + for iNdEx := len(m.Responses) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Responses[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintRaft(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + } + } + i = encodeVarintRaft(dAtA, i, uint64(m.Vote)) + i-- + dAtA[i] = 0x68 if m.Context != nil { i -= len(m.Context) copy(dAtA[i:], m.Context) @@ -919,16 +974,18 @@ func (m *Message) MarshalToSizedBuffer(dAtA []byte) (int, error) { } i-- dAtA[i] = 0x50 - { - size, err := m.Snapshot.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if m.Snapshot != nil { + { + size, err := m.Snapshot.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintRaft(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintRaft(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x4a } - i-- - dAtA[i] = 0x4a i = encodeVarintRaft(dAtA, i, uint64(m.Commit)) i-- dAtA[i] = 0x40 @@ -1247,14 +1304,23 @@ func (m *Message) Size() (n int) { } } n += 1 + sovRaft(uint64(m.Commit)) - l = m.Snapshot.Size() - n += 1 + l + sovRaft(uint64(l)) + if m.Snapshot != nil { + l = m.Snapshot.Size() + n += 1 + l + sovRaft(uint64(l)) + } n += 2 n += 1 + sovRaft(uint64(m.RejectHint)) if m.Context != nil { l = len(m.Context) n += 1 + l + sovRaft(uint64(l)) } + n += 1 + sovRaft(uint64(m.Vote)) + if len(m.Responses) > 0 { + for _, e := range m.Responses { + l = e.Size() + n += 1 + l + sovRaft(uint64(l)) + } + } return n } @@ -1957,6 +2023,9 @@ func (m *Message) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + if m.Snapshot == nil { + m.Snapshot = &Snapshot{} + } if err := m.Snapshot.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } @@ -2034,6 +2103,59 @@ func (m *Message) Unmarshal(dAtA []byte) error { m.Context = []byte{} } iNdEx = postIndex + case 13: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Vote", wireType) + } + m.Vote = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaft + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Vote |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Responses", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowRaft + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthRaft + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthRaft + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Responses = append(m.Responses, Message{}) + if err := m.Responses[len(m.Responses)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipRaft(dAtA[iNdEx:]) diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.proto b/etcd/vendor/go.etcd.io/raft/v3/raftpb/raft.proto similarity index 73% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.proto rename to etcd/vendor/go.etcd.io/raft/v3/raftpb/raft.proto index f46a54c948..a8598ee5c9 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/raftpb/raft.proto +++ b/etcd/vendor/go.etcd.io/raft/v3/raftpb/raft.proto @@ -37,27 +37,35 @@ message Snapshot { } // For description of different message types, see: -// https://pkg.go.dev/go.etcd.io/etcd/raft/v3#hdr-MessageType +// https://pkg.go.dev/go.etcd.io/raft/v3#hdr-MessageType enum MessageType { - MsgHup = 0; - MsgBeat = 1; - MsgProp = 2; - MsgApp = 3; - MsgAppResp = 4; - MsgVote = 5; - MsgVoteResp = 6; - MsgSnap = 7; - MsgHeartbeat = 8; - MsgHeartbeatResp = 9; - MsgUnreachable = 10; - MsgSnapStatus = 11; - MsgCheckQuorum = 12; - MsgTransferLeader = 13; - MsgTimeoutNow = 14; - MsgReadIndex = 15; - MsgReadIndexResp = 16; - MsgPreVote = 17; - MsgPreVoteResp = 18; + MsgHup = 0; + MsgBeat = 1; + MsgProp = 2; + MsgApp = 3; + MsgAppResp = 4; + MsgVote = 5; + MsgVoteResp = 6; + MsgSnap = 7; + MsgHeartbeat = 8; + MsgHeartbeatResp = 9; + MsgUnreachable = 10; + MsgSnapStatus = 11; + MsgCheckQuorum = 12; + MsgTransferLeader = 13; + MsgTimeoutNow = 14; + MsgReadIndex = 15; + MsgReadIndexResp = 16; + MsgPreVote = 17; + MsgPreVoteResp = 18; + MsgStorageAppend = 19; + MsgStorageAppendResp = 20; + MsgStorageApply = 21; + MsgStorageApplyResp = 22; + MsgForgetLeader = 23; + // NOTE: when adding new message types, remember to update the isLocalMsg and + // isResponseMsg arrays in raft/util.go and update the corresponding tests in + // raft/util_test.go. } message Message { @@ -66,18 +74,37 @@ message Message { optional uint64 from = 3 [(gogoproto.nullable) = false]; optional uint64 term = 4 [(gogoproto.nullable) = false]; // logTerm is generally used for appending Raft logs to followers. For example, - // (type=MsgApp,index=100,logTerm=5) means leader appends entries starting at - // index=101, and the term of entry at index 100 is 5. + // (type=MsgApp,index=100,logTerm=5) means the leader appends entries starting + // at index=101, and the term of the entry at index 100 is 5. // (type=MsgAppResp,reject=true,index=100,logTerm=5) means follower rejects some // entries from its leader as it already has an entry with term 5 at index 100. + // (type=MsgStorageAppendResp,index=100,logTerm=5) means the local node wrote + // entries up to index=100 in stable storage, and the term of the entry at index + // 100 was 5. This doesn't always mean that the corresponding MsgStorageAppend + // message was the one that carried these entries, just that those entries were + // stable at the time of processing the corresponding MsgStorageAppend. optional uint64 logTerm = 5 [(gogoproto.nullable) = false]; optional uint64 index = 6 [(gogoproto.nullable) = false]; repeated Entry entries = 7 [(gogoproto.nullable) = false]; optional uint64 commit = 8 [(gogoproto.nullable) = false]; - optional Snapshot snapshot = 9 [(gogoproto.nullable) = false]; + // (type=MsgStorageAppend,vote=5,term=10) means the local node is voting for + // peer 5 in term 10. For MsgStorageAppends, the term, vote, and commit fields + // will either all be set (to facilitate the construction of a HardState) if + // any of the fields have changed or will all be unset if none of the fields + // have changed. + optional uint64 vote = 13 [(gogoproto.nullable) = false]; + // snapshot is non-nil and non-empty for MsgSnap messages and nil for all other + // message types. However, peer nodes running older binary versions may send a + // non-nil, empty value for the snapshot field of non-MsgSnap messages. Code + // should be prepared to handle such messages. + optional Snapshot snapshot = 9 [(gogoproto.nullable) = true]; optional bool reject = 10 [(gogoproto.nullable) = false]; optional uint64 rejectHint = 11 [(gogoproto.nullable) = false]; - optional bytes context = 12; + optional bytes context = 12 [(gogoproto.nullable) = true]; + // responses are populated by a raft node to instruct storage threads on how + // to respond and who to respond to when the work associated with a message + // is complete. Populated for MsgStorageAppend and MsgStorageApply messages. + repeated Message responses = 14 [(gogoproto.nullable) = false]; } message HardState { @@ -132,13 +159,13 @@ enum ConfChangeType { message ConfChange { optional ConfChangeType type = 2 [(gogoproto.nullable) = false]; - optional uint64 node_id = 3 [(gogoproto.nullable) = false, (gogoproto.customname) = "NodeID" ]; + optional uint64 node_id = 3 [(gogoproto.nullable) = false, (gogoproto.customname) = "NodeID"]; optional bytes context = 4; // NB: this is used only by etcd to thread through a unique identifier. // Ideally it should really use the Context instead. No counterpart to // this field exists in ConfChangeV2. - optional uint64 id = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ID" ]; + optional uint64 id = 1 [(gogoproto.nullable) = false, (gogoproto.customname) = "ID"]; } // ConfChangeSingle is an individual configuration change operation. Multiple diff --git a/etcd/vendor/go.etcd.io/raft/v3/rawnode.go b/etcd/vendor/go.etcd.io/raft/v3/rawnode.go new file mode 100644 index 0000000000..a4da2ae2e2 --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/rawnode.go @@ -0,0 +1,562 @@ +// Copyright 2015 The etcd 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 raft + +import ( + "errors" + + pb "go.etcd.io/raft/v3/raftpb" + "go.etcd.io/raft/v3/tracker" +) + +// ErrStepLocalMsg is returned when try to step a local raft message +var ErrStepLocalMsg = errors.New("raft: cannot step raft local message") + +// ErrStepPeerNotFound is returned when try to step a response message +// but there is no peer found in raft.trk for that node. +var ErrStepPeerNotFound = errors.New("raft: cannot step as peer not found") + +// RawNode is a thread-unsafe Node. +// The methods of this struct correspond to the methods of Node and are described +// more fully there. +type RawNode struct { + raft *raft + asyncStorageWrites bool + + // Mutable fields. + prevSoftSt *SoftState + prevHardSt pb.HardState + stepsOnAdvance []pb.Message +} + +// NewRawNode instantiates a RawNode from the given configuration. +// +// See Bootstrap() for bootstrapping an initial state; this replaces the former +// 'peers' argument to this method (with identical behavior). However, It is +// recommended that instead of calling Bootstrap, applications bootstrap their +// state manually by setting up a Storage that has a first index > 1 and which +// stores the desired ConfState as its InitialState. +func NewRawNode(config *Config) (*RawNode, error) { + r := newRaft(config) + rn := &RawNode{ + raft: r, + } + rn.asyncStorageWrites = config.AsyncStorageWrites + ss := r.softState() + rn.prevSoftSt = &ss + rn.prevHardSt = r.hardState() + return rn, nil +} + +// Tick advances the internal logical clock by a single tick. +func (rn *RawNode) Tick() { + rn.raft.tick() +} + +// TickQuiesced advances the internal logical clock by a single tick without +// performing any other state machine processing. It allows the caller to avoid +// periodic heartbeats and elections when all of the peers in a Raft group are +// known to be at the same state. Expected usage is to periodically invoke Tick +// or TickQuiesced depending on whether the group is "active" or "quiesced". +// +// WARNING: Be very careful about using this method as it subverts the Raft +// state machine. You should probably be using Tick instead. +// +// DEPRECATED: This method will be removed in a future release. +func (rn *RawNode) TickQuiesced() { + rn.raft.electionElapsed++ +} + +// Campaign causes this RawNode to transition to candidate state. +func (rn *RawNode) Campaign() error { + return rn.raft.Step(pb.Message{ + Type: pb.MsgHup, + }) +} + +// Propose proposes data be appended to the raft log. +func (rn *RawNode) Propose(data []byte) error { + return rn.raft.Step(pb.Message{ + Type: pb.MsgProp, + From: rn.raft.id, + Entries: []pb.Entry{ + {Data: data}, + }}) +} + +// ProposeConfChange proposes a config change. See (Node).ProposeConfChange for +// details. +func (rn *RawNode) ProposeConfChange(cc pb.ConfChangeI) error { + m, err := confChangeToMsg(cc) + if err != nil { + return err + } + return rn.raft.Step(m) +} + +// ApplyConfChange applies a config change to the local node. The app must call +// this when it applies a configuration change, except when it decides to reject +// the configuration change, in which case no call must take place. +func (rn *RawNode) ApplyConfChange(cc pb.ConfChangeI) *pb.ConfState { + cs := rn.raft.applyConfChange(cc.AsV2()) + return &cs +} + +// Step advances the state machine using the given message. +func (rn *RawNode) Step(m pb.Message) error { + // Ignore unexpected local messages receiving over network. + if IsLocalMsg(m.Type) && !IsLocalMsgTarget(m.From) { + return ErrStepLocalMsg + } + if IsResponseMsg(m.Type) && !IsLocalMsgTarget(m.From) && rn.raft.trk.Progress[m.From] == nil { + return ErrStepPeerNotFound + } + return rn.raft.Step(m) +} + +// Ready returns the outstanding work that the application needs to handle. This +// includes appending and applying entries or a snapshot, updating the HardState, +// and sending messages. The returned Ready() *must* be handled and subsequently +// passed back via Advance(). +func (rn *RawNode) Ready() Ready { + rd := rn.readyWithoutAccept() + rn.acceptReady(rd) + return rd +} + +// readyWithoutAccept returns a Ready. This is a read-only operation, i.e. there +// is no obligation that the Ready must be handled. +func (rn *RawNode) readyWithoutAccept() Ready { + r := rn.raft + + rd := Ready{ + Entries: r.raftLog.nextUnstableEnts(), + CommittedEntries: r.raftLog.nextCommittedEnts(rn.applyUnstableEntries()), + Messages: r.msgs, + } + if softSt := r.softState(); !softSt.equal(rn.prevSoftSt) { + // Allocate only when SoftState changes. + escapingSoftSt := softSt + rd.SoftState = &escapingSoftSt + } + if hardSt := r.hardState(); !isHardStateEqual(hardSt, rn.prevHardSt) { + rd.HardState = hardSt + } + if r.raftLog.hasNextUnstableSnapshot() { + rd.Snapshot = *r.raftLog.nextUnstableSnapshot() + } + if len(r.readStates) != 0 { + rd.ReadStates = r.readStates + } + rd.MustSync = MustSync(r.hardState(), rn.prevHardSt, len(rd.Entries)) + + if rn.asyncStorageWrites { + // If async storage writes are enabled, enqueue messages to + // local storage threads, where applicable. + if needStorageAppendMsg(r, rd) { + m := newStorageAppendMsg(r, rd) + rd.Messages = append(rd.Messages, m) + } + if needStorageApplyMsg(rd) { + m := newStorageApplyMsg(r, rd) + rd.Messages = append(rd.Messages, m) + } + } else { + // If async storage writes are disabled, immediately enqueue + // msgsAfterAppend to be sent out. The Ready struct contract + // mandates that Messages cannot be sent until after Entries + // are written to stable storage. + for _, m := range r.msgsAfterAppend { + if m.To != r.id { + rd.Messages = append(rd.Messages, m) + } + } + } + + return rd +} + +// MustSync returns true if the hard state and count of Raft entries indicate +// that a synchronous write to persistent storage is required. +func MustSync(st, prevst pb.HardState, entsnum int) bool { + // Persistent state on all servers: + // (Updated on stable storage before responding to RPCs) + // currentTerm + // votedFor + // log entries[] + return entsnum != 0 || st.Vote != prevst.Vote || st.Term != prevst.Term +} + +func needStorageAppendMsg(r *raft, rd Ready) bool { + // Return true if log entries, hard state, or a snapshot need to be written + // to stable storage. Also return true if any messages are contingent on all + // prior MsgStorageAppend being processed. + return len(rd.Entries) > 0 || + !IsEmptyHardState(rd.HardState) || + !IsEmptySnap(rd.Snapshot) || + len(r.msgsAfterAppend) > 0 +} + +func needStorageAppendRespMsg(r *raft, rd Ready) bool { + // Return true if raft needs to hear about stabilized entries or an applied + // snapshot. See the comment in newStorageAppendRespMsg, which explains why + // we check hasNextOrInProgressUnstableEnts instead of len(rd.Entries) > 0. + return r.raftLog.hasNextOrInProgressUnstableEnts() || + !IsEmptySnap(rd.Snapshot) +} + +// newStorageAppendMsg creates the message that should be sent to the local +// append thread to instruct it to append log entries, write an updated hard +// state, and apply a snapshot. The message also carries a set of responses +// that should be delivered after the rest of the message is processed. Used +// with AsyncStorageWrites. +func newStorageAppendMsg(r *raft, rd Ready) pb.Message { + m := pb.Message{ + Type: pb.MsgStorageAppend, + To: LocalAppendThread, + From: r.id, + Entries: rd.Entries, + } + if !IsEmptyHardState(rd.HardState) { + // If the Ready includes a HardState update, assign each of its fields + // to the corresponding fields in the Message. This allows clients to + // reconstruct the HardState and save it to stable storage. + // + // If the Ready does not include a HardState update, make sure to not + // assign a value to any of the fields so that a HardState reconstructed + // from them will be empty (return true from raft.IsEmptyHardState). + m.Term = rd.Term + m.Vote = rd.Vote + m.Commit = rd.Commit + } + if !IsEmptySnap(rd.Snapshot) { + snap := rd.Snapshot + m.Snapshot = &snap + } + // Attach all messages in msgsAfterAppend as responses to be delivered after + // the message is processed, along with a self-directed MsgStorageAppendResp + // to acknowledge the entry stability. + // + // NB: it is important for performance that MsgStorageAppendResp message be + // handled after self-directed MsgAppResp messages on the leader (which will + // be contained in msgsAfterAppend). This ordering allows the MsgAppResp + // handling to use a fast-path in r.raftLog.term() before the newly appended + // entries are removed from the unstable log. + m.Responses = r.msgsAfterAppend + if needStorageAppendRespMsg(r, rd) { + m.Responses = append(m.Responses, newStorageAppendRespMsg(r, rd)) + } + return m +} + +// newStorageAppendRespMsg creates the message that should be returned to node +// after the unstable log entries, hard state, and snapshot in the current Ready +// (along with those in all prior Ready structs) have been saved to stable +// storage. +func newStorageAppendRespMsg(r *raft, rd Ready) pb.Message { + m := pb.Message{ + Type: pb.MsgStorageAppendResp, + To: r.id, + From: LocalAppendThread, + // Dropped after term change, see below. + Term: r.Term, + } + if r.raftLog.hasNextOrInProgressUnstableEnts() { + // If the raft log has unstable entries, attach the last index and term of the + // append to the response message. This (index, term) tuple will be handed back + // and consulted when the stability of those log entries is signaled to the + // unstable. If the (index, term) match the unstable log by the time the + // response is received (unstable.stableTo), the unstable log can be truncated. + // + // However, with just this logic, there would be an ABA problem[^1] that could + // lead to the unstable log and the stable log getting out of sync temporarily + // and leading to an inconsistent view. Consider the following example with 5 + // nodes, A B C D E: + // + // 1. A is the leader. + // 2. A proposes some log entries but only B receives these entries. + // 3. B gets the Ready and the entries are appended asynchronously. + // 4. A crashes and C becomes leader after getting a vote from D and E. + // 5. C proposes some log entries and B receives these entries, overwriting the + // previous unstable log entries that are in the process of being appended. + // The entries have a larger term than the previous entries but the same + // indexes. It begins appending these new entries asynchronously. + // 6. C crashes and A restarts and becomes leader again after getting the vote + // from D and E. + // 7. B receives the entries from A which are the same as the ones from step 2, + // overwriting the previous unstable log entries that are in the process of + // being appended from step 5. The entries have the original terms and + // indexes from step 2. Recall that log entries retain their original term + // numbers when a leader replicates entries from previous terms. It begins + // appending these new entries asynchronously. + // 8. The asynchronous log appends from the first Ready complete and stableTo + // is called. + // 9. However, the log entries from the second Ready are still in the + // asynchronous append pipeline and will overwrite (in stable storage) the + // entries from the first Ready at some future point. We can't truncate the + // unstable log yet or a future read from Storage might see the entries from + // step 5 before they have been replaced by the entries from step 7. + // Instead, we must wait until we are sure that the entries are stable and + // that no in-progress appends might overwrite them before removing entries + // from the unstable log. + // + // To prevent these kinds of problems, we also attach the current term to the + // MsgStorageAppendResp (above). If the term has changed by the time the + // MsgStorageAppendResp if returned, the response is ignored and the unstable + // log is not truncated. The unstable log is only truncated when the term has + // remained unchanged from the time that the MsgStorageAppend was sent to the + // time that the MsgStorageAppendResp is received, indicating that no-one else + // is in the process of truncating the stable log. + // + // However, this replaces a correctness problem with a liveness problem. If we + // only attempted to truncate the unstable log when appending new entries but + // also occasionally dropped these responses, then quiescence of new log entries + // could lead to the unstable log never being truncated. + // + // To combat this, we attempt to truncate the log on all MsgStorageAppendResp + // messages where the unstable log is not empty, not just those associated with + // entry appends. This includes MsgStorageAppendResp messages associated with an + // updated HardState, which occur after a term change. + // + // In other words, we set Index and LogTerm in a block that looks like: + // + // if r.raftLog.hasNextOrInProgressUnstableEnts() { ... } + // + // not like: + // + // if len(rd.Entries) > 0 { ... } + // + // To do so, we attach r.raftLog.lastIndex() and r.raftLog.lastTerm(), not the + // (index, term) of the last entry in rd.Entries. If rd.Entries is not empty, + // these will be the same. However, if rd.Entries is empty, we still want to + // attest that this (index, term) is correct at the current term, in case the + // MsgStorageAppend that contained the last entry in the unstable slice carried + // an earlier term and was dropped. + // + // A MsgStorageAppend with a new term is emitted on each term change. This is + // the same condition that causes MsgStorageAppendResp messages with earlier + // terms to be ignored. As a result, we are guaranteed that, assuming a bounded + // number of term changes, there will eventually be a MsgStorageAppendResp + // message that is not ignored. This means that entries in the unstable log + // which have been appended to stable storage will eventually be truncated and + // dropped from memory. + // + // [^1]: https://en.wikipedia.org/wiki/ABA_problem + last := r.raftLog.lastEntryID() + m.Index = last.index + m.LogTerm = last.term + } + if !IsEmptySnap(rd.Snapshot) { + snap := rd.Snapshot + m.Snapshot = &snap + } + return m +} + +func needStorageApplyMsg(rd Ready) bool { return len(rd.CommittedEntries) > 0 } +func needStorageApplyRespMsg(rd Ready) bool { return needStorageApplyMsg(rd) } + +// newStorageApplyMsg creates the message that should be sent to the local +// apply thread to instruct it to apply committed log entries. The message +// also carries a response that should be delivered after the rest of the +// message is processed. Used with AsyncStorageWrites. +func newStorageApplyMsg(r *raft, rd Ready) pb.Message { + ents := rd.CommittedEntries + return pb.Message{ + Type: pb.MsgStorageApply, + To: LocalApplyThread, + From: r.id, + Term: 0, // committed entries don't apply under a specific term + Entries: ents, + Responses: []pb.Message{ + newStorageApplyRespMsg(r, ents), + }, + } +} + +// newStorageApplyRespMsg creates the message that should be returned to node +// after the committed entries in the current Ready (along with those in all +// prior Ready structs) have been applied to the local state machine. +func newStorageApplyRespMsg(r *raft, ents []pb.Entry) pb.Message { + return pb.Message{ + Type: pb.MsgStorageApplyResp, + To: r.id, + From: LocalApplyThread, + Term: 0, // committed entries don't apply under a specific term + Entries: ents, + } +} + +// acceptReady is called when the consumer of the RawNode has decided to go +// ahead and handle a Ready. Nothing must alter the state of the RawNode between +// this call and the prior call to Ready(). +func (rn *RawNode) acceptReady(rd Ready) { + if rd.SoftState != nil { + rn.prevSoftSt = rd.SoftState + } + if !IsEmptyHardState(rd.HardState) { + rn.prevHardSt = rd.HardState + } + if len(rd.ReadStates) != 0 { + rn.raft.readStates = nil + } + if !rn.asyncStorageWrites { + if len(rn.stepsOnAdvance) != 0 { + rn.raft.logger.Panicf("two accepted Ready structs without call to Advance") + } + for _, m := range rn.raft.msgsAfterAppend { + if m.To == rn.raft.id { + rn.stepsOnAdvance = append(rn.stepsOnAdvance, m) + } + } + if needStorageAppendRespMsg(rn.raft, rd) { + m := newStorageAppendRespMsg(rn.raft, rd) + rn.stepsOnAdvance = append(rn.stepsOnAdvance, m) + } + if needStorageApplyRespMsg(rd) { + m := newStorageApplyRespMsg(rn.raft, rd.CommittedEntries) + rn.stepsOnAdvance = append(rn.stepsOnAdvance, m) + } + } + rn.raft.msgs = nil + rn.raft.msgsAfterAppend = nil + rn.raft.raftLog.acceptUnstable() + if len(rd.CommittedEntries) > 0 { + ents := rd.CommittedEntries + index := ents[len(ents)-1].Index + rn.raft.raftLog.acceptApplying(index, entsSize(ents), rn.applyUnstableEntries()) + } + + traceReady(rn.raft) +} + +// applyUnstableEntries returns whether entries are allowed to be applied once +// they are known to be committed but before they have been written locally to +// stable storage. +func (rn *RawNode) applyUnstableEntries() bool { + return !rn.asyncStorageWrites +} + +// HasReady called when RawNode user need to check if any Ready pending. +func (rn *RawNode) HasReady() bool { + // TODO(nvanbenschoten): order these cases in terms of cost and frequency. + r := rn.raft + if softSt := r.softState(); !softSt.equal(rn.prevSoftSt) { + return true + } + if hardSt := r.hardState(); !IsEmptyHardState(hardSt) && !isHardStateEqual(hardSt, rn.prevHardSt) { + return true + } + if r.raftLog.hasNextUnstableSnapshot() { + return true + } + if len(r.msgs) > 0 || len(r.msgsAfterAppend) > 0 { + return true + } + if r.raftLog.hasNextUnstableEnts() || r.raftLog.hasNextCommittedEnts(rn.applyUnstableEntries()) { + return true + } + if len(r.readStates) != 0 { + return true + } + return false +} + +// Advance notifies the RawNode that the application has applied and saved progress in the +// last Ready results. +// +// NOTE: Advance must not be called when using AsyncStorageWrites. Response messages from +// the local append and apply threads take its place. +func (rn *RawNode) Advance(_ Ready) { + // The actions performed by this function are encoded into stepsOnAdvance in + // acceptReady. In earlier versions of this library, they were computed from + // the provided Ready struct. Retain the unused parameter for compatibility. + if rn.asyncStorageWrites { + rn.raft.logger.Panicf("Advance must not be called when using AsyncStorageWrites") + } + for i, m := range rn.stepsOnAdvance { + _ = rn.raft.Step(m) + rn.stepsOnAdvance[i] = pb.Message{} + } + rn.stepsOnAdvance = rn.stepsOnAdvance[:0] +} + +// Status returns the current status of the given group. This allocates, see +// BasicStatus and WithProgress for allocation-friendlier choices. +func (rn *RawNode) Status() Status { + status := getStatus(rn.raft) + return status +} + +// BasicStatus returns a BasicStatus. Notably this does not contain the +// Progress map; see WithProgress for an allocation-free way to inspect it. +func (rn *RawNode) BasicStatus() BasicStatus { + return getBasicStatus(rn.raft) +} + +// ProgressType indicates the type of replica a Progress corresponds to. +type ProgressType byte + +const ( + // ProgressTypePeer accompanies a Progress for a regular peer replica. + ProgressTypePeer ProgressType = iota + // ProgressTypeLearner accompanies a Progress for a learner replica. + ProgressTypeLearner +) + +// WithProgress is a helper to introspect the Progress for this node and its +// peers. +func (rn *RawNode) WithProgress(visitor func(id uint64, typ ProgressType, pr tracker.Progress)) { + rn.raft.trk.Visit(func(id uint64, pr *tracker.Progress) { + typ := ProgressTypePeer + if pr.IsLearner { + typ = ProgressTypeLearner + } + p := *pr + p.Inflights = nil + visitor(id, typ, p) + }) +} + +// ReportUnreachable reports the given node is not reachable for the last send. +func (rn *RawNode) ReportUnreachable(id uint64) { + _ = rn.raft.Step(pb.Message{Type: pb.MsgUnreachable, From: id}) +} + +// ReportSnapshot reports the status of the sent snapshot. +func (rn *RawNode) ReportSnapshot(id uint64, status SnapshotStatus) { + rej := status == SnapshotFailure + + _ = rn.raft.Step(pb.Message{Type: pb.MsgSnapStatus, From: id, Reject: rej}) +} + +// TransferLeader tries to transfer leadership to the given transferee. +func (rn *RawNode) TransferLeader(transferee uint64) { + _ = rn.raft.Step(pb.Message{Type: pb.MsgTransferLeader, From: transferee}) +} + +// ForgetLeader forgets a follower's current leader, changing it to None. +// See (Node).ForgetLeader for details. +func (rn *RawNode) ForgetLeader() error { + return rn.raft.Step(pb.Message{Type: pb.MsgForgetLeader}) +} + +// ReadIndex requests a read state. The read state will be set in ready. +// Read State has a read index. Once the application advances further than the read +// index, any linearizable read requests issued before the read request can be +// processed safely. The read state will have the same rctx attached. +func (rn *RawNode) ReadIndex(rctx []byte) { + _ = rn.raft.Step(pb.Message{Type: pb.MsgReadIndex, Entries: []pb.Entry{{Data: rctx}}}) +} diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/read_only.go b/etcd/vendor/go.etcd.io/raft/v3/read_only.go similarity index 97% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/read_only.go rename to etcd/vendor/go.etcd.io/raft/v3/read_only.go index ad0688522d..5a53f0ca80 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/read_only.go +++ b/etcd/vendor/go.etcd.io/raft/v3/read_only.go @@ -14,7 +14,7 @@ package raft -import pb "go.etcd.io/etcd/raft/v3/raftpb" +import pb "go.etcd.io/raft/v3/raftpb" // ReadState provides state for read only query. // It's caller's responsibility to call ReadIndex first before getting @@ -85,7 +85,7 @@ func (ro *readOnly) advance(m pb.Message) []*readIndexStatus { ) ctx := string(m.Context) - rss := []*readIndexStatus{} + var rss []*readIndexStatus for _, okctx := range ro.readIndexQueue { i++ diff --git a/etcd/vendor/go.etcd.io/raft/v3/state_trace.go b/etcd/vendor/go.etcd.io/raft/v3/state_trace.go new file mode 100644 index 0000000000..8712dc6a45 --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/state_trace.go @@ -0,0 +1,339 @@ +// Copyright 2024 The etcd 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. + +//go:build with_tla + +package raft + +import ( + "strconv" + "time" + + "go.etcd.io/raft/v3/raftpb" + "go.etcd.io/raft/v3/tracker" +) + +const StateTraceDeployed = true + +type stateMachineEventType int + +const ( + rsmInitState stateMachineEventType = iota + rsmBecomeCandidate + rsmBecomeFollower + rsmBecomeLeader + rsmCommit + rsmReplicate + rsmChangeConf + rsmApplyConfChange + rsmReady + rsmSendAppendEntriesRequest + rsmReceiveAppendEntriesRequest + rsmSendAppendEntriesResponse + rsmReceiveAppendEntriesResponse + rsmSendRequestVoteRequest + rsmReceiveRequestVoteRequest + rsmSendRequestVoteResponse + rsmReceiveRequestVoteResponse + rsmSendSnapshot + rsmReceiveSnapshot +) + +func (e stateMachineEventType) String() string { + return []string{ + "InitState", + "BecomeCandidate", + "BecomeFollower", + "BecomeLeader", + "Commit", + "Replicate", + "ChangeConf", + "ApplyConfChange", + "Ready", + "SendAppendEntriesRequest", + "ReceiveAppendEntriesRequest", + "SendAppendEntriesResponse", + "ReceiveAppendEntriesResponse", + "SendRequestVoteRequest", + "ReceiveRequestVoteRequest", + "SendRequestVoteResponse", + "ReceiveRequestVoteResponse", + "SendSnapshot", + "ReceiveSnapshot", + }[e] +} + +const ( + ConfChangeAddNewServer string = "AddNewServer" + ConfChangeRemoveServer string = "RemoveServer" + ConfChangeAddLearner string = "AddLearner" +) + +type TracingEvent struct { + Name string `json:"name"` + NodeID string `json:"nid"` + State TracingState `json:"state"` + Role string `json:"role"` + LogSize uint64 `json:"log"` + Conf [2][]string `json:"conf"` + Message *TracingMessage `json:"msg,omitempty"` + ConfChange *TracingConfChange `json:"cc,omitempty"` + Properties map[string]any `json:"prop,omitempty"` +} + +type TracingState struct { + Term uint64 `json:"term"` + Vote string `json:"vote"` + Commit uint64 `json:"commit"` +} + +type TracingMessage struct { + Type string `json:"type"` + Term uint64 `json:"term"` + From string `json:"from"` + To string `json:"to"` + EntryLength int `json:"entries"` + LogTerm uint64 `json:"logTerm"` + Index uint64 `json:"index"` + Commit uint64 `json:"commit"` + Vote string `json:"vote"` + Reject bool `json:"reject"` + RejectHint uint64 `json:"rejectHint"` +} + +type SingleConfChange struct { + NodeID string `json:"nid"` + Action string `json:"action"` +} + +type TracingConfChange struct { + Changes []SingleConfChange `json:"changes,omitempty"` + NewConf []string `json:"newconf,omitempty"` +} + +func makeTracingState(r *raft) TracingState { + hs := r.hardState() + return TracingState{ + Term: hs.Term, + Vote: strconv.FormatUint(hs.Vote, 10), + Commit: hs.Commit, + } +} + +func makeTracingMessage(m *raftpb.Message) *TracingMessage { + if m == nil { + return nil + } + + logTerm := m.LogTerm + entries := len(m.Entries) + index := m.Index + if m.Type == raftpb.MsgSnap { + index = 0 + logTerm = 0 + entries = int(m.Snapshot.Metadata.Index) + } + return &TracingMessage{ + Type: m.Type.String(), + Term: m.Term, + From: strconv.FormatUint(m.From, 10), + To: strconv.FormatUint(m.To, 10), + EntryLength: entries, + LogTerm: logTerm, + Index: index, + Commit: m.Commit, + Vote: strconv.FormatUint(m.Vote, 10), + Reject: m.Reject, + RejectHint: m.RejectHint, + } +} + +type TraceLogger interface { + TraceEvent(*TracingEvent) +} + +func traceEvent(evt stateMachineEventType, r *raft, m *raftpb.Message, prop map[string]any) { + if r.traceLogger == nil { + return + } + + r.traceLogger.TraceEvent(&TracingEvent{ + Name: evt.String(), + NodeID: strconv.FormatUint(r.id, 10), + State: makeTracingState(r), + LogSize: r.raftLog.lastIndex(), + Conf: [2][]string{formatConf(r.trk.Voters[0].Slice()), formatConf(r.trk.Voters[1].Slice())}, + Role: r.state.String(), + Message: makeTracingMessage(m), + Properties: prop, + }) +} + +func traceNodeEvent(evt stateMachineEventType, r *raft) { + traceEvent(evt, r, nil, nil) +} + +func formatConf(s []uint64) []string { + if s == nil { + return []string{} + } + + r := make([]string, len(s)) + for i, v := range s { + r[i] = strconv.FormatUint(v, 10) + } + return r +} + +// Use following helper functions to trace specific state and/or +// transition at corresponding code lines +func traceInitState(r *raft) { + if r.traceLogger == nil { + return + } + + traceNodeEvent(rsmInitState, r) +} + +func traceReady(r *raft) { + traceNodeEvent(rsmReady, r) +} + +func traceCommit(r *raft) { + traceNodeEvent(rsmCommit, r) +} + +func traceReplicate(r *raft, es ...raftpb.Entry) { + for i := range es { + if es[i].Type == raftpb.EntryNormal { + traceNodeEvent(rsmReplicate, r) + } + } +} + +func traceBecomeFollower(r *raft) { + traceNodeEvent(rsmBecomeFollower, r) +} + +func traceBecomeCandidate(r *raft) { + traceNodeEvent(rsmBecomeCandidate, r) +} + +func traceBecomeLeader(r *raft) { + traceNodeEvent(rsmBecomeLeader, r) +} + +func traceChangeConfEvent(cci raftpb.ConfChangeI, r *raft) { + cc2 := cci.AsV2() + cc := &TracingConfChange{ + Changes: []SingleConfChange{}, + NewConf: []string{}, + } + for _, c := range cc2.Changes { + switch c.Type { + case raftpb.ConfChangeAddNode: + cc.Changes = append(cc.Changes, SingleConfChange{ + NodeID: strconv.FormatUint(c.NodeID, 10), + Action: ConfChangeAddNewServer, + }) + case raftpb.ConfChangeRemoveNode: + cc.Changes = append(cc.Changes, SingleConfChange{ + NodeID: strconv.FormatUint(c.NodeID, 10), + Action: ConfChangeRemoveServer, + }) + case raftpb.ConfChangeAddLearnerNode: + cc.Changes = append(cc.Changes, SingleConfChange{ + NodeID: strconv.FormatUint(c.NodeID, 10), + Action: ConfChangeAddLearner, + }) + } + } + + if len(cc.Changes) == 0 { + return + } + + p := map[string]any{} + p["cc"] = cc + traceEvent(rsmChangeConf, r, nil, p) +} + +func traceConfChangeEvent(cfg tracker.Config, r *raft) { + if r.traceLogger == nil { + return + } + + cc := &TracingConfChange{ + Changes: []SingleConfChange{}, + NewConf: formatConf(cfg.Voters[0].Slice()), + } + + p := map[string]any{} + p["cc"] = cc + traceEvent(rsmApplyConfChange, r, nil, p) +} + +func traceSendMessage(r *raft, m *raftpb.Message) { + if r.traceLogger == nil { + return + } + + prop := map[string]any{} + + var evt stateMachineEventType + switch m.Type { + case raftpb.MsgApp: + evt = rsmSendAppendEntriesRequest + if p, exist := r.trk.Progress[m.From]; exist { + prop["match"] = p.Match + prop["next"] = p.Next + } + + case raftpb.MsgHeartbeat, raftpb.MsgSnap: + evt = rsmSendAppendEntriesRequest + case raftpb.MsgAppResp, raftpb.MsgHeartbeatResp: + evt = rsmSendAppendEntriesResponse + case raftpb.MsgVote: + evt = rsmSendRequestVoteRequest + case raftpb.MsgVoteResp: + evt = rsmSendRequestVoteResponse + default: + return + } + + traceEvent(evt, r, m, prop) +} + +func traceReceiveMessage(r *raft, m *raftpb.Message) { + if r.traceLogger == nil { + return + } + + var evt stateMachineEventType + switch m.Type { + case raftpb.MsgApp, raftpb.MsgHeartbeat, raftpb.MsgSnap: + evt = rsmReceiveAppendEntriesRequest + case raftpb.MsgAppResp, raftpb.MsgHeartbeatResp: + evt = rsmReceiveAppendEntriesResponse + case raftpb.MsgVote: + evt = rsmReceiveRequestVoteRequest + case raftpb.MsgVoteResp: + evt = rsmReceiveRequestVoteResponse + default: + return + } + + time.Sleep(time.Millisecond) // sleep 1ms to reduce time shift impact accross node + traceEvent(evt, r, m, nil) +} diff --git a/etcd/vendor/go.etcd.io/raft/v3/state_trace_nop.go b/etcd/vendor/go.etcd.io/raft/v3/state_trace_nop.go new file mode 100644 index 0000000000..cdeb99b0f6 --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/state_trace_nop.go @@ -0,0 +1,50 @@ +// Copyright 2024 The etcd 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. + +//go:build !with_tla + +package raft + +import ( + "go.etcd.io/raft/v3/raftpb" + "go.etcd.io/raft/v3/tracker" +) + +const StateTraceDeployed = false + +type TraceLogger interface{} + +type TracingEvent struct{} + +func traceInitState(*raft) {} + +func traceReady(*raft) {} + +func traceCommit(*raft) {} + +func traceReplicate(*raft, ...raftpb.Entry) {} + +func traceBecomeFollower(*raft) {} + +func traceBecomeCandidate(*raft) {} + +func traceBecomeLeader(*raft) {} + +func traceChangeConfEvent(raftpb.ConfChangeI, *raft) {} + +func traceConfChangeEvent(tracker.Config, *raft) {} + +func traceSendMessage(*raft, *raftpb.Message) {} + +func traceReceiveMessage(*raft, *raftpb.Message) {} diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/status.go b/etcd/vendor/go.etcd.io/raft/v3/status.go similarity index 92% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/status.go rename to etcd/vendor/go.etcd.io/raft/v3/status.go index acfb56c391..ded0c0ec6c 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/status.go +++ b/etcd/vendor/go.etcd.io/raft/v3/status.go @@ -17,8 +17,8 @@ package raft import ( "fmt" - pb "go.etcd.io/etcd/raft/v3/raftpb" - "go.etcd.io/etcd/raft/v3/tracker" + pb "go.etcd.io/raft/v3/raftpb" + "go.etcd.io/raft/v3/tracker" ) // Status contains information about this Raft peer and its view of the system. @@ -43,7 +43,7 @@ type BasicStatus struct { func getProgressCopy(r *raft) map[uint64]tracker.Progress { m := make(map[uint64]tracker.Progress) - r.prs.Visit(func(id uint64, pr *tracker.Progress) { + r.trk.Visit(func(id uint64, pr *tracker.Progress) { p := *pr p.Inflights = pr.Inflights.Clone() pr = nil @@ -59,7 +59,7 @@ func getBasicStatus(r *raft) BasicStatus { LeadTransferee: r.leadTransferee, } s.HardState = r.hardState() - s.SoftState = *r.softState() + s.SoftState = r.softState() s.Applied = r.raftLog.applied return s } @@ -71,7 +71,7 @@ func getStatus(r *raft) Status { if s.RaftState == StateLeader { s.Progress = getProgressCopy(r) } - s.Config = r.prs.Config.Clone() + s.Config = r.trk.Config.Clone() return s } diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/storage.go b/etcd/vendor/go.etcd.io/raft/v3/storage.go similarity index 78% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/storage.go rename to etcd/vendor/go.etcd.io/raft/v3/storage.go index 8b16d4fa24..f616c3150f 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/storage.go +++ b/etcd/vendor/go.etcd.io/raft/v3/storage.go @@ -18,7 +18,7 @@ import ( "errors" "sync" - pb "go.etcd.io/etcd/raft/v3/raftpb" + pb "go.etcd.io/raft/v3/raftpb" ) // ErrCompacted is returned by Storage.Entries/Compact when a requested @@ -48,10 +48,28 @@ type Storage interface { // InitialState returns the saved HardState and ConfState information. InitialState() (pb.HardState, pb.ConfState, error) - // Entries returns a slice of log entries in the range [lo,hi). - // MaxSize limits the total size of the log entries returned, but - // Entries returns at least one entry if any. + + // Entries returns a slice of consecutive log entries in the range [lo, hi), + // starting from lo. The maxSize limits the total size of the log entries + // returned, but Entries returns at least one entry if any. + // + // The caller of Entries owns the returned slice, and may append to it. The + // individual entries in the slice must not be mutated, neither by the Storage + // implementation nor the caller. Note that raft may forward these entries + // back to the application via Ready struct, so the corresponding handler must + // not mutate entries either (see comments in Ready struct). + // + // Since the caller may append to the returned slice, Storage implementation + // must protect its state from corruption that such appends may cause. For + // example, common ways to do so are: + // - allocate the slice before returning it (safest option), + // - return a slice protected by Go full slice expression, which causes + // copying on appends (see MemoryStorage). + // + // Returns ErrCompacted if entry lo has been compacted, or ErrUnavailable if + // encountered an unavailable entry in [lo, hi). Entries(lo, hi, maxSize uint64) ([]pb.Entry, error) + // Term returns the term of entry i, which must be in the range // [FirstIndex()-1, LastIndex()]. The term of the entry before // FirstIndex is retained for matching purposes even though the @@ -71,6 +89,10 @@ type Storage interface { Snapshot() (pb.Snapshot, error) } +type inMemStorageCallStats struct { + initialState, firstIndex, lastIndex, entries, term, snapshot int +} + // MemoryStorage implements the Storage interface backed by an // in-memory array. type MemoryStorage struct { @@ -83,6 +105,8 @@ type MemoryStorage struct { snapshot pb.Snapshot // ents[i] has raft log position i+snapshot.Metadata.Index ents []pb.Entry + + callStats inMemStorageCallStats } // NewMemoryStorage creates an empty MemoryStorage. @@ -95,6 +119,7 @@ func NewMemoryStorage() *MemoryStorage { // InitialState implements the Storage interface. func (ms *MemoryStorage) InitialState() (pb.HardState, pb.ConfState, error) { + ms.callStats.initialState++ return ms.hardState, ms.snapshot.Metadata.ConfState, nil } @@ -110,6 +135,7 @@ func (ms *MemoryStorage) SetHardState(st pb.HardState) error { func (ms *MemoryStorage) Entries(lo, hi, maxSize uint64) ([]pb.Entry, error) { ms.Lock() defer ms.Unlock() + ms.callStats.entries++ offset := ms.ents[0].Index if lo <= offset { return nil, ErrCompacted @@ -122,14 +148,18 @@ func (ms *MemoryStorage) Entries(lo, hi, maxSize uint64) ([]pb.Entry, error) { return nil, ErrUnavailable } - ents := ms.ents[lo-offset : hi-offset] - return limitSize(ents, maxSize), nil + ents := limitSize(ms.ents[lo-offset:hi-offset], entryEncodingSize(maxSize)) + // NB: use the full slice expression to limit what the caller can do with the + // returned slice. For example, an append will reallocate and copy this slice + // instead of corrupting the neighbouring ms.ents. + return ents[:len(ents):len(ents)], nil } // Term implements the Storage interface. func (ms *MemoryStorage) Term(i uint64) (uint64, error) { ms.Lock() defer ms.Unlock() + ms.callStats.term++ offset := ms.ents[0].Index if i < offset { return 0, ErrCompacted @@ -144,6 +174,7 @@ func (ms *MemoryStorage) Term(i uint64) (uint64, error) { func (ms *MemoryStorage) LastIndex() (uint64, error) { ms.Lock() defer ms.Unlock() + ms.callStats.lastIndex++ return ms.lastIndex(), nil } @@ -155,6 +186,7 @@ func (ms *MemoryStorage) lastIndex() uint64 { func (ms *MemoryStorage) FirstIndex() (uint64, error) { ms.Lock() defer ms.Unlock() + ms.callStats.firstIndex++ return ms.firstIndex(), nil } @@ -166,6 +198,7 @@ func (ms *MemoryStorage) firstIndex() uint64 { func (ms *MemoryStorage) Snapshot() (pb.Snapshot, error) { ms.Lock() defer ms.Unlock() + ms.callStats.snapshot++ return ms.snapshot, nil } @@ -227,7 +260,10 @@ func (ms *MemoryStorage) Compact(compactIndex uint64) error { } i := compactIndex - offset - ents := make([]pb.Entry, 1, 1+uint64(len(ms.ents))-i) + // NB: allocate a new slice instead of reusing the old ms.ents. Entries in + // ms.ents are immutable, and can be referenced from outside MemoryStorage + // through slices returned by ms.Entries(). + ents := make([]pb.Entry, 1, uint64(len(ms.ents))-i) ents[0].Index = ms.ents[i].Index ents[0].Term = ms.ents[i].Term ents = append(ents, ms.ents[i+1:]...) @@ -261,8 +297,9 @@ func (ms *MemoryStorage) Append(entries []pb.Entry) error { offset := entries[0].Index - ms.ents[0].Index switch { case uint64(len(ms.ents)) > offset: - ms.ents = append([]pb.Entry{}, ms.ents[:offset]...) - ms.ents = append(ms.ents, entries...) + // NB: full slice expression protects ms.ents at index >= offset from + // rewrites, as they may still be referenced from outside MemoryStorage. + ms.ents = append(ms.ents[:offset:offset], entries...) case uint64(len(ms.ents)) == offset: ms.ents = append(ms.ents, entries...) default: diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/inflights.go b/etcd/vendor/go.etcd.io/raft/v3/tracker/inflights.go similarity index 62% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/inflights.go rename to etcd/vendor/go.etcd.io/raft/v3/tracker/inflights.go index 1a056341ab..cb091e542a 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/inflights.go +++ b/etcd/vendor/go.etcd.io/raft/v3/tracker/inflights.go @@ -14,6 +14,12 @@ package tracker +// inflight describes an in-flight MsgApp message. +type inflight struct { + index uint64 // the index of the last entry inside the message + bytes uint64 // the total byte size of the entries in the message +} + // Inflights limits the number of MsgApp (represented by the largest index // contained within) sent to followers but not yet acknowledged by them. Callers // use Full() to check whether more messages can be sent, call Add() whenever @@ -22,21 +28,25 @@ package tracker type Inflights struct { // the starting index in the buffer start int - // number of inflights in the buffer - count int - // the size of the buffer - size int + count int // number of inflight messages in the buffer + bytes uint64 // number of inflight bytes + + size int // the max number of inflight messages + maxBytes uint64 // the max total byte size of inflight messages - // buffer contains the index of the last entry - // inside one message. - buffer []uint64 + // buffer is a ring buffer containing info about all in-flight messages. + buffer []inflight } -// NewInflights sets up an Inflights that allows up to 'size' inflight messages. -func NewInflights(size int) *Inflights { +// NewInflights sets up an Inflights that allows up to size inflight messages, +// with the total byte size up to maxBytes. If maxBytes is 0 then there is no +// byte size limit. The maxBytes limit is soft, i.e. we accept a single message +// that brings it from size < maxBytes to size >= maxBytes. +func NewInflights(size int, maxBytes uint64) *Inflights { return &Inflights{ - size: size, + size: size, + maxBytes: maxBytes, } } @@ -44,15 +54,15 @@ func NewInflights(size int) *Inflights { // the receiver. func (in *Inflights) Clone() *Inflights { ins := *in - ins.buffer = append([]uint64(nil), in.buffer...) + ins.buffer = append([]inflight(nil), in.buffer...) return &ins } -// Add notifies the Inflights that a new message with the given index is being -// dispatched. Full() must be called prior to Add() to verify that there is room -// for one more message, and consecutive calls to add Add() must provide a -// monotonic sequence of indexes. -func (in *Inflights) Add(inflight uint64) { +// Add notifies the Inflights that a new message with the given index and byte +// size is being dispatched. Full() must be called prior to Add() to verify that +// there is room for one more message, and consecutive calls to Add() must +// provide a monotonic sequence of indexes. +func (in *Inflights) Add(index, bytes uint64) { if in.Full() { panic("cannot add into a Full inflights") } @@ -64,8 +74,9 @@ func (in *Inflights) Add(inflight uint64) { if next >= len(in.buffer) { in.grow() } - in.buffer[next] = inflight + in.buffer[next] = inflight{index: index, bytes: bytes} in.count++ + in.bytes += bytes } // grow the inflight buffer by doubling up to inflights.size. We grow on demand @@ -78,24 +89,26 @@ func (in *Inflights) grow() { } else if newSize > in.size { newSize = in.size } - newBuffer := make([]uint64, newSize) + newBuffer := make([]inflight, newSize) copy(newBuffer, in.buffer) in.buffer = newBuffer } // FreeLE frees the inflights smaller or equal to the given `to` flight. func (in *Inflights) FreeLE(to uint64) { - if in.count == 0 || to < in.buffer[in.start] { + if in.count == 0 || to < in.buffer[in.start].index { // out of the left side of the window return } idx := in.start var i int + var bytes uint64 for i = 0; i < in.count; i++ { - if to < in.buffer[idx] { // found the first large inflight + if to < in.buffer[idx].index { // found the first large inflight break } + bytes += in.buffer[idx].bytes // increase index and maybe rotate size := in.size @@ -105,6 +118,7 @@ func (in *Inflights) FreeLE(to uint64) { } // free i inflights and set new start index in.count -= i + in.bytes -= bytes in.start = idx if in.count == 0 { // inflights is empty, reset the start index so that we don't grow the @@ -113,13 +127,9 @@ func (in *Inflights) FreeLE(to uint64) { } } -// FreeFirstOne releases the first inflight. This is a no-op if nothing is -// inflight. -func (in *Inflights) FreeFirstOne() { in.FreeLE(in.buffer[in.start]) } - // Full returns true if no more messages can be sent at the moment. func (in *Inflights) Full() bool { - return in.count == in.size + return in.count == in.size || (in.maxBytes != 0 && in.bytes >= in.maxBytes) } // Count returns the number of inflight messages. @@ -127,6 +137,7 @@ func (in *Inflights) Count() int { return in.count } // reset frees all inflights. func (in *Inflights) reset() { - in.count = 0 in.start = 0 + in.count = 0 + in.bytes = 0 } diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/progress.go b/etcd/vendor/go.etcd.io/raft/v3/tracker/progress.go similarity index 57% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/progress.go rename to etcd/vendor/go.etcd.io/raft/v3/tracker/progress.go index a36e5261ac..5716661c86 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/progress.go +++ b/etcd/vendor/go.etcd.io/raft/v3/tracker/progress.go @@ -16,7 +16,7 @@ package tracker import ( "fmt" - "sort" + "slices" "strings" ) @@ -28,7 +28,26 @@ import ( // strewn around `*raft.raft`. Additionally, some fields are only used when in a // certain State. All of this isn't ideal. type Progress struct { - Match, Next uint64 + // Match is the index up to which the follower's log is known to match the + // leader's. + Match uint64 + // Next is the log index of the next entry to send to this follower. All + // entries with indices in (Match, Next) interval are already in flight. + // + // Invariant: 0 <= Match < Next. + // NB: it follows that Next >= 1. + // + // In StateSnapshot, Next == PendingSnapshot + 1. + Next uint64 + + // sentCommit is the highest commit index in flight to the follower. + // + // Generally, it is monotonic, but con regress in some cases, e.g. when + // converting to `StateProbe` or when receiving a rejection from a follower. + // + // In StateSnapshot, sentCommit == PendingSnapshot == Next-1. + sentCommit uint64 + // State defines how the leader should interact with the follower. // // When in StateProbe, leader sends at most one replication message @@ -42,24 +61,42 @@ type Progress struct { // before and stops sending any replication message. State StateType - // PendingSnapshot is used in StateSnapshot. - // If there is a pending snapshot, the pendingSnapshot will be set to the - // index of the snapshot. If pendingSnapshot is set, the replication process of - // this Progress will be paused. raft will not resend snapshot until the pending one - // is reported to be failed. + // PendingSnapshot is used in StateSnapshot and tracks the last index of the + // leader at the time at which it realized a snapshot was necessary. This + // matches the index in the MsgSnap message emitted from raft. + // + // While there is a pending snapshot, replication to the follower is paused. + // The follower will transition back to StateReplicate if the leader + // receives an MsgAppResp from it that reconnects the follower to the + // leader's log (such an MsgAppResp is emitted when the follower applies a + // snapshot). It may be surprising that PendingSnapshot is not taken into + // account here, but consider that complex systems may delegate the sending + // of snapshots to alternative datasources (i.e. not the leader). In such + // setups, it is difficult to manufacture a snapshot at a particular index + // requested by raft and the actual index may be ahead or behind. This + // should be okay, as long as the snapshot allows replication to resume. + // + // The follower will transition to StateProbe if ReportSnapshot is called on + // the leader; if SnapshotFinish is passed then PendingSnapshot becomes the + // basis for the next attempt to append. In practice, the first mechanism is + // the one that is relevant in most cases. However, if this MsgAppResp is + // lost (fallible network) then the second mechanism ensures that in this + // case the follower does not erroneously remain in StateSnapshot. PendingSnapshot uint64 // RecentActive is true if the progress is recently active. Receiving any messages // from the corresponding follower indicates the progress is active. // RecentActive can be reset to false after an election timeout. - // - // TODO(tbg): the leader should always have this set to true. + // This is always true on the leader. RecentActive bool - // ProbeSent is used while this follower is in StateProbe. When ProbeSent is - // true, raft should pause sending replication message to this peer until - // ProbeSent is reset. See ProbeAcked() and IsPaused(). - ProbeSent bool + // MsgAppFlowPaused is used when the MsgApp flow to a node is throttled. This + // happens in StateProbe, or StateReplicate with saturated Inflights. In both + // cases, we need to continue sending MsgApp once in a while to guarantee + // progress, but we only do so when MsgAppFlowPaused is false (it is reset on + // receiving a heartbeat response), to not overflow the receiver. See + // IsPaused(). + MsgAppFlowPaused bool // Inflights is a sliding window for the inflight messages. // Each inflight message contains one or more log entries. @@ -79,36 +116,15 @@ type Progress struct { IsLearner bool } -// ResetState moves the Progress into the specified State, resetting ProbeSent, +// ResetState moves the Progress into the specified State, resetting MsgAppFlowPaused, // PendingSnapshot, and Inflights. func (pr *Progress) ResetState(state StateType) { - pr.ProbeSent = false + pr.MsgAppFlowPaused = false pr.PendingSnapshot = 0 pr.State = state pr.Inflights.reset() } -func max(a, b uint64) uint64 { - if a > b { - return a - } - return b -} - -func min(a, b uint64) uint64 { - if a > b { - return b - } - return a -} - -// ProbeAcked is called when this peer has accepted an append. It resets -// ProbeSent to signal that additional append messages should be sent without -// further delay. -func (pr *Progress) ProbeAcked() { - pr.ProbeSent = false -} - // BecomeProbe transitions into StateProbe. Next is reset to Match+1 or, // optionally and if larger, the index of the pending snapshot. func (pr *Progress) BecomeProbe() { @@ -123,6 +139,7 @@ func (pr *Progress) BecomeProbe() { pr.ResetState(StateProbe) pr.Next = pr.Match + 1 } + pr.sentCommit = min(pr.sentCommit, pr.Next-1) } // BecomeReplicate transitions into StateReplicate, resetting Next to Match+1. @@ -136,26 +153,65 @@ func (pr *Progress) BecomeReplicate() { func (pr *Progress) BecomeSnapshot(snapshoti uint64) { pr.ResetState(StateSnapshot) pr.PendingSnapshot = snapshoti + pr.Next = snapshoti + 1 + pr.sentCommit = snapshoti +} + +// SentEntries updates the progress on the given number of consecutive entries +// being sent in a MsgApp, with the given total bytes size, appended at log +// indices >= pr.Next. +// +// Must be used with StateProbe or StateReplicate. +func (pr *Progress) SentEntries(entries int, bytes uint64) { + switch pr.State { + case StateReplicate: + if entries > 0 { + pr.Next += uint64(entries) + pr.Inflights.Add(pr.Next-1, bytes) + } + // If this message overflows the in-flights tracker, or it was already full, + // consider this message being a probe, so that the flow is paused. + pr.MsgAppFlowPaused = pr.Inflights.Full() + case StateProbe: + // TODO(pavelkalinnikov): this condition captures the previous behaviour, + // but we should set MsgAppFlowPaused unconditionally for simplicity, because any + // MsgApp in StateProbe is a probe, not only non-empty ones. + if entries > 0 { + pr.MsgAppFlowPaused = true + } + default: + panic(fmt.Sprintf("sending append in unhandled state %s", pr.State)) + } +} + +// CanBumpCommit returns true if sending the given commit index can potentially +// advance the follower's commit index. +func (pr *Progress) CanBumpCommit(index uint64) bool { + // Sending the given commit index may bump the follower's commit index up to + // Next-1 in normal operation, or higher in some rare cases. Allow sending a + // commit index eagerly only if we haven't already sent one that bumps the + // follower's commit all the way to Next-1. + return index > pr.sentCommit && pr.sentCommit < pr.Next-1 +} + +// SentCommit updates the sentCommit. +func (pr *Progress) SentCommit(commit uint64) { + pr.sentCommit = commit } // MaybeUpdate is called when an MsgAppResp arrives from the follower, with the // index acked by it. The method returns false if the given n index comes from // an outdated message. Otherwise it updates the progress and returns true. func (pr *Progress) MaybeUpdate(n uint64) bool { - var updated bool - if pr.Match < n { - pr.Match = n - updated = true - pr.ProbeAcked() + if n <= pr.Match { + return false } - pr.Next = max(pr.Next, n+1) - return updated + pr.Match = n + pr.Next = max(pr.Next, n+1) // invariant: Match < Next + pr.MsgAppFlowPaused = false + return true } -// OptimisticUpdate signals that appends all the way up to and including index n -// are in-flight. As a result, Next is increased to n+1. -func (pr *Progress) OptimisticUpdate(n uint64) { pr.Next = n + 1 } - // MaybeDecrTo adjusts the Progress to the receipt of a MsgApp rejection. The // arguments are the index of the append message rejected by the follower, and // the hint that we want to decrease to. @@ -178,17 +234,22 @@ func (pr *Progress) MaybeDecrTo(rejected, matchHint uint64) bool { // // TODO(tbg): why not use matchHint if it's larger? pr.Next = pr.Match + 1 + // Regress the sentCommit since it unlikely has been applied. + pr.sentCommit = min(pr.sentCommit, pr.Next-1) return true } // The rejection must be stale if "rejected" does not match next - 1. This // is because non-replicating followers are probed one entry at a time. + // The check is a best effort assuming message reordering is rare. if pr.Next-1 != rejected { return false } - pr.Next = max(min(rejected, matchHint+1), 1) - pr.ProbeSent = false + pr.Next = max(min(rejected, matchHint+1), pr.Match+1) + // Regress the sentCommit since it unlikely has been applied. + pr.sentCommit = min(pr.sentCommit, pr.Next-1) + pr.MsgAppFlowPaused = false return true } @@ -201,9 +262,9 @@ func (pr *Progress) MaybeDecrTo(rejected, matchHint uint64) bool { func (pr *Progress) IsPaused() bool { switch pr.State { case StateProbe: - return pr.ProbeSent + return pr.MsgAppFlowPaused case StateReplicate: - return pr.Inflights.Full() + return pr.MsgAppFlowPaused case StateSnapshot: return true default: @@ -224,7 +285,7 @@ func (pr *Progress) String() string { fmt.Fprintf(&buf, " pendingSnap=%d", pr.PendingSnapshot) } if !pr.RecentActive { - fmt.Fprintf(&buf, " inactive") + fmt.Fprint(&buf, " inactive") } if n := pr.Inflights.Count(); n > 0 { fmt.Fprintf(&buf, " inflight=%d", n) @@ -244,9 +305,7 @@ func (m ProgressMap) String() string { for k := range m { ids = append(ids, k) } - sort.Slice(ids, func(i, j int) bool { - return ids[i] < ids[j] - }) + slices.Sort(ids) var buf strings.Builder for _, id := range ids { fmt.Fprintf(&buf, "%d: %s\n", id, m[id]) diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/state.go b/etcd/vendor/go.etcd.io/raft/v3/tracker/state.go similarity index 95% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/state.go rename to etcd/vendor/go.etcd.io/raft/v3/tracker/state.go index 285b4b8f58..7dbdd63fa6 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/state.go +++ b/etcd/vendor/go.etcd.io/raft/v3/tracker/state.go @@ -39,4 +39,4 @@ var prstmap = [...]string{ "StateSnapshot", } -func (st StateType) String() string { return prstmap[uint64(st)] } +func (st StateType) String() string { return prstmap[st] } diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/tracker.go b/etcd/vendor/go.etcd.io/raft/v3/tracker/tracker.go similarity index 93% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/tracker.go rename to etcd/vendor/go.etcd.io/raft/v3/tracker/tracker.go index 72dcc73b86..17c4c93f97 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/tracker/tracker.go +++ b/etcd/vendor/go.etcd.io/raft/v3/tracker/tracker.go @@ -16,11 +16,11 @@ package tracker import ( "fmt" - "sort" + "slices" "strings" - "go.etcd.io/etcd/raft/v3/quorum" - pb "go.etcd.io/etcd/raft/v3/raftpb" + "go.etcd.io/raft/v3/quorum" + pb "go.etcd.io/raft/v3/raftpb" ) // Config reflects the configuration tracked in a ProgressTracker. @@ -87,7 +87,7 @@ func (c Config) String() string { fmt.Fprintf(&buf, " learners_next=%s", quorum.MajorityConfig(c.LearnersNext).String()) } if c.AutoLeave { - fmt.Fprintf(&buf, " autoleave") + fmt.Fprint(&buf, " autoleave") } return buf.String() } @@ -121,13 +121,15 @@ type ProgressTracker struct { Votes map[uint64]bool - MaxInflight int + MaxInflight int + MaxInflightBytes uint64 } // MakeProgressTracker initializes a ProgressTracker. -func MakeProgressTracker(maxInflight int) ProgressTracker { +func MakeProgressTracker(maxInflight int, maxBytes uint64) ProgressTracker { p := ProgressTracker{ - MaxInflight: maxInflight, + MaxInflight: maxInflight, + MaxInflightBytes: maxBytes, Config: Config{ Voters: quorum.JointConfig{ quorum.MajorityConfig{}, @@ -178,15 +180,6 @@ func (p *ProgressTracker) Committed() uint64 { return uint64(p.Voters.CommittedIndex(matchAckIndexer(p.Progress))) } -func insertionSort(sl []uint64) { - a, b := 0, len(sl) - for i := a + 1; i < b; i++ { - for j := i; j > a && sl[j] < sl[j-1]; j-- { - sl[j], sl[j-1] = sl[j-1], sl[j] - } - } -} - // Visit invokes the supplied closure for all tracked progresses in stable order. func (p *ProgressTracker) Visit(f func(id uint64, pr *Progress)) { n := len(p.Progress) @@ -204,7 +197,7 @@ func (p *ProgressTracker) Visit(f func(id uint64, pr *Progress)) { n-- ids[n] = id } - insertionSort(ids) + slices.Sort(ids) for _, id := range ids { f(id, p.Progress[id]) } @@ -231,7 +224,7 @@ func (p *ProgressTracker) VoterNodes() []uint64 { for id := range m { nodes = append(nodes, id) } - sort.Slice(nodes, func(i, j int) bool { return nodes[i] < nodes[j] }) + slices.Sort(nodes) return nodes } @@ -244,7 +237,7 @@ func (p *ProgressTracker) LearnerNodes() []uint64 { for id := range p.Learners { nodes = append(nodes, id) } - sort.Slice(nodes, func(i, j int) bool { return nodes[i] < nodes[j] }) + slices.Sort(nodes) return nodes } diff --git a/etcd/vendor/go.etcd.io/raft/v3/types.go b/etcd/vendor/go.etcd.io/raft/v3/types.go new file mode 100644 index 0000000000..bb24d434f2 --- /dev/null +++ b/etcd/vendor/go.etcd.io/raft/v3/types.go @@ -0,0 +1,106 @@ +// Copyright 2024 The etcd 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 raft + +import ( + "fmt" + + pb "go.etcd.io/raft/v3/raftpb" +) + +// entryID uniquely identifies a raft log entry. +// +// Every entry is associated with a leadership term which issued this entry and +// initially appended it to the log. There can only be one leader at any term, +// and a leader never issues two entries with the same index. +type entryID struct { + term uint64 + index uint64 +} + +// pbEntryID returns the ID of the given pb.Entry. +func pbEntryID(entry *pb.Entry) entryID { + return entryID{term: entry.Term, index: entry.Index} +} + +// logSlice describes a correct slice of a raft log. +// +// Every log slice is considered in a context of a specific leader term. This +// term does not necessarily match entryID.term of the entries, since a leader +// log contains both entries from its own term, and some earlier terms. +// +// Two slices with a matching logSlice.term are guaranteed to be consistent, +// i.e. they never contain two different entries at the same index. The reverse +// is not true: two slices with different logSlice.term may contain both +// matching and mismatching entries. Specifically, logs at two different leader +// terms share a common prefix, after which they *permanently* diverge. +// +// A well-formed logSlice conforms to raft safety properties. It provides the +// following guarantees: +// +// 1. entries[i].Index == prev.index + 1 + i, +// 2. prev.term <= entries[0].Term, +// 3. entries[i-1].Term <= entries[i].Term, +// 4. entries[len-1].Term <= term. +// +// Property (1) means the slice is contiguous. Properties (2) and (3) mean that +// the terms of the entries in a log never regress. Property (4) means that a +// leader log at a specific term never has entries from higher terms. +// +// Users of this struct can assume the invariants hold true. Exception is the +// "gateway" code that initially constructs logSlice, such as when its content +// is sourced from a message that was received via transport, or from Storage, +// or in a test code that manually hard-codes this struct. In these cases, the +// invariants should be validated using the valid() method. +type logSlice struct { + // term is the leader term containing the given entries in its log. + term uint64 + // prev is the ID of the entry immediately preceding the entries. + prev entryID + // entries contains the consecutive entries representing this slice. + entries []pb.Entry +} + +// lastIndex returns the index of the last entry in this log slice. Returns +// prev.index if there are no entries. +func (s logSlice) lastIndex() uint64 { + return s.prev.index + uint64(len(s.entries)) +} + +// lastEntryID returns the ID of the last entry in this log slice, or prev if +// there are no entries. +func (s logSlice) lastEntryID() entryID { + if ln := len(s.entries); ln != 0 { + return pbEntryID(&s.entries[ln-1]) + } + return s.prev +} + +// valid returns nil iff the logSlice is a well-formed log slice. See logSlice +// comment for details on what constitutes a valid raft log slice. +func (s logSlice) valid() error { + prev := s.prev + for i := range s.entries { + id := pbEntryID(&s.entries[i]) + if id.term < prev.term || id.index != prev.index+1 { + return fmt.Errorf("leader term %d: entries %+v and %+v not consistent", s.term, prev, id) + } + prev = id + } + if s.term < prev.term { + return fmt.Errorf("leader term %d: entry %+v has a newer term", s.term, prev) + } + return nil +} diff --git a/etcd/vendor/go.etcd.io/etcd/raft/v3/util.go b/etcd/vendor/go.etcd.io/raft/v3/util.go similarity index 55% rename from etcd/vendor/go.etcd.io/etcd/raft/v3/util.go rename to etcd/vendor/go.etcd.io/raft/v3/util.go index 94ab368f60..8f78178829 100644 --- a/etcd/vendor/go.etcd.io/etcd/raft/v3/util.go +++ b/etcd/vendor/go.etcd.io/raft/v3/util.go @@ -19,34 +19,51 @@ import ( "fmt" "strings" - pb "go.etcd.io/etcd/raft/v3/raftpb" + pb "go.etcd.io/raft/v3/raftpb" ) func (st StateType) MarshalJSON() ([]byte, error) { return []byte(fmt.Sprintf("%q", st.String())), nil } -func min(a, b uint64) uint64 { - if a > b { - return b - } - return a +var isLocalMsg = [...]bool{ + pb.MsgHup: true, + pb.MsgBeat: true, + pb.MsgUnreachable: true, + pb.MsgSnapStatus: true, + pb.MsgCheckQuorum: true, + pb.MsgStorageAppend: true, + pb.MsgStorageAppendResp: true, + pb.MsgStorageApply: true, + pb.MsgStorageApplyResp: true, } -func max(a, b uint64) uint64 { - if a > b { - return a - } - return b +var isResponseMsg = [...]bool{ + pb.MsgAppResp: true, + pb.MsgVoteResp: true, + pb.MsgHeartbeatResp: true, + pb.MsgUnreachable: true, + pb.MsgReadIndexResp: true, + pb.MsgPreVoteResp: true, + pb.MsgStorageAppendResp: true, + pb.MsgStorageApplyResp: true, +} + +func isMsgInArray(msgt pb.MessageType, arr []bool) bool { + i := int(msgt) + return i < len(arr) && arr[i] } func IsLocalMsg(msgt pb.MessageType) bool { - return msgt == pb.MsgHup || msgt == pb.MsgBeat || msgt == pb.MsgUnreachable || - msgt == pb.MsgSnapStatus || msgt == pb.MsgCheckQuorum + return isMsgInArray(msgt, isLocalMsg[:]) } func IsResponseMsg(msgt pb.MessageType) bool { - return msgt == pb.MsgAppResp || msgt == pb.MsgVoteResp || msgt == pb.MsgHeartbeatResp || msgt == pb.MsgUnreachable || msgt == pb.MsgPreVoteResp + return isMsgInArray(msgt, isResponseMsg[:]) +} + +func IsLocalMsgTarget(id uint64) bool { + return id == LocalAppendThread || id == LocalApplyThread } // voteResponseType maps vote and prevote message types to their corresponding responses. @@ -131,34 +148,57 @@ type EntryFormatter func([]byte) string // DescribeMessage returns a concise human-readable description of a // Message for debugging. func DescribeMessage(m pb.Message, f EntryFormatter) string { + return describeMessageWithIndent("", m, f) +} + +func describeMessageWithIndent(indent string, m pb.Message, f EntryFormatter) string { var buf bytes.Buffer - fmt.Fprintf(&buf, "%x->%x %v Term:%d Log:%d/%d", m.From, m.To, m.Type, m.Term, m.LogTerm, m.Index) + fmt.Fprintf(&buf, "%s%s->%s %v Term:%d Log:%d/%d", indent, + describeTarget(m.From), describeTarget(m.To), m.Type, m.Term, m.LogTerm, m.Index) if m.Reject { fmt.Fprintf(&buf, " Rejected (Hint: %d)", m.RejectHint) } if m.Commit != 0 { fmt.Fprintf(&buf, " Commit:%d", m.Commit) } - if len(m.Entries) > 0 { - fmt.Fprintf(&buf, " Entries:[") - for i, e := range m.Entries { - if i != 0 { - buf.WriteString(", ") - } + if m.Vote != 0 { + fmt.Fprintf(&buf, " Vote:%d", m.Vote) + } + if ln := len(m.Entries); ln == 1 { + fmt.Fprintf(&buf, " Entries:[%s]", DescribeEntry(m.Entries[0], f)) + } else if ln > 1 { + fmt.Fprint(&buf, " Entries:[") + for _, e := range m.Entries { + fmt.Fprintf(&buf, "\n%s ", indent) buf.WriteString(DescribeEntry(e, f)) } - fmt.Fprintf(&buf, "]") + fmt.Fprintf(&buf, "\n%s]", indent) } - if !IsEmptySnap(m.Snapshot) { - fmt.Fprintf(&buf, " Snapshot: %s", DescribeSnapshot(m.Snapshot)) + if s := m.Snapshot; s != nil && !IsEmptySnap(*s) { + fmt.Fprintf(&buf, "\n%s Snapshot: %s", indent, DescribeSnapshot(*s)) + } + if len(m.Responses) > 0 { + fmt.Fprintf(&buf, " Responses:[") + for _, m := range m.Responses { + buf.WriteString("\n") + buf.WriteString(describeMessageWithIndent(indent+" ", m, f)) + } + fmt.Fprintf(&buf, "\n%s]", indent) } return buf.String() } -// PayloadSize is the size of the payload of this Entry. Notably, it does not -// depend on its Index or Term. -func PayloadSize(e pb.Entry) int { - return len(e.Data) +func describeTarget(id uint64) string { + switch id { + case None: + return "None" + case LocalAppendThread: + return "AppendThread" + case LocalApplyThread: + return "ApplyThread" + default: + return fmt.Sprintf("%x", id) + } } // DescribeEntry returns a concise human-readable description of an @@ -209,19 +249,54 @@ func DescribeEntries(ents []pb.Entry, f EntryFormatter) string { return buf.String() } -func limitSize(ents []pb.Entry, maxSize uint64) []pb.Entry { +// entryEncodingSize represents the protocol buffer encoding size of one or more +// entries. +type entryEncodingSize uint64 + +func entsSize(ents []pb.Entry) entryEncodingSize { + var size entryEncodingSize + for _, ent := range ents { + size += entryEncodingSize(ent.Size()) + } + return size +} + +// limitSize returns the longest prefix of the given entries slice, such that +// its total byte size does not exceed maxSize. Always returns a non-empty slice +// if the input is non-empty, so, as an exception, if the size of the first +// entry exceeds maxSize, a non-empty slice with just this entry is returned. +func limitSize(ents []pb.Entry, maxSize entryEncodingSize) []pb.Entry { if len(ents) == 0 { return ents } size := ents[0].Size() - var limit int - for limit = 1; limit < len(ents); limit++ { + for limit := 1; limit < len(ents); limit++ { size += ents[limit].Size() - if uint64(size) > maxSize { - break + if entryEncodingSize(size) > maxSize { + return ents[:limit] } } - return ents[:limit] + return ents +} + +// entryPayloadSize represents the size of one or more entries' payloads. +// Notably, it does not depend on its Index or Term. Entries with empty +// payloads, like those proposed after a leadership change, are considered +// to be zero size. +type entryPayloadSize uint64 + +// payloadSize is the size of the payload of the provided entry. +func payloadSize(e pb.Entry) entryPayloadSize { + return entryPayloadSize(len(e.Data)) +} + +// payloadsSize is the size of the payloads of the provided entries. +func payloadsSize(ents []pb.Entry) entryPayloadSize { + var s entryPayloadSize + for _, e := range ents { + s += payloadSize(e) + } + return s } func assertConfStatesEquivalent(l Logger, cs1, cs2 pb.ConfState) { @@ -231,3 +306,20 @@ func assertConfStatesEquivalent(l Logger, cs1, cs2 pb.ConfState) { } l.Panic(err) } + +// extend appends vals to the given dst slice. It differs from the standard +// slice append only in the way it allocates memory. If cap(dst) is not enough +// for appending the values, precisely size len(dst)+len(vals) is allocated. +// +// Use this instead of standard append in situations when this is the last +// append to dst, so there is no sense in allocating more than needed. +func extend(dst, vals []pb.Entry) []pb.Entry { + need := len(dst) + len(vals) + if need <= cap(dst) { + return append(dst, vals...) // does not allocate + } + buf := make([]pb.Entry, need, need) // allocates precisely what's needed + copy(buf, dst) + copy(buf[len(dst):], vals) + return buf +} diff --git a/etcd/vendor/go.opentelemetry.io/otel/semconv/internal/http.go b/etcd/vendor/go.opentelemetry.io/otel/semconv/internal/http.go deleted file mode 100644 index e9eb577345..0000000000 --- a/etcd/vendor/go.opentelemetry.io/otel/semconv/internal/http.go +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Package internal provides common semconv functionality. -package internal // import "go.opentelemetry.io/otel/semconv/internal" - -import ( - "fmt" - "net" - "net/http" - "strconv" - "strings" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" - "go.opentelemetry.io/otel/trace" -) - -// SemanticConventions are the semantic convention values defined for a -// version of the OpenTelemetry specification. -type SemanticConventions struct { - EnduserIDKey attribute.Key - HTTPClientIPKey attribute.Key - HTTPFlavorKey attribute.Key - HTTPHostKey attribute.Key - HTTPMethodKey attribute.Key - HTTPRequestContentLengthKey attribute.Key - HTTPRouteKey attribute.Key - HTTPSchemeHTTP attribute.KeyValue - HTTPSchemeHTTPS attribute.KeyValue - HTTPServerNameKey attribute.Key - HTTPStatusCodeKey attribute.Key - HTTPTargetKey attribute.Key - HTTPURLKey attribute.Key - HTTPUserAgentKey attribute.Key - NetHostIPKey attribute.Key - NetHostNameKey attribute.Key - NetHostPortKey attribute.Key - NetPeerIPKey attribute.Key - NetPeerNameKey attribute.Key - NetPeerPortKey attribute.Key - NetTransportIP attribute.KeyValue - NetTransportOther attribute.KeyValue - NetTransportTCP attribute.KeyValue - NetTransportUDP attribute.KeyValue - NetTransportUnix attribute.KeyValue -} - -// NetAttributesFromHTTPRequest generates attributes of the net -// namespace as specified by the OpenTelemetry specification for a -// span. The network parameter is a string that net.Dial function -// from standard library can understand. -func (sc *SemanticConventions) NetAttributesFromHTTPRequest( - network string, - request *http.Request, -) []attribute.KeyValue { - attrs := []attribute.KeyValue{} - - switch network { - case "tcp", "tcp4", "tcp6": - attrs = append(attrs, sc.NetTransportTCP) - case "udp", "udp4", "udp6": - attrs = append(attrs, sc.NetTransportUDP) - case "ip", "ip4", "ip6": - attrs = append(attrs, sc.NetTransportIP) - case "unix", "unixgram", "unixpacket": - attrs = append(attrs, sc.NetTransportUnix) - default: - attrs = append(attrs, sc.NetTransportOther) - } - - peerIP, peerName, peerPort := hostIPNamePort(request.RemoteAddr) - if peerIP != "" { - attrs = append(attrs, sc.NetPeerIPKey.String(peerIP)) - } - if peerName != "" { - attrs = append(attrs, sc.NetPeerNameKey.String(peerName)) - } - if peerPort != 0 { - attrs = append(attrs, sc.NetPeerPortKey.Int(peerPort)) - } - - hostIP, hostName, hostPort := "", "", 0 - for _, someHost := range []string{request.Host, request.Header.Get("Host"), request.URL.Host} { - hostIP, hostName, hostPort = hostIPNamePort(someHost) - if hostIP != "" || hostName != "" || hostPort != 0 { - break - } - } - if hostIP != "" { - attrs = append(attrs, sc.NetHostIPKey.String(hostIP)) - } - if hostName != "" { - attrs = append(attrs, sc.NetHostNameKey.String(hostName)) - } - if hostPort != 0 { - attrs = append(attrs, sc.NetHostPortKey.Int(hostPort)) - } - - return attrs -} - -// hostIPNamePort extracts the IP address, name and (optional) port from hostWithPort. -// It handles both IPv4 and IPv6 addresses. If the host portion is not recognized -// as a valid IPv4 or IPv6 address, the `ip` result will be empty and the -// host portion will instead be returned in `name`. -func hostIPNamePort(hostWithPort string) (ip string, name string, port int) { - var ( - hostPart, portPart string - parsedPort uint64 - err error - ) - if hostPart, portPart, err = net.SplitHostPort(hostWithPort); err != nil { - hostPart, portPart = hostWithPort, "" - } - if parsedIP := net.ParseIP(hostPart); parsedIP != nil { - ip = parsedIP.String() - } else { - name = hostPart - } - if parsedPort, err = strconv.ParseUint(portPart, 10, 16); err == nil { - port = int(parsedPort) // nolint: gosec // Bit size of 16 checked above. - } - return -} - -// EndUserAttributesFromHTTPRequest generates attributes of the -// enduser namespace as specified by the OpenTelemetry specification -// for a span. -func (sc *SemanticConventions) EndUserAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue { - if username, _, ok := request.BasicAuth(); ok { - return []attribute.KeyValue{sc.EnduserIDKey.String(username)} - } - return nil -} - -// HTTPClientAttributesFromHTTPRequest generates attributes of the -// http namespace as specified by the OpenTelemetry specification for -// a span on the client side. -func (sc *SemanticConventions) HTTPClientAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue { - attrs := []attribute.KeyValue{} - - // remove any username/password info that may be in the URL - // before adding it to the attributes - userinfo := request.URL.User - request.URL.User = nil - - attrs = append(attrs, sc.HTTPURLKey.String(request.URL.String())) - - // restore any username/password info that was removed - request.URL.User = userinfo - - return append(attrs, sc.httpCommonAttributesFromHTTPRequest(request)...) -} - -func (sc *SemanticConventions) httpCommonAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue { - attrs := []attribute.KeyValue{} - if ua := request.UserAgent(); ua != "" { - attrs = append(attrs, sc.HTTPUserAgentKey.String(ua)) - } - if request.ContentLength > 0 { - attrs = append(attrs, sc.HTTPRequestContentLengthKey.Int64(request.ContentLength)) - } - - return append(attrs, sc.httpBasicAttributesFromHTTPRequest(request)...) -} - -func (sc *SemanticConventions) httpBasicAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue { - // as these attributes are used by HTTPServerMetricAttributesFromHTTPRequest, they should be low-cardinality - attrs := []attribute.KeyValue{} - - if request.TLS != nil { - attrs = append(attrs, sc.HTTPSchemeHTTPS) - } else { - attrs = append(attrs, sc.HTTPSchemeHTTP) - } - - if request.Host != "" { - attrs = append(attrs, sc.HTTPHostKey.String(request.Host)) - } else if request.URL != nil && request.URL.Host != "" { - attrs = append(attrs, sc.HTTPHostKey.String(request.URL.Host)) - } - - flavor := "" - switch request.ProtoMajor { - case 1: - flavor = fmt.Sprintf("1.%d", request.ProtoMinor) - case 2: - flavor = "2" - } - if flavor != "" { - attrs = append(attrs, sc.HTTPFlavorKey.String(flavor)) - } - - if request.Method != "" { - attrs = append(attrs, sc.HTTPMethodKey.String(request.Method)) - } else { - attrs = append(attrs, sc.HTTPMethodKey.String(http.MethodGet)) - } - - return attrs -} - -// HTTPServerMetricAttributesFromHTTPRequest generates low-cardinality attributes -// to be used with server-side HTTP metrics. -func (sc *SemanticConventions) HTTPServerMetricAttributesFromHTTPRequest( - serverName string, - request *http.Request, -) []attribute.KeyValue { - attrs := []attribute.KeyValue{} - if serverName != "" { - attrs = append(attrs, sc.HTTPServerNameKey.String(serverName)) - } - return append(attrs, sc.httpBasicAttributesFromHTTPRequest(request)...) -} - -// HTTPServerAttributesFromHTTPRequest generates attributes of the -// http namespace as specified by the OpenTelemetry specification for -// a span on the server side. Currently, only basic authentication is -// supported. -func (sc *SemanticConventions) HTTPServerAttributesFromHTTPRequest( - serverName, route string, - request *http.Request, -) []attribute.KeyValue { - attrs := []attribute.KeyValue{ - sc.HTTPTargetKey.String(request.RequestURI), - } - - if serverName != "" { - attrs = append(attrs, sc.HTTPServerNameKey.String(serverName)) - } - if route != "" { - attrs = append(attrs, sc.HTTPRouteKey.String(route)) - } - if values := request.Header["X-Forwarded-For"]; len(values) > 0 { - addr := values[0] - if i := strings.Index(addr, ","); i > 0 { - addr = addr[:i] - } - attrs = append(attrs, sc.HTTPClientIPKey.String(addr)) - } - - return append(attrs, sc.httpCommonAttributesFromHTTPRequest(request)...) -} - -// HTTPAttributesFromHTTPStatusCode generates attributes of the http -// namespace as specified by the OpenTelemetry specification for a -// span. -func (sc *SemanticConventions) HTTPAttributesFromHTTPStatusCode(code int) []attribute.KeyValue { - attrs := []attribute.KeyValue{ - sc.HTTPStatusCodeKey.Int(code), - } - return attrs -} - -type codeRange struct { - fromInclusive int - toInclusive int -} - -func (r codeRange) contains(code int) bool { - return r.fromInclusive <= code && code <= r.toInclusive -} - -var validRangesPerCategory = map[int][]codeRange{ - 1: { - {http.StatusContinue, http.StatusEarlyHints}, - }, - 2: { - {http.StatusOK, http.StatusAlreadyReported}, - {http.StatusIMUsed, http.StatusIMUsed}, - }, - 3: { - {http.StatusMultipleChoices, http.StatusUseProxy}, - {http.StatusTemporaryRedirect, http.StatusPermanentRedirect}, - }, - 4: { - {http.StatusBadRequest, http.StatusTeapot}, // yes, teapot is so useful… - {http.StatusMisdirectedRequest, http.StatusUpgradeRequired}, - {http.StatusPreconditionRequired, http.StatusTooManyRequests}, - {http.StatusRequestHeaderFieldsTooLarge, http.StatusRequestHeaderFieldsTooLarge}, - {http.StatusUnavailableForLegalReasons, http.StatusUnavailableForLegalReasons}, - }, - 5: { - {http.StatusInternalServerError, http.StatusLoopDetected}, - {http.StatusNotExtended, http.StatusNetworkAuthenticationRequired}, - }, -} - -// SpanStatusFromHTTPStatusCode generates a status code and a message -// as specified by the OpenTelemetry specification for a span. -func SpanStatusFromHTTPStatusCode(code int) (codes.Code, string) { - spanCode, valid := validateHTTPStatusCode(code) - if !valid { - return spanCode, fmt.Sprintf("Invalid HTTP status code %d", code) - } - return spanCode, "" -} - -// SpanStatusFromHTTPStatusCodeAndSpanKind generates a status code and a message -// as specified by the OpenTelemetry specification for a span. -// Exclude 4xx for SERVER to set the appropriate status. -func SpanStatusFromHTTPStatusCodeAndSpanKind(code int, spanKind trace.SpanKind) (codes.Code, string) { - spanCode, valid := validateHTTPStatusCode(code) - if !valid { - return spanCode, fmt.Sprintf("Invalid HTTP status code %d", code) - } - category := code / 100 - if spanKind == trace.SpanKindServer && category == 4 { - return codes.Unset, "" - } - return spanCode, "" -} - -// validateHTTPStatusCode validates the HTTP status code and returns -// corresponding span status code. If the `code` is not a valid HTTP status -// code, returns span status Error and false. -func validateHTTPStatusCode(code int) (codes.Code, bool) { - category := code / 100 - ranges, ok := validRangesPerCategory[category] - if !ok { - return codes.Error, false - } - ok = false - for _, crange := range ranges { - ok = crange.contains(code) - if ok { - break - } - } - if !ok { - return codes.Error, false - } - if category > 0 && category < 4 { - return codes.Unset, true - } - return codes.Error, true -} diff --git a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/README.md b/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/README.md deleted file mode 100644 index cfbc9055b3..0000000000 --- a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Semconv v1.4.0 - -[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/otel/semconv/v1.4.0)](https://pkg.go.dev/go.opentelemetry.io/otel/semconv/v1.4.0) diff --git a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/doc.go b/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/doc.go deleted file mode 100644 index d83a66b9b4..0000000000 --- a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Package semconv implements OpenTelemetry semantic conventions. -// -// OpenTelemetry semantic conventions are agreed standardized naming -// patterns for OpenTelemetry things. This package represents the conventions -// as of the v1.4.0 version of the OpenTelemetry specification. -package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0" diff --git a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/exception.go b/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/exception.go deleted file mode 100644 index 71a2ece3d3..0000000000 --- a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/exception.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0" - -const ( - // ExceptionEventName is the name of the Span event representing an exception. - ExceptionEventName = "exception" -) diff --git a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/http.go b/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/http.go deleted file mode 100644 index f0c023cafb..0000000000 --- a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/http.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0" - -import ( - "net/http" - - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/codes" - "go.opentelemetry.io/otel/semconv/internal" - "go.opentelemetry.io/otel/trace" -) - -// HTTP scheme attributes. -var ( - HTTPSchemeHTTP = HTTPSchemeKey.String("http") - HTTPSchemeHTTPS = HTTPSchemeKey.String("https") -) - -var sc = &internal.SemanticConventions{ - EnduserIDKey: EnduserIDKey, - HTTPClientIPKey: HTTPClientIPKey, - HTTPFlavorKey: HTTPFlavorKey, - HTTPHostKey: HTTPHostKey, - HTTPMethodKey: HTTPMethodKey, - HTTPRequestContentLengthKey: HTTPRequestContentLengthKey, - HTTPRouteKey: HTTPRouteKey, - HTTPSchemeHTTP: HTTPSchemeHTTP, - HTTPSchemeHTTPS: HTTPSchemeHTTPS, - HTTPServerNameKey: HTTPServerNameKey, - HTTPStatusCodeKey: HTTPStatusCodeKey, - HTTPTargetKey: HTTPTargetKey, - HTTPURLKey: HTTPURLKey, - HTTPUserAgentKey: HTTPUserAgentKey, - NetHostIPKey: NetHostIPKey, - NetHostNameKey: NetHostNameKey, - NetHostPortKey: NetHostPortKey, - NetPeerIPKey: NetPeerIPKey, - NetPeerNameKey: NetPeerNameKey, - NetPeerPortKey: NetPeerPortKey, - NetTransportIP: NetTransportIP, - NetTransportOther: NetTransportOther, - NetTransportTCP: NetTransportTCP, - NetTransportUDP: NetTransportUDP, - NetTransportUnix: NetTransportUnix, -} - -// NetAttributesFromHTTPRequest generates attributes of the net -// namespace as specified by the OpenTelemetry specification for a -// span. The network parameter is a string that net.Dial function -// from standard library can understand. -func NetAttributesFromHTTPRequest(network string, request *http.Request) []attribute.KeyValue { - return sc.NetAttributesFromHTTPRequest(network, request) -} - -// EndUserAttributesFromHTTPRequest generates attributes of the -// enduser namespace as specified by the OpenTelemetry specification -// for a span. -func EndUserAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue { - return sc.EndUserAttributesFromHTTPRequest(request) -} - -// HTTPClientAttributesFromHTTPRequest generates attributes of the -// http namespace as specified by the OpenTelemetry specification for -// a span on the client side. -func HTTPClientAttributesFromHTTPRequest(request *http.Request) []attribute.KeyValue { - return sc.HTTPClientAttributesFromHTTPRequest(request) -} - -// HTTPServerMetricAttributesFromHTTPRequest generates low-cardinality attributes -// to be used with server-side HTTP metrics. -func HTTPServerMetricAttributesFromHTTPRequest(serverName string, request *http.Request) []attribute.KeyValue { - return sc.HTTPServerMetricAttributesFromHTTPRequest(serverName, request) -} - -// HTTPServerAttributesFromHTTPRequest generates attributes of the -// http namespace as specified by the OpenTelemetry specification for -// a span on the server side. Currently, only basic authentication is -// supported. -func HTTPServerAttributesFromHTTPRequest(serverName, route string, request *http.Request) []attribute.KeyValue { - return sc.HTTPServerAttributesFromHTTPRequest(serverName, route, request) -} - -// HTTPAttributesFromHTTPStatusCode generates attributes of the http -// namespace as specified by the OpenTelemetry specification for a -// span. -func HTTPAttributesFromHTTPStatusCode(code int) []attribute.KeyValue { - return sc.HTTPAttributesFromHTTPStatusCode(code) -} - -// SpanStatusFromHTTPStatusCode generates a status code and a message -// as specified by the OpenTelemetry specification for a span. -func SpanStatusFromHTTPStatusCode(code int) (codes.Code, string) { - return internal.SpanStatusFromHTTPStatusCode(code) -} - -// SpanStatusFromHTTPStatusCodeAndSpanKind generates a status code and a message -// as specified by the OpenTelemetry specification for a span. -// Exclude 4xx for SERVER to set the appropriate status. -func SpanStatusFromHTTPStatusCodeAndSpanKind(code int, spanKind trace.SpanKind) (codes.Code, string) { - return internal.SpanStatusFromHTTPStatusCodeAndSpanKind(code, spanKind) -} diff --git a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/resource.go b/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/resource.go deleted file mode 100644 index 66c340c121..0000000000 --- a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/resource.go +++ /dev/null @@ -1,895 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated from semantic convention specification. DO NOT EDIT. - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0" - -import "go.opentelemetry.io/otel/attribute" - -// A cloud environment (e.g. GCP, Azure, AWS) -const ( - // Name of the cloud provider. - // - // Type: Enum - // Required: No - // Stability: stable - // Examples: 'gcp' - CloudProviderKey = attribute.Key("cloud.provider") - // The cloud account ID the resource is assigned to. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '111111111111', 'opentelemetry' - CloudAccountIDKey = attribute.Key("cloud.account.id") - // The geographical region the resource is running. Refer to your provider's docs - // to see the available regions, for example [AWS - // regions](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/), - // [Azure regions](https://azure.microsoft.com/en-us/global- - // infrastructure/geographies/), or [Google Cloud - // regions](https://cloud.google.com/about/locations). - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'us-central1', 'us-east-1' - CloudRegionKey = attribute.Key("cloud.region") - // Cloud regions often have multiple, isolated locations known as zones to - // increase availability. Availability zone represents the zone where the resource - // is running. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'us-east-1c' - // Note: Availability zones are called "zones" on Google Cloud. - CloudAvailabilityZoneKey = attribute.Key("cloud.availability_zone") - // The cloud platform in use. - // - // Type: Enum - // Required: No - // Stability: stable - // Examples: 'aws_ec2', 'azure_vm', 'gcp_compute_engine' - // Note: The prefix of the service SHOULD match the one specified in - // `cloud.provider`. - CloudPlatformKey = attribute.Key("cloud.platform") -) - -var ( - // Amazon Web Services - CloudProviderAWS = CloudProviderKey.String("aws") - // Microsoft Azure - CloudProviderAzure = CloudProviderKey.String("azure") - // Google Cloud Platform - CloudProviderGCP = CloudProviderKey.String("gcp") -) - -var ( - // AWS Elastic Compute Cloud - CloudPlatformAWSEC2 = CloudPlatformKey.String("aws_ec2") - // AWS Elastic Container Service - CloudPlatformAWSECS = CloudPlatformKey.String("aws_ecs") - // AWS Elastic Kubernetes Service - CloudPlatformAWSEKS = CloudPlatformKey.String("aws_eks") - // AWS Lambda - CloudPlatformAWSLambda = CloudPlatformKey.String("aws_lambda") - // AWS Elastic Beanstalk - CloudPlatformAWSElasticBeanstalk = CloudPlatformKey.String("aws_elastic_beanstalk") - // Azure Virtual Machines - CloudPlatformAzureVM = CloudPlatformKey.String("azure_vm") - // Azure Container Instances - CloudPlatformAzureContainerInstances = CloudPlatformKey.String("azure_container_instances") - // Azure Kubernetes Service - CloudPlatformAzureAKS = CloudPlatformKey.String("azure_aks") - // Azure Functions - CloudPlatformAzureFunctions = CloudPlatformKey.String("azure_functions") - // Azure App Service - CloudPlatformAzureAppService = CloudPlatformKey.String("azure_app_service") - // Google Cloud Compute Engine (GCE) - CloudPlatformGCPComputeEngine = CloudPlatformKey.String("gcp_compute_engine") - // Google Cloud Run - CloudPlatformGCPCloudRun = CloudPlatformKey.String("gcp_cloud_run") - // Google Cloud Kubernetes Engine (GKE) - CloudPlatformGCPKubernetesEngine = CloudPlatformKey.String("gcp_kubernetes_engine") - // Google Cloud Functions (GCF) - CloudPlatformGCPCloudFunctions = CloudPlatformKey.String("gcp_cloud_functions") - // Google Cloud App Engine (GAE) - CloudPlatformGCPAppEngine = CloudPlatformKey.String("gcp_app_engine") -) - -// Resources used by AWS Elastic Container Service (ECS). -const ( - // The Amazon Resource Name (ARN) of an [ECS container instance](https://docs.aws. - // amazon.com/AmazonECS/latest/developerguide/ECS_instances.html). - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'arn:aws:ecs:us- - // west-1:123456789123:container/32624152-9086-4f0e-acae-1a75b14fe4d9' - AWSECSContainerARNKey = attribute.Key("aws.ecs.container.arn") - // The ARN of an [ECS cluster](https://docs.aws.amazon.com/AmazonECS/latest/develo - // perguide/clusters.html). - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' - AWSECSClusterARNKey = attribute.Key("aws.ecs.cluster.arn") - // The [launch type](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/l - // aunch_types.html) for an ECS task. - // - // Type: Enum - // Required: No - // Stability: stable - // Examples: 'ec2', 'fargate' - AWSECSLaunchtypeKey = attribute.Key("aws.ecs.launchtype") - // The ARN of an [ECS task definition](https://docs.aws.amazon.com/AmazonECS/lates - // t/developerguide/task_definitions.html). - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'arn:aws:ecs:us- - // west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b' - AWSECSTaskARNKey = attribute.Key("aws.ecs.task.arn") - // The task definition family this task definition is a member of. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry-family' - AWSECSTaskFamilyKey = attribute.Key("aws.ecs.task.family") - // The revision for this task definition. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '8', '26' - AWSECSTaskRevisionKey = attribute.Key("aws.ecs.task.revision") -) - -var ( - // ec2 - AWSECSLaunchtypeEC2 = AWSECSLaunchtypeKey.String("ec2") - // fargate - AWSECSLaunchtypeFargate = AWSECSLaunchtypeKey.String("fargate") -) - -// Resources used by AWS Elastic Kubernetes Service (EKS). -const ( - // The ARN of an EKS cluster. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' - AWSEKSClusterARNKey = attribute.Key("aws.eks.cluster.arn") -) - -// Resources specific to Amazon Web Services. -const ( - // The name(s) of the AWS log group(s) an application is writing to. - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: '/aws/lambda/my-function', 'opentelemetry-service' - // Note: Multiple log groups must be supported for cases like multi-container - // applications, where a single application has sidecar containers, and each write - // to their own log group. - AWSLogGroupNamesKey = attribute.Key("aws.log.group.names") - // The Amazon Resource Name(s) (ARN) of the AWS log group(s). - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:*' - // Note: See the [log group ARN format - // documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam- - // access-control-overview-cwl.html#CWL_ARN_Format). - AWSLogGroupARNsKey = attribute.Key("aws.log.group.arns") - // The name(s) of the AWS log stream(s) an application is writing to. - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: 'logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' - AWSLogStreamNamesKey = attribute.Key("aws.log.stream.names") - // The ARN(s) of the AWS log stream(s). - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:log- - // stream:logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' - // Note: See the [log stream ARN format - // documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam- - // access-control-overview-cwl.html#CWL_ARN_Format). One log group can contain - // several log streams, so these ARNs necessarily identify both a log group and a - // log stream. - AWSLogStreamARNsKey = attribute.Key("aws.log.stream.arns") -) - -// A container instance. -const ( - // Container name. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry-autoconf' - ContainerNameKey = attribute.Key("container.name") - // Container ID. Usually a UUID, as for example used to [identify Docker - // containers](https://docs.docker.com/engine/reference/run/#container- - // identification). The UUID might be abbreviated. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'a3bf90e006b2' - ContainerIDKey = attribute.Key("container.id") - // The container runtime managing this container. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'docker', 'containerd', 'rkt' - ContainerRuntimeKey = attribute.Key("container.runtime") - // Name of the image the container was built on. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'gcr.io/opentelemetry/operator' - ContainerImageNameKey = attribute.Key("container.image.name") - // Container image tag. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '0.1' - ContainerImageTagKey = attribute.Key("container.image.tag") -) - -// The software deployment. -const ( - // Name of the [deployment - // environment](https://en.wikipedia.org/wiki/Deployment_environment) (aka - // deployment tier). - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'staging', 'production' - DeploymentEnvironmentKey = attribute.Key("deployment.environment") -) - -// The device on which the process represented by this resource is running. -const ( - // A unique identifier representing the device - // - // Type: string - // Required: No - // Stability: stable - // Examples: '2ab2916d-a51f-4ac8-80ee-45ac31a28092' - // Note: The device identifier MUST only be defined using the values outlined - // below. This value is not an advertising identifier and MUST NOT be used as - // such. On iOS (Swift or Objective-C), this value MUST be equal to the [vendor id - // entifier](https://developer.apple.com/documentation/uikit/uidevice/1620059-iden - // tifierforvendor). On Android (Java or Kotlin), this value MUST be equal to the - // Firebase Installation ID or a globally unique UUID which is persisted across - // sessions in your application. More information can be found - // [here](https://developer.android.com/training/articles/user-data-ids) on best - // practices and exact implementation details. Caution should be taken when - // storing personal data or anything which can identify a user. GDPR and data - // protection laws may apply, ensure you do your own due diligence. - DeviceIDKey = attribute.Key("device.id") - // The model identifier for the device - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'iPhone3,4', 'SM-G920F' - // Note: It's recommended this value represents a machine readable version of the - // model identifier rather than the market or consumer-friendly name of the - // device. - DeviceModelIdentifierKey = attribute.Key("device.model.identifier") - // The marketing name for the device model - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'iPhone 6s Plus', 'Samsung Galaxy S6' - // Note: It's recommended this value represents a human readable version of the - // device model rather than a machine readable alternative. - DeviceModelNameKey = attribute.Key("device.model.name") -) - -// A serverless instance. -const ( - // The name of the function being executed. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'my-function' - FaaSNameKey = attribute.Key("faas.name") - // The unique ID of the function being executed. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'arn:aws:lambda:us-west-2:123456789012:function:my-function' - // Note: For example, in AWS Lambda this field corresponds to the - // [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and- - // namespaces.html) value, in GCP to the URI of the resource, and in Azure to the - // [FunctionDirectory](https://github.com/Azure/azure-functions- - // host/wiki/Retrieving-information-about-the-currently-running-function) field. - FaaSIDKey = attribute.Key("faas.id") - // The version string of the function being executed as defined in [Version - // Attributes](../../resource/semantic_conventions/README.md#version-attributes). - // - // Type: string - // Required: No - // Stability: stable - // Examples: '2.0.0' - FaaSVersionKey = attribute.Key("faas.version") - // The execution environment ID as a string. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'my-function:instance-0001' - FaaSInstanceKey = attribute.Key("faas.instance") - // The amount of memory available to the serverless function in MiB. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 128 - // Note: It's recommended to set this attribute since e.g. too little memory can - // easily stop a Java AWS Lambda function from working correctly. On AWS Lambda, - // the environment variable `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` provides this - // information. - FaaSMaxMemoryKey = attribute.Key("faas.max_memory") -) - -// A host is defined as a general computing instance. -const ( - // Unique host ID. For Cloud, this must be the instance_id assigned by the cloud - // provider. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry-test' - HostIDKey = attribute.Key("host.id") - // Name of the host. On Unix systems, it may contain what the hostname command - // returns, or the fully qualified hostname, or another name specified by the - // user. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry-test' - HostNameKey = attribute.Key("host.name") - // Type of host. For Cloud, this must be the machine type. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'n1-standard-1' - HostTypeKey = attribute.Key("host.type") - // The CPU architecture the host system is running on. - // - // Type: Enum - // Required: No - // Stability: stable - HostArchKey = attribute.Key("host.arch") - // Name of the VM image or OS install the host was instantiated from. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'infra-ami-eks-worker-node-7d4ec78312', 'CentOS-8-x86_64-1905' - HostImageNameKey = attribute.Key("host.image.name") - // VM image ID. For Cloud, this value is from the provider. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'ami-07b06b442921831e5' - HostImageIDKey = attribute.Key("host.image.id") - // The version string of the VM image as defined in [Version - // Attributes](README.md#version-attributes). - // - // Type: string - // Required: No - // Stability: stable - // Examples: '0.1' - HostImageVersionKey = attribute.Key("host.image.version") -) - -var ( - // AMD64 - HostArchAMD64 = HostArchKey.String("amd64") - // ARM32 - HostArchARM32 = HostArchKey.String("arm32") - // ARM64 - HostArchARM64 = HostArchKey.String("arm64") - // Itanium - HostArchIA64 = HostArchKey.String("ia64") - // 32-bit PowerPC - HostArchPPC32 = HostArchKey.String("ppc32") - // 64-bit PowerPC - HostArchPPC64 = HostArchKey.String("ppc64") - // 32-bit x86 - HostArchX86 = HostArchKey.String("x86") -) - -// A Kubernetes Cluster. -const ( - // The name of the cluster. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry-cluster' - K8SClusterNameKey = attribute.Key("k8s.cluster.name") -) - -// A Kubernetes Node object. -const ( - // The name of the Node. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'node-1' - K8SNodeNameKey = attribute.Key("k8s.node.name") - // The UID of the Node. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2' - K8SNodeUIDKey = attribute.Key("k8s.node.uid") -) - -// A Kubernetes Namespace. -const ( - // The name of the namespace that the pod is running in. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'default' - K8SNamespaceNameKey = attribute.Key("k8s.namespace.name") -) - -// A Kubernetes Pod object. -const ( - // The UID of the Pod. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SPodUIDKey = attribute.Key("k8s.pod.uid") - // The name of the Pod. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry-pod-autoconf' - K8SPodNameKey = attribute.Key("k8s.pod.name") -) - -// A container in a [PodTemplate](https://kubernetes.io/docs/concepts/workloads/pods/#pod-templates). -const ( - // The name of the Container in a Pod template. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'redis' - K8SContainerNameKey = attribute.Key("k8s.container.name") -) - -// A Kubernetes ReplicaSet object. -const ( - // The UID of the ReplicaSet. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SReplicasetUIDKey = attribute.Key("k8s.replicaset.uid") - // The name of the ReplicaSet. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry' - K8SReplicasetNameKey = attribute.Key("k8s.replicaset.name") -) - -// A Kubernetes Deployment object. -const ( - // The UID of the Deployment. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SDeploymentUIDKey = attribute.Key("k8s.deployment.uid") - // The name of the Deployment. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry' - K8SDeploymentNameKey = attribute.Key("k8s.deployment.name") -) - -// A Kubernetes StatefulSet object. -const ( - // The UID of the StatefulSet. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SStatefulsetUIDKey = attribute.Key("k8s.statefulset.uid") - // The name of the StatefulSet. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry' - K8SStatefulsetNameKey = attribute.Key("k8s.statefulset.name") -) - -// A Kubernetes DaemonSet object. -const ( - // The UID of the DaemonSet. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SDaemonsetUIDKey = attribute.Key("k8s.daemonset.uid") - // The name of the DaemonSet. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry' - K8SDaemonsetNameKey = attribute.Key("k8s.daemonset.name") -) - -// A Kubernetes Job object. -const ( - // The UID of the Job. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SJobUIDKey = attribute.Key("k8s.job.uid") - // The name of the Job. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry' - K8SJobNameKey = attribute.Key("k8s.job.name") -) - -// A Kubernetes CronJob object. -const ( - // The UID of the CronJob. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' - K8SCronJobUIDKey = attribute.Key("k8s.cronjob.uid") - // The name of the CronJob. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry' - K8SCronJobNameKey = attribute.Key("k8s.cronjob.name") -) - -// The operating system (OS) on which the process represented by this resource is running. -const ( - // The operating system type. - // - // Type: Enum - // Required: Always - // Stability: stable - OSTypeKey = attribute.Key("os.type") - // Human readable (not intended to be parsed) OS version information, like e.g. - // reported by `ver` or `lsb_release -a` commands. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'Microsoft Windows [Version 10.0.18363.778]', 'Ubuntu 18.04.1 LTS' - OSDescriptionKey = attribute.Key("os.description") - // Human readable operating system name. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'iOS', 'Android', 'Ubuntu' - OSNameKey = attribute.Key("os.name") - // The version string of the operating system as defined in [Version - // Attributes](../../resource/semantic_conventions/README.md#version-attributes). - // - // Type: string - // Required: No - // Stability: stable - // Examples: '14.2.1', '18.04.1' - OSVersionKey = attribute.Key("os.version") -) - -var ( - // Microsoft Windows - OSTypeWindows = OSTypeKey.String("windows") - // Linux - OSTypeLinux = OSTypeKey.String("linux") - // Apple Darwin - OSTypeDarwin = OSTypeKey.String("darwin") - // FreeBSD - OSTypeFreeBSD = OSTypeKey.String("freebsd") - // NetBSD - OSTypeNetBSD = OSTypeKey.String("netbsd") - // OpenBSD - OSTypeOpenBSD = OSTypeKey.String("openbsd") - // DragonFly BSD - OSTypeDragonflyBSD = OSTypeKey.String("dragonflybsd") - // HP-UX (Hewlett Packard Unix) - OSTypeHPUX = OSTypeKey.String("hpux") - // AIX (Advanced Interactive eXecutive) - OSTypeAIX = OSTypeKey.String("aix") - // Oracle Solaris - OSTypeSolaris = OSTypeKey.String("solaris") - // IBM z/OS - OSTypeZOS = OSTypeKey.String("z_os") -) - -// An operating system process. -const ( - // Process identifier (PID). - // - // Type: int - // Required: No - // Stability: stable - // Examples: 1234 - ProcessPIDKey = attribute.Key("process.pid") - // The name of the process executable. On Linux based systems, can be set to the - // `Name` in `proc/[pid]/status`. On Windows, can be set to the base name of - // `GetProcessImageFileNameW`. - // - // Type: string - // Required: See below - // Stability: stable - // Examples: 'otelcol' - ProcessExecutableNameKey = attribute.Key("process.executable.name") - // The full path to the process executable. On Linux based systems, can be set to - // the target of `proc/[pid]/exe`. On Windows, can be set to the result of - // `GetProcessImageFileNameW`. - // - // Type: string - // Required: See below - // Stability: stable - // Examples: '/usr/bin/cmd/otelcol' - ProcessExecutablePathKey = attribute.Key("process.executable.path") - // The command used to launch the process (i.e. the command name). On Linux based - // systems, can be set to the zeroth string in `proc/[pid]/cmdline`. On Windows, - // can be set to the first parameter extracted from `GetCommandLineW`. - // - // Type: string - // Required: See below - // Stability: stable - // Examples: 'cmd/otelcol' - ProcessCommandKey = attribute.Key("process.command") - // The full command used to launch the process as a single string representing the - // full command. On Windows, can be set to the result of `GetCommandLineW`. Do not - // set this if you have to assemble it just for monitoring; use - // `process.command_args` instead. - // - // Type: string - // Required: See below - // Stability: stable - // Examples: 'C:\\cmd\\otecol --config="my directory\\config.yaml"' - ProcessCommandLineKey = attribute.Key("process.command_line") - // All the command arguments (including the command/executable itself) as received - // by the process. On Linux-based systems (and some other Unixoid systems - // supporting procfs), can be set according to the list of null-delimited strings - // extracted from `proc/[pid]/cmdline`. For libc-based executables, this would be - // the full argv vector passed to `main`. - // - // Type: string[] - // Required: See below - // Stability: stable - // Examples: 'cmd/otecol', '--config=config.yaml' - ProcessCommandArgsKey = attribute.Key("process.command_args") - // The username of the user that owns the process. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'root' - ProcessOwnerKey = attribute.Key("process.owner") -) - -// The single (language) runtime instance which is monitored. -const ( - // The name of the runtime of this process. For compiled native binaries, this - // SHOULD be the name of the compiler. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'OpenJDK Runtime Environment' - ProcessRuntimeNameKey = attribute.Key("process.runtime.name") - // The version of the runtime of this process, as returned by the runtime without - // modification. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '14.0.2' - ProcessRuntimeVersionKey = attribute.Key("process.runtime.version") - // An additional description about the runtime of the process, for example a - // specific vendor customization of the runtime environment. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'Eclipse OpenJ9 Eclipse OpenJ9 VM openj9-0.21.0' - ProcessRuntimeDescriptionKey = attribute.Key("process.runtime.description") -) - -// A service instance. -const ( - // Logical name of the service. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'shoppingcart' - // Note: MUST be the same for all instances of horizontally scaled services. If - // the value was not specified, SDKs MUST fallback to `unknown_service:` - // concatenated with [`process.executable.name`](process.md#process), e.g. - // `unknown_service:bash`. If `process.executable.name` is not available, the - // value MUST be set to `unknown_service`. - ServiceNameKey = attribute.Key("service.name") - // A namespace for `service.name`. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'Shop' - // Note: A string value having a meaning that helps to distinguish a group of - // services, for example the team name that owns a group of services. - // `service.name` is expected to be unique within the same namespace. If - // `service.namespace` is not specified in the Resource then `service.name` is - // expected to be unique for all services that have no explicit namespace defined - // (so the empty/unspecified namespace is simply one more valid namespace). Zero- - // length namespace string is assumed equal to unspecified namespace. - ServiceNamespaceKey = attribute.Key("service.namespace") - // The string ID of the service instance. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '627cc493-f310-47de-96bd-71410b7dec09' - // Note: MUST be unique for each instance of the same - // `service.namespace,service.name` pair (in other words - // `service.namespace,service.name,service.instance.id` triplet MUST be globally - // unique). The ID helps to distinguish instances of the same service that exist - // at the same time (e.g. instances of a horizontally scaled service). It is - // preferable for the ID to be persistent and stay the same for the lifetime of - // the service instance, however it is acceptable that the ID is ephemeral and - // changes during important lifetime events for the service (e.g. service - // restarts). If the service has no inherent unique ID that can be used as the - // value of this attribute it is recommended to generate a random Version 1 or - // Version 4 RFC 4122 UUID (services aiming for reproducible UUIDs may also use - // Version 5, see RFC 4122 for more recommendations). - ServiceInstanceIDKey = attribute.Key("service.instance.id") - // The version string of the service API or implementation. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '2.0.0' - ServiceVersionKey = attribute.Key("service.version") -) - -// The telemetry SDK used to capture data recorded by the instrumentation libraries. -const ( - // The name of the telemetry SDK as defined above. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'opentelemetry' - TelemetrySDKNameKey = attribute.Key("telemetry.sdk.name") - // The language of the telemetry SDK. - // - // Type: Enum - // Required: No - // Stability: stable - TelemetrySDKLanguageKey = attribute.Key("telemetry.sdk.language") - // The version string of the telemetry SDK. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '1.2.3' - TelemetrySDKVersionKey = attribute.Key("telemetry.sdk.version") - // The version string of the auto instrumentation agent, if used. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '1.2.3' - TelemetryAutoVersionKey = attribute.Key("telemetry.auto.version") -) - -var ( - // cpp - TelemetrySDKLanguageCPP = TelemetrySDKLanguageKey.String("cpp") - // dotnet - TelemetrySDKLanguageDotnet = TelemetrySDKLanguageKey.String("dotnet") - // erlang - TelemetrySDKLanguageErlang = TelemetrySDKLanguageKey.String("erlang") - // go - TelemetrySDKLanguageGo = TelemetrySDKLanguageKey.String("go") - // java - TelemetrySDKLanguageJava = TelemetrySDKLanguageKey.String("java") - // nodejs - TelemetrySDKLanguageNodejs = TelemetrySDKLanguageKey.String("nodejs") - // php - TelemetrySDKLanguagePHP = TelemetrySDKLanguageKey.String("php") - // python - TelemetrySDKLanguagePython = TelemetrySDKLanguageKey.String("python") - // ruby - TelemetrySDKLanguageRuby = TelemetrySDKLanguageKey.String("ruby") - // webjs - TelemetrySDKLanguageWebjs = TelemetrySDKLanguageKey.String("webjs") -) - -// Resource describing the packaged software running the application code. Web engines are typically executed using process.runtime. -const ( - // The name of the web engine. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'WildFly' - WebEngineNameKey = attribute.Key("webengine.name") - // The version of the web engine. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '21.0.0' - WebEngineVersionKey = attribute.Key("webengine.version") - // Additional description of the web engine (e.g. detailed version and edition - // information). - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) - 2.2.2.Final' - WebEngineDescriptionKey = attribute.Key("webengine.description") -) diff --git a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/schema.go b/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/schema.go deleted file mode 100644 index b9457bc0b8..0000000000 --- a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/schema.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0" - -// SchemaURL is the schema URL that matches the version of the semantic conventions -// that this package defines. Semconv packages starting from v1.4.0 must declare -// non-empty schema URL in the form https://opentelemetry.io/schemas/ -const SchemaURL = "https://opentelemetry.io/schemas/1.4.0" diff --git a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/trace.go b/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/trace.go deleted file mode 100644 index 006482a307..0000000000 --- a/etcd/vendor/go.opentelemetry.io/otel/semconv/v1.4.0/trace.go +++ /dev/null @@ -1,1367 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -// Code generated from semantic convention specification. DO NOT EDIT. - -package semconv // import "go.opentelemetry.io/otel/semconv/v1.4.0" - -import "go.opentelemetry.io/otel/attribute" - -// This document defines the attributes used to perform database client calls. -const ( - // An identifier for the database management system (DBMS) product being used. See - // below for a list of well-known identifiers. - // - // Type: Enum - // Required: Always - // Stability: stable - DBSystemKey = attribute.Key("db.system") - // The connection string used to connect to the database. It is recommended to - // remove embedded credentials. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'Server=(localdb)\\v11.0;Integrated Security=true;' - DBConnectionStringKey = attribute.Key("db.connection_string") - // Username for accessing the database. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'readonly_user', 'reporting_user' - DBUserKey = attribute.Key("db.user") - // The fully-qualified class name of the [Java Database Connectivity - // (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) driver - // used to connect. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'org.postgresql.Driver', - // 'com.microsoft.sqlserver.jdbc.SQLServerDriver' - DBJDBCDriverClassnameKey = attribute.Key("db.jdbc.driver_classname") - // If no [tech-specific attribute](#call-level-attributes-for-specific- - // technologies) is defined, this attribute is used to report the name of the - // database being accessed. For commands that switch the database, this should be - // set to the target database (even if the command fails). - // - // Type: string - // Required: Required, if applicable and no more-specific attribute is defined. - // Stability: stable - // Examples: 'customers', 'main' - // Note: In some SQL databases, the database name to be used is called "schema - // name". - DBNameKey = attribute.Key("db.name") - // The database statement being executed. - // - // Type: string - // Required: Required if applicable and not explicitly disabled via - // instrumentation configuration. - // Stability: stable - // Examples: 'SELECT * FROM wuser_table', 'SET mykey "WuValue"' - // Note: The value may be sanitized to exclude sensitive information. - DBStatementKey = attribute.Key("db.statement") - // The name of the operation being executed, e.g. the [MongoDB command - // name](https://docs.mongodb.com/manual/reference/command/#database-operations) - // such as `findAndModify`, or the SQL keyword. - // - // Type: string - // Required: Required, if `db.statement` is not applicable. - // Stability: stable - // Examples: 'findAndModify', 'HMSET', 'SELECT' - // Note: When setting this to an SQL keyword, it is not recommended to attempt any - // client-side parsing of `db.statement` just to get this property, but it should - // be set if the operation name is provided by the library being instrumented. If - // the SQL statement has an ambiguous operation, or performs more than one - // operation, this value may be omitted. - DBOperationKey = attribute.Key("db.operation") -) - -var ( - // Some other SQL database. Fallback only. See notes - DBSystemOtherSQL = DBSystemKey.String("other_sql") - // Microsoft SQL Server - DBSystemMSSQL = DBSystemKey.String("mssql") - // MySQL - DBSystemMySQL = DBSystemKey.String("mysql") - // Oracle Database - DBSystemOracle = DBSystemKey.String("oracle") - // IBM DB2 - DBSystemDB2 = DBSystemKey.String("db2") - // PostgreSQL - DBSystemPostgreSQL = DBSystemKey.String("postgresql") - // Amazon Redshift - DBSystemRedshift = DBSystemKey.String("redshift") - // Apache Hive - DBSystemHive = DBSystemKey.String("hive") - // Cloudscape - DBSystemCloudscape = DBSystemKey.String("cloudscape") - // HyperSQL DataBase - DBSystemHSQLDB = DBSystemKey.String("hsqldb") - // Progress Database - DBSystemProgress = DBSystemKey.String("progress") - // SAP MaxDB - DBSystemMaxDB = DBSystemKey.String("maxdb") - // SAP HANA - DBSystemHanaDB = DBSystemKey.String("hanadb") - // Ingres - DBSystemIngres = DBSystemKey.String("ingres") - // FirstSQL - DBSystemFirstSQL = DBSystemKey.String("firstsql") - // EnterpriseDB - DBSystemEDB = DBSystemKey.String("edb") - // InterSystems Caché - DBSystemCache = DBSystemKey.String("cache") - // Adabas (Adaptable Database System) - DBSystemAdabas = DBSystemKey.String("adabas") - // Firebird - DBSystemFirebird = DBSystemKey.String("firebird") - // Apache Derby - DBSystemDerby = DBSystemKey.String("derby") - // FileMaker - DBSystemFilemaker = DBSystemKey.String("filemaker") - // Informix - DBSystemInformix = DBSystemKey.String("informix") - // InstantDB - DBSystemInstantDB = DBSystemKey.String("instantdb") - // InterBase - DBSystemInterbase = DBSystemKey.String("interbase") - // MariaDB - DBSystemMariaDB = DBSystemKey.String("mariadb") - // Netezza - DBSystemNetezza = DBSystemKey.String("netezza") - // Pervasive PSQL - DBSystemPervasive = DBSystemKey.String("pervasive") - // PointBase - DBSystemPointbase = DBSystemKey.String("pointbase") - // SQLite - DBSystemSqlite = DBSystemKey.String("sqlite") - // Sybase - DBSystemSybase = DBSystemKey.String("sybase") - // Teradata - DBSystemTeradata = DBSystemKey.String("teradata") - // Vertica - DBSystemVertica = DBSystemKey.String("vertica") - // H2 - DBSystemH2 = DBSystemKey.String("h2") - // ColdFusion IMQ - DBSystemColdfusion = DBSystemKey.String("coldfusion") - // Apache Cassandra - DBSystemCassandra = DBSystemKey.String("cassandra") - // Apache HBase - DBSystemHBase = DBSystemKey.String("hbase") - // MongoDB - DBSystemMongoDB = DBSystemKey.String("mongodb") - // Redis - DBSystemRedis = DBSystemKey.String("redis") - // Couchbase - DBSystemCouchbase = DBSystemKey.String("couchbase") - // CouchDB - DBSystemCouchDB = DBSystemKey.String("couchdb") - // Microsoft Azure Cosmos DB - DBSystemCosmosDB = DBSystemKey.String("cosmosdb") - // Amazon DynamoDB - DBSystemDynamoDB = DBSystemKey.String("dynamodb") - // Neo4j - DBSystemNeo4j = DBSystemKey.String("neo4j") - // Apache Geode - DBSystemGeode = DBSystemKey.String("geode") - // Elasticsearch - DBSystemElasticsearch = DBSystemKey.String("elasticsearch") - // Memcached - DBSystemMemcached = DBSystemKey.String("memcached") - // CockroachDB - DBSystemCockroachdb = DBSystemKey.String("cockroachdb") -) - -// Connection-level attributes for Microsoft SQL Server -const ( - // The Microsoft SQL Server [instance name](https://docs.microsoft.com/en- - // us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) - // connecting to. This name is used to determine the port of a named instance. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'MSSQLSERVER' - // Note: If setting a `db.mssql.instance_name`, `net.peer.port` is no longer - // required (but still recommended if non-standard). - DBMSSQLInstanceNameKey = attribute.Key("db.mssql.instance_name") -) - -// Call-level attributes for Cassandra -const ( - // The name of the keyspace being accessed. To be used instead of the generic - // `db.name` attribute. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'mykeyspace' - DBCassandraKeyspaceKey = attribute.Key("db.cassandra.keyspace") - // The fetch size used for paging, i.e. how many rows will be returned at once. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 5000 - DBCassandraPageSizeKey = attribute.Key("db.cassandra.page_size") - // The consistency level of the query. Based on consistency values from - // [CQL](https://docs.datastax.com/en/cassandra- - // oss/3.0/cassandra/dml/dmlConfigConsistency.html). - // - // Type: Enum - // Required: No - // Stability: stable - DBCassandraConsistencyLevelKey = attribute.Key("db.cassandra.consistency_level") - // The name of the primary table that the operation is acting upon, including the - // schema name (if applicable). - // - // Type: string - // Required: Recommended if available. - // Stability: stable - // Examples: 'mytable' - // Note: This mirrors the db.sql.table attribute but references cassandra rather - // than sql. It is not recommended to attempt any client-side parsing of - // `db.statement` just to get this property, but it should be set if it is - // provided by the library being instrumented. If the operation is acting upon an - // anonymous table, or more than one table, this value MUST NOT be set. - DBCassandraTableKey = attribute.Key("db.cassandra.table") - // Whether or not the query is idempotent. - // - // Type: boolean - // Required: No - // Stability: stable - DBCassandraIdempotenceKey = attribute.Key("db.cassandra.idempotence") - // The number of times a query was speculatively executed. Not set or `0` if the - // query was not executed speculatively. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 0, 2 - DBCassandraSpeculativeExecutionCountKey = attribute.Key("db.cassandra.speculative_execution_count") - // The ID of the coordinating node for a query. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'be13faa2-8574-4d71-926d-27f16cf8a7af' - DBCassandraCoordinatorIDKey = attribute.Key("db.cassandra.coordinator.id") - // The data center of the coordinating node for a query. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'us-west-2' - DBCassandraCoordinatorDCKey = attribute.Key("db.cassandra.coordinator.dc") -) - -var ( - // all - DBCassandraConsistencyLevelAll = DBCassandraConsistencyLevelKey.String("all") - // each_quorum - DBCassandraConsistencyLevelEachQuorum = DBCassandraConsistencyLevelKey.String("each_quorum") - // quorum - DBCassandraConsistencyLevelQuorum = DBCassandraConsistencyLevelKey.String("quorum") - // local_quorum - DBCassandraConsistencyLevelLocalQuorum = DBCassandraConsistencyLevelKey.String("local_quorum") - // one - DBCassandraConsistencyLevelOne = DBCassandraConsistencyLevelKey.String("one") - // two - DBCassandraConsistencyLevelTwo = DBCassandraConsistencyLevelKey.String("two") - // three - DBCassandraConsistencyLevelThree = DBCassandraConsistencyLevelKey.String("three") - // local_one - DBCassandraConsistencyLevelLocalOne = DBCassandraConsistencyLevelKey.String("local_one") - // any - DBCassandraConsistencyLevelAny = DBCassandraConsistencyLevelKey.String("any") - // serial - DBCassandraConsistencyLevelSerial = DBCassandraConsistencyLevelKey.String("serial") - // local_serial - DBCassandraConsistencyLevelLocalSerial = DBCassandraConsistencyLevelKey.String("local_serial") -) - -// Call-level attributes for Apache HBase -const ( - // The [HBase namespace](https://hbase.apache.org/book.html#_namespace) being - // accessed. To be used instead of the generic `db.name` attribute. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'default' - DBHBaseNamespaceKey = attribute.Key("db.hbase.namespace") -) - -// Call-level attributes for Redis -const ( - // The index of the database being accessed as used in the [`SELECT` - // command](https://redis.io/commands/select), provided as an integer. To be used - // instead of the generic `db.name` attribute. - // - // Type: int - // Required: Required, if other than the default database (`0`). - // Stability: stable - // Examples: 0, 1, 15 - DBRedisDBIndexKey = attribute.Key("db.redis.database_index") -) - -// Call-level attributes for MongoDB -const ( - // The collection being accessed within the database stated in `db.name`. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'customers', 'products' - DBMongoDBCollectionKey = attribute.Key("db.mongodb.collection") -) - -// Call-level attrbiutes for SQL databases -const ( - // The name of the primary table that the operation is acting upon, including the - // schema name (if applicable). - // - // Type: string - // Required: Recommended if available. - // Stability: stable - // Examples: 'public.users', 'customers' - // Note: It is not recommended to attempt any client-side parsing of - // `db.statement` just to get this property, but it should be set if it is - // provided by the library being instrumented. If the operation is acting upon an - // anonymous table, or more than one table, this value MUST NOT be set. - DBSQLTableKey = attribute.Key("db.sql.table") -) - -// This document defines the attributes used to report a single exception associated with a span. -const ( - // The type of the exception (its fully-qualified class name, if applicable). The - // dynamic type of the exception should be preferred over the static type in - // languages that support it. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'java.net.ConnectException', 'OSError' - ExceptionTypeKey = attribute.Key("exception.type") - // The exception message. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'Division by zero', "Can't convert 'int' object to str implicitly" - ExceptionMessageKey = attribute.Key("exception.message") - // A stacktrace as a string in the natural representation for the language - // runtime. The representation is to be determined and documented by each language - // SIG. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'Exception in thread "main" java.lang.RuntimeException: Test - // exception\\n at ' - // 'com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at ' - // 'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at ' - // 'com.example.GenerateTrace.main(GenerateTrace.java:5)' - ExceptionStacktraceKey = attribute.Key("exception.stacktrace") - // SHOULD be set to true if the exception event is recorded at a point where it is - // known that the exception is escaping the scope of the span. - // - // Type: boolean - // Required: No - // Stability: stable - // Note: An exception is considered to have escaped (or left) the scope of a span, - // if that span is ended while the exception is still logically "in flight". - // This may be actually "in flight" in some languages (e.g. if the exception - // is passed to a Context manager's `__exit__` method in Python) but will - // usually be caught at the point of recording the exception in most languages. - - // It is usually not possible to determine at the point where an exception is - // thrown - // whether it will escape the scope of a span. - // However, it is trivial to know that an exception - // will escape, if one checks for an active exception just before ending the span, - // as done in the [example above](#exception-end-example). - - // It follows that an exception may still escape the scope of the span - // even if the `exception.escaped` attribute was not set or set to false, - // since the event might have been recorded at a time where it was not - // clear whether the exception will escape. - ExceptionEscapedKey = attribute.Key("exception.escaped") -) - -// This semantic convention describes an instance of a function that runs without provisioning or managing of servers (also known as serverless functions or Function as a Service (FaaS)) with spans. -const ( - // Type of the trigger on which the function is executed. - // - // Type: Enum - // Required: On FaaS instances, faas.trigger MUST be set on incoming invocations. - // Clients invoking FaaS instances MUST set `faas.trigger` on outgoing - // invocations, if it is known to the client. This is, for example, not the case, - // when the transport layer is abstracted in a FaaS client framework without - // access to its configuration. - // Stability: stable - FaaSTriggerKey = attribute.Key("faas.trigger") - // The execution ID of the current function execution. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'af9d5aa4-a685-4c5f-a22b-444f80b3cc28' - FaaSExecutionKey = attribute.Key("faas.execution") -) - -var ( - // A response to some data source operation such as a database or filesystem read/write - FaaSTriggerDatasource = FaaSTriggerKey.String("datasource") - // To provide an answer to an inbound HTTP request - FaaSTriggerHTTP = FaaSTriggerKey.String("http") - // A function is set to be executed when messages are sent to a messaging system - FaaSTriggerPubsub = FaaSTriggerKey.String("pubsub") - // A function is scheduled to be executed regularly - FaaSTriggerTimer = FaaSTriggerKey.String("timer") - // If none of the others apply - FaaSTriggerOther = FaaSTriggerKey.String("other") -) - -// Semantic Convention for FaaS triggered as a response to some data source operation such as a database or filesystem read/write. -const ( - // The name of the source on which the triggering operation was performed. For - // example, in Cloud Storage or S3 corresponds to the bucket name, and in Cosmos - // DB to the database name. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'myBucketName', 'myDBName' - FaaSDocumentCollectionKey = attribute.Key("faas.document.collection") - // Describes the type of the operation that was performed on the data. - // - // Type: Enum - // Required: Always - // Stability: stable - FaaSDocumentOperationKey = attribute.Key("faas.document.operation") - // A string containing the time when the data was accessed in the [ISO - // 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format expressed - // in [UTC](https://www.w3.org/TR/NOTE-datetime). - // - // Type: string - // Required: Always - // Stability: stable - // Examples: '2020-01-23T13:47:06Z' - FaaSDocumentTimeKey = attribute.Key("faas.document.time") - // The document name/table subjected to the operation. For example, in Cloud - // Storage or S3 is the name of the file, and in Cosmos DB the table name. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'myFile.txt', 'myTableName' - FaaSDocumentNameKey = attribute.Key("faas.document.name") -) - -var ( - // When a new object is created - FaaSDocumentOperationInsert = FaaSDocumentOperationKey.String("insert") - // When an object is modified - FaaSDocumentOperationEdit = FaaSDocumentOperationKey.String("edit") - // When an object is deleted - FaaSDocumentOperationDelete = FaaSDocumentOperationKey.String("delete") -) - -// Semantic Convention for FaaS scheduled to be executed regularly. -const ( - // A string containing the function invocation time in the [ISO - // 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format expressed - // in [UTC](https://www.w3.org/TR/NOTE-datetime). - // - // Type: string - // Required: Always - // Stability: stable - // Examples: '2020-01-23T13:47:06Z' - FaaSTimeKey = attribute.Key("faas.time") - // A string containing the schedule period as [Cron Expression](https://docs.oracl - // e.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm). - // - // Type: string - // Required: No - // Stability: stable - // Examples: '0/5 * * * ? *' - FaaSCronKey = attribute.Key("faas.cron") -) - -// Contains additional attributes for incoming FaaS spans. -const ( - // A boolean that is true if the serverless function is executed for the first - // time (aka cold-start). - // - // Type: boolean - // Required: No - // Stability: stable - FaaSColdstartKey = attribute.Key("faas.coldstart") -) - -// Contains additional attributes for outgoing FaaS spans. -const ( - // The name of the invoked function. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'my-function' - // Note: SHOULD be equal to the `faas.name` resource attribute of the invoked - // function. - FaaSInvokedNameKey = attribute.Key("faas.invoked_name") - // The cloud provider of the invoked function. - // - // Type: Enum - // Required: Always - // Stability: stable - // Examples: 'aws' - // Note: SHOULD be equal to the `cloud.provider` resource attribute of the invoked - // function. - FaaSInvokedProviderKey = attribute.Key("faas.invoked_provider") - // The cloud region of the invoked function. - // - // Type: string - // Required: For some cloud providers, like AWS or GCP, the region in which a - // function is hosted is essential to uniquely identify the function and also part - // of its endpoint. Since it's part of the endpoint being called, the region is - // always known to clients. In these cases, `faas.invoked_region` MUST be set - // accordingly. If the region is unknown to the client or not required for - // identifying the invoked function, setting `faas.invoked_region` is optional. - // Stability: stable - // Examples: 'eu-central-1' - // Note: SHOULD be equal to the `cloud.region` resource attribute of the invoked - // function. - FaaSInvokedRegionKey = attribute.Key("faas.invoked_region") -) - -var ( - // Amazon Web Services - FaaSInvokedProviderAWS = FaaSInvokedProviderKey.String("aws") - // Microsoft Azure - FaaSInvokedProviderAzure = FaaSInvokedProviderKey.String("azure") - // Google Cloud Platform - FaaSInvokedProviderGCP = FaaSInvokedProviderKey.String("gcp") -) - -// These attributes may be used for any network related operation. -const ( - // Transport protocol used. See note below. - // - // Type: Enum - // Required: No - // Stability: stable - // Examples: 'ip_tcp' - NetTransportKey = attribute.Key("net.transport") - // Remote address of the peer (dotted decimal for IPv4 or - // [RFC5952](https://tools.ietf.org/html/rfc5952) for IPv6) - // - // Type: string - // Required: No - // Stability: stable - // Examples: '127.0.0.1' - NetPeerIPKey = attribute.Key("net.peer.ip") - // Remote port number. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 80, 8080, 443 - NetPeerPortKey = attribute.Key("net.peer.port") - // Remote hostname or similar, see note below. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'example.com' - NetPeerNameKey = attribute.Key("net.peer.name") - // Like `net.peer.ip` but for the host IP. Useful in case of a multi-IP host. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '192.168.0.1' - NetHostIPKey = attribute.Key("net.host.ip") - // Like `net.peer.port` but for the host port. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 35555 - NetHostPortKey = attribute.Key("net.host.port") - // Local hostname or similar, see note below. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'localhost' - NetHostNameKey = attribute.Key("net.host.name") -) - -var ( - // ip_tcp - NetTransportTCP = NetTransportKey.String("ip_tcp") - // ip_udp - NetTransportUDP = NetTransportKey.String("ip_udp") - // Another IP-based protocol - NetTransportIP = NetTransportKey.String("ip") - // Unix Domain socket. See below - NetTransportUnix = NetTransportKey.String("unix") - // Named or anonymous pipe. See note below - NetTransportPipe = NetTransportKey.String("pipe") - // In-process communication - NetTransportInProc = NetTransportKey.String("inproc") - // Something else (non IP-based) - NetTransportOther = NetTransportKey.String("other") -) - -// Operations that access some remote service. -const ( - // The [`service.name`](../../resource/semantic_conventions/README.md#service) of - // the remote service. SHOULD be equal to the actual `service.name` resource - // attribute of the remote service if any. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'AuthTokenCache' - PeerServiceKey = attribute.Key("peer.service") -) - -// These attributes may be used for any operation with an authenticated and/or authorized enduser. -const ( - // Username or client_id extracted from the access token or - // [Authorization](https://tools.ietf.org/html/rfc7235#section-4.2) header in the - // inbound request from outside the system. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'username' - EnduserIDKey = attribute.Key("enduser.id") - // Actual/assumed role the client is making the request under extracted from token - // or application security context. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'admin' - EnduserRoleKey = attribute.Key("enduser.role") - // Scopes or granted authorities the client currently possesses extracted from - // token or application security context. The value would come from the scope - // associated with an [OAuth 2.0 Access - // Token](https://tools.ietf.org/html/rfc6749#section-3.3) or an attribute value - // in a [SAML 2.0 Assertion](http://docs.oasis- - // open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html). - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'read:message, write:files' - EnduserScopeKey = attribute.Key("enduser.scope") -) - -// These attributes may be used for any operation to store information about a thread that started a span. -const ( - // Current "managed" thread ID (as opposed to OS thread ID). - // - // Type: int - // Required: No - // Stability: stable - // Examples: 42 - ThreadIDKey = attribute.Key("thread.id") - // Current thread name. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'main' - ThreadNameKey = attribute.Key("thread.name") -) - -// These attributes allow to report this unit of code and therefore to provide more context about the span. -const ( - // The method or function name, or equivalent (usually rightmost part of the code - // unit's name). - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'serveRequest' - CodeFunctionKey = attribute.Key("code.function") - // The "namespace" within which `code.function` is defined. Usually the qualified - // class or module name, such that `code.namespace` + some separator + - // `code.function` form a unique identifier for the code unit. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'com.example.MyHTTPService' - CodeNamespaceKey = attribute.Key("code.namespace") - // The source code file name that identifies the code unit as uniquely as possible - // (preferably an absolute file path). - // - // Type: string - // Required: No - // Stability: stable - // Examples: '/usr/local/MyApplication/content_root/app/index.php' - CodeFilepathKey = attribute.Key("code.filepath") - // The line number in `code.filepath` best representing the operation. It SHOULD - // point within the code unit named in `code.function`. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 42 - CodeLineNumberKey = attribute.Key("code.lineno") -) - -// This document defines semantic conventions for HTTP client and server Spans. -const ( - // HTTP request method. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'GET', 'POST', 'HEAD' - HTTPMethodKey = attribute.Key("http.method") - // Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]`. - // Usually the fragment is not transmitted over HTTP, but if it is known, it - // should be included nevertheless. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv' - // Note: `http.url` MUST NOT contain credentials passed via URL in form of - // `https://username:password@www.example.com/`. In such case the attribute's - // value should be `https://www.example.com/`. - HTTPURLKey = attribute.Key("http.url") - // The full request target as passed in a HTTP request line or equivalent. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '/path/12314/?q=ddds#123' - HTTPTargetKey = attribute.Key("http.target") - // The value of the [HTTP host - // header](https://tools.ietf.org/html/rfc7230#section-5.4). When the header is - // empty or not present, this attribute should be the same. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'www.example.org' - HTTPHostKey = attribute.Key("http.host") - // The URI scheme identifying the used protocol. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'http', 'https' - HTTPSchemeKey = attribute.Key("http.scheme") - // [HTTP response status code](https://tools.ietf.org/html/rfc7231#section-6). - // - // Type: int - // Required: If and only if one was received/sent. - // Stability: stable - // Examples: 200 - HTTPStatusCodeKey = attribute.Key("http.status_code") - // Kind of HTTP protocol used. - // - // Type: Enum - // Required: No - // Stability: stable - // Examples: '1.0' - // Note: If `net.transport` is not specified, it can be assumed to be `IP.TCP` - // except if `http.flavor` is `QUIC`, in which case `IP.UDP` is assumed. - HTTPFlavorKey = attribute.Key("http.flavor") - // Value of the [HTTP User- - // Agent](https://tools.ietf.org/html/rfc7231#section-5.5.3) header sent by the - // client. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'CERN-LineMode/2.15 libwww/2.17b3' - HTTPUserAgentKey = attribute.Key("http.user_agent") - // The size of the request payload body in bytes. This is the number of bytes - // transferred excluding headers and is often, but not always, present as the - // [Content-Length](https://tools.ietf.org/html/rfc7230#section-3.3.2) header. For - // requests using transport encoding, this should be the compressed size. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 3495 - HTTPRequestContentLengthKey = attribute.Key("http.request_content_length") - // The size of the uncompressed request payload body after transport decoding. Not - // set if transport encoding not used. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 5493 - HTTPRequestContentLengthUncompressedKey = attribute.Key("http.request_content_length_uncompressed") - // The size of the response payload body in bytes. This is the number of bytes - // transferred excluding headers and is often, but not always, present as the - // [Content-Length](https://tools.ietf.org/html/rfc7230#section-3.3.2) header. For - // requests using transport encoding, this should be the compressed size. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 3495 - HTTPResponseContentLengthKey = attribute.Key("http.response_content_length") - // The size of the uncompressed response payload body after transport decoding. - // Not set if transport encoding not used. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 5493 - HTTPResponseContentLengthUncompressedKey = attribute.Key("http.response_content_length_uncompressed") -) - -var ( - // HTTP 1.0 - HTTPFlavorHTTP10 = HTTPFlavorKey.String("1.0") - // HTTP 1.1 - HTTPFlavorHTTP11 = HTTPFlavorKey.String("1.1") - // HTTP 2 - HTTPFlavorHTTP20 = HTTPFlavorKey.String("2.0") - // SPDY protocol - HTTPFlavorSPDY = HTTPFlavorKey.String("SPDY") - // QUIC protocol - HTTPFlavorQUIC = HTTPFlavorKey.String("QUIC") -) - -// Semantic Convention for HTTP Server -const ( - // The primary server name of the matched virtual host. This should be obtained - // via configuration. If no such configuration can be obtained, this attribute - // MUST NOT be set ( `net.host.name` should be used instead). - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'example.com' - // Note: `http.url` is usually not readily available on the server side but would - // have to be assembled in a cumbersome and sometimes lossy process from other - // information (see e.g. open-telemetry/opentelemetry-python/pull/148). It is thus - // preferred to supply the raw data that is available. - HTTPServerNameKey = attribute.Key("http.server_name") - // The matched route (path template). - // - // Type: string - // Required: No - // Stability: stable - // Examples: '/users/:userID?' - HTTPRouteKey = attribute.Key("http.route") - // The IP address of the original client behind all proxies, if known (e.g. from - // [X-Forwarded-For](https://developer.mozilla.org/en- - // US/docs/Web/HTTP/Headers/X-Forwarded-For)). - // - // Type: string - // Required: No - // Stability: stable - // Examples: '83.164.160.102' - // Note: This is not necessarily the same as `net.peer.ip`, which would identify - // the network-level peer, which may be a proxy. - HTTPClientIPKey = attribute.Key("http.client_ip") -) - -// Attributes that exist for multiple DynamoDB request types. -const ( - // The keys in the `RequestItems` object field. - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: 'Users', 'Cats' - AWSDynamoDBTableNamesKey = attribute.Key("aws.dynamodb.table_names") - // The JSON-serialized value of each item in the `ConsumedCapacity` response - // field. - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: '{ "CapacityUnits": number, "GlobalSecondaryIndexes": { "string" : { - // "CapacityUnits": number, "ReadCapacityUnits": number, "WriteCapacityUnits": - // number } }, "LocalSecondaryIndexes": { "string" : { "CapacityUnits": number, - // "ReadCapacityUnits": number, "WriteCapacityUnits": number } }, - // "ReadCapacityUnits": number, "Table": { "CapacityUnits": number, - // "ReadCapacityUnits": number, "WriteCapacityUnits": number }, "TableName": - // "string", "WriteCapacityUnits": number }' - AWSDynamoDBConsumedCapacityKey = attribute.Key("aws.dynamodb.consumed_capacity") - // The JSON-serialized value of the `ItemCollectionMetrics` response field. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '{ "string" : [ { "ItemCollectionKey": { "string" : { "B": blob, - // "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": { "string" : - // "AttributeValue" }, "N": "string", "NS": [ "string" ], "NULL": boolean, "S": - // "string", "SS": [ "string" ] } }, "SizeEstimateRangeGB": [ number ] } ] }' - AWSDynamoDBItemCollectionMetricsKey = attribute.Key("aws.dynamodb.item_collection_metrics") - // The value of the `ProvisionedThroughput.ReadCapacityUnits` request parameter. - // - // Type: double - // Required: No - // Stability: stable - // Examples: 1.0, 2.0 - AWSDynamoDBProvisionedReadCapacityKey = attribute.Key("aws.dynamodb.provisioned_read_capacity") - // The value of the `ProvisionedThroughput.WriteCapacityUnits` request parameter. - // - // Type: double - // Required: No - // Stability: stable - // Examples: 1.0, 2.0 - AWSDynamoDBProvisionedWriteCapacityKey = attribute.Key("aws.dynamodb.provisioned_write_capacity") - // The value of the `ConsistentRead` request parameter. - // - // Type: boolean - // Required: No - // Stability: stable - AWSDynamoDBConsistentReadKey = attribute.Key("aws.dynamodb.consistent_read") - // The value of the `ProjectionExpression` request parameter. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'Title', 'Title, Price, Color', 'Title, Description, RelatedItems, - // ProductReviews' - AWSDynamoDBProjectionKey = attribute.Key("aws.dynamodb.projection") - // The value of the `Limit` request parameter. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 10 - AWSDynamoDBLimitKey = attribute.Key("aws.dynamodb.limit") - // The value of the `AttributesToGet` request parameter. - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: 'lives', 'id' - AWSDynamoDBAttributesToGetKey = attribute.Key("aws.dynamodb.attributes_to_get") - // The value of the `IndexName` request parameter. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'name_to_group' - AWSDynamoDBIndexNameKey = attribute.Key("aws.dynamodb.index_name") - // The value of the `Select` request parameter. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'ALL_ATTRIBUTES', 'COUNT' - AWSDynamoDBSelectKey = attribute.Key("aws.dynamodb.select") -) - -// DynamoDB.CreateTable -const ( - // The JSON-serialized value of each item of the `GlobalSecondaryIndexes` request - // field - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: '{ "IndexName": "string", "KeySchema": [ { "AttributeName": "string", - // "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], - // "ProjectionType": "string" }, "ProvisionedThroughput": { "ReadCapacityUnits": - // number, "WriteCapacityUnits": number } }' - AWSDynamoDBGlobalSecondaryIndexesKey = attribute.Key("aws.dynamodb.global_secondary_indexes") - // The JSON-serialized value of each item of the `LocalSecondaryIndexes` request - // field. - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: '{ "IndexARN": "string", "IndexName": "string", "IndexSizeBytes": - // number, "ItemCount": number, "KeySchema": [ { "AttributeName": "string", - // "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], - // "ProjectionType": "string" } }' - AWSDynamoDBLocalSecondaryIndexesKey = attribute.Key("aws.dynamodb.local_secondary_indexes") -) - -// DynamoDB.ListTables -const ( - // The value of the `ExclusiveStartTableName` request parameter. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'Users', 'CatsTable' - AWSDynamoDBExclusiveStartTableKey = attribute.Key("aws.dynamodb.exclusive_start_table") - // The number of items in the `TableNames` response parameter. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 20 - AWSDynamoDBTableCountKey = attribute.Key("aws.dynamodb.table_count") -) - -// DynamoDB.Query -const ( - // The value of the `ScanIndexForward` request parameter. - // - // Type: boolean - // Required: No - // Stability: stable - AWSDynamoDBScanForwardKey = attribute.Key("aws.dynamodb.scan_forward") -) - -// DynamoDB.Scan -const ( - // The value of the `Segment` request parameter. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 10 - AWSDynamoDBSegmentKey = attribute.Key("aws.dynamodb.segment") - // The value of the `TotalSegments` request parameter. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 100 - AWSDynamoDBTotalSegmentsKey = attribute.Key("aws.dynamodb.total_segments") - // The value of the `Count` response parameter. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 10 - AWSDynamoDBCountKey = attribute.Key("aws.dynamodb.count") - // The value of the `ScannedCount` response parameter. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 50 - AWSDynamoDBScannedCountKey = attribute.Key("aws.dynamodb.scanned_count") -) - -// DynamoDB.UpdateTable -const ( - // The JSON-serialized value of each item in the `AttributeDefinitions` request - // field. - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: '{ "AttributeName": "string", "AttributeType": "string" }' - AWSDynamoDBAttributeDefinitionsKey = attribute.Key("aws.dynamodb.attribute_definitions") - // The JSON-serialized value of each item in the `GlobalSecondaryIndexUpdates` - // request field. - // - // Type: string[] - // Required: No - // Stability: stable - // Examples: '{ "Create": { "IndexName": "string", "KeySchema": [ { - // "AttributeName": "string", "KeyType": "string" } ], "Projection": { - // "NonKeyAttributes": [ "string" ], "ProjectionType": "string" }, - // "ProvisionedThroughput": { "ReadCapacityUnits": number, "WriteCapacityUnits": - // number } }' - AWSDynamoDBGlobalSecondaryIndexUpdatesKey = attribute.Key("aws.dynamodb.global_secondary_index_updates") -) - -// This document defines the attributes used in messaging systems. -const ( - // A string identifying the messaging system. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'kafka', 'rabbitmq', 'activemq', 'AmazonSQS' - MessagingSystemKey = attribute.Key("messaging.system") - // The message destination name. This might be equal to the span name but is - // required nevertheless. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'MyQueue', 'MyTopic' - MessagingDestinationKey = attribute.Key("messaging.destination") - // The kind of message destination - // - // Type: Enum - // Required: Required only if the message destination is either a `queue` or - // `topic`. - // Stability: stable - MessagingDestinationKindKey = attribute.Key("messaging.destination_kind") - // A boolean that is true if the message destination is temporary. - // - // Type: boolean - // Required: If missing, it is assumed to be false. - // Stability: stable - MessagingTempDestinationKey = attribute.Key("messaging.temp_destination") - // The name of the transport protocol. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'AMQP', 'MQTT' - MessagingProtocolKey = attribute.Key("messaging.protocol") - // The version of the transport protocol. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '0.9.1' - MessagingProtocolVersionKey = attribute.Key("messaging.protocol_version") - // Connection string. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'tibjmsnaming://localhost:7222', - // 'https://queue.amazonaws.com/80398EXAMPLE/MyQueue' - MessagingURLKey = attribute.Key("messaging.url") - // A value used by the messaging system as an identifier for the message, - // represented as a string. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '452a7c7c7c7048c2f887f61572b18fc2' - MessagingMessageIDKey = attribute.Key("messaging.message_id") - // The [conversation ID](#conversations) identifying the conversation to which the - // message belongs, represented as a string. Sometimes called "Correlation ID". - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'MyConversationID' - MessagingConversationIDKey = attribute.Key("messaging.conversation_id") - // The (uncompressed) size of the message payload in bytes. Also use this - // attribute if it is unknown whether the compressed or uncompressed payload size - // is reported. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 2738 - MessagingMessagePayloadSizeBytesKey = attribute.Key("messaging.message_payload_size_bytes") - // The compressed size of the message payload in bytes. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 2048 - MessagingMessagePayloadCompressedSizeBytesKey = attribute.Key("messaging.message_payload_compressed_size_bytes") -) - -var ( - // A message sent to a queue - MessagingDestinationKindQueue = MessagingDestinationKindKey.String("queue") - // A message sent to a topic - MessagingDestinationKindTopic = MessagingDestinationKindKey.String("topic") -) - -// Semantic convention for a consumer of messages received from a messaging system -const ( - // A string identifying the kind of message consumption as defined in the - // [Operation names](#operation-names) section above. If the operation is "send", - // this attribute MUST NOT be set, since the operation can be inferred from the - // span kind in that case. - // - // Type: Enum - // Required: No - // Stability: stable - MessagingOperationKey = attribute.Key("messaging.operation") -) - -var ( - // receive - MessagingOperationReceive = MessagingOperationKey.String("receive") - // process - MessagingOperationProcess = MessagingOperationKey.String("process") -) - -// Attributes for RabbitMQ -const ( - // RabbitMQ message routing key. - // - // Type: string - // Required: Unless it is empty. - // Stability: stable - // Examples: 'myKey' - MessagingRabbitmqRoutingKeyKey = attribute.Key("messaging.rabbitmq.routing_key") -) - -// Attributes for Apache Kafka -const ( - // Message keys in Kafka are used for grouping alike messages to ensure they're - // processed on the same partition. They differ from `messaging.message_id` in - // that they're not unique. If the key is `null`, the attribute MUST NOT be set. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'myKey' - // Note: If the key type is not string, it's string representation has to be - // supplied for the attribute. If the key has no unambiguous, canonical string - // form, don't include its value. - MessagingKafkaMessageKeyKey = attribute.Key("messaging.kafka.message_key") - // Name of the Kafka Consumer Group that is handling the message. Only applies to - // consumers, not producers. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'my-group' - MessagingKafkaConsumerGroupKey = attribute.Key("messaging.kafka.consumer_group") - // Client ID for the Consumer or Producer that is handling the message. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'client-5' - MessagingKafkaClientIDKey = attribute.Key("messaging.kafka.client_id") - // Partition the message is sent to. - // - // Type: int - // Required: No - // Stability: stable - // Examples: 2 - MessagingKafkaPartitionKey = attribute.Key("messaging.kafka.partition") - // A boolean that is true if the message is a tombstone. - // - // Type: boolean - // Required: If missing, it is assumed to be false. - // Stability: stable - MessagingKafkaTombstoneKey = attribute.Key("messaging.kafka.tombstone") -) - -// This document defines semantic conventions for remote procedure calls. -const ( - // A string identifying the remoting system. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'grpc', 'java_rmi', 'wcf' - RPCSystemKey = attribute.Key("rpc.system") - // The full name of the service being called, including its package name, if - // applicable. - // - // Type: string - // Required: No, but recommended - // Stability: stable - // Examples: 'myservice.EchoService' - RPCServiceKey = attribute.Key("rpc.service") - // The name of the method being called, must be equal to the $method part in the - // span name. - // - // Type: string - // Required: No, but recommended - // Stability: stable - // Examples: 'exampleMethod' - RPCMethodKey = attribute.Key("rpc.method") -) - -// Tech-specific attributes for gRPC. -const ( - // The [numeric status - // code](https://github.com/grpc/grpc/blob/v1.33.2/doc/statuscodes.md) of the gRPC - // request. - // - // Type: Enum - // Required: Always - // Stability: stable - // Examples: 0, 1, 16 - RPCGRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code") -) - -var ( - // OK - RPCGRPCStatusCodeOk = RPCGRPCStatusCodeKey.Int(0) - // CANCELLED - RPCGRPCStatusCodeCancelled = RPCGRPCStatusCodeKey.Int(1) - // UNKNOWN - RPCGRPCStatusCodeUnknown = RPCGRPCStatusCodeKey.Int(2) - // INVALID_ARGUMENT - RPCGRPCStatusCodeInvalidArgument = RPCGRPCStatusCodeKey.Int(3) - // DEADLINE_EXCEEDED - RPCGRPCStatusCodeDeadlineExceeded = RPCGRPCStatusCodeKey.Int(4) - // NOT_FOUND - RPCGRPCStatusCodeNotFound = RPCGRPCStatusCodeKey.Int(5) - // ALREADY_EXISTS - RPCGRPCStatusCodeAlreadyExists = RPCGRPCStatusCodeKey.Int(6) - // PERMISSION_DENIED - RPCGRPCStatusCodePermissionDenied = RPCGRPCStatusCodeKey.Int(7) - // RESOURCE_EXHAUSTED - RPCGRPCStatusCodeResourceExhausted = RPCGRPCStatusCodeKey.Int(8) - // FAILED_PRECONDITION - RPCGRPCStatusCodeFailedPrecondition = RPCGRPCStatusCodeKey.Int(9) - // ABORTED - RPCGRPCStatusCodeAborted = RPCGRPCStatusCodeKey.Int(10) - // OUT_OF_RANGE - RPCGRPCStatusCodeOutOfRange = RPCGRPCStatusCodeKey.Int(11) - // UNIMPLEMENTED - RPCGRPCStatusCodeUnimplemented = RPCGRPCStatusCodeKey.Int(12) - // INTERNAL - RPCGRPCStatusCodeInternal = RPCGRPCStatusCodeKey.Int(13) - // UNAVAILABLE - RPCGRPCStatusCodeUnavailable = RPCGRPCStatusCodeKey.Int(14) - // DATA_LOSS - RPCGRPCStatusCodeDataLoss = RPCGRPCStatusCodeKey.Int(15) - // UNAUTHENTICATED - RPCGRPCStatusCodeUnauthenticated = RPCGRPCStatusCodeKey.Int(16) -) - -// Tech-specific attributes for [JSON RPC](https://www.jsonrpc.org/). -const ( - // Protocol version as in `jsonrpc` property of request/response. Since JSON-RPC - // 1.0 does not specify this, the value can be omitted. - // - // Type: string - // Required: If missing, it is assumed to be "1.0". - // Stability: stable - // Examples: '2.0', '1.0' - RPCJsonrpcVersionKey = attribute.Key("rpc.jsonrpc.version") - // `method` property from request. Unlike `rpc.method`, this may not relate to the - // actual method being called. Useful for client-side traces since client does not - // know what will be called on the server. - // - // Type: string - // Required: Always - // Stability: stable - // Examples: 'users.create', 'get_users' - RPCJsonrpcMethodKey = attribute.Key("rpc.jsonrpc.method") - // `id` property of request or response. Since protocol allows id to be int, - // string, `null` or missing (for notifications), value is expected to be cast to - // string for simplicity. Use empty string in case of `null` value. Omit entirely - // if this is a notification. - // - // Type: string - // Required: No - // Stability: stable - // Examples: '10', 'request-7', '' - RPCJsonrpcRequestIDKey = attribute.Key("rpc.jsonrpc.request_id") - // `error.code` property of response if it is an error response. - // - // Type: int - // Required: If missing, response is assumed to be successful. - // Stability: stable - // Examples: -32700, 100 - RPCJsonrpcErrorCodeKey = attribute.Key("rpc.jsonrpc.error_code") - // `error.message` property of response if it is an error response. - // - // Type: string - // Required: No - // Stability: stable - // Examples: 'Parse error', 'User already exists' - RPCJsonrpcErrorMessageKey = attribute.Key("rpc.jsonrpc.error_message") -) diff --git a/etcd/vendor/google.golang.org/genproto/LICENSE b/etcd/vendor/google.golang.org/genproto/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/etcd/vendor/google.golang.org/genproto/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/etcd/vendor/google.golang.org/grpc/reflection/README.md b/etcd/vendor/google.golang.org/grpc/reflection/README.md new file mode 100644 index 0000000000..9ace83ccb6 --- /dev/null +++ b/etcd/vendor/google.golang.org/grpc/reflection/README.md @@ -0,0 +1,18 @@ +# Reflection + +Package reflection implements server reflection service. + +The service implemented is defined in: https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1/reflection.proto. + +To register server reflection on a gRPC server: +```go +import "google.golang.org/grpc/reflection" + +s := grpc.NewServer() +pb.RegisterYourOwnServer(s, &server{}) + +// Register reflection service on gRPC server. +reflection.Register(s) + +s.Serve(lis) +``` diff --git a/etcd/vendor/google.golang.org/grpc/reflection/adapt.go b/etcd/vendor/google.golang.org/grpc/reflection/adapt.go new file mode 100644 index 0000000000..6997e47403 --- /dev/null +++ b/etcd/vendor/google.golang.org/grpc/reflection/adapt.go @@ -0,0 +1,57 @@ +/* + * + * Copyright 2023 gRPC 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 reflection + +import ( + "google.golang.org/grpc/reflection/internal" + + v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1" + v1reflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1" + v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" +) + +// asV1Alpha returns an implementation of the v1alpha version of the reflection +// interface that delegates all calls to the given v1 version. +func asV1Alpha(svr v1reflectiongrpc.ServerReflectionServer) v1alphareflectiongrpc.ServerReflectionServer { + return v1AlphaServerImpl{svr: svr} +} + +type v1AlphaServerImpl struct { + svr v1reflectiongrpc.ServerReflectionServer +} + +func (s v1AlphaServerImpl) ServerReflectionInfo(stream v1alphareflectiongrpc.ServerReflection_ServerReflectionInfoServer) error { + return s.svr.ServerReflectionInfo(v1AlphaServerStreamAdapter{stream}) +} + +type v1AlphaServerStreamAdapter struct { + v1alphareflectiongrpc.ServerReflection_ServerReflectionInfoServer +} + +func (s v1AlphaServerStreamAdapter) Send(response *v1reflectionpb.ServerReflectionResponse) error { + return s.ServerReflection_ServerReflectionInfoServer.Send(internal.V1ToV1AlphaResponse(response)) +} + +func (s v1AlphaServerStreamAdapter) Recv() (*v1reflectionpb.ServerReflectionRequest, error) { + resp, err := s.ServerReflection_ServerReflectionInfoServer.Recv() + if err != nil { + return nil, err + } + return internal.V1AlphaToV1Request(resp), nil +} diff --git a/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go b/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go new file mode 100644 index 0000000000..92f5292211 --- /dev/null +++ b/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go @@ -0,0 +1,777 @@ +// Copyright 2016 The gRPC 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. + +// Service exported by server reflection. A more complete description of how +// server reflection works can be found at +// https://github.com/grpc/grpc/blob/master/doc/server-reflection.md +// +// The canonical version of this proto can be found at +// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v5.27.1 +// source: grpc/reflection/v1/reflection.proto + +package grpc_reflection_v1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The message sent by the client when calling ServerReflectionInfo method. +type ServerReflectionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` + // To use reflection service, the client should set one of the following + // fields in message_request. The server distinguishes requests by their + // defined field and then handles them using corresponding methods. + // + // Types that are valid to be assigned to MessageRequest: + // + // *ServerReflectionRequest_FileByFilename + // *ServerReflectionRequest_FileContainingSymbol + // *ServerReflectionRequest_FileContainingExtension + // *ServerReflectionRequest_AllExtensionNumbersOfType + // *ServerReflectionRequest_ListServices + MessageRequest isServerReflectionRequest_MessageRequest `protobuf_oneof:"message_request"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServerReflectionRequest) Reset() { + *x = ServerReflectionRequest{} + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServerReflectionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerReflectionRequest) ProtoMessage() {} + +func (x *ServerReflectionRequest) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerReflectionRequest.ProtoReflect.Descriptor instead. +func (*ServerReflectionRequest) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{0} +} + +func (x *ServerReflectionRequest) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + +func (x *ServerReflectionRequest) GetMessageRequest() isServerReflectionRequest_MessageRequest { + if x != nil { + return x.MessageRequest + } + return nil +} + +func (x *ServerReflectionRequest) GetFileByFilename() string { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileByFilename); ok { + return x.FileByFilename + } + } + return "" +} + +func (x *ServerReflectionRequest) GetFileContainingSymbol() string { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileContainingSymbol); ok { + return x.FileContainingSymbol + } + } + return "" +} + +func (x *ServerReflectionRequest) GetFileContainingExtension() *ExtensionRequest { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileContainingExtension); ok { + return x.FileContainingExtension + } + } + return nil +} + +func (x *ServerReflectionRequest) GetAllExtensionNumbersOfType() string { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_AllExtensionNumbersOfType); ok { + return x.AllExtensionNumbersOfType + } + } + return "" +} + +func (x *ServerReflectionRequest) GetListServices() string { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_ListServices); ok { + return x.ListServices + } + } + return "" +} + +type isServerReflectionRequest_MessageRequest interface { + isServerReflectionRequest_MessageRequest() +} + +type ServerReflectionRequest_FileByFilename struct { + // Find a proto file by the file name. + FileByFilename string `protobuf:"bytes,3,opt,name=file_by_filename,json=fileByFilename,proto3,oneof"` +} + +type ServerReflectionRequest_FileContainingSymbol struct { + // Find the proto file that declares the given fully-qualified symbol name. + // This field should be a fully-qualified symbol name + // (e.g. .[.] or .). + FileContainingSymbol string `protobuf:"bytes,4,opt,name=file_containing_symbol,json=fileContainingSymbol,proto3,oneof"` +} + +type ServerReflectionRequest_FileContainingExtension struct { + // Find the proto file which defines an extension extending the given + // message type with the given field number. + FileContainingExtension *ExtensionRequest `protobuf:"bytes,5,opt,name=file_containing_extension,json=fileContainingExtension,proto3,oneof"` +} + +type ServerReflectionRequest_AllExtensionNumbersOfType struct { + // Finds the tag numbers used by all known extensions of the given message + // type, and appends them to ExtensionNumberResponse in an undefined order. + // Its corresponding method is best-effort: it's not guaranteed that the + // reflection service will implement this method, and it's not guaranteed + // that this method will provide all extensions. Returns + // StatusCode::UNIMPLEMENTED if it's not implemented. + // This field should be a fully-qualified type name. The format is + // . + AllExtensionNumbersOfType string `protobuf:"bytes,6,opt,name=all_extension_numbers_of_type,json=allExtensionNumbersOfType,proto3,oneof"` +} + +type ServerReflectionRequest_ListServices struct { + // List the full names of registered services. The content will not be + // checked. + ListServices string `protobuf:"bytes,7,opt,name=list_services,json=listServices,proto3,oneof"` +} + +func (*ServerReflectionRequest_FileByFilename) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_FileContainingSymbol) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_FileContainingExtension) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_AllExtensionNumbersOfType) isServerReflectionRequest_MessageRequest() { +} + +func (*ServerReflectionRequest_ListServices) isServerReflectionRequest_MessageRequest() {} + +// The type name and extension number sent by the client when requesting +// file_containing_extension. +type ExtensionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Fully-qualified type name. The format should be . + ContainingType string `protobuf:"bytes,1,opt,name=containing_type,json=containingType,proto3" json:"containing_type,omitempty"` + ExtensionNumber int32 `protobuf:"varint,2,opt,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExtensionRequest) Reset() { + *x = ExtensionRequest{} + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExtensionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionRequest) ProtoMessage() {} + +func (x *ExtensionRequest) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionRequest.ProtoReflect.Descriptor instead. +func (*ExtensionRequest) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{1} +} + +func (x *ExtensionRequest) GetContainingType() string { + if x != nil { + return x.ContainingType + } + return "" +} + +func (x *ExtensionRequest) GetExtensionNumber() int32 { + if x != nil { + return x.ExtensionNumber + } + return 0 +} + +// The message sent by the server to answer ServerReflectionInfo method. +type ServerReflectionResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + ValidHost string `protobuf:"bytes,1,opt,name=valid_host,json=validHost,proto3" json:"valid_host,omitempty"` + OriginalRequest *ServerReflectionRequest `protobuf:"bytes,2,opt,name=original_request,json=originalRequest,proto3" json:"original_request,omitempty"` + // The server sets one of the following fields according to the message_request + // in the request. + // + // Types that are valid to be assigned to MessageResponse: + // + // *ServerReflectionResponse_FileDescriptorResponse + // *ServerReflectionResponse_AllExtensionNumbersResponse + // *ServerReflectionResponse_ListServicesResponse + // *ServerReflectionResponse_ErrorResponse + MessageResponse isServerReflectionResponse_MessageResponse `protobuf_oneof:"message_response"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServerReflectionResponse) Reset() { + *x = ServerReflectionResponse{} + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServerReflectionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerReflectionResponse) ProtoMessage() {} + +func (x *ServerReflectionResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerReflectionResponse.ProtoReflect.Descriptor instead. +func (*ServerReflectionResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{2} +} + +func (x *ServerReflectionResponse) GetValidHost() string { + if x != nil { + return x.ValidHost + } + return "" +} + +func (x *ServerReflectionResponse) GetOriginalRequest() *ServerReflectionRequest { + if x != nil { + return x.OriginalRequest + } + return nil +} + +func (x *ServerReflectionResponse) GetMessageResponse() isServerReflectionResponse_MessageResponse { + if x != nil { + return x.MessageResponse + } + return nil +} + +func (x *ServerReflectionResponse) GetFileDescriptorResponse() *FileDescriptorResponse { + if x != nil { + if x, ok := x.MessageResponse.(*ServerReflectionResponse_FileDescriptorResponse); ok { + return x.FileDescriptorResponse + } + } + return nil +} + +func (x *ServerReflectionResponse) GetAllExtensionNumbersResponse() *ExtensionNumberResponse { + if x != nil { + if x, ok := x.MessageResponse.(*ServerReflectionResponse_AllExtensionNumbersResponse); ok { + return x.AllExtensionNumbersResponse + } + } + return nil +} + +func (x *ServerReflectionResponse) GetListServicesResponse() *ListServiceResponse { + if x != nil { + if x, ok := x.MessageResponse.(*ServerReflectionResponse_ListServicesResponse); ok { + return x.ListServicesResponse + } + } + return nil +} + +func (x *ServerReflectionResponse) GetErrorResponse() *ErrorResponse { + if x != nil { + if x, ok := x.MessageResponse.(*ServerReflectionResponse_ErrorResponse); ok { + return x.ErrorResponse + } + } + return nil +} + +type isServerReflectionResponse_MessageResponse interface { + isServerReflectionResponse_MessageResponse() +} + +type ServerReflectionResponse_FileDescriptorResponse struct { + // This message is used to answer file_by_filename, file_containing_symbol, + // file_containing_extension requests with transitive dependencies. + // As the repeated label is not allowed in oneof fields, we use a + // FileDescriptorResponse message to encapsulate the repeated fields. + // The reflection service is allowed to avoid sending FileDescriptorProtos + // that were previously sent in response to earlier requests in the stream. + FileDescriptorResponse *FileDescriptorResponse `protobuf:"bytes,4,opt,name=file_descriptor_response,json=fileDescriptorResponse,proto3,oneof"` +} + +type ServerReflectionResponse_AllExtensionNumbersResponse struct { + // This message is used to answer all_extension_numbers_of_type requests. + AllExtensionNumbersResponse *ExtensionNumberResponse `protobuf:"bytes,5,opt,name=all_extension_numbers_response,json=allExtensionNumbersResponse,proto3,oneof"` +} + +type ServerReflectionResponse_ListServicesResponse struct { + // This message is used to answer list_services requests. + ListServicesResponse *ListServiceResponse `protobuf:"bytes,6,opt,name=list_services_response,json=listServicesResponse,proto3,oneof"` +} + +type ServerReflectionResponse_ErrorResponse struct { + // This message is used when an error occurs. + ErrorResponse *ErrorResponse `protobuf:"bytes,7,opt,name=error_response,json=errorResponse,proto3,oneof"` +} + +func (*ServerReflectionResponse_FileDescriptorResponse) isServerReflectionResponse_MessageResponse() { +} + +func (*ServerReflectionResponse_AllExtensionNumbersResponse) isServerReflectionResponse_MessageResponse() { +} + +func (*ServerReflectionResponse_ListServicesResponse) isServerReflectionResponse_MessageResponse() {} + +func (*ServerReflectionResponse_ErrorResponse) isServerReflectionResponse_MessageResponse() {} + +// Serialized FileDescriptorProto messages sent by the server answering +// a file_by_filename, file_containing_symbol, or file_containing_extension +// request. +type FileDescriptorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Serialized FileDescriptorProto messages. We avoid taking a dependency on + // descriptor.proto, which uses proto2 only features, by making them opaque + // bytes instead. + FileDescriptorProto [][]byte `protobuf:"bytes,1,rep,name=file_descriptor_proto,json=fileDescriptorProto,proto3" json:"file_descriptor_proto,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FileDescriptorResponse) Reset() { + *x = FileDescriptorResponse{} + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FileDescriptorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileDescriptorResponse) ProtoMessage() {} + +func (x *FileDescriptorResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileDescriptorResponse.ProtoReflect.Descriptor instead. +func (*FileDescriptorResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{3} +} + +func (x *FileDescriptorResponse) GetFileDescriptorProto() [][]byte { + if x != nil { + return x.FileDescriptorProto + } + return nil +} + +// A list of extension numbers sent by the server answering +// all_extension_numbers_of_type request. +type ExtensionNumberResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Full name of the base type, including the package name. The format + // is . + BaseTypeName string `protobuf:"bytes,1,opt,name=base_type_name,json=baseTypeName,proto3" json:"base_type_name,omitempty"` + ExtensionNumber []int32 `protobuf:"varint,2,rep,packed,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExtensionNumberResponse) Reset() { + *x = ExtensionNumberResponse{} + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExtensionNumberResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionNumberResponse) ProtoMessage() {} + +func (x *ExtensionNumberResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionNumberResponse.ProtoReflect.Descriptor instead. +func (*ExtensionNumberResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{4} +} + +func (x *ExtensionNumberResponse) GetBaseTypeName() string { + if x != nil { + return x.BaseTypeName + } + return "" +} + +func (x *ExtensionNumberResponse) GetExtensionNumber() []int32 { + if x != nil { + return x.ExtensionNumber + } + return nil +} + +// A list of ServiceResponse sent by the server answering list_services request. +type ListServiceResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The information of each service may be expanded in the future, so we use + // ServiceResponse message to encapsulate it. + Service []*ServiceResponse `protobuf:"bytes,1,rep,name=service,proto3" json:"service,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListServiceResponse) Reset() { + *x = ListServiceResponse{} + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListServiceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServiceResponse) ProtoMessage() {} + +func (x *ListServiceResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServiceResponse.ProtoReflect.Descriptor instead. +func (*ListServiceResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{5} +} + +func (x *ListServiceResponse) GetService() []*ServiceResponse { + if x != nil { + return x.Service + } + return nil +} + +// The information of a single service used by ListServiceResponse to answer +// list_services request. +type ServiceResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Full name of a registered service, including its package name. The format + // is . + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServiceResponse) Reset() { + *x = ServiceResponse{} + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServiceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServiceResponse) ProtoMessage() {} + +func (x *ServiceResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServiceResponse.ProtoReflect.Descriptor instead. +func (*ServiceResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{6} +} + +func (x *ServiceResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The error code and error message sent by the server when an error occurs. +type ErrorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // This field uses the error codes defined in grpc::StatusCode. + ErrorCode int32 `protobuf:"varint,1,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"` + ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ErrorResponse) Reset() { + *x = ErrorResponse{} + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ErrorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ErrorResponse) ProtoMessage() {} + +func (x *ErrorResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1_reflection_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ErrorResponse.ProtoReflect.Descriptor instead. +func (*ErrorResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1_reflection_proto_rawDescGZIP(), []int{7} +} + +func (x *ErrorResponse) GetErrorCode() int32 { + if x != nil { + return x.ErrorCode + } + return 0 +} + +func (x *ErrorResponse) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +var File_grpc_reflection_v1_reflection_proto protoreflect.FileDescriptor + +const file_grpc_reflection_v1_reflection_proto_rawDesc = "" + + "\n" + + "#grpc/reflection/v1/reflection.proto\x12\x12grpc.reflection.v1\"\xf3\x02\n" + + "\x17ServerReflectionRequest\x12\x12\n" + + "\x04host\x18\x01 \x01(\tR\x04host\x12*\n" + + "\x10file_by_filename\x18\x03 \x01(\tH\x00R\x0efileByFilename\x126\n" + + "\x16file_containing_symbol\x18\x04 \x01(\tH\x00R\x14fileContainingSymbol\x12b\n" + + "\x19file_containing_extension\x18\x05 \x01(\v2$.grpc.reflection.v1.ExtensionRequestH\x00R\x17fileContainingExtension\x12B\n" + + "\x1dall_extension_numbers_of_type\x18\x06 \x01(\tH\x00R\x19allExtensionNumbersOfType\x12%\n" + + "\rlist_services\x18\a \x01(\tH\x00R\flistServicesB\x11\n" + + "\x0fmessage_request\"f\n" + + "\x10ExtensionRequest\x12'\n" + + "\x0fcontaining_type\x18\x01 \x01(\tR\x0econtainingType\x12)\n" + + "\x10extension_number\x18\x02 \x01(\x05R\x0fextensionNumber\"\xae\x04\n" + + "\x18ServerReflectionResponse\x12\x1d\n" + + "\n" + + "valid_host\x18\x01 \x01(\tR\tvalidHost\x12V\n" + + "\x10original_request\x18\x02 \x01(\v2+.grpc.reflection.v1.ServerReflectionRequestR\x0foriginalRequest\x12f\n" + + "\x18file_descriptor_response\x18\x04 \x01(\v2*.grpc.reflection.v1.FileDescriptorResponseH\x00R\x16fileDescriptorResponse\x12r\n" + + "\x1eall_extension_numbers_response\x18\x05 \x01(\v2+.grpc.reflection.v1.ExtensionNumberResponseH\x00R\x1ballExtensionNumbersResponse\x12_\n" + + "\x16list_services_response\x18\x06 \x01(\v2'.grpc.reflection.v1.ListServiceResponseH\x00R\x14listServicesResponse\x12J\n" + + "\x0eerror_response\x18\a \x01(\v2!.grpc.reflection.v1.ErrorResponseH\x00R\rerrorResponseB\x12\n" + + "\x10message_response\"L\n" + + "\x16FileDescriptorResponse\x122\n" + + "\x15file_descriptor_proto\x18\x01 \x03(\fR\x13fileDescriptorProto\"j\n" + + "\x17ExtensionNumberResponse\x12$\n" + + "\x0ebase_type_name\x18\x01 \x01(\tR\fbaseTypeName\x12)\n" + + "\x10extension_number\x18\x02 \x03(\x05R\x0fextensionNumber\"T\n" + + "\x13ListServiceResponse\x12=\n" + + "\aservice\x18\x01 \x03(\v2#.grpc.reflection.v1.ServiceResponseR\aservice\"%\n" + + "\x0fServiceResponse\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\"S\n" + + "\rErrorResponse\x12\x1d\n" + + "\n" + + "error_code\x18\x01 \x01(\x05R\terrorCode\x12#\n" + + "\rerror_message\x18\x02 \x01(\tR\ferrorMessage2\x89\x01\n" + + "\x10ServerReflection\x12u\n" + + "\x14ServerReflectionInfo\x12+.grpc.reflection.v1.ServerReflectionRequest\x1a,.grpc.reflection.v1.ServerReflectionResponse(\x010\x01Bf\n" + + "\x15io.grpc.reflection.v1B\x15ServerReflectionProtoP\x01Z4google.golang.org/grpc/reflection/grpc_reflection_v1b\x06proto3" + +var ( + file_grpc_reflection_v1_reflection_proto_rawDescOnce sync.Once + file_grpc_reflection_v1_reflection_proto_rawDescData []byte +) + +func file_grpc_reflection_v1_reflection_proto_rawDescGZIP() []byte { + file_grpc_reflection_v1_reflection_proto_rawDescOnce.Do(func() { + file_grpc_reflection_v1_reflection_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_grpc_reflection_v1_reflection_proto_rawDesc), len(file_grpc_reflection_v1_reflection_proto_rawDesc))) + }) + return file_grpc_reflection_v1_reflection_proto_rawDescData +} + +var file_grpc_reflection_v1_reflection_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_grpc_reflection_v1_reflection_proto_goTypes = []any{ + (*ServerReflectionRequest)(nil), // 0: grpc.reflection.v1.ServerReflectionRequest + (*ExtensionRequest)(nil), // 1: grpc.reflection.v1.ExtensionRequest + (*ServerReflectionResponse)(nil), // 2: grpc.reflection.v1.ServerReflectionResponse + (*FileDescriptorResponse)(nil), // 3: grpc.reflection.v1.FileDescriptorResponse + (*ExtensionNumberResponse)(nil), // 4: grpc.reflection.v1.ExtensionNumberResponse + (*ListServiceResponse)(nil), // 5: grpc.reflection.v1.ListServiceResponse + (*ServiceResponse)(nil), // 6: grpc.reflection.v1.ServiceResponse + (*ErrorResponse)(nil), // 7: grpc.reflection.v1.ErrorResponse +} +var file_grpc_reflection_v1_reflection_proto_depIdxs = []int32{ + 1, // 0: grpc.reflection.v1.ServerReflectionRequest.file_containing_extension:type_name -> grpc.reflection.v1.ExtensionRequest + 0, // 1: grpc.reflection.v1.ServerReflectionResponse.original_request:type_name -> grpc.reflection.v1.ServerReflectionRequest + 3, // 2: grpc.reflection.v1.ServerReflectionResponse.file_descriptor_response:type_name -> grpc.reflection.v1.FileDescriptorResponse + 4, // 3: grpc.reflection.v1.ServerReflectionResponse.all_extension_numbers_response:type_name -> grpc.reflection.v1.ExtensionNumberResponse + 5, // 4: grpc.reflection.v1.ServerReflectionResponse.list_services_response:type_name -> grpc.reflection.v1.ListServiceResponse + 7, // 5: grpc.reflection.v1.ServerReflectionResponse.error_response:type_name -> grpc.reflection.v1.ErrorResponse + 6, // 6: grpc.reflection.v1.ListServiceResponse.service:type_name -> grpc.reflection.v1.ServiceResponse + 0, // 7: grpc.reflection.v1.ServerReflection.ServerReflectionInfo:input_type -> grpc.reflection.v1.ServerReflectionRequest + 2, // 8: grpc.reflection.v1.ServerReflection.ServerReflectionInfo:output_type -> grpc.reflection.v1.ServerReflectionResponse + 8, // [8:9] is the sub-list for method output_type + 7, // [7:8] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_grpc_reflection_v1_reflection_proto_init() } +func file_grpc_reflection_v1_reflection_proto_init() { + if File_grpc_reflection_v1_reflection_proto != nil { + return + } + file_grpc_reflection_v1_reflection_proto_msgTypes[0].OneofWrappers = []any{ + (*ServerReflectionRequest_FileByFilename)(nil), + (*ServerReflectionRequest_FileContainingSymbol)(nil), + (*ServerReflectionRequest_FileContainingExtension)(nil), + (*ServerReflectionRequest_AllExtensionNumbersOfType)(nil), + (*ServerReflectionRequest_ListServices)(nil), + } + file_grpc_reflection_v1_reflection_proto_msgTypes[2].OneofWrappers = []any{ + (*ServerReflectionResponse_FileDescriptorResponse)(nil), + (*ServerReflectionResponse_AllExtensionNumbersResponse)(nil), + (*ServerReflectionResponse_ListServicesResponse)(nil), + (*ServerReflectionResponse_ErrorResponse)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_grpc_reflection_v1_reflection_proto_rawDesc), len(file_grpc_reflection_v1_reflection_proto_rawDesc)), + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_grpc_reflection_v1_reflection_proto_goTypes, + DependencyIndexes: file_grpc_reflection_v1_reflection_proto_depIdxs, + MessageInfos: file_grpc_reflection_v1_reflection_proto_msgTypes, + }.Build() + File_grpc_reflection_v1_reflection_proto = out.File + file_grpc_reflection_v1_reflection_proto_goTypes = nil + file_grpc_reflection_v1_reflection_proto_depIdxs = nil +} diff --git a/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go b/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go new file mode 100644 index 0000000000..f4a361c644 --- /dev/null +++ b/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go @@ -0,0 +1,138 @@ +// Copyright 2016 The gRPC 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. + +// Service exported by server reflection. A more complete description of how +// server reflection works can be found at +// https://github.com/grpc/grpc/blob/master/doc/server-reflection.md +// +// The canonical version of this proto can be found at +// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.27.1 +// source: grpc/reflection/v1/reflection.proto + +package grpc_reflection_v1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + ServerReflection_ServerReflectionInfo_FullMethodName = "/grpc.reflection.v1.ServerReflection/ServerReflectionInfo" +) + +// ServerReflectionClient is the client API for ServerReflection service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ServerReflectionClient interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse], error) +} + +type serverReflectionClient struct { + cc grpc.ClientConnInterface +} + +func NewServerReflectionClient(cc grpc.ClientConnInterface) ServerReflectionClient { + return &serverReflectionClient{cc} +} + +func (c *serverReflectionClient) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &ServerReflection_ServiceDesc.Streams[0], ServerReflection_ServerReflectionInfo_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[ServerReflectionRequest, ServerReflectionResponse]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ServerReflection_ServerReflectionInfoClient = grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse] + +// ServerReflectionServer is the server API for ServerReflection service. +// All implementations should embed UnimplementedServerReflectionServer +// for forward compatibility. +type ServerReflectionServer interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error +} + +// UnimplementedServerReflectionServer should be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedServerReflectionServer struct{} + +func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error { + return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented") +} +func (UnimplementedServerReflectionServer) testEmbeddedByValue() {} + +// UnsafeServerReflectionServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ServerReflectionServer will +// result in compilation errors. +type UnsafeServerReflectionServer interface { + mustEmbedUnimplementedServerReflectionServer() +} + +func RegisterServerReflectionServer(s grpc.ServiceRegistrar, srv ServerReflectionServer) { + // If the following call panics, it indicates UnimplementedServerReflectionServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&ServerReflection_ServiceDesc, srv) +} + +func _ServerReflection_ServerReflectionInfo_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ServerReflectionServer).ServerReflectionInfo(&grpc.GenericServerStream[ServerReflectionRequest, ServerReflectionResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ServerReflection_ServerReflectionInfoServer = grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse] + +// ServerReflection_ServiceDesc is the grpc.ServiceDesc for ServerReflection service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ServerReflection_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.reflection.v1.ServerReflection", + HandlerType: (*ServerReflectionServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ServerReflectionInfo", + Handler: _ServerReflection_ServerReflectionInfo_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "grpc/reflection/v1/reflection.proto", +} diff --git a/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go b/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go new file mode 100644 index 0000000000..5253e862f0 --- /dev/null +++ b/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go @@ -0,0 +1,847 @@ +// Copyright 2016 The gRPC 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. +// Service exported by server reflection + +// Warning: this entire file is deprecated. Use this instead: +// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.6 +// protoc v5.27.1 +// grpc/reflection/v1alpha/reflection.proto is a deprecated file. + +package grpc_reflection_v1alpha + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// The message sent by the client when calling ServerReflectionInfo method. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ServerReflectionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + Host string `protobuf:"bytes,1,opt,name=host,proto3" json:"host,omitempty"` + // To use reflection service, the client should set one of the following + // fields in message_request. The server distinguishes requests by their + // defined field and then handles them using corresponding methods. + // + // Types that are valid to be assigned to MessageRequest: + // + // *ServerReflectionRequest_FileByFilename + // *ServerReflectionRequest_FileContainingSymbol + // *ServerReflectionRequest_FileContainingExtension + // *ServerReflectionRequest_AllExtensionNumbersOfType + // *ServerReflectionRequest_ListServices + MessageRequest isServerReflectionRequest_MessageRequest `protobuf_oneof:"message_request"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServerReflectionRequest) Reset() { + *x = ServerReflectionRequest{} + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServerReflectionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerReflectionRequest) ProtoMessage() {} + +func (x *ServerReflectionRequest) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerReflectionRequest.ProtoReflect.Descriptor instead. +func (*ServerReflectionRequest) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{0} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetHost() string { + if x != nil { + return x.Host + } + return "" +} + +func (x *ServerReflectionRequest) GetMessageRequest() isServerReflectionRequest_MessageRequest { + if x != nil { + return x.MessageRequest + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetFileByFilename() string { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileByFilename); ok { + return x.FileByFilename + } + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetFileContainingSymbol() string { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileContainingSymbol); ok { + return x.FileContainingSymbol + } + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetFileContainingExtension() *ExtensionRequest { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_FileContainingExtension); ok { + return x.FileContainingExtension + } + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetAllExtensionNumbersOfType() string { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_AllExtensionNumbersOfType); ok { + return x.AllExtensionNumbersOfType + } + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionRequest) GetListServices() string { + if x != nil { + if x, ok := x.MessageRequest.(*ServerReflectionRequest_ListServices); ok { + return x.ListServices + } + } + return "" +} + +type isServerReflectionRequest_MessageRequest interface { + isServerReflectionRequest_MessageRequest() +} + +type ServerReflectionRequest_FileByFilename struct { + // Find a proto file by the file name. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileByFilename string `protobuf:"bytes,3,opt,name=file_by_filename,json=fileByFilename,proto3,oneof"` +} + +type ServerReflectionRequest_FileContainingSymbol struct { + // Find the proto file that declares the given fully-qualified symbol name. + // This field should be a fully-qualified symbol name + // (e.g. .[.] or .). + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileContainingSymbol string `protobuf:"bytes,4,opt,name=file_containing_symbol,json=fileContainingSymbol,proto3,oneof"` +} + +type ServerReflectionRequest_FileContainingExtension struct { + // Find the proto file which defines an extension extending the given + // message type with the given field number. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileContainingExtension *ExtensionRequest `protobuf:"bytes,5,opt,name=file_containing_extension,json=fileContainingExtension,proto3,oneof"` +} + +type ServerReflectionRequest_AllExtensionNumbersOfType struct { + // Finds the tag numbers used by all known extensions of extendee_type, and + // appends them to ExtensionNumberResponse in an undefined order. + // Its corresponding method is best-effort: it's not guaranteed that the + // reflection service will implement this method, and it's not guaranteed + // that this method will provide all extensions. Returns + // StatusCode::UNIMPLEMENTED if it's not implemented. + // This field should be a fully-qualified type name. The format is + // . + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + AllExtensionNumbersOfType string `protobuf:"bytes,6,opt,name=all_extension_numbers_of_type,json=allExtensionNumbersOfType,proto3,oneof"` +} + +type ServerReflectionRequest_ListServices struct { + // List the full names of registered services. The content will not be + // checked. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ListServices string `protobuf:"bytes,7,opt,name=list_services,json=listServices,proto3,oneof"` +} + +func (*ServerReflectionRequest_FileByFilename) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_FileContainingSymbol) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_FileContainingExtension) isServerReflectionRequest_MessageRequest() {} + +func (*ServerReflectionRequest_AllExtensionNumbersOfType) isServerReflectionRequest_MessageRequest() { +} + +func (*ServerReflectionRequest_ListServices) isServerReflectionRequest_MessageRequest() {} + +// The type name and extension number sent by the client when requesting +// file_containing_extension. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ExtensionRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Fully-qualified type name. The format should be . + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ContainingType string `protobuf:"bytes,1,opt,name=containing_type,json=containingType,proto3" json:"containing_type,omitempty"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ExtensionNumber int32 `protobuf:"varint,2,opt,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExtensionRequest) Reset() { + *x = ExtensionRequest{} + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExtensionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionRequest) ProtoMessage() {} + +func (x *ExtensionRequest) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionRequest.ProtoReflect.Descriptor instead. +func (*ExtensionRequest) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{1} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ExtensionRequest) GetContainingType() string { + if x != nil { + return x.ContainingType + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ExtensionRequest) GetExtensionNumber() int32 { + if x != nil { + return x.ExtensionNumber + } + return 0 +} + +// The message sent by the server to answer ServerReflectionInfo method. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ServerReflectionResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ValidHost string `protobuf:"bytes,1,opt,name=valid_host,json=validHost,proto3" json:"valid_host,omitempty"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + OriginalRequest *ServerReflectionRequest `protobuf:"bytes,2,opt,name=original_request,json=originalRequest,proto3" json:"original_request,omitempty"` + // The server set one of the following fields according to the message_request + // in the request. + // + // Types that are valid to be assigned to MessageResponse: + // + // *ServerReflectionResponse_FileDescriptorResponse + // *ServerReflectionResponse_AllExtensionNumbersResponse + // *ServerReflectionResponse_ListServicesResponse + // *ServerReflectionResponse_ErrorResponse + MessageResponse isServerReflectionResponse_MessageResponse `protobuf_oneof:"message_response"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServerReflectionResponse) Reset() { + *x = ServerReflectionResponse{} + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServerReflectionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServerReflectionResponse) ProtoMessage() {} + +func (x *ServerReflectionResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServerReflectionResponse.ProtoReflect.Descriptor instead. +func (*ServerReflectionResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{2} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetValidHost() string { + if x != nil { + return x.ValidHost + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetOriginalRequest() *ServerReflectionRequest { + if x != nil { + return x.OriginalRequest + } + return nil +} + +func (x *ServerReflectionResponse) GetMessageResponse() isServerReflectionResponse_MessageResponse { + if x != nil { + return x.MessageResponse + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetFileDescriptorResponse() *FileDescriptorResponse { + if x != nil { + if x, ok := x.MessageResponse.(*ServerReflectionResponse_FileDescriptorResponse); ok { + return x.FileDescriptorResponse + } + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetAllExtensionNumbersResponse() *ExtensionNumberResponse { + if x != nil { + if x, ok := x.MessageResponse.(*ServerReflectionResponse_AllExtensionNumbersResponse); ok { + return x.AllExtensionNumbersResponse + } + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetListServicesResponse() *ListServiceResponse { + if x != nil { + if x, ok := x.MessageResponse.(*ServerReflectionResponse_ListServicesResponse); ok { + return x.ListServicesResponse + } + } + return nil +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServerReflectionResponse) GetErrorResponse() *ErrorResponse { + if x != nil { + if x, ok := x.MessageResponse.(*ServerReflectionResponse_ErrorResponse); ok { + return x.ErrorResponse + } + } + return nil +} + +type isServerReflectionResponse_MessageResponse interface { + isServerReflectionResponse_MessageResponse() +} + +type ServerReflectionResponse_FileDescriptorResponse struct { + // This message is used to answer file_by_filename, file_containing_symbol, + // file_containing_extension requests with transitive dependencies. As + // the repeated label is not allowed in oneof fields, we use a + // FileDescriptorResponse message to encapsulate the repeated fields. + // The reflection service is allowed to avoid sending FileDescriptorProtos + // that were previously sent in response to earlier requests in the stream. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileDescriptorResponse *FileDescriptorResponse `protobuf:"bytes,4,opt,name=file_descriptor_response,json=fileDescriptorResponse,proto3,oneof"` +} + +type ServerReflectionResponse_AllExtensionNumbersResponse struct { + // This message is used to answer all_extension_numbers_of_type request. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + AllExtensionNumbersResponse *ExtensionNumberResponse `protobuf:"bytes,5,opt,name=all_extension_numbers_response,json=allExtensionNumbersResponse,proto3,oneof"` +} + +type ServerReflectionResponse_ListServicesResponse struct { + // This message is used to answer list_services request. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ListServicesResponse *ListServiceResponse `protobuf:"bytes,6,opt,name=list_services_response,json=listServicesResponse,proto3,oneof"` +} + +type ServerReflectionResponse_ErrorResponse struct { + // This message is used when an error occurs. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ErrorResponse *ErrorResponse `protobuf:"bytes,7,opt,name=error_response,json=errorResponse,proto3,oneof"` +} + +func (*ServerReflectionResponse_FileDescriptorResponse) isServerReflectionResponse_MessageResponse() { +} + +func (*ServerReflectionResponse_AllExtensionNumbersResponse) isServerReflectionResponse_MessageResponse() { +} + +func (*ServerReflectionResponse_ListServicesResponse) isServerReflectionResponse_MessageResponse() {} + +func (*ServerReflectionResponse_ErrorResponse) isServerReflectionResponse_MessageResponse() {} + +// Serialized FileDescriptorProto messages sent by the server answering +// a file_by_filename, file_containing_symbol, or file_containing_extension +// request. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type FileDescriptorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Serialized FileDescriptorProto messages. We avoid taking a dependency on + // descriptor.proto, which uses proto2 only features, by making them opaque + // bytes instead. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + FileDescriptorProto [][]byte `protobuf:"bytes,1,rep,name=file_descriptor_proto,json=fileDescriptorProto,proto3" json:"file_descriptor_proto,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *FileDescriptorResponse) Reset() { + *x = FileDescriptorResponse{} + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FileDescriptorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileDescriptorResponse) ProtoMessage() {} + +func (x *FileDescriptorResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileDescriptorResponse.ProtoReflect.Descriptor instead. +func (*FileDescriptorResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{3} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *FileDescriptorResponse) GetFileDescriptorProto() [][]byte { + if x != nil { + return x.FileDescriptorProto + } + return nil +} + +// A list of extension numbers sent by the server answering +// all_extension_numbers_of_type request. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ExtensionNumberResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Full name of the base type, including the package name. The format + // is . + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + BaseTypeName string `protobuf:"bytes,1,opt,name=base_type_name,json=baseTypeName,proto3" json:"base_type_name,omitempty"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ExtensionNumber []int32 `protobuf:"varint,2,rep,packed,name=extension_number,json=extensionNumber,proto3" json:"extension_number,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExtensionNumberResponse) Reset() { + *x = ExtensionNumberResponse{} + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExtensionNumberResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtensionNumberResponse) ProtoMessage() {} + +func (x *ExtensionNumberResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtensionNumberResponse.ProtoReflect.Descriptor instead. +func (*ExtensionNumberResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{4} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ExtensionNumberResponse) GetBaseTypeName() string { + if x != nil { + return x.BaseTypeName + } + return "" +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ExtensionNumberResponse) GetExtensionNumber() []int32 { + if x != nil { + return x.ExtensionNumber + } + return nil +} + +// A list of ServiceResponse sent by the server answering list_services request. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ListServiceResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The information of each service may be expanded in the future, so we use + // ServiceResponse message to encapsulate it. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + Service []*ServiceResponse `protobuf:"bytes,1,rep,name=service,proto3" json:"service,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListServiceResponse) Reset() { + *x = ListServiceResponse{} + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListServiceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListServiceResponse) ProtoMessage() {} + +func (x *ListServiceResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListServiceResponse.ProtoReflect.Descriptor instead. +func (*ListServiceResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{5} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ListServiceResponse) GetService() []*ServiceResponse { + if x != nil { + return x.Service + } + return nil +} + +// The information of a single service used by ListServiceResponse to answer +// list_services request. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ServiceResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Full name of a registered service, including its package name. The format + // is . + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ServiceResponse) Reset() { + *x = ServiceResponse{} + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ServiceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ServiceResponse) ProtoMessage() {} + +func (x *ServiceResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ServiceResponse.ProtoReflect.Descriptor instead. +func (*ServiceResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{6} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ServiceResponse) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The error code and error message sent by the server when an error occurs. +// +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +type ErrorResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + // This field uses the error codes defined in grpc::StatusCode. + // + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ErrorCode int32 `protobuf:"varint,1,opt,name=error_code,json=errorCode,proto3" json:"error_code,omitempty"` + // Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. + ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ErrorResponse) Reset() { + *x = ErrorResponse{} + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ErrorResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ErrorResponse) ProtoMessage() {} + +func (x *ErrorResponse) ProtoReflect() protoreflect.Message { + mi := &file_grpc_reflection_v1alpha_reflection_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ErrorResponse.ProtoReflect.Descriptor instead. +func (*ErrorResponse) Descriptor() ([]byte, []int) { + return file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP(), []int{7} +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ErrorResponse) GetErrorCode() int32 { + if x != nil { + return x.ErrorCode + } + return 0 +} + +// Deprecated: The entire proto file grpc/reflection/v1alpha/reflection.proto is marked as deprecated. +func (x *ErrorResponse) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +var File_grpc_reflection_v1alpha_reflection_proto protoreflect.FileDescriptor + +const file_grpc_reflection_v1alpha_reflection_proto_rawDesc = "" + + "\n" + + "(grpc/reflection/v1alpha/reflection.proto\x12\x17grpc.reflection.v1alpha\"\xf8\x02\n" + + "\x17ServerReflectionRequest\x12\x12\n" + + "\x04host\x18\x01 \x01(\tR\x04host\x12*\n" + + "\x10file_by_filename\x18\x03 \x01(\tH\x00R\x0efileByFilename\x126\n" + + "\x16file_containing_symbol\x18\x04 \x01(\tH\x00R\x14fileContainingSymbol\x12g\n" + + "\x19file_containing_extension\x18\x05 \x01(\v2).grpc.reflection.v1alpha.ExtensionRequestH\x00R\x17fileContainingExtension\x12B\n" + + "\x1dall_extension_numbers_of_type\x18\x06 \x01(\tH\x00R\x19allExtensionNumbersOfType\x12%\n" + + "\rlist_services\x18\a \x01(\tH\x00R\flistServicesB\x11\n" + + "\x0fmessage_request\"f\n" + + "\x10ExtensionRequest\x12'\n" + + "\x0fcontaining_type\x18\x01 \x01(\tR\x0econtainingType\x12)\n" + + "\x10extension_number\x18\x02 \x01(\x05R\x0fextensionNumber\"\xc7\x04\n" + + "\x18ServerReflectionResponse\x12\x1d\n" + + "\n" + + "valid_host\x18\x01 \x01(\tR\tvalidHost\x12[\n" + + "\x10original_request\x18\x02 \x01(\v20.grpc.reflection.v1alpha.ServerReflectionRequestR\x0foriginalRequest\x12k\n" + + "\x18file_descriptor_response\x18\x04 \x01(\v2/.grpc.reflection.v1alpha.FileDescriptorResponseH\x00R\x16fileDescriptorResponse\x12w\n" + + "\x1eall_extension_numbers_response\x18\x05 \x01(\v20.grpc.reflection.v1alpha.ExtensionNumberResponseH\x00R\x1ballExtensionNumbersResponse\x12d\n" + + "\x16list_services_response\x18\x06 \x01(\v2,.grpc.reflection.v1alpha.ListServiceResponseH\x00R\x14listServicesResponse\x12O\n" + + "\x0eerror_response\x18\a \x01(\v2&.grpc.reflection.v1alpha.ErrorResponseH\x00R\rerrorResponseB\x12\n" + + "\x10message_response\"L\n" + + "\x16FileDescriptorResponse\x122\n" + + "\x15file_descriptor_proto\x18\x01 \x03(\fR\x13fileDescriptorProto\"j\n" + + "\x17ExtensionNumberResponse\x12$\n" + + "\x0ebase_type_name\x18\x01 \x01(\tR\fbaseTypeName\x12)\n" + + "\x10extension_number\x18\x02 \x03(\x05R\x0fextensionNumber\"Y\n" + + "\x13ListServiceResponse\x12B\n" + + "\aservice\x18\x01 \x03(\v2(.grpc.reflection.v1alpha.ServiceResponseR\aservice\"%\n" + + "\x0fServiceResponse\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\"S\n" + + "\rErrorResponse\x12\x1d\n" + + "\n" + + "error_code\x18\x01 \x01(\x05R\terrorCode\x12#\n" + + "\rerror_message\x18\x02 \x01(\tR\ferrorMessage2\x93\x01\n" + + "\x10ServerReflection\x12\x7f\n" + + "\x14ServerReflectionInfo\x120.grpc.reflection.v1alpha.ServerReflectionRequest\x1a1.grpc.reflection.v1alpha.ServerReflectionResponse(\x010\x01Bs\n" + + "\x1aio.grpc.reflection.v1alphaB\x15ServerReflectionProtoP\x01Z9google.golang.org/grpc/reflection/grpc_reflection_v1alpha\xb8\x01\x01b\x06proto3" + +var ( + file_grpc_reflection_v1alpha_reflection_proto_rawDescOnce sync.Once + file_grpc_reflection_v1alpha_reflection_proto_rawDescData []byte +) + +func file_grpc_reflection_v1alpha_reflection_proto_rawDescGZIP() []byte { + file_grpc_reflection_v1alpha_reflection_proto_rawDescOnce.Do(func() { + file_grpc_reflection_v1alpha_reflection_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_grpc_reflection_v1alpha_reflection_proto_rawDesc), len(file_grpc_reflection_v1alpha_reflection_proto_rawDesc))) + }) + return file_grpc_reflection_v1alpha_reflection_proto_rawDescData +} + +var file_grpc_reflection_v1alpha_reflection_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_grpc_reflection_v1alpha_reflection_proto_goTypes = []any{ + (*ServerReflectionRequest)(nil), // 0: grpc.reflection.v1alpha.ServerReflectionRequest + (*ExtensionRequest)(nil), // 1: grpc.reflection.v1alpha.ExtensionRequest + (*ServerReflectionResponse)(nil), // 2: grpc.reflection.v1alpha.ServerReflectionResponse + (*FileDescriptorResponse)(nil), // 3: grpc.reflection.v1alpha.FileDescriptorResponse + (*ExtensionNumberResponse)(nil), // 4: grpc.reflection.v1alpha.ExtensionNumberResponse + (*ListServiceResponse)(nil), // 5: grpc.reflection.v1alpha.ListServiceResponse + (*ServiceResponse)(nil), // 6: grpc.reflection.v1alpha.ServiceResponse + (*ErrorResponse)(nil), // 7: grpc.reflection.v1alpha.ErrorResponse +} +var file_grpc_reflection_v1alpha_reflection_proto_depIdxs = []int32{ + 1, // 0: grpc.reflection.v1alpha.ServerReflectionRequest.file_containing_extension:type_name -> grpc.reflection.v1alpha.ExtensionRequest + 0, // 1: grpc.reflection.v1alpha.ServerReflectionResponse.original_request:type_name -> grpc.reflection.v1alpha.ServerReflectionRequest + 3, // 2: grpc.reflection.v1alpha.ServerReflectionResponse.file_descriptor_response:type_name -> grpc.reflection.v1alpha.FileDescriptorResponse + 4, // 3: grpc.reflection.v1alpha.ServerReflectionResponse.all_extension_numbers_response:type_name -> grpc.reflection.v1alpha.ExtensionNumberResponse + 5, // 4: grpc.reflection.v1alpha.ServerReflectionResponse.list_services_response:type_name -> grpc.reflection.v1alpha.ListServiceResponse + 7, // 5: grpc.reflection.v1alpha.ServerReflectionResponse.error_response:type_name -> grpc.reflection.v1alpha.ErrorResponse + 6, // 6: grpc.reflection.v1alpha.ListServiceResponse.service:type_name -> grpc.reflection.v1alpha.ServiceResponse + 0, // 7: grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo:input_type -> grpc.reflection.v1alpha.ServerReflectionRequest + 2, // 8: grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo:output_type -> grpc.reflection.v1alpha.ServerReflectionResponse + 8, // [8:9] is the sub-list for method output_type + 7, // [7:8] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name +} + +func init() { file_grpc_reflection_v1alpha_reflection_proto_init() } +func file_grpc_reflection_v1alpha_reflection_proto_init() { + if File_grpc_reflection_v1alpha_reflection_proto != nil { + return + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[0].OneofWrappers = []any{ + (*ServerReflectionRequest_FileByFilename)(nil), + (*ServerReflectionRequest_FileContainingSymbol)(nil), + (*ServerReflectionRequest_FileContainingExtension)(nil), + (*ServerReflectionRequest_AllExtensionNumbersOfType)(nil), + (*ServerReflectionRequest_ListServices)(nil), + } + file_grpc_reflection_v1alpha_reflection_proto_msgTypes[2].OneofWrappers = []any{ + (*ServerReflectionResponse_FileDescriptorResponse)(nil), + (*ServerReflectionResponse_AllExtensionNumbersResponse)(nil), + (*ServerReflectionResponse_ListServicesResponse)(nil), + (*ServerReflectionResponse_ErrorResponse)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_grpc_reflection_v1alpha_reflection_proto_rawDesc), len(file_grpc_reflection_v1alpha_reflection_proto_rawDesc)), + NumEnums: 0, + NumMessages: 8, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_grpc_reflection_v1alpha_reflection_proto_goTypes, + DependencyIndexes: file_grpc_reflection_v1alpha_reflection_proto_depIdxs, + MessageInfos: file_grpc_reflection_v1alpha_reflection_proto_msgTypes, + }.Build() + File_grpc_reflection_v1alpha_reflection_proto = out.File + file_grpc_reflection_v1alpha_reflection_proto_goTypes = nil + file_grpc_reflection_v1alpha_reflection_proto_depIdxs = nil +} diff --git a/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go b/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go new file mode 100644 index 0000000000..0a43b521c9 --- /dev/null +++ b/etcd/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go @@ -0,0 +1,135 @@ +// Copyright 2016 The gRPC 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. +// Service exported by server reflection + +// Warning: this entire file is deprecated. Use this instead: +// https://github.com/grpc/grpc-proto/blob/master/grpc/reflection/v1/reflection.proto + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.27.1 +// grpc/reflection/v1alpha/reflection.proto is a deprecated file. + +package grpc_reflection_v1alpha + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + ServerReflection_ServerReflectionInfo_FullMethodName = "/grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo" +) + +// ServerReflectionClient is the client API for ServerReflection service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type ServerReflectionClient interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse], error) +} + +type serverReflectionClient struct { + cc grpc.ClientConnInterface +} + +func NewServerReflectionClient(cc grpc.ClientConnInterface) ServerReflectionClient { + return &serverReflectionClient{cc} +} + +func (c *serverReflectionClient) ServerReflectionInfo(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &ServerReflection_ServiceDesc.Streams[0], ServerReflection_ServerReflectionInfo_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[ServerReflectionRequest, ServerReflectionResponse]{ClientStream: stream} + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ServerReflection_ServerReflectionInfoClient = grpc.BidiStreamingClient[ServerReflectionRequest, ServerReflectionResponse] + +// ServerReflectionServer is the server API for ServerReflection service. +// All implementations should embed UnimplementedServerReflectionServer +// for forward compatibility. +type ServerReflectionServer interface { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error +} + +// UnimplementedServerReflectionServer should be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedServerReflectionServer struct{} + +func (UnimplementedServerReflectionServer) ServerReflectionInfo(grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse]) error { + return status.Error(codes.Unimplemented, "method ServerReflectionInfo not implemented") +} +func (UnimplementedServerReflectionServer) testEmbeddedByValue() {} + +// UnsafeServerReflectionServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to ServerReflectionServer will +// result in compilation errors. +type UnsafeServerReflectionServer interface { + mustEmbedUnimplementedServerReflectionServer() +} + +func RegisterServerReflectionServer(s grpc.ServiceRegistrar, srv ServerReflectionServer) { + // If the following call panics, it indicates UnimplementedServerReflectionServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&ServerReflection_ServiceDesc, srv) +} + +func _ServerReflection_ServerReflectionInfo_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(ServerReflectionServer).ServerReflectionInfo(&grpc.GenericServerStream[ServerReflectionRequest, ServerReflectionResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type ServerReflection_ServerReflectionInfoServer = grpc.BidiStreamingServer[ServerReflectionRequest, ServerReflectionResponse] + +// ServerReflection_ServiceDesc is the grpc.ServiceDesc for ServerReflection service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var ServerReflection_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "grpc.reflection.v1alpha.ServerReflection", + HandlerType: (*ServerReflectionServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "ServerReflectionInfo", + Handler: _ServerReflection_ServerReflectionInfo_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "grpc/reflection/v1alpha/reflection.proto", +} diff --git a/etcd/vendor/google.golang.org/grpc/reflection/internal/internal.go b/etcd/vendor/google.golang.org/grpc/reflection/internal/internal.go new file mode 100644 index 0000000000..902fc6d35c --- /dev/null +++ b/etcd/vendor/google.golang.org/grpc/reflection/internal/internal.go @@ -0,0 +1,436 @@ +/* + * + * Copyright 2024 gRPC 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 internal contains code that is shared by both reflection package and +// the test package. The packages are split in this way inorder to avoid +// dependency to deprecated package github.com/golang/protobuf. +package internal + +import ( + "io" + "sort" + + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protodesc" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" + + v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1" + v1reflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1" + v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" + v1alphareflectionpb "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" +) + +// ServiceInfoProvider is an interface used to retrieve metadata about the +// services to expose. +type ServiceInfoProvider interface { + GetServiceInfo() map[string]grpc.ServiceInfo +} + +// ExtensionResolver is the interface used to query details about extensions. +// This interface is satisfied by protoregistry.GlobalTypes. +type ExtensionResolver interface { + protoregistry.ExtensionTypeResolver + RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) +} + +// ServerReflectionServer is the server API for ServerReflection service. +type ServerReflectionServer struct { + v1alphareflectiongrpc.UnimplementedServerReflectionServer + S ServiceInfoProvider + DescResolver protodesc.Resolver + ExtResolver ExtensionResolver +} + +// FileDescWithDependencies returns a slice of serialized fileDescriptors in +// wire format ([]byte). The fileDescriptors will include fd and all the +// transitive dependencies of fd with names not in sentFileDescriptors. +func (s *ServerReflectionServer) FileDescWithDependencies(fd protoreflect.FileDescriptor, sentFileDescriptors map[string]bool) ([][]byte, error) { + if fd.IsPlaceholder() { + // If the given root file is a placeholder, treat it + // as missing instead of serializing it. + return nil, protoregistry.NotFound + } + var r [][]byte + queue := []protoreflect.FileDescriptor{fd} + for len(queue) > 0 { + currentfd := queue[0] + queue = queue[1:] + if currentfd.IsPlaceholder() { + // Skip any missing files in the dependency graph. + continue + } + if sent := sentFileDescriptors[currentfd.Path()]; len(r) == 0 || !sent { + sentFileDescriptors[currentfd.Path()] = true + fdProto := protodesc.ToFileDescriptorProto(currentfd) + currentfdEncoded, err := proto.Marshal(fdProto) + if err != nil { + return nil, err + } + r = append(r, currentfdEncoded) + } + for i := 0; i < currentfd.Imports().Len(); i++ { + queue = append(queue, currentfd.Imports().Get(i)) + } + } + return r, nil +} + +// FileDescEncodingContainingSymbol finds the file descriptor containing the +// given symbol, finds all of its previously unsent transitive dependencies, +// does marshalling on them, and returns the marshalled result. The given symbol +// can be a type, a service or a method. +func (s *ServerReflectionServer) FileDescEncodingContainingSymbol(name string, sentFileDescriptors map[string]bool) ([][]byte, error) { + d, err := s.DescResolver.FindDescriptorByName(protoreflect.FullName(name)) + if err != nil { + return nil, err + } + return s.FileDescWithDependencies(d.ParentFile(), sentFileDescriptors) +} + +// FileDescEncodingContainingExtension finds the file descriptor containing +// given extension, finds all of its previously unsent transitive dependencies, +// does marshalling on them, and returns the marshalled result. +func (s *ServerReflectionServer) FileDescEncodingContainingExtension(typeName string, extNum int32, sentFileDescriptors map[string]bool) ([][]byte, error) { + xt, err := s.ExtResolver.FindExtensionByNumber(protoreflect.FullName(typeName), protoreflect.FieldNumber(extNum)) + if err != nil { + return nil, err + } + return s.FileDescWithDependencies(xt.TypeDescriptor().ParentFile(), sentFileDescriptors) +} + +// AllExtensionNumbersForTypeName returns all extension numbers for the given type. +func (s *ServerReflectionServer) AllExtensionNumbersForTypeName(name string) ([]int32, error) { + var numbers []int32 + s.ExtResolver.RangeExtensionsByMessage(protoreflect.FullName(name), func(xt protoreflect.ExtensionType) bool { + numbers = append(numbers, int32(xt.TypeDescriptor().Number())) + return true + }) + sort.Slice(numbers, func(i, j int) bool { + return numbers[i] < numbers[j] + }) + if len(numbers) == 0 { + // maybe return an error if given type name is not known + if _, err := s.DescResolver.FindDescriptorByName(protoreflect.FullName(name)); err != nil { + return nil, err + } + } + return numbers, nil +} + +// ListServices returns the names of services this server exposes. +func (s *ServerReflectionServer) ListServices() []*v1reflectionpb.ServiceResponse { + serviceInfo := s.S.GetServiceInfo() + resp := make([]*v1reflectionpb.ServiceResponse, 0, len(serviceInfo)) + for svc := range serviceInfo { + resp = append(resp, &v1reflectionpb.ServiceResponse{Name: svc}) + } + sort.Slice(resp, func(i, j int) bool { + return resp[i].Name < resp[j].Name + }) + return resp +} + +// ServerReflectionInfo is the reflection service handler. +func (s *ServerReflectionServer) ServerReflectionInfo(stream v1reflectiongrpc.ServerReflection_ServerReflectionInfoServer) error { + sentFileDescriptors := make(map[string]bool) + for { + in, err := stream.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + + out := &v1reflectionpb.ServerReflectionResponse{ + ValidHost: in.Host, + OriginalRequest: in, + } + switch req := in.MessageRequest.(type) { + case *v1reflectionpb.ServerReflectionRequest_FileByFilename: + var b [][]byte + fd, err := s.DescResolver.FindFileByPath(req.FileByFilename) + if err == nil { + b, err = s.FileDescWithDependencies(fd, sentFileDescriptors) + } + if err != nil { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1reflectionpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b}, + } + } + case *v1reflectionpb.ServerReflectionRequest_FileContainingSymbol: + b, err := s.FileDescEncodingContainingSymbol(req.FileContainingSymbol, sentFileDescriptors) + if err != nil { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1reflectionpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b}, + } + } + case *v1reflectionpb.ServerReflectionRequest_FileContainingExtension: + typeName := req.FileContainingExtension.ContainingType + extNum := req.FileContainingExtension.ExtensionNumber + b, err := s.FileDescEncodingContainingExtension(typeName, extNum, sentFileDescriptors) + if err != nil { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1reflectionpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{FileDescriptorProto: b}, + } + } + case *v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType: + extNums, err := s.AllExtensionNumbersForTypeName(req.AllExtensionNumbersOfType) + if err != nil { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1reflectionpb.ErrorResponse{ + ErrorCode: int32(codes.NotFound), + ErrorMessage: err.Error(), + }, + } + } else { + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{ + AllExtensionNumbersResponse: &v1reflectionpb.ExtensionNumberResponse{ + BaseTypeName: req.AllExtensionNumbersOfType, + ExtensionNumber: extNums, + }, + } + } + case *v1reflectionpb.ServerReflectionRequest_ListServices: + out.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ListServicesResponse{ + ListServicesResponse: &v1reflectionpb.ListServiceResponse{ + Service: s.ListServices(), + }, + } + default: + return status.Errorf(codes.InvalidArgument, "invalid MessageRequest: %v", in.MessageRequest) + } + + if err := stream.Send(out); err != nil { + return err + } + } +} + +// V1ToV1AlphaResponse converts a v1 ServerReflectionResponse to a v1alpha. +func V1ToV1AlphaResponse(v1 *v1reflectionpb.ServerReflectionResponse) *v1alphareflectionpb.ServerReflectionResponse { + var v1alpha v1alphareflectionpb.ServerReflectionResponse + v1alpha.ValidHost = v1.ValidHost + if v1.OriginalRequest != nil { + v1alpha.OriginalRequest = V1ToV1AlphaRequest(v1.OriginalRequest) + } + switch mr := v1.MessageResponse.(type) { + case *v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse: + if mr != nil { + v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &v1alphareflectionpb.FileDescriptorResponse{ + FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(), + }, + } + } + case *v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse: + if mr != nil { + v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{ + AllExtensionNumbersResponse: &v1alphareflectionpb.ExtensionNumberResponse{ + BaseTypeName: mr.AllExtensionNumbersResponse.GetBaseTypeName(), + ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(), + }, + } + } + case *v1reflectionpb.ServerReflectionResponse_ListServicesResponse: + if mr != nil { + svcs := make([]*v1alphareflectionpb.ServiceResponse, len(mr.ListServicesResponse.GetService())) + for i, svc := range mr.ListServicesResponse.GetService() { + svcs[i] = &v1alphareflectionpb.ServiceResponse{ + Name: svc.GetName(), + } + } + v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_ListServicesResponse{ + ListServicesResponse: &v1alphareflectionpb.ListServiceResponse{ + Service: svcs, + }, + } + } + case *v1reflectionpb.ServerReflectionResponse_ErrorResponse: + if mr != nil { + v1alpha.MessageResponse = &v1alphareflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1alphareflectionpb.ErrorResponse{ + ErrorCode: mr.ErrorResponse.GetErrorCode(), + ErrorMessage: mr.ErrorResponse.GetErrorMessage(), + }, + } + } + default: + // no value set + } + return &v1alpha +} + +// V1AlphaToV1Request converts a v1alpha ServerReflectionRequest to a v1. +func V1AlphaToV1Request(v1alpha *v1alphareflectionpb.ServerReflectionRequest) *v1reflectionpb.ServerReflectionRequest { + var v1 v1reflectionpb.ServerReflectionRequest + v1.Host = v1alpha.Host + switch mr := v1alpha.MessageRequest.(type) { + case *v1alphareflectionpb.ServerReflectionRequest_FileByFilename: + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_FileByFilename{ + FileByFilename: mr.FileByFilename, + } + case *v1alphareflectionpb.ServerReflectionRequest_FileContainingSymbol: + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_FileContainingSymbol{ + FileContainingSymbol: mr.FileContainingSymbol, + } + case *v1alphareflectionpb.ServerReflectionRequest_FileContainingExtension: + if mr.FileContainingExtension != nil { + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_FileContainingExtension{ + FileContainingExtension: &v1reflectionpb.ExtensionRequest{ + ContainingType: mr.FileContainingExtension.GetContainingType(), + ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(), + }, + } + } + case *v1alphareflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType: + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType{ + AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType, + } + case *v1alphareflectionpb.ServerReflectionRequest_ListServices: + v1.MessageRequest = &v1reflectionpb.ServerReflectionRequest_ListServices{ + ListServices: mr.ListServices, + } + default: + // no value set + } + return &v1 +} + +// V1ToV1AlphaRequest converts a v1 ServerReflectionRequest to a v1alpha. +func V1ToV1AlphaRequest(v1 *v1reflectionpb.ServerReflectionRequest) *v1alphareflectionpb.ServerReflectionRequest { + var v1alpha v1alphareflectionpb.ServerReflectionRequest + v1alpha.Host = v1.Host + switch mr := v1.MessageRequest.(type) { + case *v1reflectionpb.ServerReflectionRequest_FileByFilename: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_FileByFilename{ + FileByFilename: mr.FileByFilename, + } + } + case *v1reflectionpb.ServerReflectionRequest_FileContainingSymbol: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_FileContainingSymbol{ + FileContainingSymbol: mr.FileContainingSymbol, + } + } + case *v1reflectionpb.ServerReflectionRequest_FileContainingExtension: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_FileContainingExtension{ + FileContainingExtension: &v1alphareflectionpb.ExtensionRequest{ + ContainingType: mr.FileContainingExtension.GetContainingType(), + ExtensionNumber: mr.FileContainingExtension.GetExtensionNumber(), + }, + } + } + case *v1reflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_AllExtensionNumbersOfType{ + AllExtensionNumbersOfType: mr.AllExtensionNumbersOfType, + } + } + case *v1reflectionpb.ServerReflectionRequest_ListServices: + if mr != nil { + v1alpha.MessageRequest = &v1alphareflectionpb.ServerReflectionRequest_ListServices{ + ListServices: mr.ListServices, + } + } + default: + // no value set + } + return &v1alpha +} + +// V1AlphaToV1Response converts a v1alpha ServerReflectionResponse to a v1. +func V1AlphaToV1Response(v1alpha *v1alphareflectionpb.ServerReflectionResponse) *v1reflectionpb.ServerReflectionResponse { + var v1 v1reflectionpb.ServerReflectionResponse + v1.ValidHost = v1alpha.ValidHost + if v1alpha.OriginalRequest != nil { + v1.OriginalRequest = V1AlphaToV1Request(v1alpha.OriginalRequest) + } + switch mr := v1alpha.MessageResponse.(type) { + case *v1alphareflectionpb.ServerReflectionResponse_FileDescriptorResponse: + if mr != nil { + v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_FileDescriptorResponse{ + FileDescriptorResponse: &v1reflectionpb.FileDescriptorResponse{ + FileDescriptorProto: mr.FileDescriptorResponse.GetFileDescriptorProto(), + }, + } + } + case *v1alphareflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse: + if mr != nil { + v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_AllExtensionNumbersResponse{ + AllExtensionNumbersResponse: &v1reflectionpb.ExtensionNumberResponse{ + BaseTypeName: mr.AllExtensionNumbersResponse.GetBaseTypeName(), + ExtensionNumber: mr.AllExtensionNumbersResponse.GetExtensionNumber(), + }, + } + } + case *v1alphareflectionpb.ServerReflectionResponse_ListServicesResponse: + if mr != nil { + svcs := make([]*v1reflectionpb.ServiceResponse, len(mr.ListServicesResponse.GetService())) + for i, svc := range mr.ListServicesResponse.GetService() { + svcs[i] = &v1reflectionpb.ServiceResponse{ + Name: svc.GetName(), + } + } + v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ListServicesResponse{ + ListServicesResponse: &v1reflectionpb.ListServiceResponse{ + Service: svcs, + }, + } + } + case *v1alphareflectionpb.ServerReflectionResponse_ErrorResponse: + if mr != nil { + v1.MessageResponse = &v1reflectionpb.ServerReflectionResponse_ErrorResponse{ + ErrorResponse: &v1reflectionpb.ErrorResponse{ + ErrorCode: mr.ErrorResponse.GetErrorCode(), + ErrorMessage: mr.ErrorResponse.GetErrorMessage(), + }, + } + } + default: + // no value set + } + return &v1 +} diff --git a/etcd/vendor/google.golang.org/grpc/reflection/serverreflection.go b/etcd/vendor/google.golang.org/grpc/reflection/serverreflection.go new file mode 100644 index 0000000000..13a94e2dd2 --- /dev/null +++ b/etcd/vendor/google.golang.org/grpc/reflection/serverreflection.go @@ -0,0 +1,160 @@ +/* + * + * Copyright 2016 gRPC 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 reflection implements server reflection service. + +The service implemented is defined in: +https://github.com/grpc/grpc/blob/master/src/proto/grpc/reflection/v1alpha/reflection.proto. + +To register server reflection on a gRPC server: + + import "google.golang.org/grpc/reflection" + + s := grpc.NewServer() + pb.RegisterYourOwnServer(s, &server{}) + + // Register reflection service on gRPC server. + reflection.Register(s) + + s.Serve(lis) +*/ +package reflection // import "google.golang.org/grpc/reflection" + +import ( + "google.golang.org/grpc" + "google.golang.org/grpc/reflection/internal" + "google.golang.org/protobuf/reflect/protodesc" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/reflect/protoregistry" + + v1reflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1" + v1alphareflectiongrpc "google.golang.org/grpc/reflection/grpc_reflection_v1alpha" +) + +// GRPCServer is the interface provided by a gRPC server. It is implemented by +// *grpc.Server, but could also be implemented by other concrete types. It acts +// as a registry, for accumulating the services exposed by the server. +type GRPCServer interface { + grpc.ServiceRegistrar + ServiceInfoProvider +} + +var _ GRPCServer = (*grpc.Server)(nil) + +// Register registers the server reflection service on the given gRPC server. +// Both the v1 and v1alpha versions are registered. +func Register(s GRPCServer) { + svr := NewServerV1(ServerOptions{Services: s}) + v1alphareflectiongrpc.RegisterServerReflectionServer(s, asV1Alpha(svr)) + v1reflectiongrpc.RegisterServerReflectionServer(s, svr) +} + +// RegisterV1 registers only the v1 version of the server reflection service +// on the given gRPC server. Many clients may only support v1alpha so most +// users should use Register instead, at least until clients have upgraded. +func RegisterV1(s GRPCServer) { + svr := NewServerV1(ServerOptions{Services: s}) + v1reflectiongrpc.RegisterServerReflectionServer(s, svr) +} + +// ServiceInfoProvider is an interface used to retrieve metadata about the +// services to expose. +// +// The reflection service is only interested in the service names, but the +// signature is this way so that *grpc.Server implements it. So it is okay +// for a custom implementation to return zero values for the +// grpc.ServiceInfo values in the map. +// +// # Experimental +// +// Notice: This type is EXPERIMENTAL and may be changed or removed in a +// later release. +type ServiceInfoProvider interface { + GetServiceInfo() map[string]grpc.ServiceInfo +} + +// ExtensionResolver is the interface used to query details about extensions. +// This interface is satisfied by protoregistry.GlobalTypes. +// +// # Experimental +// +// Notice: This type is EXPERIMENTAL and may be changed or removed in a +// later release. +type ExtensionResolver interface { + protoregistry.ExtensionTypeResolver + RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) +} + +// ServerOptions represents the options used to construct a reflection server. +// +// # Experimental +// +// Notice: This type is EXPERIMENTAL and may be changed or removed in a +// later release. +type ServerOptions struct { + // The source of advertised RPC services. If not specified, the reflection + // server will report an empty list when asked to list services. + // + // This value will typically be a *grpc.Server. But the set of advertised + // services can be customized by wrapping a *grpc.Server or using an + // alternate implementation that returns a custom set of service names. + Services ServiceInfoProvider + // Optional resolver used to load descriptors. If not specified, + // protoregistry.GlobalFiles will be used. + DescriptorResolver protodesc.Resolver + // Optional resolver used to query for known extensions. If not specified, + // protoregistry.GlobalTypes will be used. + ExtensionResolver ExtensionResolver +} + +// NewServer returns a reflection server implementation using the given options. +// This can be used to customize behavior of the reflection service. Most usages +// should prefer to use Register instead. For backwards compatibility reasons, +// this returns the v1alpha version of the reflection server. For a v1 version +// of the reflection server, see NewServerV1. +// +// # Experimental +// +// Notice: This function is EXPERIMENTAL and may be changed or removed in a +// later release. +func NewServer(opts ServerOptions) v1alphareflectiongrpc.ServerReflectionServer { + return asV1Alpha(NewServerV1(opts)) +} + +// NewServerV1 returns a reflection server implementation using the given options. +// This can be used to customize behavior of the reflection service. Most usages +// should prefer to use Register instead. +// +// # Experimental +// +// Notice: This function is EXPERIMENTAL and may be changed or removed in a +// later release. +func NewServerV1(opts ServerOptions) v1reflectiongrpc.ServerReflectionServer { + if opts.DescriptorResolver == nil { + opts.DescriptorResolver = protoregistry.GlobalFiles + } + if opts.ExtensionResolver == nil { + opts.ExtensionResolver = protoregistry.GlobalTypes + } + return &internal.ServerReflectionServer{ + S: opts.Services, + DescResolver: opts.DescriptorResolver, + ExtResolver: opts.ExtensionResolver, + } +} diff --git a/etcd/vendor/k8s.io/client-go/util/cert/cert.go b/etcd/vendor/k8s.io/client-go/util/cert/cert.go index 1220461264..48c78b595e 100644 --- a/etcd/vendor/k8s.io/client-go/util/cert/cert.go +++ b/etcd/vendor/k8s.io/client-go/util/cert/cert.go @@ -75,13 +75,15 @@ func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, erro CommonName: cfg.CommonName, Organization: cfg.Organization, }, - DNSNames: []string{cfg.CommonName}, NotBefore: notBefore, NotAfter: now.Add(duration365d * 10).UTC(), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, IsCA: true, } + if len(cfg.CommonName) > 0 { + tmpl.DNSNames = []string{cfg.CommonName} + } certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &tmpl, &tmpl, key.Public(), key) if err != nil { diff --git a/etcd/vendor/k8s.io/utils/net/multi_listen.go b/etcd/vendor/k8s.io/utils/net/multi_listen.go index 7cb7795bec..e5d508055d 100644 --- a/etcd/vendor/k8s.io/utils/net/multi_listen.go +++ b/etcd/vendor/k8s.io/utils/net/multi_listen.go @@ -21,6 +21,7 @@ import ( "fmt" "net" "sync" + "sync/atomic" ) // connErrPair pairs conn and error which is returned by accept on sub-listeners. @@ -38,6 +39,7 @@ type multiListener struct { connCh chan connErrPair // stopCh communicates from parent to child listeners. stopCh chan struct{} + closed atomic.Bool } // compile time check to ensure *multiListener implements net.Listener @@ -150,10 +152,8 @@ func (ml *multiListener) Accept() (net.Conn, error) { // the go-routines to exit. func (ml *multiListener) Close() error { // Make sure this can be called repeatedly without explosions. - select { - case <-ml.stopCh: + if !ml.closed.CompareAndSwap(false, true) { return fmt.Errorf("use of closed network connection") - default: } // Tell all sub-listeners to stop. diff --git a/etcd/vendor/modules.txt b/etcd/vendor/modules.txt index 1fb84a60a4..3dba563acb 100644 --- a/etcd/vendor/modules.txt +++ b/etcd/vendor/modules.txt @@ -48,18 +48,12 @@ github.com/evanphx/json-patch # github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f ## explicit; go 1.15 github.com/exponent-io/jsonpath -# github.com/fsnotify/fsnotify v1.9.0 -## explicit; go 1.17 # github.com/fxamacker/cbor/v2 v2.9.0 ## explicit; go 1.20 github.com/fxamacker/cbor/v2 -# github.com/ghodss/yaml v1.0.0 -## explicit # github.com/go-errors/errors v1.4.2 ## explicit; go 1.14 github.com/go-errors/errors -# github.com/go-kit/kit v0.9.0 -## explicit # github.com/go-kit/log v0.2.1 ## explicit; go 1.17 github.com/go-kit/log @@ -84,27 +78,18 @@ github.com/go-openapi/jsonreference/internal # github.com/go-openapi/swag v0.23.0 ## explicit; go 1.20 github.com/go-openapi/swag -# github.com/go-viper/mapstructure/v2 v2.4.0 -## explicit; go 1.18 # github.com/gogo/protobuf v1.3.2 ## explicit; go 1.15 github.com/gogo/protobuf/gogoproto github.com/gogo/protobuf/proto github.com/gogo/protobuf/protoc-gen-gogo/descriptor github.com/gogo/protobuf/sortkeys -# github.com/golang-jwt/jwt/v4 v4.5.2 -## explicit; go 1.16 -github.com/golang-jwt/jwt/v4 +# github.com/golang-jwt/jwt/v5 v5.2.2 +## explicit; go 1.18 +github.com/golang-jwt/jwt/v5 # github.com/golang/protobuf v1.5.4 ## explicit; go 1.17 -github.com/golang/protobuf/descriptor -github.com/golang/protobuf/jsonpb github.com/golang/protobuf/proto -github.com/golang/protobuf/protoc-gen-go/descriptor -github.com/golang/protobuf/ptypes/any -github.com/golang/protobuf/ptypes/duration -github.com/golang/protobuf/ptypes/timestamp -github.com/golang/protobuf/ptypes/wrappers # github.com/google/btree v1.1.3 ## explicit; go 1.18 github.com/google/btree @@ -131,20 +116,16 @@ github.com/gorilla/websocket # github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 ## explicit github.com/gregjones/httpcache -# github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 -## explicit; go 1.14 -github.com/grpc-ecosystem/go-grpc-middleware -# github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 -## explicit -github.com/grpc-ecosystem/go-grpc-prometheus -# github.com/grpc-ecosystem/grpc-gateway v1.16.0 -## explicit; go 1.14 -github.com/grpc-ecosystem/grpc-gateway/internal -github.com/grpc-ecosystem/grpc-gateway/runtime -github.com/grpc-ecosystem/grpc-gateway/utilities +# github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 +## explicit; go 1.19 +github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus +# github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 +## explicit; go 1.23 +github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors # github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 ## explicit; go 1.23.0 github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule +github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options github.com/grpc-ecosystem/grpc-gateway/v2/runtime github.com/grpc-ecosystem/grpc-gateway/v2/utilities # github.com/inconshreveable/mousetrap v1.1.0 @@ -170,8 +151,6 @@ github.com/mailru/easyjson/jwriter # github.com/mitchellh/go-wordwrap v1.0.1 ## explicit; go 1.14 github.com/mitchellh/go-wordwrap -# github.com/mitchellh/mapstructure v1.5.0 -## explicit; go 1.14 # github.com/moby/spdystream v0.5.0 ## explicit; go 1.13 github.com/moby/spdystream @@ -198,11 +177,12 @@ github.com/mxk/go-flowrate/flowrate # github.com/oklog/run v1.2.0 ## explicit; go 1.20 github.com/oklog/run -# github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7 +# github.com/openshift/api v0.0.0-20251117165054-348370f055bf ## explicit; go 1.24.0 github.com/openshift/api/config/v1 +github.com/openshift/api/features github.com/openshift/api/operator/v1 -# github.com/openshift/build-machinery-go v0.0.0-20250602125535-1b6d00b8c37c +# github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af ## explicit; go 1.22.0 github.com/openshift/build-machinery-go github.com/openshift/build-machinery-go/make @@ -212,7 +192,7 @@ 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-20251015151611-6fc7a74b67c5 +# github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/crypto github.com/openshift/library-go/pkg/operator/apiserver/audit @@ -223,8 +203,6 @@ github.com/openshift/microshift/pkg/config/apiserver github.com/openshift/microshift/pkg/util github.com/openshift/microshift/pkg/util/cryptomaterial github.com/openshift/microshift/pkg/version -# github.com/pelletier/go-toml/v2 v2.2.4 -## explicit; go 1.21.0 # github.com/peterbourgon/diskv v2.0.1+incompatible ## explicit github.com/peterbourgon/diskv @@ -258,34 +236,22 @@ github.com/prometheus/procfs/internal/util # github.com/russross/blackfriday/v2 v2.1.0 ## explicit github.com/russross/blackfriday/v2 -# github.com/sagikazarmark/locafero v0.11.0 -## explicit; go 1.23.0 # github.com/sirupsen/logrus v1.9.3 ## explicit; go 1.13 github.com/sirupsen/logrus # github.com/soheilhy/cmux v0.1.5 ## explicit; go 1.11 github.com/soheilhy/cmux -# github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 -## explicit; go 1.20 -# github.com/spf13/afero v1.15.0 -## explicit; go 1.23.0 -# github.com/spf13/cast v1.10.0 -## explicit; go 1.21.0 # github.com/spf13/cobra v1.9.1 ## explicit; go 1.15 github.com/spf13/cobra # github.com/spf13/pflag v1.0.10 ## explicit; go 1.12 github.com/spf13/pflag -# github.com/spf13/viper v1.21.0 -## explicit; go 1.23.0 # github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 ## explicit; go 1.24.0 github.com/squat/generic-device-plugin/absolute github.com/squat/generic-device-plugin/deviceplugin -# github.com/subosito/gotenv v1.6.0 -## explicit; go 1.18 # github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 ## explicit; go 1.15 github.com/tmc/grpc-websocket-proxy/wsproxy @@ -305,14 +271,14 @@ github.com/xiang90/probing # github.com/xlab/treeprint v1.2.0 ## explicit; go 1.13 github.com/xlab/treeprint -# go.etcd.io/bbolt v1.4.2 +# go.etcd.io/bbolt v1.4.3 ## explicit; go 1.23 go.etcd.io/bbolt go.etcd.io/bbolt/errors go.etcd.io/bbolt/internal/common go.etcd.io/bbolt/internal/freelist -# go.etcd.io/etcd/api/v3 v3.6.4 => github.com/openshift/etcd/api/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -## explicit; go 1.23.0 +# go.etcd.io/etcd/api/v3 v3.6.5 => github.com/openshift/etcd/api/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 +## explicit; go 1.24 go.etcd.io/etcd/api/v3/authpb go.etcd.io/etcd/api/v3/etcdserverpb go.etcd.io/etcd/api/v3/etcdserverpb/gw @@ -320,8 +286,9 @@ go.etcd.io/etcd/api/v3/membershippb 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/client/pkg/v3 v3.6.4 => github.com/openshift/etcd/client/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -## explicit; go 1.23.0 +go.etcd.io/etcd/api/v3/versionpb +# go.etcd.io/etcd/client/pkg/v3 v3.6.5 => github.com/openshift/etcd/client/pkg/v3 v3.0.0-20251111143920-806f690e1f14 +## 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/pathutil @@ -330,64 +297,54 @@ go.etcd.io/etcd/client/pkg/v3/systemd 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/v2 v2.305.21 -## explicit; go 1.23.0 -go.etcd.io/etcd/client/v2 -# go.etcd.io/etcd/client/v3 v3.6.4 => github.com/openshift/etcd/client/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -## explicit; go 1.23.0 +go.etcd.io/etcd/client/pkg/v3/verify +# go.etcd.io/etcd/client/v3 v3.6.5 => github.com/openshift/etcd/client/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 +## explicit; go 1.24 go.etcd.io/etcd/client/v3 go.etcd.io/etcd/client/v3/concurrency go.etcd.io/etcd/client/v3/credentials go.etcd.io/etcd/client/v3/internal/endpoint go.etcd.io/etcd/client/v3/internal/resolver -# go.etcd.io/etcd/pkg/v3 v3.6.4 => github.com/openshift/etcd/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -## explicit; go 1.23.0 +# go.etcd.io/etcd/pkg/v3 v3.6.5 => github.com/openshift/etcd/pkg/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 +## explicit; go 1.24 go.etcd.io/etcd/pkg/v3/adt go.etcd.io/etcd/pkg/v3/contention go.etcd.io/etcd/pkg/v3/cpuutil go.etcd.io/etcd/pkg/v3/crc go.etcd.io/etcd/pkg/v3/debugutil +go.etcd.io/etcd/pkg/v3/featuregate go.etcd.io/etcd/pkg/v3/flags go.etcd.io/etcd/pkg/v3/httputil go.etcd.io/etcd/pkg/v3/idutil go.etcd.io/etcd/pkg/v3/ioutil go.etcd.io/etcd/pkg/v3/netutil +go.etcd.io/etcd/pkg/v3/notify go.etcd.io/etcd/pkg/v3/pbutil go.etcd.io/etcd/pkg/v3/runtime go.etcd.io/etcd/pkg/v3/schedule go.etcd.io/etcd/pkg/v3/traceutil go.etcd.io/etcd/pkg/v3/wait -# go.etcd.io/etcd/raft/v3 v3.5.21 => github.com/openshift/etcd/raft/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -## explicit; go 1.23.0 -go.etcd.io/etcd/raft/v3 -go.etcd.io/etcd/raft/v3/confchange -go.etcd.io/etcd/raft/v3/quorum -go.etcd.io/etcd/raft/v3/raftpb -go.etcd.io/etcd/raft/v3/tracker -# go.etcd.io/etcd/server/v3 v3.6.4 => github.com/openshift/etcd/server/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -## explicit; go 1.23.0 +# go.etcd.io/etcd/server/v3 v3.6.4 => github.com/openshift/etcd/server/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 +## explicit; go 1.24 go.etcd.io/etcd/server/v3/auth go.etcd.io/etcd/server/v3/config -go.etcd.io/etcd/server/v3/datadir go.etcd.io/etcd/server/v3/embed go.etcd.io/etcd/server/v3/etcdserver go.etcd.io/etcd/server/v3/etcdserver/api go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp +go.etcd.io/etcd/server/v3/etcdserver/api/etcdhttp/types go.etcd.io/etcd/server/v3/etcdserver/api/membership go.etcd.io/etcd/server/v3/etcdserver/api/rafthttp go.etcd.io/etcd/server/v3/etcdserver/api/snap go.etcd.io/etcd/server/v3/etcdserver/api/snap/snappb -go.etcd.io/etcd/server/v3/etcdserver/api/v2auth go.etcd.io/etcd/server/v3/etcdserver/api/v2discovery go.etcd.io/etcd/server/v3/etcdserver/api/v2error -go.etcd.io/etcd/server/v3/etcdserver/api/v2http -go.etcd.io/etcd/server/v3/etcdserver/api/v2http/httptypes go.etcd.io/etcd/server/v3/etcdserver/api/v2stats go.etcd.io/etcd/server/v3/etcdserver/api/v2store -go.etcd.io/etcd/server/v3/etcdserver/api/v2v3 go.etcd.io/etcd/server/v3/etcdserver/api/v3alarm go.etcd.io/etcd/server/v3/etcdserver/api/v3client go.etcd.io/etcd/server/v3/etcdserver/api/v3compactor +go.etcd.io/etcd/server/v3/etcdserver/api/v3discovery go.etcd.io/etcd/server/v3/etcdserver/api/v3election go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb go.etcd.io/etcd/server/v3/etcdserver/api/v3election/v3electionpb/gw @@ -395,18 +352,33 @@ go.etcd.io/etcd/server/v3/etcdserver/api/v3lock go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb go.etcd.io/etcd/server/v3/etcdserver/api/v3lock/v3lockpb/gw go.etcd.io/etcd/server/v3/etcdserver/api/v3rpc +go.etcd.io/etcd/server/v3/etcdserver/apply go.etcd.io/etcd/server/v3/etcdserver/cindex +go.etcd.io/etcd/server/v3/etcdserver/errors +go.etcd.io/etcd/server/v3/etcdserver/txn +go.etcd.io/etcd/server/v3/etcdserver/version +go.etcd.io/etcd/server/v3/features +go.etcd.io/etcd/server/v3/internal/clientv2 go.etcd.io/etcd/server/v3/lease go.etcd.io/etcd/server/v3/lease/leasehttp go.etcd.io/etcd/server/v3/lease/leasepb -go.etcd.io/etcd/server/v3/mvcc -go.etcd.io/etcd/server/v3/mvcc/backend -go.etcd.io/etcd/server/v3/mvcc/buckets go.etcd.io/etcd/server/v3/proxy/grpcproxy/adapter go.etcd.io/etcd/server/v3/revbump +go.etcd.io/etcd/server/v3/storage +go.etcd.io/etcd/server/v3/storage/backend +go.etcd.io/etcd/server/v3/storage/datadir +go.etcd.io/etcd/server/v3/storage/mvcc +go.etcd.io/etcd/server/v3/storage/schema +go.etcd.io/etcd/server/v3/storage/wal +go.etcd.io/etcd/server/v3/storage/wal/walpb go.etcd.io/etcd/server/v3/verify -go.etcd.io/etcd/server/v3/wal -go.etcd.io/etcd/server/v3/wal/walpb +# go.etcd.io/raft/v3 v3.6.0 +## explicit; go 1.23 +go.etcd.io/raft/v3 +go.etcd.io/raft/v3/confchange +go.etcd.io/raft/v3/quorum +go.etcd.io/raft/v3/raftpb +go.etcd.io/raft/v3/tracker # go.opentelemetry.io/auto/sdk v1.1.0 ## explicit; go 1.22.0 go.opentelemetry.io/auto/sdk @@ -425,11 +397,9 @@ go.opentelemetry.io/otel/codes go.opentelemetry.io/otel/internal/baggage go.opentelemetry.io/otel/internal/global go.opentelemetry.io/otel/propagation -go.opentelemetry.io/otel/semconv/internal go.opentelemetry.io/otel/semconv/v1.17.0 go.opentelemetry.io/otel/semconv/v1.26.0 go.opentelemetry.io/otel/semconv/v1.34.0 -go.opentelemetry.io/otel/semconv/v1.4.0 # go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 ## explicit; go 1.22.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace @@ -537,9 +507,6 @@ golang.org/x/text/unicode/norm # golang.org/x/time v0.9.0 ## explicit; go 1.18 golang.org/x/time/rate -# google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 -## explicit; go 1.19 -google.golang.org/genproto/protobuf/field_mask # google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b ## explicit; go 1.23.0 google.golang.org/genproto/googleapis/api @@ -608,6 +575,10 @@ google.golang.org/grpc/keepalive google.golang.org/grpc/mem google.golang.org/grpc/metadata google.golang.org/grpc/peer +google.golang.org/grpc/reflection +google.golang.org/grpc/reflection/grpc_reflection_v1 +google.golang.org/grpc/reflection/grpc_reflection_v1alpha +google.golang.org/grpc/reflection/internal google.golang.org/grpc/resolver google.golang.org/grpc/resolver/dns google.golang.org/grpc/resolver/manual @@ -667,12 +638,10 @@ gopkg.in/inf.v0 # gopkg.in/natefinch/lumberjack.v2 v2.2.1 ## explicit; go 1.13 gopkg.in/natefinch/lumberjack.v2 -# gopkg.in/yaml.v2 v2.4.0 -## explicit; go 1.15 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# k8s.io/api v1.34.1 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/api +# k8s.io/api v1.34.2 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/api ## explicit; go 1.24.0 k8s.io/api/admission/v1 k8s.io/api/admission/v1beta1 @@ -734,7 +703,7 @@ k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 k8s.io/api/storagemigration/v1alpha1 -# k8s.io/apimachinery v1.34.1 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery +# k8s.io/apimachinery v1.34.2 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery ## explicit; go 1.24.0 k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors @@ -800,18 +769,18 @@ k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/reflect -# k8s.io/apiserver v1.34.1 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiserver +# k8s.io/apiserver v1.34.2 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiserver ## explicit; go 1.24.0 k8s.io/apiserver/pkg/apis/audit k8s.io/apiserver/pkg/apis/audit/v1 k8s.io/apiserver/pkg/authentication/user -# k8s.io/cli-runtime v1.34.1 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime +# k8s.io/cli-runtime v1.34.2 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime ## explicit; go 1.24.0 k8s.io/cli-runtime/pkg/genericclioptions k8s.io/cli-runtime/pkg/genericiooptions k8s.io/cli-runtime/pkg/printers k8s.io/cli-runtime/pkg/resource -# k8s.io/client-go v1.34.1 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go +# k8s.io/client-go v1.34.2 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go ## explicit; go 1.24.0 k8s.io/client-go/applyconfigurations/admissionregistration/v1 k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1 @@ -970,7 +939,7 @@ k8s.io/client-go/util/homedir k8s.io/client-go/util/jsonpath k8s.io/client-go/util/keyutil k8s.io/client-go/util/workqueue -# k8s.io/component-base v1.34.1 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/component-base +# k8s.io/component-base v1.34.2 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/component-base ## explicit; go 1.24.0 k8s.io/component-base/cli k8s.io/component-base/cli/flag @@ -1007,7 +976,7 @@ k8s.io/kube-openapi/pkg/spec3 k8s.io/kube-openapi/pkg/util/proto k8s.io/kube-openapi/pkg/util/proto/validation k8s.io/kube-openapi/pkg/validation/spec -# k8s.io/kubectl v1.34.1 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubectl +# k8s.io/kubectl v1.34.2 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubectl ## explicit; go 1.24.0 k8s.io/kubectl/pkg/cmd/util k8s.io/kubectl/pkg/scheme @@ -1017,10 +986,10 @@ k8s.io/kubectl/pkg/util/openapi k8s.io/kubectl/pkg/util/templates k8s.io/kubectl/pkg/util/term k8s.io/kubectl/pkg/validation -# k8s.io/kubelet v1.34.1 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubelet +# k8s.io/kubelet v1.34.2 => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubelet ## explicit; go 1.24.0 k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1 -# k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 +# k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 ## explicit; go 1.18 k8s.io/utils/clock k8s.io/utils/exec @@ -1128,12 +1097,11 @@ sigs.k8s.io/yaml/kyaml # github.com/openshift/microshift/pkg/config => ../pkg/config # github.com/openshift/microshift/pkg/util/cryptomaterial => ../pkg/util/cryptomaterial # github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 -# go.etcd.io/etcd/api/v3 => github.com/openshift/etcd/api/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -# go.etcd.io/etcd/client/pkg/v3 => github.com/openshift/etcd/client/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -# go.etcd.io/etcd/client/v3 => github.com/openshift/etcd/client/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -# go.etcd.io/etcd/pkg/v3 => github.com/openshift/etcd/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -# go.etcd.io/etcd/raft/v3 => github.com/openshift/etcd/raft/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 -# go.etcd.io/etcd/server/v3 => github.com/openshift/etcd/server/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 +# go.etcd.io/etcd/api/v3 => github.com/openshift/etcd/api/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 +# go.etcd.io/etcd/client/pkg/v3 => github.com/openshift/etcd/client/pkg/v3 v3.0.0-20251111143920-806f690e1f14 +# go.etcd.io/etcd/client/v3 => github.com/openshift/etcd/client/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 +# go.etcd.io/etcd/pkg/v3 => github.com/openshift/etcd/pkg/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 +# go.etcd.io/etcd/server/v3 => github.com/openshift/etcd/server/v3 v3.5.0-alpha.0.0.20251111143920-806f690e1f14 # k8s.io/api => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/api # k8s.io/apiextensions-apiserver => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver # k8s.io/apimachinery => ../deps/github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery diff --git a/go.mod b/go.mod index ad9ff5e7ef..0ddd33b65a 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,10 @@ require ( github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e // openshift-controller-manager github.com/google/go-cmp v0.7.0 github.com/miekg/dns v1.1.63 // microshift - github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7 - github.com/openshift/build-machinery-go v0.0.0-20250602125535-1b6d00b8c37c + github.com/openshift/api v0.0.0-20251117165054-348370f055bf + github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235 - github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 + github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f github.com/pkg/errors v0.9.1 // indirect github.com/spf13/cobra v1.9.1 github.com/spf13/pflag v1.0.10 @@ -31,25 +31,25 @@ require ( github.com/go-kit/kit v0.9.0 github.com/gogo/protobuf v1.3.2 github.com/golang/snappy v0.0.4 - github.com/openshift/cluster-policy-controller v0.0.0-20251007100337-ef703966fe6e - github.com/openshift/route-controller-manager v0.0.0-20251008111043-c337cf413bbb + github.com/openshift/cluster-policy-controller v0.0.0-20251120141414-8b775487512f + github.com/openshift/route-controller-manager v0.0.0-20251106134803-8a69194a461d github.com/prometheus/client_model v0.6.2 github.com/prometheus/common v0.66.1 github.com/prometheus/prometheus v0.302.1 github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v1.34.1 - k8s.io/apiextensions-apiserver v1.34.1 - k8s.io/apimachinery v1.34.1 - k8s.io/apiserver v1.34.1 - k8s.io/cli-runtime v1.34.1 - k8s.io/client-go v1.34.1 - k8s.io/cloud-provider v1.34.1 - k8s.io/component-base v1.34.1 - k8s.io/kube-aggregator v1.34.1 - k8s.io/kubectl v1.34.1 - k8s.io/kubelet v1.34.1 - k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 + k8s.io/api v1.34.2 + k8s.io/apiextensions-apiserver v1.34.2 + k8s.io/apimachinery v1.34.2 + k8s.io/apiserver v1.34.2 + k8s.io/cli-runtime v1.34.2 + k8s.io/client-go v1.34.2 + k8s.io/cloud-provider v1.34.2 + k8s.io/component-base v1.34.2 + k8s.io/kube-aggregator v1.34.2 + k8s.io/kubectl v1.34.2 + k8s.io/kubelet v1.34.2 + k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 sigs.k8s.io/kube-storage-version-migrator v0.0.6-0.20230721195810-5c8923c5ff96 sigs.k8s.io/kustomize/api v0.20.1 sigs.k8s.io/kustomize/kyaml v0.20.1 @@ -85,7 +85,6 @@ require ( github.com/felixge/fgprof v0.9.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect - github.com/ghodss/yaml v1.0.0 // indirect github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-ldap/ldap/v3 v3.4.11 // indirect @@ -96,7 +95,6 @@ require ( github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/go-stack/stack v1.8.1 // indirect - github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/btree v1.1.3 // indirect @@ -115,7 +113,6 @@ require ( github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/moby/spdystream v0.5.0 // indirect github.com/moby/sys/mountinfo v0.7.2 // indirect github.com/moby/sys/userns v0.1.0 // indirect @@ -131,7 +128,6 @@ require ( github.com/opencontainers/runtime-spec v1.2.0 // indirect github.com/opencontainers/selinux v1.11.1 // indirect github.com/openshift/apiserver-library-go v0.0.0-20251015164739-79d04067059d // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pquerna/cachecontrol v0.1.0 // indirect github.com/prometheus/client_golang v1.23.2 // indirect @@ -139,13 +135,7 @@ require ( github.com/robfig/cron v1.2.0 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/sagikazarmark/locafero v0.11.0 // indirect - github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect - github.com/spf13/afero v1.15.0 // indirect - github.com/spf13/cast v1.10.0 // indirect - github.com/spf13/viper v1.21.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect - github.com/subosito/gotenv v1.6.0 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xlab/treeprint v1.2.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect @@ -171,21 +161,21 @@ require ( 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 - k8s.io/cluster-bootstrap v1.34.1 // indirect - k8s.io/component-helpers v1.34.1 // indirect - k8s.io/controller-manager v1.34.1 // indirect - k8s.io/cri-api v1.34.1 // indirect - k8s.io/cri-client v1.34.1 // indirect - k8s.io/csi-translation-lib v1.34.1 // indirect - k8s.io/dynamic-resource-allocation v1.34.1 // indirect - k8s.io/endpointslice v1.34.1 // indirect - k8s.io/externaljwt v1.34.1 // indirect - k8s.io/kms v1.34.1 // indirect - k8s.io/kube-controller-manager v1.34.1 // indirect - k8s.io/kube-scheduler v1.34.1 // indirect - k8s.io/metrics v1.34.1 // indirect - k8s.io/mount-utils v1.34.1 // indirect - k8s.io/pod-security-admission v1.34.1 // indirect + k8s.io/cluster-bootstrap v1.34.2 // indirect + k8s.io/component-helpers v1.34.2 // indirect + k8s.io/controller-manager v1.34.2 // indirect + k8s.io/cri-api v1.34.2 // indirect + k8s.io/cri-client v1.34.2 // indirect + k8s.io/csi-translation-lib v1.34.2 // indirect + k8s.io/dynamic-resource-allocation v1.34.2 // indirect + k8s.io/endpointslice v1.34.2 // indirect + k8s.io/externaljwt v1.34.2 // indirect + k8s.io/kms v1.34.2 // indirect + k8s.io/kube-controller-manager v1.34.2 // indirect + k8s.io/kube-scheduler v1.34.2 // indirect + k8s.io/metrics v1.34.2 // indirect + 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/randfill v1.0.0 // indirect @@ -227,7 +217,7 @@ require ( 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.1 + k8s.io/kubernetes v1.34.2 ) replace ( diff --git a/go.sum b/go.sum index 012a19f185..7af9b7cf11 100644 --- a/go.sum +++ b/go.sum @@ -103,8 +103,6 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -134,8 +132,6 @@ github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= -github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY= @@ -232,8 +228,6 @@ github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible h1 github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU= @@ -258,8 +252,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= -github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E= github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= @@ -277,27 +269,25 @@ github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.11.1 h1:nHFvthhM0qY8/m+vfhJylliSshm8G1jJ2jDMcgULaH8= github.com/opencontainers/selinux v1.11.1/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec= -github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7 h1:Ot2fbEEPmF3WlPQkyEW/bUCV38GMugH/UmZvxpWceNc= -github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY= +github.com/openshift/api v0.0.0-20251117165054-348370f055bf h1:8VzLlQFneh4bnHA3SS+Bb9VWdVaR7WugtSeqIngMC3s= +github.com/openshift/api v0.0.0-20251117165054-348370f055bf/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY= github.com/openshift/apiserver-library-go v0.0.0-20251015164739-79d04067059d h1:Mfya3RxHWvidOrKyHj3bmFn5x2B89DLZIvDAhwm+C2s= github.com/openshift/apiserver-library-go v0.0.0-20251015164739-79d04067059d/go.mod h1:zm2/rIUp0p83pz0/1kkSoKTqhTr3uUKSKQ9fP7Z3g7Y= -github.com/openshift/build-machinery-go v0.0.0-20250602125535-1b6d00b8c37c h1:gJvhduWIrpzoUTwrJjjeul+hGETKkhRhEZosBg/X3Hg= -github.com/openshift/build-machinery-go v0.0.0-20250602125535-1b6d00b8c37c/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= +github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af h1:UiYYMi/CCV+kwWrXuXfuUSOY2yNXOpWpNVgHc6aLQlE= +github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE= github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235 h1:9JBeIXmnHlpXTQPi7LPmu1jdxznBhAE7bb1K+3D8gxY= github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235/go.mod h1:L49W6pfrZkfOE5iC1PqEkuLkXG4W0BX4w8b+L2Bv7fM= -github.com/openshift/cluster-policy-controller v0.0.0-20251007100337-ef703966fe6e h1:ys/6s5dhaXP/QgBnB6xON3yhhbV4dbBHvzV75uvqvoE= -github.com/openshift/cluster-policy-controller v0.0.0-20251007100337-ef703966fe6e/go.mod h1:977DPepMAwnGNdJQdAzVSL+Qpem/aLS9d9sGnt1yEsg= +github.com/openshift/cluster-policy-controller v0.0.0-20251120141414-8b775487512f h1:qL/G4RbBeYWNBeZ8XIhB6MAOh1rld7HWUAue22l0cw8= +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.20251007192956-ce5ff17e9a81 h1:Zrt/uXU77g4M1hMF4jgAvZiCOR2dEFeWECeA/gHW1CE= github.com/openshift/kubernetes-kube-storage-version-migrator v0.0.3-0.20251007192956-ce5ff17e9a81/go.mod h1:o5cKv/pQ+exEYKq97WapNa5cxSPxuwBezHZHNW5RNRo= -github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 h1:bANtDc8SgetSK4nQehf59x3+H9FqVJCprgjs49/OTg0= -github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5/go.mod h1:OlFFws1AO51uzfc48MsStGE4SFMWlMZD0+f5a/zCtKI= +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/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-20251008111043-c337cf413bbb h1:ebiJRvuhxAsK/BjnoaVXSqVGyYTu0nJOMFeN4BysyqI= -github.com/openshift/route-controller-manager v0.0.0-20251008111043-c337cf413bbb/go.mod h1:/tw1PYHkUdzPG+EuC+ANJdDD81Ik2pPzYjLBZhyzyME= +github.com/openshift/route-controller-manager v0.0.0-20251106134803-8a69194a461d h1:nKdsySfewGYK5ALohGfHS7GAs0x2Sq/5B4s0WxreUXE= +github.com/openshift/route-controller-manager v0.0.0-20251106134803-8a69194a461d/go.mod h1:/tw1PYHkUdzPG+EuC+ANJdDD81Ik2pPzYjLBZhyzyME= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= 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= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -311,20 +301,12 @@ github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8 github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.74.0 h1:AHzMWDxNiAVscJL6+4wkvFRTpMnJqiaZFEKA/osaBXE= github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.74.0/go.mod h1:wAR5JopumPtAZnu0Cjv2PSqV4p4QB09LMhc6fZZTXuA= -github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= -github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/prometheus/prometheus v0.302.1 h1:xqVdrwrB4WNpdgJqxsz5loqFWNUZitsK8myqLuSZ6Ag= @@ -337,31 +319,17 @@ github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 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/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= -github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 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/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= -github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= -github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= -github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= -github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= -github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= 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/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M= -github.com/spf13/pflag v1.0.7/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/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= -github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= -github.com/squat/generic-device-plugin v0.0.0-20250710162141-0f7fddf166f1 h1:jNjbOvtxFsLW9OkNs20b1hY/8Q8DWccUjYyOOxi1O00= -github.com/squat/generic-device-plugin v0.0.0-20250710162141-0f7fddf166f1/go.mod h1:rFRt0GxGw04yGcbfSqoUENZH0p+1oL6IziAVQ31NAVw= github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 h1:wPJNupO/W9VJkwf/5vVnEReuS3pf5u+V+RGv6TOPrLM= github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31/go.mod h1:9pAOQhVkVgGnpJcHSumKIQXSp8ALx3TeYoGUih9BNwY= github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs= @@ -377,12 +345,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= -github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 h1:6fotK7otjonDflCTK0BCfls4SPy3NcCVb5dqqmbRknE= github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75/go.mod h1:KO6IkyS8Y3j8OdNO85qEYBsRPuteD+YciPomcXdrMnk= github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= @@ -421,27 +385,18 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSG go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I= 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.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= -go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= -go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= -go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= -go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= @@ -475,8 +430,6 @@ 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.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= -golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= -golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= 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= @@ -518,20 +471,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950= -google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b h1:ULiyYQ0FdsJhwwZUwbaXpZF5yUE3h+RA+gxvBu37ucc= google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:oDOGiMSXHL4sDTJvFvIB9nRQCGdLP1o/iVaqQK8zB+M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I= google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 h1:pmJpJEvT846VzausCQ5d7KreSROcDqmO388w5YbnltA= google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= -google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA= -google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -554,8 +501,8 @@ k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f h1:SLb+kxmzfA87x4E4brQzB33VBb 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/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y= -k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +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= diff --git a/origin/skip.txt b/origin/skip.txt index 46cd3e86f2..984330e54c 100644 --- a/origin/skip.txt +++ b/origin/skip.txt @@ -2,70 +2,134 @@ "[sig-scheduling][Early] The HAProxy router pods [apigroup:route.openshift.io] should be scheduled on different nodes [Skipped:SingleReplicaTopology] [Suite:openshift/conformance/parallel]" "[sig-scheduling][Early] The HAProxy router pods [apigroup:route.openshift.io] should be scheduled on different nodes [Suite:openshift/conformance/parallel]" "[sig-network] Netpol NetworkPolicy between server and client should allow ingress access on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes] [Skipped:Network/OpenShiftSDN/Multitenant] [Skipped:Network/OpenShiftSDN] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-network] Netpol NetworkPolicy between server and client should allow ingress access on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes] [Skipped:Network/OpenShiftSDN/Multitenant] [Skipped:Network/OpenShiftSDN]" "[sig-network] Netpol NetworkPolicy between server and client should allow ingress access on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-network] Netpol NetworkPolicy between server and client should allow ingress access on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes]" "[sig-node] Mount propagation should propagate mounts within defined scopes [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-node] Mount propagation should propagate mounts within defined scopes" "[sig-arch][Early] APIs for openshift.io must have stable versions [Suite:openshift/conformance/parallel]" "[sig-network] Netpol NetworkPolicy between server and client should allow ingress access from namespace on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes] [Skipped:Network/OpenShiftSDN/Multitenant] [Skipped:Network/OpenShiftSDN] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-network] Netpol NetworkPolicy between server and client should allow ingress access from namespace on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes] [Skipped:Network/OpenShiftSDN/Multitenant] [Skipped:Network/OpenShiftSDN]" "[sig-network] Netpol NetworkPolicy between server and client should allow ingress access from namespace on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-network] Netpol NetworkPolicy between server and client should allow ingress access from namespace on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes]" "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicationController light Should scale from 1 pod to 2 pods [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) ReplicationController light Should scale from 1 pod to 2 pods" "[sig-apps] Daemon set [Serial] should rollback without unnecessary restarts [Conformance] [Skipped:SingleReplicaTopology] [Suite:openshift/conformance/serial/minimal] [Suite:k8s]" +"[sig-apps] Daemon set [Serial] should rollback without unnecessary restarts [Conformance] [Skipped:SingleReplicaTopology]" "[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) CustomResourceDefinition Should scale with a CRD targetRef [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-autoscaling] [Feature:HPA] Horizontal pod autoscaling (scale resource: CPU) CustomResourceDefinition Should scale with a CRD targetRef" "[sig-network] Netpol NetworkPolicy between server and client should allow egress access on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes] [Skipped:Network/OpenShiftSDN/Multitenant] [Skipped:Network/OpenShiftSDN] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-network] Netpol NetworkPolicy between server and client should allow egress access on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes] [Skipped:Network/OpenShiftSDN/Multitenant] [Skipped:Network/OpenShiftSDN]" "[sig-network] Netpol NetworkPolicy between server and client should allow egress access on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-network] Netpol NetworkPolicy between server and client should allow egress access on one named port [Feature:NetworkPolicy] [Skipped:Network/OVNKubernetes]" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read/write inline ephemeral volume" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support multiple inline ephemeral volumes" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read-only inline ephemeral volume" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support existing single file [LinuxOnly]" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should mount multiple PV pointing to the same storage on the same node" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should create read/write inline ephemeral volume" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should support two pods which have the same volume definition" "[sig-storage] Volumes NFSv4 should be mountable for NFSv4 [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] Volumes NFSv4 should be mountable for NFSv4" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] volumes should store data [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Inline-volume (default fs)] volumes should store data" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support existing directory" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] provisioning should provision storage with mount options" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support file as subpath [LinuxOnly]" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] volumes should allow exec of files on the volume" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] volumes should store data [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Inline-volume (default fs)] volumes should store data" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support non-existent path" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should be able to unmount after the subpath directory is deleted [LinuxOnly]" "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV and a pre-bound PVC: test write access [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV and a pre-bound PVC: test write access" "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs should create a non-pre-bound PV and PVC: test write access [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs should create a non-pre-bound PV and PVC: test write access " "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PVC and a pre-bound PV: test write access [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PVC and a pre-bound PV: test write access" "[sig-storage] PersistentVolumes NFS with multiple PVs and PVCs all in same ns should create 3 PVs and 3 PVCs: test write access [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] PersistentVolumes NFS with multiple PVs and PVCs all in same ns should create 3 PVs and 3 PVCs: test write access" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] volumes should store data [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] volumes should store data" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] volumes should store data [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] volumes should store data" "[sig-storage] Volumes NFSv3 should be mountable for NFSv3 [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] Volumes NFSv3 should be mountable for NFSv3" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] volumes should allow exec of files on the volume" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (immediate-binding)] ephemeral should create read-only inline ephemeral volume" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] volumes should allow exec of files on the volume" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Pre-provisioned PV (default fs)] volumes should store data" "[sig-storage] PersistentVolumes NFS when invoking the Recycle reclaim policy should test that a PV becomes Available and is clean after the PVC is deleted. [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] PersistentVolumes NFS when invoking the Recycle reclaim policy should test that a PV becomes Available and is clean after the PVC is deleted." "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PVC and non-pre-bound PV: test write access [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PVC and non-pre-bound PV: test write access" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]" "[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Generic Ephemeral-volume (default fs) (late-binding)] ephemeral should support two pods which have the same volume definition" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly directory specified in the volumeMount" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support readOnly file specified in the volumeMount [LinuxOnly]" "[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] In-tree Volumes [Driver: nfs3] [Testpattern: Dynamic PV (default fs)] subPath should support existing directories when readOnly specified in the volumeSource" "[sig-storage] PersistentVolumes NFS with multiple PVs and PVCs all in same ns should create 2 PVs and 4 PVCs: test write access [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] PersistentVolumes NFS with multiple PVs and PVCs all in same ns should create 2 PVs and 4 PVCs: test write access" "[sig-network][Feature:Router][apigroup:route.openshift.io] The HAProxy router reports the expected host names in admitted routes' statuses [Suite:openshift/conformance/parallel]" "[sig-arch] Managed cluster should ensure platform components have system-* priority class associated [Suite:openshift/conformance/parallel]" "[sig-network][Feature:Router][apigroup:route.openshift.io] when FIPS is enabled the HAProxy router should not work when configured with a 1024-bit RSA key [Suite:openshift/conformance/parallel]" @@ -100,16 +164,22 @@ "[sig-etcd] etcd leader changes are not excessive [Late] [Suite:openshift/conformance/parallel]" "[sig-node] Managed cluster should verify that nodes have no unexpected reboots [Late] [Suite:openshift/conformance/parallel]" "[sig-architecture] Conformance Tests should have at least two untainted nodes [Conformance] [Skipped:SingleReplicaTopology] [Suite:openshift/conformance/parallel/minimal] [Suite:k8s]" +"[sig-architecture] Conformance Tests should have at least two untainted nodes [Conformance] [Skipped:SingleReplicaTopology]" "[sig-network-edge][Feature:Idling] Unidling with Deployments [apigroup:route.openshift.io] should handle many TCP connections by possibly dropping those over a certain bound [Serial] [Suite:openshift/conformance/serial]" "[sig-network-edge][Feature:Idling] Unidling with Deployments [apigroup:route.openshift.io] should handle many UDP senders (by continuing to drop all packets on the floor) [Serial] [Suite:openshift/conformance/serial]" "[sig-network-edge][Feature:Idling] Unidling with Deployments [apigroup:route.openshift.io] should work with TCP (when fully idled) [Suite:openshift/conformance/parallel]" "[sig-network-edge][Feature:Idling] Unidling with Deployments [apigroup:route.openshift.io] should work with UDP [Suite:openshift/conformance/parallel]" "[sig-ci] [Early] prow job name should match security mode [Suite:openshift/conformance/parallel]" "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV and a pre-bound PVC: test phase transition timestamp is set [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV and a pre-bound PVC: test phase transition timestamp is set" "[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV and a pre-bound PVC: test phase transition timestamp multiple updates [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-storage] PersistentVolumes NFS with Single PV - PVC pairs create a PV and a pre-bound PVC: test phase transition timestamp multiple updates" "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to preserve UDP traffic when server pod cycles for a LoadBalancer service on the same nodes [Skipped:alibabacloud] [Skipped:aws] [Skipped:baremetal] [Skipped:ibmcloud] [Skipped:kubevirt] [Skipped:nutanix] [Skipped:openstack] [Skipped:ovirt] [Skipped:vsphere] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to preserve UDP traffic when server pod cycles for a LoadBalancer service on the same nodes [Skipped:alibabacloud] [Skipped:aws] [Skipped:baremetal] [Skipped:ibmcloud] [Skipped:kubevirt] [Skipped:nutanix] [Skipped:openstack] [Skipped:ovirt] [Skipped:vsphere]" "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to preserve UDP traffic when server pod cycles for a LoadBalancer service on the same nodes [Skipped:alibabacloud] [Skipped:aws] [Skipped:baremetal] [Skipped:external] [Skipped:ibmcloud] [Skipped:kubevirt] [Skipped:nutanix] [Skipped:openstack] [Skipped:ovirt] [Skipped:vsphere] [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to preserve UDP traffic when server pod cycles for a LoadBalancer service on the same nodes [Skipped:alibabacloud] [Skipped:aws] [Skipped:baremetal] [Skipped:external] [Skipped:ibmcloud] [Skipped:kubevirt] [Skipped:nutanix] [Skipped:openstack] [Skipped:ovirt] [Skipped:vsphere]" "[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to preserve UDP traffic when server pod cycles for a LoadBalancer service on the same nodes [Suite:openshift/conformance/parallel] [Suite:k8s]" +"[sig-network] LoadBalancers [Feature:LoadBalancer] should be able to preserve UDP traffic when server pod cycles for a LoadBalancer service on the same nodes" "[sig-network][Feature:tuning] pod should start with all sysctl on whitelist [apigroup:k8s.cni.cncf.io] [Suite:openshift/conformance/parallel]" "[sig-network][Feature:Whereabouts] should use whereabouts net-attach-def to limit IP ranges for newly created pods [apigroup:k8s.cni.cncf.io] [Suite:openshift/conformance/parallel]" "[sig-network][Feature:vlan] should create pingable pods with ipvlan interface on an in-container master [apigroup:k8s.cni.cncf.io] [Suite:openshift/conformance/parallel]" @@ -122,3 +192,5 @@ "[sig-network][Feature:Whereabouts] should assign unique IP addresses to each pod in the event of a race condition case [apigroup:k8s.cni.cncf.io] [Suite:openshift/conformance/parallel]" "[sig-network][Feature:bond] should create a pod with bond interface [apigroup:k8s.cni.cncf.io] [Suite:openshift/conformance/parallel]" "[sig-network][Feature:tuning] pod should not start for sysctls not on whitelist [apigroup:k8s.cni.cncf.io] net.ipv4.conf.IFNAME.arp_filter [Suite:openshift/conformance/parallel]" +"[Jira:service-ca][sig-api-machinery] Service CA Operator should have a running operator and managed resources [Suite:openshift/service-ca-operator/conformance/parallel]" + diff --git a/packaging/crio.conf.d/10-microshift_amd64.conf b/packaging/crio.conf.d/10-microshift_amd64.conf index f745c99004..e8967915a6 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:ae71cf6109569070d74d35dcb8e83d6153e45e1403549acdd8cb827c2fed80e7" +pause_image = "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:0622e764c91f3206b12a10df5025a804b032f81a280075f72480d5d4c4eac44d" 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 d3865a62c3..d8d3cfdcd6 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:39d9a5da43a3dbe850a27fcfb07b0437d1cc0d32f5f0b9eef05a10c48bdd3baa" +pause_image = "quay.io/openshift-release-dev/ocp-v4.0-art-dev@sha256:c3ca03c9bde6e9824886bac4f94d54a402743b0f143d9940f8d5d0db2b7399e1" pause_image_auth_file = "/etc/crio/openshift-pull-secret" pause_command = "/usr/bin/pod" diff --git a/packaging/images/Makefile b/packaging/images/Makefile index 11760d0a73..88a099b2cf 100644 --- a/packaging/images/Makefile +++ b/packaging/images/Makefile @@ -2,7 +2,7 @@ ARCH ?= $$(uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/') BASE_IMAGE_URL ?= quay.io/centos/centos BASE_IMAGE_TAG ?= stream9 DEST_IMAGE_REPO ?= quay.io/microshift/microshift-ci -RHIT_CERT_FILE ?= /etc/pki/ca-trust/source/anchors/2015-RH-IT-Root-CA.pem +RHIT_CERT_FILE ?= /etc/pki/ca-trust/source/anchors/2022-IT-Root-CA.pem .PHONY: all build publish manifest all: diff --git a/packaging/images/README.md b/packaging/images/README.md index a5b539f9be..d1f0a5a9cb 100644 --- a/packaging/images/README.md +++ b/packaging/images/README.md @@ -19,7 +19,7 @@ Usage: make > **Important:**

> Run the build on a Red Hat CSB machine to get access to the Red Hat IT Root -> Certificate at `/etc/pki/ca-trust/source/anchors/2015-RH-IT-Root-CA.pem`. +> Certificate at `/etc/pki/ca-trust/source/anchors/2022-IT-Root-CA.pem`. > Otherwise, download the certificate to your build host and specify its path > using `RHIT_CERT_FILE=/path/to/file` build option. @@ -32,7 +32,7 @@ Run the following commands to build and publish the container images. ```bash $ make build \ - RHIT_CERT_FILE=/etc/pki/ca-trust/source/anchors/2015-RH-IT-Root-CA.pem + RHIT_CERT_FILE=/etc/pki/ca-trust/source/anchors/2022-IT-Root-CA.pem $ make publish ``` diff --git a/packaging/microshift/config.yaml b/packaging/microshift/config.yaml index 0cbcda48cb..7a20f173ca 100644 --- a/packaging/microshift/config.yaml +++ b/packaging/microshift/config.yaml @@ -14,6 +14,11 @@ apiServer: maxFiles: 10 # profile is the OpenShift profile specifying a specific logging policy profile: Default + featureGates: + customNoUpgrade: + disabled: [] + enabled: [] + featureSet: "" # List of custom certificates used to secure requests to specific host names namedCertificates: - certPath: "" @@ -47,6 +52,19 @@ dns: # example: # microshift.example.com baseDomain: example.com + # Hosts contains configuration for the hosts file. + hosts: + # File is the path to the hosts file to monitor. + # If not specified, defaults to "/etc/hosts". + # example: + # /etc/hosts + file: /etc/hosts + # Status controls whether the hosts file is enabled or disabled. + # Allowed values are "Enabled" and "Disabled". + # If not specified, defaults to "Disabled". + # example: + # Enabled + status: Disabled etcd: # Set a memory limit on the etcd process; etcd will begin paging # memory when it gets to this value. 0 means no limit. diff --git a/packaging/rpm/make-rpm.sh b/packaging/rpm/make-rpm.sh index 0ed274807c..3c7e14b553 100755 --- a/packaging/rpm/make-rpm.sh +++ b/packaging/rpm/make-rpm.sh @@ -57,6 +57,7 @@ build_commit() { %global commit ${1} %global embedded_git_tag ${SOURCE_GIT_TAG} %global embedded_git_tree_state ${SOURCE_GIT_TREE_STATE} +%global microshift_variant ${MICROSHIFT_VARIANT} EOF cat "${SCRIPT_DIR}/microshift.spec" >> "${RPMBUILD_DIR}SPECS/microshift.spec" @@ -71,7 +72,6 @@ EOF rpmbuild --quiet ${RPMBUILD_OPT} \ --define "_topdir ${RPMBUILD_DIR}" \ --define "_binary_payload w19T8.zstdio" \ - --define "microshift_variant ${MICROSHIFT_VARIANT}" \ "${RPMBUILD_DIR}"SPECS/microshift.spec } diff --git a/packaging/rpm/microshift.spec b/packaging/rpm/microshift.spec index da015d1f35..a8b61629c4 100644 --- a/packaging/rpm/microshift.spec +++ b/packaging/rpm/microshift.spec @@ -252,6 +252,24 @@ The microshift-cert-manager-release-info package provides release information fi release. These files contain the list of container image references used by Cert Manager and can be used to embed those images into osbuilder blueprints or bootc containerfiles. +%package sriov +Summary: SR-IOV Network Operator for MicroShift +ExclusiveArch: x86_64 aarch64 +Requires: microshift = %{version} + +%description sriov +The microshift-sriov package provides the required manifests for the SR-IOV Network Operator to be installed on MicroShift. + +%package sriov-release-info +Summary: Release information for SR-IOV Network Operator for MicroShift +BuildArch: noarch +Requires: microshift = %{version} + +%description sriov-release-info +The microshift-sriov-release-info package provides release information files for this +release. These files contain the list of container image references used by SR-IOV Network Operator +and can be used to embed those images into osbuilder blueprints or bootc containerfiles. + %prep # Dynamic detection of the available golang version also works for non-RPM golang packages golang_detected=$(go version | awk '{print $3}' | tr -d '[a-z]' | cut -f1-2 -d.) @@ -460,6 +478,12 @@ install -p -m644 ./assets/optional/ai-model-serving/kserve/configmap/* %{buildr install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/crd/ install -p -m644 ./assets/optional/ai-model-serving/kserve/crd/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/crd/ +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/crd/external/gateway-inference-extension +install -p -m644 ./assets/optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/crd/external/gateway-inference-extension + +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/crd/external/opendatahub-operator +install -p -m644 ./assets/optional/ai-model-serving/kserve/crd/external/opendatahub-operator/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/crd/external/opendatahub-operator + install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/crd/full/ install -p -m644 ./assets/optional/ai-model-serving/kserve/crd/full/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/crd/full/ @@ -473,7 +497,11 @@ install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshi install -p -m644 ./assets/optional/ai-model-serving/kserve/manager/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/manager/ install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/overlays/odh/ -install -p -m644 ./assets/optional/ai-model-serving/kserve/overlays/odh/* %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/overlays/odh/ +install -p -m644 ./assets/optional/ai-model-serving/kserve/overlays/odh/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/overlays/odh/ +install -p -m644 ./assets/optional/ai-model-serving/kserve/overlays/odh/*.env %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/overlays/odh/ + +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/overlays/odh/patches/ +install -p -m644 ./assets/optional/ai-model-serving/kserve/overlays/odh/patches/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/overlays/odh/patches/ install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/rbac/ install -p -m644 ./assets/optional/ai-model-serving/kserve/rbac/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/rbac/ @@ -481,6 +509,24 @@ install -p -m644 ./assets/optional/ai-model-serving/kserve/rbac/*.yaml %{buildr install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/rbac/localmodel/ install -p -m644 ./assets/optional/ai-model-serving/kserve/rbac/localmodel/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/rbac/localmodel/ +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/rbac/localmodelnode/ +install -p -m644 ./assets/optional/ai-model-serving/kserve/rbac/localmodelnode/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/rbac/localmodelnode/ + +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/localmodels/ +install -p -m644 ./assets/optional/ai-model-serving/kserve/localmodels/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/localmodels/ + +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/localmodelnodes/ +install -p -m644 ./assets/optional/ai-model-serving/kserve/localmodelnodes/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/localmodelnodes/ + +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/llmisvc/ +install -p -m644 ./assets/optional/ai-model-serving/kserve/llmisvc/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/llmisvc/ + +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/certmanager/ +install -p -m644 ./assets/optional/ai-model-serving/kserve/certmanager/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/certmanager/ + +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/monitoring/llmisvc/ +install -p -m644 ./assets/optional/ai-model-serving/kserve/monitoring/llmisvc/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/monitoring/llmisvc/ + install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/webhook/ install -p -m644 ./assets/optional/ai-model-serving/kserve/webhook/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/010-microshift-ai-model-serving-kserve/webhook/ @@ -525,6 +571,18 @@ install -p -m644 assets/optional/cert-manager/kustomization.yaml %{buildroot}/%{ mkdir -p -m755 %{buildroot}%{_datadir}/microshift/release install -p -m644 assets/optional/cert-manager/release-cert-manager-{x86_64,aarch64}.json %{buildroot}%{_datadir}/microshift/release/ +# sriov +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/crd +install -p -m644 assets/optional/sriov/crd/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/crd +install -d -m755 %{buildroot}/%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/deploy +install -p -m644 assets/optional/sriov/deploy/*.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/deploy +install -p -m644 assets/optional/sriov/kustomization.yaml %{buildroot}/%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/kustomization.yaml + +# sriov-release-info +mkdir -p -m755 %{buildroot}%{_datadir}/microshift/release +install -p -m644 assets/optional/sriov/release-sriov-{x86_64,aarch64}.json %{buildroot}%{_datadir}/microshift/release/ + %pre networking getent group hugetlbfs >/dev/null || groupadd -r hugetlbfs @@ -577,7 +635,7 @@ systemctl enable --now --quiet openvswitch || true %post greenboot # Make sure that the greenboot-healthcheck service is enabled -systemctl is-enabled --quiet greenboot-healthcheck || systemctl enable --now --quiet greenboot-healthcheck +systemctl is-enabled --quiet greenboot-healthcheck || systemctl enable --quiet greenboot-healthcheck %post multus # only for install, not on upgrades @@ -705,6 +763,17 @@ fi %files cert-manager-release-info %{_datadir}/microshift/release/release-cert-manager-{x86_64,aarch64}.json +%files sriov +%dir %{_prefix}/lib/microshift/manifests.d/070-microshift-sriov +%dir %{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/crd +%dir %{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/deploy +%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/kustomization.yaml +%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/crd/* +%{_prefix}/lib/microshift/manifests.d/070-microshift-sriov/deploy/* + +%files sriov-release-info +%{_datadir}/microshift/release/release-sriov-{x86_64,aarch64}.json + # Use Git command to generate the log and replace the VERSION string # LANG=C git log --date="format:%a %b %d %Y" --pretty="tformat:* %cd %an <%ae> VERSION%n- %s%n" packaging/rpm/microshift.spec diff --git a/pkg/admin/prerun/featuregate_lock.go b/pkg/admin/prerun/featuregate_lock.go new file mode 100644 index 0000000000..467660f711 --- /dev/null +++ b/pkg/admin/prerun/featuregate_lock.go @@ -0,0 +1,215 @@ +package prerun + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "reflect" + + "github.com/openshift/microshift/pkg/config" + "github.com/openshift/microshift/pkg/util" + "k8s.io/klog/v2" + "sigs.k8s.io/yaml" +) + +var ( + featureGateLockFilePath = filepath.Join(config.DataDir, "no-upgrade") + errLockFileDoesNotExist = errors.New("feature gate lock file does not exist") +) + +// featureGateLockFile represents the structure of the lock file +// that tracks custom feature gate configuration and prevents changes/upgrades +type featureGateLockFile struct { + FeatureSet string `json:"featureSet"` + CustomNoUpgrade config.CustomNoUpgrade `json:"customNoUpgrade"` + Version versionMetadata `json:"version"` +} + +// FeatureGateLockManagement manages the feature gate lock file +// that prevents upgrades and config changes when custom feature gates are configured +func FeatureGateLockManagement(cfg *config.Config) error { + klog.InfoS("START feature gate lock management") + if err := featureGateLockManagement(cfg); err != nil { + klog.ErrorS(err, "FAIL feature gate lock management") + return err + } + klog.InfoS("END feature gate lock management") + return nil +} + +func featureGateLockManagement(cfg *config.Config) error { + // If a lock file exists, it must be validated regardless of current config + // This prevents users from removing feature gates from config in order to block upgrades and configuration changes + lockExists, err := util.PathExists(featureGateLockFilePath) + if err != nil { + return fmt.Errorf("failed to check if lock file exists: %w", err) + } + + // Lock file exists - validate configuration + if lockExists { + return validateFeatureGateLockFile(cfg) + } + + // No lock file exists yet and custom feature gates are configured, so this is the first time configuring custom feature gates + if hasCustomFeatureGates(cfg.ApiServer.FeatureGates) { + klog.InfoS("Custom feature gates detected", "featureSet", cfg.ApiServer.FeatureGates.FeatureSet) + return createFeatureGateLockFile(cfg) + } + + // No lock file and no custom feature gates - normal operation + klog.InfoS("No custom feature gates configured - skipping lock file management") + return nil +} + +// hasCustomFeatureGates checks if any custom feature gates are configured +func hasCustomFeatureGates(fg config.FeatureGates) bool { + // Empty feature set means no custom feature gates + if fg.FeatureSet == "" { + return false + } + + // TechPreviewNoUpgrade and DevPreviewNoUpgrade are considered custom + if fg.FeatureSet == config.FeatureSetTechPreviewNoUpgrade || + fg.FeatureSet == config.FeatureSetDevPreviewNoUpgrade { + return true + } + + // CustomNoUpgrade requires actual enabled or disabled features + if fg.FeatureSet == config.FeatureSetCustomNoUpgrade { + return len(fg.CustomNoUpgrade.Enabled) > 0 || len(fg.CustomNoUpgrade.Disabled) > 0 + } + + return false +} + +// createFeatureGateLockFile creates the lock file with current configuration +func createFeatureGateLockFile(cfg *config.Config) error { + klog.InfoS("Creating feature gate lock file - this cluster can no longer be upgraded", + "path", featureGateLockFilePath) + + // Get current version from version file + currentVersion, err := getVersionOfData() + if err != nil { + // If version file doesn't exist yet, get executable version + klog.InfoS("Version file does not exist yet, using executable version") + currentVersion, err = GetVersionOfExecutable() + if err != nil { + return fmt.Errorf("failed to get version: %w", err) + } + } + + lockFile := featureGateLockFile{ + FeatureSet: cfg.ApiServer.FeatureGates.FeatureSet, + CustomNoUpgrade: cfg.ApiServer.FeatureGates.CustomNoUpgrade, + Version: currentVersion, + } + + if err := writeFeatureGateLockFile(featureGateLockFilePath, lockFile); err != nil { + return fmt.Errorf("failed to write lock file: %w", err) + } + + klog.InfoS("Feature gate lock file created successfully", + "featureSet", lockFile.FeatureSet, + "version", lockFile.Version.String()) + + return nil +} + +// validateFeatureGateLockFile validates that the current configuration matches the lock file +// and that no version upgrade has occurred +func validateFeatureGateLockFile(cfg *config.Config) error { + klog.InfoS("Validating feature gate lock file", "path", featureGateLockFilePath) + + lockFile, err := readFeatureGateLockFile(featureGateLockFilePath) + if err != nil { + return fmt.Errorf("failed to read lock file: %w", err) + } + + // Check if feature gate configuration has changed + if err := compareFeatureGates(lockFile, cfg.ApiServer.FeatureGates); err != nil { + return fmt.Errorf("feature gate configuration has changed: %w\n\n"+ + "Custom feature gates cannot be modified or reverted once applied.\n"+ + "To restore MicroShift to a supported state, you must:\n"+ + "1. Run: sudo microshift-cleanup-data --all\n"+ + "2. Remove custom feature gates from /etc/microshift/config.yaml\n"+ + "3. Restart MicroShift: sudo systemctl restart microshift", err) + } + + // Check if version has changed (upgrade attempted) + currentVersion, err := getVersionOfData() + if err != nil { + return fmt.Errorf("failed to get current version: %w", err) + } + + if lockFile.Version != currentVersion { + return fmt.Errorf("version upgrade detected with custom feature gates: locked version %s, current version %s\n\n"+ + "Upgrades are not supported when custom feature gates are configured.\n"+ + "Custom feature gates (%s) were configured in version %s.\n"+ + "To restore MicroShift to a supported state, you must:\n"+ + "1. Roll back to version %s, OR\n"+ + "2. Run: sudo microshift-cleanup-data --all\n"+ + "3. Remove custom feature gates from /etc/microshift/config.yaml\n"+ + "4. Restart MicroShift: sudo systemctl restart microshift", + lockFile.Version.String(), currentVersion.String(), + lockFile.FeatureSet, lockFile.Version.String(), lockFile.Version.String()) + } + + klog.InfoS("Feature gate lock file validation successful") + return nil +} + +// compareFeatureGates compares the lock file with current configuration +func compareFeatureGates(lockFile featureGateLockFile, current config.FeatureGates) error { + var errs []error + + if lockFile.FeatureSet != current.FeatureSet { + errs = append(errs, fmt.Errorf("feature set changed: locked config has %q, current config has %q", + lockFile.FeatureSet, current.FeatureSet)) + } + + if !reflect.DeepEqual(lockFile.CustomNoUpgrade, current.CustomNoUpgrade) { + errs = append(errs, fmt.Errorf("custom feature gates changed: locked config has %#v, current config has %#v", + lockFile.CustomNoUpgrade, current.CustomNoUpgrade)) + } + + return errors.Join(errs...) +} + +// writeFeatureGateLockFile writes the lock file to disk in YAML format +func writeFeatureGateLockFile(path string, lockFile featureGateLockFile) error { + data, err := yaml.Marshal(lockFile) + if err != nil { + return fmt.Errorf("failed to marshal lock file: %w", err) + } + + if err := os.WriteFile(path, data, 0600); err != nil { + return fmt.Errorf("failed to write lock file to %q: %w", path, err) + } + + return nil +} + +// readFeatureGateLockFile reads the lock file from disk in YAML format +func readFeatureGateLockFile(path string) (featureGateLockFile, error) { + exists, err := util.PathExists(path) + if err != nil { + return featureGateLockFile{}, fmt.Errorf("failed to check if lock file exists: %w", err) + } + + if !exists { + return featureGateLockFile{}, errLockFileDoesNotExist + } + + data, err := os.ReadFile(path) + if err != nil { + return featureGateLockFile{}, fmt.Errorf("failed to read lock file from %q: %w", path, err) + } + + var lockFile featureGateLockFile + if err := yaml.Unmarshal(data, &lockFile); err != nil { + return featureGateLockFile{}, fmt.Errorf("failed to unmarshal lock file: %w", err) + } + + return lockFile, nil +} diff --git a/pkg/admin/prerun/featuregate_lock_test.go b/pkg/admin/prerun/featuregate_lock_test.go new file mode 100644 index 0000000000..0c3db09eb8 --- /dev/null +++ b/pkg/admin/prerun/featuregate_lock_test.go @@ -0,0 +1,482 @@ +package prerun + +import ( + "encoding/json" + "errors" + "os" + "path/filepath" + "reflect" + "testing" + + "github.com/openshift/microshift/pkg/config" + "sigs.k8s.io/yaml" +) + +func TestFeatureGateLockFile_Marshal(t *testing.T) { + tests := []struct { + name string + lockFile featureGateLockFile + wantErr bool + }{ + { + name: "custom feature gates with enabled and disabled", + lockFile: featureGateLockFile{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA", "FeatureB"}, + Disabled: []string{"FeatureC"}, + }, + }, + wantErr: false, + }, + { + name: "TechPreviewNoUpgrade", + lockFile: featureGateLockFile{ + FeatureSet: config.FeatureSetTechPreviewNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{}, + }, + wantErr: false, + }, + { + name: "DevPreviewNoUpgrade", + lockFile: featureGateLockFile{ + FeatureSet: config.FeatureSetDevPreviewNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{}, + }, + wantErr: false, + }, + { + name: "empty feature gates", + lockFile: featureGateLockFile{ + FeatureSet: "", + CustomNoUpgrade: config.CustomNoUpgrade{}, + }, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + data, err := yaml.Marshal(tt.lockFile) + if (err != nil) != tt.wantErr { + t.Errorf("Marshal() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !tt.wantErr { + var unmarshaled featureGateLockFile + if err := yaml.Unmarshal(data, &unmarshaled); err != nil { + t.Errorf("Unmarshal() error = %v", err) + return + } + if !reflect.DeepEqual(tt.lockFile, unmarshaled) { + t.Errorf("Marshal/Unmarshal roundtrip failed: got %#v, want %#v", unmarshaled, tt.lockFile) + } + } + }) + } +} + +func TestIsCustomFeatureGatesConfigured(t *testing.T) { + tests := []struct { + name string + fg config.FeatureGates + want bool + }{ + { + name: "CustomNoUpgrade with enabled features", + fg: config.FeatureGates{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA"}, + }, + }, + want: true, + }, + { + name: "TechPreviewNoUpgrade", + fg: config.FeatureGates{ + FeatureSet: config.FeatureSetTechPreviewNoUpgrade, + }, + want: true, + }, + { + name: "DevPreviewNoUpgrade", + fg: config.FeatureGates{ + FeatureSet: config.FeatureSetDevPreviewNoUpgrade, + }, + want: true, + }, + { + name: "empty feature gates", + fg: config.FeatureGates{ + FeatureSet: "", + }, + want: false, + }, + { + name: "CustomNoUpgrade without any enabled/disabled", + fg: config.FeatureGates{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{}, + }, + want: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := hasCustomFeatureGates(tt.fg) + if got != tt.want { + t.Errorf("isCustomFeatureGatesConfigured() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestFeatureGateLockFile_ReadWrite(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "featuregate-lockFile-test-*") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + lockFilePath := filepath.Join(tmpDir, "no-upgrade") + + tests := []struct { + name string + lockFile featureGateLockFile + }{ + { + name: "write and read custom feature gates", + lockFile: featureGateLockFile{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA", "FeatureB"}, + Disabled: []string{"FeatureC"}, + }, + }, + }, + { + name: "write and read TechPreviewNoUpgrade", + lockFile: featureGateLockFile{ + FeatureSet: config.FeatureSetTechPreviewNoUpgrade, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Write lockFile file + if err := writeFeatureGateLockFile(lockFilePath, tt.lockFile); err != nil { + t.Errorf("writeFeatureGateLockFile() error = %v", err) + return + } + + // Read lockFile file + got, err := readFeatureGateLockFile(lockFilePath) + if err != nil { + t.Errorf("readFeatureGateLockFile() error = %v", err) + return + } + + if !reflect.DeepEqual(got, tt.lockFile) { + t.Errorf("readFeatureGateLockFile() = %#v, want %#v", got, tt.lockFile) + } + + // Clean up for next test + os.Remove(lockFilePath) + }) + } +} + +func TestFeatureGateLockFile_ReadNonExistent(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "featuregate-lockFile-test-*") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + lockFilePath := filepath.Join(tmpDir, "no-upgrade") + + _, err = readFeatureGateLockFile(lockFilePath) + if !errors.Is(err, errLockFileDoesNotExist) { + t.Errorf("readFeatureGateLockFile() error = %v, want %v", err, errLockFileDoesNotExist) + } +} + +func TestCompareFeatureGates(t *testing.T) { + tests := []struct { + name string + lockFile featureGateLockFile + current config.FeatureGates + wantMatch bool + }{ + { + name: "identical custom feature gates", + lockFile: featureGateLockFile{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA", "FeatureB"}, + Disabled: []string{"FeatureC"}, + }, + }, + current: config.FeatureGates{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA", "FeatureB"}, + Disabled: []string{"FeatureC"}, + }, + }, + wantMatch: true, + }, + { + name: "different enabled features", + lockFile: featureGateLockFile{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA"}, + }, + }, + current: config.FeatureGates{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureB"}, + }, + }, + wantMatch: false, + }, + { + name: "different feature sets", + lockFile: featureGateLockFile{ + FeatureSet: config.FeatureSetTechPreviewNoUpgrade, + }, + current: config.FeatureGates{ + FeatureSet: config.FeatureSetDevPreviewNoUpgrade, + }, + wantMatch: false, + }, + { + name: "identical TechPreviewNoUpgrade", + lockFile: featureGateLockFile{ + FeatureSet: config.FeatureSetTechPreviewNoUpgrade, + }, + current: config.FeatureGates{ + FeatureSet: config.FeatureSetTechPreviewNoUpgrade, + }, + wantMatch: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := compareFeatureGates(tt.lockFile, tt.current) + gotMatch := err == nil + if gotMatch != tt.wantMatch { + t.Errorf("compareFeatureGates() match = %v, want %v, error = %v", gotMatch, tt.wantMatch, err) + } + }) + } +} + +func TestFeatureGateLockManagement_FirstRun(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "featuregate-lockFile-test-*") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + // Override the lockFile file path for testing + originalPath := featureGateLockFilePath + featureGateLockFilePath = filepath.Join(tmpDir, "no-upgrade") + defer func() { featureGateLockFilePath = originalPath }() + + // Override version file path for testing + originalVersionPath := versionFilePath + versionFilePath = filepath.Join(tmpDir, "version") + defer func() { versionFilePath = originalVersionPath }() + + // Create a version file to simulate existing data (version file uses JSON format) + versionData := versionFile{ + Version: versionMetadata{Major: 4, Minor: 18, Patch: 0}, + BootID: "test-boot", + } + versionJSON, _ := json.Marshal(versionData) + if err := os.WriteFile(versionFilePath, versionJSON, 0600); err != nil { + t.Fatal(err) + } + + cfg := &config.Config{ + ApiServer: config.ApiServer{ + FeatureGates: config.FeatureGates{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA"}, + }, + }, + }, + } + + // First run - should create lockFile file + if err := FeatureGateLockManagement(cfg); err != nil { + t.Errorf("FeatureGateLockManagement() first run error = %v", err) + } + + // Verify lockFile file was created + if _, err := os.Stat(featureGateLockFilePath); os.IsNotExist(err) { + t.Error("Lock file was not created") + } + + // Second run with same config - should succeed + if err := FeatureGateLockManagement(cfg); err != nil { + t.Errorf("FeatureGateLockManagement() second run error = %v", err) + } +} + +func TestFeatureGateLockManagement_ConfigChange(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "featuregate-lockFile-test-*") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + // Override the lockFile file path for testing + originalPath := featureGateLockFilePath + featureGateLockFilePath = filepath.Join(tmpDir, "no-upgrade") + defer func() { featureGateLockFilePath = originalPath }() + + // Override version file path for testing + originalVersionPath := versionFilePath + versionFilePath = filepath.Join(tmpDir, "version") + defer func() { versionFilePath = originalVersionPath }() + + // Create a version file to simulate existing data (version file uses JSON format) + versionData := versionFile{ + Version: versionMetadata{Major: 4, Minor: 18, Patch: 0}, + BootID: "test-boot", + } + versionJSON, _ := json.Marshal(versionData) + if err := os.WriteFile(versionFilePath, versionJSON, 0600); err != nil { + t.Fatal(err) + } + + // Create lockFile file with initial config + initialLock := featureGateLockFile{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA"}, + }, + } + if err := writeFeatureGateLockFile(featureGateLockFilePath, initialLock); err != nil { + t.Fatal(err) + } + + // Try to run with different config - should fail + cfg := &config.Config{ + ApiServer: config.ApiServer{ + FeatureGates: config.FeatureGates{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureB"}, // Different feature + }, + }, + }, + } + + err = FeatureGateLockManagement(cfg) + if err == nil { + t.Error("FeatureGateLockManagement() should have failed with config change") + } +} + +func TestFeatureGateLockManagement_VersionChange(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "featuregate-lockFile-test-*") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + // Override the lockFile file path for testing + originalPath := featureGateLockFilePath + featureGateLockFilePath = filepath.Join(tmpDir, "no-upgrade") + defer func() { featureGateLockFilePath = originalPath }() + + // Override version file path for testing + originalVersionPath := versionFilePath + versionFilePath = filepath.Join(tmpDir, "version") + defer func() { versionFilePath = originalVersionPath }() + + // Create a version file with NEW version (simulating upgrade) (version file uses JSON format) + versionData := versionFile{ + Version: versionMetadata{Major: 4, Minor: 19, Patch: 0}, // Newer version + BootID: "test-boot", + } + versionJSON, _ := json.Marshal(versionData) + if err := os.WriteFile(versionFilePath, versionJSON, 0600); err != nil { + t.Fatal(err) + } + + // Create lockFile file with OLD version + lockFile := featureGateLockFile{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA"}, + }, + Version: versionMetadata{Major: 4, Minor: 18, Patch: 0}, // Older version + } + if err := writeFeatureGateLockFile(featureGateLockFilePath, lockFile); err != nil { + t.Fatal(err) + } + + cfg := &config.Config{ + ApiServer: config.ApiServer{ + FeatureGates: config.FeatureGates{ + FeatureSet: config.FeatureSetCustomNoUpgrade, + CustomNoUpgrade: config.CustomNoUpgrade{ + Enabled: []string{"FeatureA"}, + }, + }, + }, + } + + err = FeatureGateLockManagement(cfg) + if err == nil { + t.Error("FeatureGateLockManagement() should have failed with version change") + } +} + +func TestFeatureGateLockManagement_NoCustomFeatureGates(t *testing.T) { + // Create a temporary directory for testing + tmpDir, err := os.MkdirTemp("", "featuregate-lockFile-test-*") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpDir) + + // Override the lockFile file path for testing + originalPath := featureGateLockFilePath + featureGateLockFilePath = filepath.Join(tmpDir, "no-upgrade") + defer func() { featureGateLockFilePath = originalPath }() + + cfg := &config.Config{ + ApiServer: config.ApiServer{ + FeatureGates: config.FeatureGates{ + FeatureSet: "", // No custom feature gates + }, + }, + } + + // Should succeed and not create lockFile file + if err := FeatureGateLockManagement(cfg); err != nil { + t.Errorf("FeatureGateLockManagement() with no custom feature gates error = %v", err) + } + + // Verify lockFile file was not created + if _, err := os.Stat(featureGateLockFilePath); !os.IsNotExist(err) { + t.Error("Lock file should not have been created without custom feature gates") + } +} diff --git a/pkg/assets/apps.go b/pkg/assets/apps.go index a80d027823..a4d4671356 100644 --- a/pkg/assets/apps.go +++ b/pkg/assets/apps.go @@ -52,7 +52,10 @@ func (d *dpApplier) Read(objBytes []byte, render RenderFunc, params RenderParams } func (d *dpApplier) Handle(ctx context.Context) error { - _, _, err := resourceapply.ApplyDeployment(ctx, d.Client, assetsEventRecorder, d.dp, 0) + obj, _, err := resourceapply.ApplyDeployment(ctx, d.Client, assetsEventRecorder, d.dp, 0) + if err != nil { + klog.ErrorS(err, "Failed to apply deployment asset", "actual", obj, "new", d.dp) + } return err } diff --git a/pkg/assets/crd.go b/pkg/assets/crd.go index a1a6de874d..beb2cfb14d 100644 --- a/pkg/assets/crd.go +++ b/pkg/assets/crd.go @@ -25,7 +25,7 @@ import ( ) const ( - customResourceReadyInterval = 5 * time.Second + customResourceReadyInterval = time.Second customResourceReadyTimeout = 10 * time.Minute ) diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index f994c67254..67188e9c35 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -54,11 +54,19 @@ func NewRunMicroshiftCommand() *cobra.Command { var multinode bool + multinodeDefault := true + if version.Get().BuildVariant != version.BuildVariantCommunity { + multinodeDefault = false + } + flags := cmd.Flags() - flags.BoolVar(&multinode, "multinode", false, "enable multinode mode") - err := flags.MarkHidden("multinode") - if err != nil { - panic(err) + flags.BoolVar(&multinode, "multinode", multinodeDefault, "enable multinode mode") + + if version.Get().BuildVariant != version.BuildVariantCommunity { + err := flags.MarkHidden("multinode") + if err != nil { + panic(err) + } } cmd.RunE = func(cmd *cobra.Command, args []string) error { @@ -183,6 +191,11 @@ func RunMicroshift(cfg *config.Config) error { return err } + if err := prerun.FeatureGateLockManagement(cfg); err != nil { + writeLogFileError(preRunFailedLogPath, err) + return err + } + // TODO: change to only initialize what is strictly necessary for the selected role(s) certChains, err := initCerts(cfg) if err != nil { @@ -216,6 +229,7 @@ func RunMicroshift(cfg *config.Config) error { util.Must(m.AddService(controllers.NewKubeStorageVersionMigrator(cfg))) util.Must(m.AddService(controllers.NewClusterID(cfg))) util.Must(m.AddService(controllers.NewTelemetryManager(cfg))) + util.Must(m.AddService(controllers.NewHostsWatcherManager(cfg))) util.Must(m.AddService(gdp.NewGenericDevicePlugin(cfg))) // Storing and clearing the env, so other components don't send the READY=1 until MicroShift is fully ready diff --git a/pkg/components/controllers.go b/pkg/components/controllers.go index 2777346b60..ca18b4d748 100644 --- a/pkg/components/controllers.go +++ b/pkg/components/controllers.go @@ -274,6 +274,12 @@ func startDNSController(ctx context.Context, cfg *config.Config, kubeconfigPath clusterRole = []string{ "components/openshift-dns/dns/cluster-role.yaml", } + roleBinding = []string{ + "components/openshift-dns/dns/hosts-configmap-rolebinding.yaml", + } + role = []string{ + "components/openshift-dns/dns/hosts-configmap-role.yaml", + } apps = []string{ "components/openshift-dns/dns/daemonset.yaml", "components/openshift-dns/node-resolver/daemonset.yaml", @@ -298,8 +304,10 @@ func startDNSController(ctx context.Context, cfg *config.Config, kubeconfigPath } extraParams := assets.RenderParams{ - "ClusterIP": cfg.Network.DNS, + "ClusterIP": cfg.Network.DNS, + "HostsEnabled": cfg.DNS.Hosts.Status == config.HostsStatusEnabled, } + if err := assets.ApplyServices(ctx, svc, renderTemplate, renderParamsFromConfig(cfg, extraParams), kubeconfigPath); err != nil { klog.Warningf("Failed to apply service %v %v", svc, err) // service already created by coreDNS, not re-create it. @@ -313,6 +321,14 @@ func startDNSController(ctx context.Context, cfg *config.Config, kubeconfigPath klog.Warningf("Failed to apply clusterRoleBinding %v %v", clusterRoleBinding, err) return err } + if err := assets.ApplyRoleBindings(ctx, roleBinding, kubeconfigPath); err != nil { + klog.Warningf("Failed to apply rolebinding %v: %v", roleBinding, err) + return err + } + if err := assets.ApplyRoles(ctx, role, kubeconfigPath); err != nil { + klog.Warningf("Failed to apply role %v: %v", role, err) + return err + } if err := assets.ApplyServiceAccounts(ctx, sa, kubeconfigPath); err != nil { klog.Warningf("Failed to apply serviceAccount %v %v", sa, err) return err diff --git a/pkg/components/storage.go b/pkg/components/storage.go index f86d32bcff..cec080efc5 100644 --- a/pkg/components/storage.go +++ b/pkg/components/storage.go @@ -19,9 +19,17 @@ import ( "github.com/openshift/microshift/pkg/assets" "github.com/openshift/microshift/pkg/config" "github.com/openshift/microshift/pkg/config/lvmd" + "github.com/openshift/microshift/pkg/version" ) func startCSIPlugin(ctx context.Context, cfg *config.Config, kubeconfigPath string) error { + // Community builds should deploy upstream CSI drivers, e.g. TopoLVM, etc. + // LVMS is not available without pull-secret access. + if version.Get().BuildVariant == version.BuildVariantCommunity { + klog.Warningf("CSI driver deployment is disabled for community builds") + return nil + } + if !cfg.Storage.IsEnabled() { klog.Warningf("CSI driver deployment disabled, persistent storage will not be available") return nil diff --git a/pkg/config/apiserver.go b/pkg/config/apiserver.go index 621950d391..cea5eb3be6 100644 --- a/pkg/config/apiserver.go +++ b/pkg/config/apiserver.go @@ -2,10 +2,14 @@ package config import ( "fmt" + "reflect" "slices" configv1 "github.com/openshift/api/config/v1" + featuresUtils "github.com/openshift/api/features" "github.com/openshift/library-go/pkg/crypto" + + "k8s.io/apimachinery/pkg/util/sets" ) type ApiServer struct { @@ -27,6 +31,8 @@ type ApiServer struct { TLS TLSConfig `json:"tls"` + FeatureGates FeatureGates `json:"featureGates"` + // The URL and Port of the API server cannot be changed by the user. URL string `json:"-"` Port int `json:"-"` @@ -127,3 +133,99 @@ func (t *TLSConfig) Validate() error { func getIANACipherSuites(suites []string) []string { return crypto.OpenSSLToIANACipherSuites(suites) } + +const ( + FeatureSetCustomNoUpgrade = "CustomNoUpgrade" + FeatureSetTechPreviewNoUpgrade = "TechPreviewNoUpgrade" + FeatureSetDevPreviewNoUpgrade = "DevPreviewNoUpgrade" +) + +type CustomNoUpgrade struct { + Enabled []string `json:"enabled"` + Disabled []string `json:"disabled"` +} + +// RequiredFeatureGates are the feature gates that are always enabled by MicroShift. They are defined here to enable config validation. +// They are injected into the feature-gates field later by the microshift kube-apiserver controller. +var RequiredFeatureGates = []string{"UserNamespacesSupport", "UserNamespacesPodSecurityStandards"} + +type FeatureGates struct { + FeatureSet string `json:"featureSet"` + CustomNoUpgrade CustomNoUpgrade `json:"customNoUpgrade"` +} + +func (fg FeatureGates) ToApiserverArgs() ([]string, error) { + ret := sets.NewString() + + switch fg.FeatureSet { + case FeatureSetCustomNoUpgrade: + for _, feature := range fg.CustomNoUpgrade.Enabled { + ret.Insert(fmt.Sprintf("%s=true", feature)) + } + for _, feature := range fg.CustomNoUpgrade.Disabled { + ret.Insert(fmt.Sprintf("%s=false", feature)) + } + case FeatureSetDevPreviewNoUpgrade, FeatureSetTechPreviewNoUpgrade: + fgEnabledDisabled, err := featuresUtils.FeatureSets(featuresUtils.SelfManaged, configv1.FeatureSet(fg.FeatureSet)) + if err != nil { + return nil, fmt.Errorf("failed to get feature set gates: %w", err) + } + for _, f := range fgEnabledDisabled.Enabled { + ret.Insert(fmt.Sprintf("%s=true", f.FeatureGateAttributes.Name)) + } + for _, f := range fgEnabledDisabled.Disabled { + ret.Insert(fmt.Sprintf("%s=false", f.FeatureGateAttributes.Name)) + } + } + return ret.List(), nil +} + +// Implement the GoStringer interface for better %#v printing +func (fg FeatureGates) GoString() string { + return fmt.Sprintf("FeatureGates{FeatureSet: %q, CustomNoUpgrade: %#v}", fg.FeatureSet, fg.CustomNoUpgrade) +} + +func (fg *FeatureGates) validateFeatureGates() error { + // FG is unset + if fg == nil || reflect.DeepEqual(*fg, FeatureGates{}) { + return nil + } + // Must use a recognized feature set, or else empty + if fg.FeatureSet != "" && fg.FeatureSet != FeatureSetCustomNoUpgrade && fg.FeatureSet != FeatureSetTechPreviewNoUpgrade && fg.FeatureSet != FeatureSetDevPreviewNoUpgrade { + return fmt.Errorf("invalid feature set: %s", fg.FeatureSet) + } + // Must set FeatureSet to CustomNoUpgrade to use custom feature gates + if fg.FeatureSet != FeatureSetCustomNoUpgrade && (len(fg.CustomNoUpgrade.Enabled) > 0 || len(fg.CustomNoUpgrade.Disabled) > 0) { + return fmt.Errorf("CustomNoUpgrade must be empty when FeatureSet is empty") + } + // Must set CustomNoUpgrade enabled or disabled lists when FeatureSet is CustomNoUpgrade + if fg.FeatureSet == FeatureSetCustomNoUpgrade && len(fg.CustomNoUpgrade.Enabled) == 0 && len(fg.CustomNoUpgrade.Disabled) == 0 { + return fmt.Errorf("CustomNoUpgrade enabled or disabled lists must be set when FeatureSet is CustomNoUpgrade") + } + + var errs = make(sets.Set[error], 0) + for _, requiredFG := range RequiredFeatureGates { + // Edge case: Users must not be allowed to explicitly disable required feature gates. + if sets.NewString(fg.CustomNoUpgrade.Disabled...).Has(requiredFG) { + errs.Insert(fmt.Errorf("required feature gate %s cannot be disabled: %s", requiredFG, fg.CustomNoUpgrade.Disabled)) + } + // Edge case: Users must not be allowed to explicitly enable required feature gates or else the config would be locked and the cluster + // would not be able to be upgraded. + if sets.New(fg.CustomNoUpgrade.Enabled...).Has(requiredFG) { + errs.Insert(fmt.Errorf("feature gate %s is explicitly enabled and cannot be enabled by the user", requiredFG)) + } + } + if errs.Len() > 0 { + return fmt.Errorf("invalid feature gates: %s", errs.UnsortedList()) + } + + // Must not have any feature gates that are enabled and disabled at the same time + enabledSet := sets.New(fg.CustomNoUpgrade.Enabled...) + disabledSet := sets.New(fg.CustomNoUpgrade.Disabled...) + inBothSets := enabledSet.Intersection(disabledSet) + if inBothSets.Len() > 0 { + return fmt.Errorf("featuregates cannot be enabled and disabled at the same time: %s", inBothSets.UnsortedList()) + } + + return nil +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 8e9c645262..9313a048f6 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -56,7 +56,6 @@ type Config struct { Ingress IngressConfig `json:"ingress"` Storage Storage `json:"storage"` Telemetry Telemetry `json:"telemetry"` - // Settings specified in this section are transferred as-is into the Kubelet config. // +kubebuilder:validation:Schemaless Kubelet map[string]any `json:"kubelet"` @@ -123,9 +122,7 @@ func (c *Config) fillDefaults() error { HostnameOverride: hostname, NodeIP: nodeIP, } - c.DNS = DNS{ - BaseDomain: "example.com", - } + c.Network = Network{ ServiceNodePortRange: "30000-32767", } @@ -186,7 +183,7 @@ func (c *Config) fillDefaults() error { c.Kubelet = nil c.GenericDevicePlugin = genericDevicePluginDefaults() c.Telemetry = telemetryDefaults() - + c.DNS = dnsDefaults() return nil } @@ -418,6 +415,23 @@ func (c *Config) incorporateUserSettings(u *Config) { if u.Ingress.AccessLogging.HttpCaptureCookies != nil { c.Ingress.AccessLogging.HttpCaptureCookies = u.Ingress.AccessLogging.HttpCaptureCookies } + + // HostsWatcher configuration - only set if user provided it + if u.DNS.Hosts.Status != "" { + c.DNS.Hosts.Status = u.DNS.Hosts.Status + if u.DNS.Hosts.File != "" { + c.DNS.Hosts.File = u.DNS.Hosts.File + } + } + if u.ApiServer.FeatureGates.FeatureSet != "" { + c.ApiServer.FeatureGates.FeatureSet = u.ApiServer.FeatureGates.FeatureSet + } + if len(u.ApiServer.FeatureGates.CustomNoUpgrade.Enabled) > 0 { + c.ApiServer.FeatureGates.CustomNoUpgrade.Enabled = u.ApiServer.FeatureGates.CustomNoUpgrade.Enabled + } + if len(u.ApiServer.FeatureGates.CustomNoUpgrade.Disabled) > 0 { + c.ApiServer.FeatureGates.CustomNoUpgrade.Disabled = u.ApiServer.FeatureGates.CustomNoUpgrade.Disabled + } } // updateComputedValues examins the existing settings and converts any @@ -647,6 +661,13 @@ func (c *Config) validate() error { return fmt.Errorf("error validating Generic Device Plugin configuration: %v", err) } + if err := c.ApiServer.FeatureGates.validateFeatureGates(); err != nil { + return fmt.Errorf("error validating feature gates: %v", err) + } + + if err := c.DNS.validate(); err != nil { + return fmt.Errorf("error validating DNS: %v", err) + } return nil } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index e484a04576..c41fb9a0c0 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -800,6 +800,67 @@ func TestValidate(t *testing.T) { }(), expectErr: true, }, + { + name: "feature-gates-unset", + config: func() *Config { + c := mkDefaultConfig() + c.ApiServer.FeatureGates = FeatureGates{} + return c + }(), + expectErr: false, + }, + { + name: "feature-gates-invalid-feature-set", + config: func() *Config { + c := mkDefaultConfig() + c.ApiServer.FeatureGates.FeatureSet = "invalid" + return c + }(), + expectErr: true, + }, + { + name: "feature-gates-custom-no-upgrade-with-feature-set", + config: func() *Config { + c := mkDefaultConfig() + c.ApiServer.FeatureGates.FeatureSet = "CustomNoUpgrade" + c.ApiServer.FeatureGates.CustomNoUpgrade.Enabled = []string{"feature1"} + c.ApiServer.FeatureGates.CustomNoUpgrade.Disabled = []string{"feature2"} + return c + }(), + }, + { + name: "feature-gates-custom-no-upgrade-with-feature-set-empty", + config: func() *Config { + c := mkDefaultConfig() + c.ApiServer.FeatureGates.FeatureSet = "" + c.ApiServer.FeatureGates.CustomNoUpgrade.Enabled = []string{"feature1"} + c.ApiServer.FeatureGates.CustomNoUpgrade.Disabled = []string{"feature2"} + return c + }(), + expectErr: true, + }, + { + name: "feature-gates-custom-no-upgrade-with-empty-enabled-and-disabled-lists", + config: func() *Config { + c := mkDefaultConfig() + c.ApiServer.FeatureGates.FeatureSet = "CustomNoUpgrade" + c.ApiServer.FeatureGates.CustomNoUpgrade.Enabled = []string{} + c.ApiServer.FeatureGates.CustomNoUpgrade.Disabled = []string{} + return c + }(), + expectErr: true, + }, + { + name: "feature-gates-custom-no-upgrade-enabled-and-disabled-have-same-feature-gate", + config: func() *Config { + c := mkDefaultConfig() + c.ApiServer.FeatureGates.FeatureSet = "CustomNoUpgrade" + c.ApiServer.FeatureGates.CustomNoUpgrade.Enabled = []string{"feature1"} + c.ApiServer.FeatureGates.CustomNoUpgrade.Disabled = []string{"feature1"} + return c + }(), + expectErr: true, + }, } for _, tt := range ttests { t.Run(tt.name, func(t *testing.T) { diff --git a/pkg/config/dns.go b/pkg/config/dns.go index a0b9cd24d6..d8948449c9 100644 --- a/pkg/config/dns.go +++ b/pkg/config/dns.go @@ -1,5 +1,18 @@ package config +import ( + "fmt" + "os" + "path/filepath" +) + +const ( + HostsStatusEnabled HostsStatusEnum = "Enabled" + HostsStatusDisabled HostsStatusEnum = "Disabled" +) + +type HostsStatusEnum string + type DNS struct { // baseDomain is the base domain of the cluster. All managed DNS records will // be sub-domains of this base. @@ -13,4 +26,73 @@ type DNS struct { // +kubebuilder:default=example.com // +kubebuilder:example=microshift.example.com BaseDomain string `json:"baseDomain"` + + // Hosts contains configuration for the hosts file. + Hosts HostsConfig `json:"hosts,omitempty"` +} + +// HostsConfig contains configuration for the hosts file . +type HostsConfig struct { + // File is the path to the hosts file to monitor. + // If not specified, defaults to "/etc/hosts". + // +kubebuilder:default="/etc/hosts" + // +kubebuilder:example="/etc/hosts" + File string `json:"file,omitempty"` + + // Status controls whether the hosts file is enabled or disabled. + // Allowed values are "Enabled" and "Disabled". + // If not specified, defaults to "Disabled". + // +kubebuilder:default="Disabled" + // +kubebuilder:example="Enabled" + // +kubebuilder:validation:Enum=Enabled;Disabled + Status HostsStatusEnum `json:"status,omitempty"` +} + +func dnsDefaults() DNS { + return DNS{ + BaseDomain: "example.com", + Hosts: HostsConfig{ + File: "/etc/hosts", + Status: HostsStatusDisabled, + }, + } +} + +func (t *DNS) validate() error { + switch t.Hosts.Status { + case HostsStatusEnabled: + if t.Hosts.File == "" { + break + } + + cleanPath := filepath.Clean(t.Hosts.File) + + fi, err := os.Stat(cleanPath) + // Enforce ConfigMap requirement: the file must not exceed 1MiB, as it will be mounted into a ConfigMap. + if err == nil && fi.Size() > 1048576 { + return fmt.Errorf("hosts file %s exceeds 1MiB ConfigMap (and internal buffer) size limit (got %d bytes)", t.Hosts.File, fi.Size()) + } + if !filepath.IsAbs(cleanPath) { + return fmt.Errorf("hosts file path must be absolute: got %s", t.Hosts.File) + } + + _, err = os.Stat(cleanPath) + if os.IsNotExist(err) { + return fmt.Errorf("hosts file %s does not exist", t.Hosts.File) + } else if err != nil { + return fmt.Errorf("error checking hosts file %s: %v", t.Hosts.File, err) + } + + file, err := os.Open(t.Hosts.File) + if err != nil { + return fmt.Errorf("hosts file %s is not readable: %v", t.Hosts.File, err) + } + return file.Close() + + case HostsStatusDisabled: + return nil + default: + return fmt.Errorf("invalid hosts status: %s", t.Hosts.Status) + } + return nil } diff --git a/pkg/controllers/etcd.go b/pkg/controllers/etcd.go index e5631c6173..038702c2b4 100644 --- a/pkg/controllers/etcd.go +++ b/pkg/controllers/etcd.go @@ -241,8 +241,9 @@ func getEtcdClient(ctx context.Context) (*clientv3.Client, error) { } cli, err := clientv3.New(clientv3.Config{ - Endpoints: []string{"https://localhost:2379"}, - DialTimeout: 5 * time.Second, + Endpoints: []string{"https://localhost:2379"}, + // Connecting to localhost allows for a really short timeout to bail out quickly and retry again. + DialTimeout: 100 * time.Millisecond, TLS: tlsConfig, Context: ctx, }) diff --git a/pkg/controllers/hostswatcher.go b/pkg/controllers/hostswatcher.go new file mode 100644 index 0000000000..f666cd3e90 --- /dev/null +++ b/pkg/controllers/hostswatcher.go @@ -0,0 +1,280 @@ +package controllers + +import ( + "context" + "crypto/sha256" + "fmt" + "os" + "path/filepath" + "time" + + "github.com/fsnotify/fsnotify" + "github.com/openshift/microshift/pkg/config" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/klog/v2" +) + +const ( + targetNameSpace = "openshift-dns" + configMapName = "hosts-file" +) + +type HostsWatcherManager struct { + file string + status config.HostsStatusEnum + kubeconfig string +} + +func NewHostsWatcherManager(cfg *config.Config) *HostsWatcherManager { + return &HostsWatcherManager{ + file: cfg.DNS.Hosts.File, + status: cfg.DNS.Hosts.Status, + kubeconfig: cfg.KubeConfigPath(config.KubeAdmin), + } +} + +func (s *HostsWatcherManager) Name() string { return "hosts-watcher-manager" } +func (s *HostsWatcherManager) Dependencies() []string { return []string{"kube-apiserver"} } + +func (s *HostsWatcherManager) Run(ctx context.Context, ready chan<- struct{}, stopped chan<- struct{}) error { + defer close(stopped) + + if s.status != config.HostsStatusEnabled { + klog.Infof("%s is disabled (not configured)", s.Name()) + // Delete ConfigMap if it exists when service is disabled + if kubeClient, err := s.createKubeClient(); err == nil { + if err := s.deleteConfigMap(ctx, kubeClient); err != nil { + klog.Warningf("%s failed to delete ConfigMap when disabled: %v", s.Name(), err) + } + } else { + klog.Warningf("%s could not create Kubernetes client to delete ConfigMap: %v", s.Name(), err) + } + defer close(ready) + return ctx.Err() + } + + kubeClient, err := s.createKubeClient() + if err != nil { + klog.Errorf("%s failed to create Kubernetes client: %v", s.Name(), err) + return err + } + + if err := s.updateConfigMaps(ctx, kubeClient); err != nil { + klog.Errorf("%s failed to create initial ConfigMaps: %v", s.Name(), err) + return err + } + + watcher, err := fsnotify.NewWatcher() + if err != nil { + klog.Errorf("%s failed to create file watcher: %v", s.Name(), err) + return err + } + defer func() { + if cerr := watcher.Close(); cerr != nil { + klog.Errorf("%s failed to close file watcher: %v", s.Name(), cerr) + } + }() + + if err := s.setupWatches(watcher); err != nil { + return err + } + close(ready) + klog.Infof("%s ready and watching for changes", s.Name()) + + lastHash, err := s.getFileHash(s.file) + if err != nil { + klog.Warningf("%s failed to get initial file hash: %v", s.Name(), err) + } + + klog.Infof("%s is ready", s.Name()) + + return s.eventLoop(ctx, watcher, kubeClient, lastHash) +} + +func (s *HostsWatcherManager) setupWatches(watcher *fsnotify.Watcher) error { + filesToWatch := []string{ + s.file, + filepath.Dir(s.file), + } + for i, file := range filesToWatch { + if err := watcher.Add(file); err != nil { + // Warn if directory, error out if file + if i == 0 { + klog.Errorf("%s failed to watch hosts file %s: %v", s.Name(), s.file, err) + return err + } + klog.Warningf("%s failed to watch hosts directory %s: %v", s.Name(), file, err) + } + } + return nil +} + +func (s *HostsWatcherManager) eventLoop(ctx context.Context, watcher *fsnotify.Watcher, kubeClient kubernetes.Interface, initHash string) error { + lastHash := initHash + + for { + select { + case <-ctx.Done(): + klog.Infof("%s stopping", s.Name()) + return watcher.Close() + + case event, ok := <-watcher.Events: + if !ok { + return fmt.Errorf("%s watcher channel closed", s.Name()) + } + if s.isRelevantHostsEvent(event) { + updated, newHash, updateErr := s.handleHostsChange(ctx, kubeClient, lastHash) + if updateErr != nil { + klog.Errorf("%s failed to process hosts file change: %v", s.Name(), updateErr) + continue + } + if updated { + lastHash = newHash + } + } + + case err, ok := <-watcher.Errors: + if !ok { + return fmt.Errorf("%s watcher error channel closed", s.Name()) + } + klog.Errorf("%s watcher error: %v", s.Name(), err) + } + } +} + +func (s *HostsWatcherManager) isRelevantHostsEvent(event fsnotify.Event) bool { + if event.Name != s.file { + return false + } + return event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Create == fsnotify.Create +} + +func (s *HostsWatcherManager) handleHostsChange(ctx context.Context, kubeClient kubernetes.Interface, lastHash string) (bool, string, error) { + klog.Infof("%s detected change in hosts file: %s", s.Name(), s.file) + currentHash, err := s.getFileHash(s.file) + if err != nil { + klog.Warningf("%s failed to get file hash after change: %v", s.Name(), err) + return false, lastHash, err + } + if currentHash == lastHash { + klog.V(2).Infof("%s file hash unchanged, skipping update", s.Name()) + return false, lastHash, nil + } + if err := s.updateConfigMaps(ctx, kubeClient); err != nil { + klog.Errorf("%s failed to update ConfigMaps: %v", s.Name(), err) + return false, currentHash, err + } else { + klog.Infof("%s successfully updated ConfigMaps in namespaces: %v", s.Name(), targetNameSpace) + } + return true, currentHash, nil +} + +func (s *HostsWatcherManager) createKubeClient() (*kubernetes.Clientset, error) { + config, err := clientcmd.BuildConfigFromFlags("", s.kubeconfig) + if err != nil { + return nil, fmt.Errorf("failed to build kubeconfig: %w", err) + } + + client, err := kubernetes.NewForConfig(config) + if err != nil { + return nil, fmt.Errorf("failed to create Kubernetes client: %w", err) + } + + return client, nil +} + +func (s *HostsWatcherManager) updateConfigMaps(ctx context.Context, client kubernetes.Interface) error { + hostsContent, err := s.readHostsFile() + if err != nil { + return fmt.Errorf("failed to read hosts file: %w", err) + } + + if err := s.createOrUpdateConfigMap(ctx, client, targetNameSpace, hostsContent); err != nil { + klog.Errorf("%s failed to update ConfigMap in namespace %s: %v", s.Name(), targetNameSpace, err) + } + + return nil +} + +func (s *HostsWatcherManager) createOrUpdateConfigMap(ctx context.Context, client kubernetes.Interface, namespace string, hostsContent string) error { + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: configMapName, + Namespace: namespace, + Labels: map[string]string{ + "app.kubernetes.io/name": "microshift-hosts-watcher", + "app.kubernetes.io/component": "hosts-file-sync", + "app.kubernetes.io/managed-by": "microshift", + // Restrict access to only CoreDNS pods + "microshift.io/access-restricted": "coredns-only", + }, + Annotations: map[string]string{ + "microshift.io/hosts-file-path": s.file, + "microshift.io/last-updated": time.Now().Format(time.RFC3339), + }, + }, + Data: map[string]string{ + "hosts": hostsContent, + }, + } + + configMapsClient := client.CoreV1().ConfigMaps(namespace) + + // Try to get existing ConfigMap + existing, err := configMapsClient.Get(ctx, configMapName, metav1.GetOptions{}) + if err != nil { + // ConfigMap doesn't exist, create it + _, err = configMapsClient.Create(ctx, configMap, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("failed to create ConfigMap: %w", err) + } + klog.Infof("%s created ConfigMap %s in namespace %s", s.Name(), configMapName, namespace) + } else { + // ConfigMap exists, update it + existing.Data = configMap.Data + existing.Annotations = configMap.Annotations + _, err = configMapsClient.Update(ctx, existing, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("failed to update ConfigMap: %w", err) + } + klog.V(2).Infof("%s updated ConfigMap %s in namespace %s", s.Name(), configMapName, namespace) + } + + return nil +} + +func (s *HostsWatcherManager) readHostsFile() (string, error) { + content, err := os.ReadFile(s.file) + if err != nil { + return "", fmt.Errorf("failed to read hosts file %s: %w", s.file, err) + } + return string(content), nil +} + +func (s *HostsWatcherManager) getFileHash(filePath string) (string, error) { + content, err := os.ReadFile(filePath) + if err != nil { + return "", err + } + hash := sha256.Sum256(content) + return fmt.Sprintf("%x", hash), nil +} + +func (s *HostsWatcherManager) deleteConfigMap(ctx context.Context, client kubernetes.Interface) error { + configMapsClient := client.CoreV1().ConfigMaps(targetNameSpace) + err := configMapsClient.Delete(ctx, configMapName, metav1.DeleteOptions{}) + if err != nil { + // If ConfigMap doesn't exist, that's fine - it's already deleted + if apierrors.IsNotFound(err) { + klog.V(2).Infof("%s ConfigMap %s in namespace %s does not exist, nothing to delete", s.Name(), configMapName, targetNameSpace) + return nil + } + return fmt.Errorf("failed to delete ConfigMap: %w", err) + } + klog.Infof("%s deleted ConfigMap %s in namespace %s", s.Name(), configMapName, targetNameSpace) + return nil +} diff --git a/pkg/controllers/kube-apiserver.go b/pkg/controllers/kube-apiserver.go index 41b4ac3976..70cb89dcdc 100644 --- a/pkg/controllers/kube-apiserver.go +++ b/pkg/controllers/kube-apiserver.go @@ -33,6 +33,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" @@ -63,7 +64,6 @@ var ( embedded.MustAsset("controllers/kube-apiserver/config-overrides.yaml"), } ) - var fixedTLSProfile *configv1.TLSProfileSpec func init() { @@ -169,6 +169,17 @@ func (s *KubeAPIServer) configure(ctx context.Context, cfg *config.Config) error return fmt.Errorf("failed to discover etcd servers: %w", err) } + featureGateArgs, err := cfg.ApiServer.FeatureGates.ToApiserverArgs() + if err != nil { + return fmt.Errorf("failed to convert feature gates to CLI flags: %w", err) + } + // Inject required feature gates into the feature-gates argument. + enabledRequiredFGs := make(sets.Set[string], 0) + for _, fg := range config.RequiredFeatureGates { + enabledRequiredFGs.Insert(fg + "=true") + } + featureGateArgs = sets.New(featureGateArgs...).Union(enabledRequiredFGs).UnsortedList() + overrides := &kubecontrolplanev1.KubeAPIServerConfig{ APIServerArguments: map[string]kubecontrolplanev1.Arguments{ "advertise-address": {s.advertiseAddress}, @@ -221,7 +232,7 @@ func (s *KubeAPIServer) configure(ctx context.Context, cfg *config.Config) error "enable-admission-plugins": {}, "send-retry-after-while-not-ready-once": {"true"}, "shutdown-delay-duration": {"5s"}, - "feature-gates": {"UserNamespacesSupport=true", "UserNamespacesPodSecurityStandards=true"}, + "feature-gates": featureGateArgs, }, GenericAPIServerConfig: configv1.GenericAPIServerConfig{ AdmissionConfig: configv1.AdmissionConfig{ @@ -322,24 +333,24 @@ func (s *KubeAPIServer) Run(ctx context.Context, ready chan<- struct{}, stopped ctx, cancel := context.WithCancel(ctx) defer cancel() + restConfig, err := clientcmd.BuildConfigFromFlags(s.masterURL, "") + if err != nil { + return err + } + if err := rest.SetKubernetesDefaults(restConfig); err != nil { + return err + } + restConfig.NegotiatedSerializer = serializer.NewCodecFactory(runtime.NewScheme()) + restConfig.CAFile = s.servingCAPath + + restClient, err := rest.UnversionedRESTClientFor(restConfig) + if err != nil { + return err + } + // run readiness check go func() { err := wait.PollUntilContextTimeout(ctx, time.Second, kubeAPIStartupTimeout*time.Second, true, func(ctx context.Context) (bool, error) { - restConfig, err := clientcmd.BuildConfigFromFlags(s.masterURL, "") - if err != nil { - return false, err - } - if err := rest.SetKubernetesDefaults(restConfig); err != nil { - return false, err - } - restConfig.NegotiatedSerializer = serializer.NewCodecFactory(runtime.NewScheme()) - restConfig.CAFile = s.servingCAPath - - restClient, err := rest.UnversionedRESTClientFor(restConfig) - if err != nil { - return false, err - } - var status int if err := restClient.Get().AbsPath("/readyz").Do(ctx).StatusCode(&status).Error(); err != nil { klog.Infof("%q not yet ready: %v", s.Name(), err) diff --git a/pkg/controllers/openshift-default-scc-manager.go b/pkg/controllers/openshift-default-scc-manager.go index a77fb1a027..8867a21c53 100644 --- a/pkg/controllers/openshift-default-scc-manager.go +++ b/pkg/controllers/openshift-default-scc-manager.go @@ -65,10 +65,12 @@ func ApplyDefaultSCCs(ctx context.Context, cfg *config.Config) error { "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-nonroot.yaml", "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-privileged.yaml", "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-restricted-v2.yaml", + "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-restricted-v3.yaml", "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-restricted.yaml", } clusterRoleBinding = []string{ "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v2.yaml", + "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v3.yaml", } sccs = []string{ "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-anyuid.yaml", @@ -80,6 +82,7 @@ func ApplyDefaultSCCs(ctx context.Context, cfg *config.Config) error { "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-nonroot.yaml", "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-privileged.yaml", "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-restricted-v2.yaml", + "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-restricted-v3.yaml", "controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-restricted.yaml", } ) diff --git a/pkg/healthcheck/microshift_optional_workloads.go b/pkg/healthcheck/microshift_optional_workloads.go index 163aa31af6..6a60434267 100644 --- a/pkg/healthcheck/microshift_optional_workloads.go +++ b/pkg/healthcheck/microshift_optional_workloads.go @@ -33,6 +33,10 @@ var optionalWorkloadPaths = map[string]optionalWorkloads{ Namespace: "redhat-ods-applications", Workloads: NamespaceWorkloads{Deployments: []string{"kserve-controller-manager"}}, }, + "/usr/lib/microshift/manifests.d/070-microshift-sriov": { + Namespace: "sriov-network-operator", + Workloads: NamespaceWorkloads{Deployments: []string{"sriov-network-operator"}}, + }, } // fillOptionalMicroShiftWorkloads assembles list of optional MicroShift workloads diff --git a/pkg/util/net.go b/pkg/util/net.go index 690ba82e8f..ba5c111c95 100644 --- a/pkg/util/net.go +++ b/pkg/util/net.go @@ -106,7 +106,7 @@ func RetryGet(ctx context.Context, url, additionalCAPath string) int { } } status := 0 - err = wait.PollUntilContextTimeout(ctx, 5*time.Second, 120*time.Second, false, func(ctx context.Context) (bool, error) { + err = wait.PollUntilContextTimeout(ctx, time.Second, 120*time.Second, true, func(ctx context.Context) (bool, error) { c := http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ @@ -133,8 +133,8 @@ func RetryGet(ctx context.Context, url, additionalCAPath string) int { func RetryTCPConnection(ctx context.Context, host string, port string) bool { status := false - err := wait.PollUntilContextTimeout(ctx, 5*time.Second, 120*time.Second, false, func(ctx context.Context) (bool, error) { - timeout := 30 * time.Second + err := wait.PollUntilContextTimeout(ctx, time.Second, 120*time.Second, true, func(ctx context.Context) (bool, error) { + timeout := time.Second _, err := tcpnet.DialTimeout("tcp", tcpnet.JoinHostPort(host, port), timeout) if err == nil { diff --git a/rebase.log b/rebase.log new file mode 100644 index 0000000000..ad1d7ad190 --- /dev/null +++ b/rebase.log @@ -0,0 +1,846 @@ +rebase.sh: +# Rebasing to registry.ci.openshift.org/ocp/release:4.21.0-0.nightly-2025-10-22-123727 and registry.ci.openshift.org/ocp-arm64/release-arm64:4.21.0-0.nightly-arm64-2025-10-22-190453 +# Fetching release info for registry.ci.openshift.org/ocp/release:4.21.0-0.nightly-2025-10-22-123727 (amd64) +# Fetching release info for registry.ci.openshift.org/ocp-arm64/release-arm64:4.21.0-0.nightly-arm64-2025-10-22-190453 (arm64) +# Extracting registry.ci.openshift.org/ocp/release:4.21.0-0.nightly-2025-10-22-123727 manifest content +# Cloning registry.ci.openshift.org/ocp/release:4.21.0-0.nightly-2025-10-22-123727 component repos +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/api/.git/ +HEAD is now at 8c9accaf Merge pull request #2502 from jsafrane/MutableCSINodeAllocatableCount-tp + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/cluster-csi-snapshot-controller-operator/.git/ +HEAD is now at b022cf7 Merge pull request #245 from openshift-bot/art-consistency-openshift-4.21-ose-cluster-csi-snapshot-controller-operator + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/cluster-dns-operator/.git/ +HEAD is now at 2ec8a3d Merge pull request #448 from davidesalerno/NE-2138 + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/cluster-ingress-operator/.git/ +HEAD is now at 0cac97a Merge pull request #1291 from rhamini3/ci-cluster-ossm + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/cluster-kube-apiserver-operator/.git/ +HEAD is now at adc82f6 Merge pull request #1939 from bertinatto/rebase-1.34 + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/cluster-kube-controller-manager-operator/.git/ +HEAD is now at ffe5113 Merge pull request #888 from bertinatto/rebase-1.34 + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/cluster-kube-scheduler-operator/.git/ +HEAD is now at 10d89b5 Merge pull request #583 from bertinatto/rebase-1.34 + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/cluster-network-operator/.git/ +HEAD is now at a587975 Merge pull request #2808 from maiqueb/api-l2udn-masked-subnets + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/cluster-openshift-controller-manager-operator/.git/ +HEAD is now at f90be06 Merge pull request #399 from openshift-bot/art-consistency-openshift-4.21-ose-cluster-openshift-controller-manager-operator + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/cluster-policy-controller/.git/ +HEAD is now at ef70396 Merge pull request #169 from openshift-bot/art-consistency-openshift-4.21-cluster-policy-controller + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/csi-external-snapshotter/.git/ +HEAD is now at 15313fb Merge pull request #188 from openshift-bot/art-consistency-openshift-4.21-ose-csi-snapshot-controller + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/etcd/.git/ +HEAD is now at e2b3dfdf Merge pull request #342 from openshift-bot/art-consistency-openshift-4.21-ose-etcd + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/kubernetes/.git/ +HEAD is now at 96593f323 Merge pull request #2484 from bertinatto/rebase-1.34 + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/kubernetes-kube-storage-version-migrator/.git/ +HEAD is now at ce5ff17 Merge pull request #234 from openshift-bot/art-consistency-openshift-4.21-ose-kube-storage-version-migrator + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/machine-config-operator/.git/ +HEAD is now at 06e7b70a Merge pull request #5332 from djoshy/add-cpms-support + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/openshift-controller-manager/.git/ +HEAD is now at 433bd50 Merge pull request #414 from openshift-bot/art-consistency-openshift-4.21-ose-openshift-controller-manager + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/operator-framework-olm/.git/ +HEAD is now at a0b88f9a Merge pull request #1126 from Xia-Zhao-rh/opm-cases + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/route-controller-manager/.git/ +HEAD is now at c337cf4 Merge pull request #65 from openshift-bot/art-consistency-openshift-4.21-ose-route-controller-manager + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/service-ca-operator/.git/ +HEAD is now at e5d65c6 Merge pull request #276 from openshift-bot/art-consistency-openshift-4.21-ose-service-ca-operator + +# Cloning registry.ci.openshift.org/ocp/release:4.21.0-0.nightly-2025-10-22-123727 image repos +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/amd64/oc/.git/ +HEAD is now at 8836b663 Merge pull request #2113 from wking/remove-obsolete-precheckEnabled + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/amd64/coredns/.git/ +HEAD is now at 91ae57f Merge pull request #154 from openshift-bot/art-consistency-openshift-4.21-coredns + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/amd64/csi-external-snapshotter/.git/ +HEAD is now at 15313fb Merge pull request #188 from openshift-bot/art-consistency-openshift-4.21-ose-csi-snapshot-controller + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/amd64/router/.git/ +HEAD is now at 526b4d0 Merge pull request #679 from openshift-bot/art-consistency-openshift-4.21-ose-haproxy-router-base + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/amd64/kube-rbac-proxy/.git/ +HEAD is now at cd63668 Merge pull request #126 from openshift-bot/art-consistency-openshift-4.21-kube-rbac-proxy + +lvms_operator not from release payload, skipping + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/amd64/ovn-kubernetes/.git/ +HEAD is now at a573f44e Merge pull request #2772 from openshift-bot/art-consistency-openshift-4.21-ovn-kubernetes-microshift + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/amd64/kubernetes/.git/ +HEAD is now at 96593f323 Merge pull request #2484 from bertinatto/rebase-1.34 + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/amd64/service-ca-operator/.git/ +HEAD is now at e5d65c6 Merge pull request #276 from openshift-bot/art-consistency-openshift-4.21-ose-service-ca-operator + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/arm64/oc/.git/ +HEAD is now at 8836b663 Merge pull request #2113 from wking/remove-obsolete-precheckEnabled + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/arm64/coredns/.git/ +HEAD is now at 91ae57f Merge pull request #154 from openshift-bot/art-consistency-openshift-4.21-coredns + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/arm64/csi-external-snapshotter/.git/ +HEAD is now at 15313fb Merge pull request #188 from openshift-bot/art-consistency-openshift-4.21-ose-csi-snapshot-controller + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/arm64/router/.git/ +HEAD is now at 526b4d0 Merge pull request #679 from openshift-bot/art-consistency-openshift-4.21-ose-haproxy-router-base + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/arm64/kube-rbac-proxy/.git/ +HEAD is now at cd63668 Merge pull request #126 from openshift-bot/art-consistency-openshift-4.21-kube-rbac-proxy + +lvms_operator not from release payload, skipping + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/arm64/ovn-kubernetes/.git/ +HEAD is now at a573f44e Merge pull request #2772 from openshift-bot/art-consistency-openshift-4.21-ovn-kubernetes-microshift + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/arm64/kubernetes/.git/ +HEAD is now at 96593f323 Merge pull request #2484 from bertinatto/rebase-1.34 + +Initialized empty Git repository in /go/src/github.com/openshift/microshift/_output/staging/arm64/service-ca-operator/.git/ +HEAD is now at e5d65c6 Merge pull request #276 from openshift-bot/art-consistency-openshift-4.21-ose-service-ca-operator + +Warning: env var PULL_BASE_REF not found or empty, falling back to local active branch. +error: branch 'rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22' not found +Switched to a new branch 'rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22' +## Updating last_rebase.sh +## Committing changes to last_rebase.sh +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 c63c22945] update last_rebase.sh + 1 file changed, 1 insertion(+), 1 deletion(-) +cluster-csi-snapshot-controller-operator embedded-component no change + +cluster-dns-operator embedded-component no change + +cluster-ingress-operator embedded-component no change + +cluster-kube-apiserver-operator embedded-component no change + +cluster-kube-controller-manager-operator embedded-component no change + +cluster-kube-scheduler-operator embedded-component no change + +cluster-network-operator embedded-component no change + +cluster-policy-controller embedded-component no change + +csi-external-snapshotter embedded-component no change + +etcd embedded-component no change + +kubernetes embedded-component no change + +kubernetes-kube-storage-version-migrator embedded-component no change + +route-controller-manager embedded-component no change + +service-ca-operator embedded-component no change + +coredns image-amd64 no change + +csi-external-snapshotter image-amd64 no change + +router image-amd64 no change + +kubernetes image-amd64 no change + +service-ca-operator image-amd64 no change + +coredns image-arm64 no change + +csi-external-snapshotter image-arm64 no change + +router image-arm64 no change + +kubernetes image-arm64 no change + +service-ca-operator image-arm64 no change + +## Committing changes to changelog +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 aa31d603e] update changelog + 2 files changed, 68 insertions(+), 5138 deletions(-) +# Updating microshift/go.mod +go mod edit -require github.com/openshift/cluster-policy-controller@ef703966fe6e82f5f255b06bc5c758f105bf8b28 +go: downloading github.com/stretchr/testify v1.11.1 +go: downloading github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7 +go: downloading github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235 +go: downloading github.com/openshift/library-go v0.0.0-20251015151611-6fc7a74b67c5 +go: downloading k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 +go: downloading sigs.k8s.io/yaml v1.6.0 +go: downloading github.com/fsnotify/fsnotify v1.9.0 +go: downloading github.com/vishvananda/netlink v1.3.1 +go: downloading github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e +go: downloading sigs.k8s.io/kustomize/kyaml v0.20.1 +go: downloading github.com/spf13/cobra v1.9.1 +go: downloading github.com/apparentlymart/go-cidr v1.1.0 +go: downloading go.etcd.io/etcd/client/pkg/v3 v3.6.4 +go: downloading github.com/evanphx/json-patch v4.12.0+incompatible +go: downloading go.etcd.io/etcd/client/v3 v3.6.4 +go: downloading github.com/spf13/pflag v1.0.10 +go: downloading github.com/openshift/build-machinery-go v0.0.0-20250602125535-1b6d00b8c37c +go: downloading github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 +go: downloading gopkg.in/yaml.v3 v3.0.1 +go: downloading github.com/go-kit/kit v0.9.0 +go: downloading github.com/coreos/go-systemd/v22 v22.5.0 +go: downloading github.com/openshift/cluster-policy-controller v0.0.0-20251007100337-ef703966fe6e +go: downloading github.com/miekg/dns v1.1.63 +go: downloading sigs.k8s.io/kustomize/api v0.20.1 +go: downloading github.com/openshift/route-controller-manager v0.0.0-20251008111043-c337cf413bbb +go: downloading gopkg.in/yaml.v2 v2.4.0 +go: downloading golang.org/x/sys v0.36.0 +go: downloading k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b +go: downloading github.com/gogo/protobuf v1.3.2 +go: downloading github.com/golang/snappy v0.0.4 +go: downloading github.com/openshift/kubernetes-kube-storage-version-migrator v0.0.3-0.20251007192956-ce5ff17e9a81 +go: downloading github.com/prometheus/client_model v0.6.2 +go: downloading github.com/prometheus/common v0.66.1 +go: downloading github.com/google/go-cmp v0.7.0 +go: downloading github.com/prometheus/prometheus v0.302.1 +go: downloading github.com/go-logr/logr v1.4.3 +go: downloading github.com/fxamacker/cbor/v2 v2.9.0 +go: downloading sigs.k8s.io/randfill v1.0.0 +go: downloading github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc +go: downloading github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 +go: downloading sigs.k8s.io/structured-merge-diff/v6 v6.3.0 +go: downloading github.com/google/gnostic-models v0.7.0 +go: downloading google.golang.org/protobuf v1.36.8 +go: downloading github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 +go: downloading golang.org/x/net v0.43.0 +go: downloading golang.org/x/term v0.35.0 +go: downloading go.yaml.in/yaml/v2 v2.4.2 +go: downloading go.yaml.in/yaml/v3 v3.0.4 +go: downloading github.com/vishvananda/netns v0.0.5 +go: downloading gopkg.in/evanphx/json-patch.v4 v4.12.0 +go: downloading github.com/inconshreveable/mousetrap v1.1.0 +go: downloading github.com/pkg/errors v0.9.1 +go: downloading github.com/google/uuid v1.6.0 +go: downloading go.uber.org/zap v1.27.0 +go: downloading github.com/coreos/go-semver v0.3.1 +go: downloading go.etcd.io/etcd/api/v3 v3.6.4 +go: downloading google.golang.org/grpc v1.76.0 +go: downloading github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.74.0 +go: downloading gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c +go: downloading sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 +go: downloading github.com/moby/term v0.5.0 +go: downloading github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de +go: downloading go.uber.org/goleak v1.3.0 +go: downloading github.com/jonboulle/clockwork v0.5.0 +go: downloading go.opentelemetry.io/otel/trace v1.37.0 +go: downloading golang.org/x/time v0.9.0 +go: downloading github.com/go-logfmt/logfmt v0.5.1 +go: downloading github.com/go-stack/stack v1.8.1 +go: downloading github.com/MakeNowJust/heredoc v1.0.0 +go: downloading github.com/mitchellh/go-wordwrap v1.0.1 +go: downloading github.com/russross/blackfriday/v2 v2.1.0 +go: downloading go.opentelemetry.io/otel v1.37.0 +go: downloading github.com/godbus/dbus/v5 v5.1.0 +go: downloading golang.org/x/tools v0.36.0 +go: downloading golang.org/x/sync v0.17.0 +go: downloading github.com/blang/semver/v4 v4.0.0 +go: downloading github.com/google/cadvisor v0.52.1 +go: downloading go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 +go: downloading go.opentelemetry.io/otel/metric v1.37.0 +go: downloading go.opentelemetry.io/otel/sdk v1.37.0 +go: downloading go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 +go: downloading github.com/go-kit/log v0.2.1 +go: downloading github.com/oklog/run v1.2.0 +go: downloading github.com/prometheus/client_golang v1.23.2 +go: downloading github.com/Microsoft/go-winio v0.6.2 +go: downloading k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f +go: downloading gopkg.in/inf.v0 v0.9.1 +go: downloading github.com/x448/float16 v0.8.4 +go: downloading github.com/go-openapi/swag v0.23.0 +go: downloading github.com/json-iterator/go v1.1.12 +go: downloading golang.org/x/oauth2 v0.30.0 +go: downloading github.com/stretchr/objx v0.5.2 +go: downloading github.com/prometheus/procfs v0.16.1 +go: downloading golang.org/x/text v0.29.0 +go: downloading github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 +go: downloading github.com/peterbourgon/diskv v2.0.1+incompatible +go: downloading go.uber.org/multierr v1.11.0 +go: downloading github.com/golang/protobuf v1.5.4 +go: downloading github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 +go: downloading google.golang.org/genproto/googleapis/api v0.0.0-20250804133106-a7a43d27e69b +go: downloading google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 +go: downloading github.com/go-errors/errors v1.4.2 +go: downloading github.com/go-openapi/jsonreference v0.21.0 +go: downloading github.com/kr/pretty v0.3.1 +go: downloading github.com/chai2010/gettext-go v1.0.2 +go: downloading github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20251001123353-fd5b1fb35db1 +go: downloading github.com/onsi/gomega v1.35.1 +go: downloading github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f +go: downloading github.com/creack/pty v1.1.18 +go: downloading gopkg.in/natefinch/lumberjack.v2 v2.2.1 +go: downloading gopkg.in/go-jose/go-jose.v2 v2.6.3 +go: downloading github.com/emicklei/go-restful/v3 v3.12.2 +go: downloading github.com/pkg/profile v1.7.0 +go: downloading github.com/sirupsen/logrus v1.9.3 +go: downloading go.etcd.io/etcd/server/v3 v3.6.4 +go: downloading go.uber.org/atomic v1.11.0 +go: downloading golang.org/x/crypto v0.42.0 +go: downloading go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 +go: downloading sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 +go: downloading github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 +go: downloading github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f +go: downloading github.com/openshift/apiserver-library-go v0.0.0-20251015164739-79d04067059d +go: downloading github.com/onsi/ginkgo v1.16.5 +go: downloading github.com/google/cel-go v0.26.0 +go: downloading github.com/robfig/cron/v3 v3.0.1 +go: downloading github.com/robfig/cron v1.2.0 +go: downloading github.com/opencontainers/selinux v1.11.1 +go: downloading github.com/container-storage-interface/spec v1.9.0 +go: downloading github.com/libopenstorage/openstorage v1.0.0 +go: downloading github.com/go-logr/stdr v1.2.2 +go: downloading go.opentelemetry.io/proto/otlp v1.5.0 +go: downloading github.com/opencontainers/cgroups v0.0.3 +go: downloading github.com/cyphar/filepath-securejoin v0.4.1 +go: downloading github.com/moby/sys/userns v0.1.0 +go: downloading github.com/docker/go-units v0.5.0 +go: downloading github.com/opencontainers/runc v1.2.5 +go: downloading go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.44.0 +go: downloading github.com/moby/sys/mountinfo v0.7.2 +go: downloading github.com/karrick/godirwalk v1.17.0 +go: downloading github.com/containerd/containerd/api v1.8.0 +go: downloading github.com/containerd/errdefs v1.0.0 +go: downloading github.com/containerd/errdefs/pkg v0.3.0 +go: downloading github.com/opencontainers/runtime-spec v1.2.0 +go: downloading github.com/containerd/typeurl/v2 v2.2.2 +go: downloading golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated +go: downloading github.com/mailru/easyjson v0.7.7 +go: downloading github.com/beorn7/perks v1.0.1 +go: downloading github.com/cespare/xxhash/v2 v2.3.0 +go: downloading github.com/klauspost/compress v1.18.0 +go: downloading github.com/kylelemons/godebug v1.1.0 +go: downloading github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd +go: downloading github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee +go: downloading github.com/google/btree v1.1.3 +go: downloading github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc +go: downloading github.com/go-openapi/jsonpointer v0.21.0 +go: downloading github.com/kr/text v0.2.0 +go: downloading github.com/rogpeppe/go-internal v1.13.1 +go: downloading github.com/go-logr/zapr v1.3.0 +go: downloading github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 +go: downloading github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 +go: downloading go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 +go: downloading github.com/coreos/go-oidc v2.3.0+incompatible +go: downloading github.com/felixge/fgprof v0.9.4 +go: downloading github.com/NYTimes/gziphandler v1.1.1 +go: downloading github.com/felixge/httpsnoop v1.0.4 +go: downloading github.com/moby/spdystream v0.5.0 +go: downloading github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 +go: downloading github.com/soheilhy/cmux v0.1.5 +go: downloading github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 +go: downloading go.etcd.io/bbolt v1.4.2 +go: downloading go.etcd.io/etcd/pkg/v3 v3.6.4 +go: downloading cel.dev/expr v0.24.0 +go: downloading github.com/stoewer/go-strcase v1.3.0 +go: downloading github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 +go: downloading go.opentelemetry.io/auto/sdk v1.1.0 +go: downloading github.com/cenkalti/backoff/v4 v4.3.0 +go: downloading github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible +go: downloading github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab +go: downloading github.com/distribution/reference v0.6.0 +go: downloading github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 +go: downloading github.com/Microsoft/hnslib v0.1.1 +go: downloading github.com/lithammer/dedent v1.1.0 +go: downloading go.opentelemetry.io/contrib/propagators/b3 v1.19.0 +go: downloading github.com/containerd/ttrpc v1.2.6 +go: downloading github.com/euank/go-kmsg-parser v2.0.0+incompatible +go: downloading golang.org/x/mod v0.27.0 +go: downloading golang.org/x/tools/go/expect v0.1.0-deprecated +go: downloading github.com/josharian/intern v1.0.0 +go: downloading github.com/sergi/go-diff v1.2.0 +go: downloading go.opentelemetry.io/otel/sdk/metric v1.37.0 +go: downloading github.com/fatih/camelcase v1.0.0 +go: downloading github.com/pquerna/cachecontrol v0.1.0 +go: downloading github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad +go: downloading github.com/dustin/go-humanize v1.0.1 +go: downloading go.etcd.io/raft/v3 v3.6.0 +go: downloading github.com/xiang90/probing v0.0.0-20221125231312-a49e3df8f510 +go: downloading github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 +go: downloading github.com/antlr4-go/antlr/v4 v4.13.0 +go: downloading github.com/opencontainers/go-digest v1.0.0 +go: downloading github.com/docker/docker v27.4.1+incompatible +go: downloading github.com/docker/go-connections v0.5.0 +go: downloading github.com/opencontainers/image-spec v1.1.1 +go: downloading github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 +go: downloading github.com/xlab/treeprint v1.2.0 +go: downloading github.com/containerd/log v0.1.0 +go: downloading gonum.org/v1/gonum v0.16.0 +go: downloading github.com/golang-jwt/jwt/v5 v5.2.2 +go: downloading github.com/go-ldap/ldap/v3 v3.4.11 +go: downloading github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.0 +go: downloading github.com/go-task/slim-sprig/v3 v3.0.0 +go: downloading golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 +go: downloading github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 +go: downloading github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 +go: downloading github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa +go: downloading github.com/jcmturner/gokrb5/v8 v8.4.4 +go: downloading github.com/jcmturner/gofork v1.7.6 +go: downloading github.com/hashicorp/go-uuid v1.0.3 +go: downloading github.com/jcmturner/dnsutils/v2 v2.0.0 +go: downloading github.com/jcmturner/goidentity/v6 v6.0.1 +go: downloading github.com/jcmturner/aescts/v2 v2.0.0 +go: downloading github.com/jcmturner/rpc/v2 v2.0.3 +go: downloading github.com/moby/docker-image-spec v1.3.1 +go mod edit -replace github.com/onsi/ginkgo/v2=github.com/openshift/onsi-ginkgo/v2@v2.6.1-0.20251001123353-fd5b1fb35db1 +Handling 'k8s.io/klog/v2' dep: cloning 'https://github.com/kubernetes/klog' @ 'v2.130.1' to /go/src/github.com/openshift/microshift/./deps/k8s.io/klog +Cloning into '/go/src/github.com/openshift/microshift/./deps/k8s.io/klog'... +Handling 'k8s.io/kubernetes' dep: copying /go/src/github.com/openshift/microshift/_output/staging/kubernetes -> /go/src/github.com/openshift/microshift/./deps/github.com/openshift/kubernetes +go mod edit -replace sigs.k8s.io/kube-storage-version-migrator=github.com/openshift/kubernetes-kube-storage-version-migrator@ce5ff17e9a81ce754567e6dd5053d13409c251e9 +Handling 'k8s.io/api' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/apiextensions-apiserver' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/apimachinery' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/apiserver' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/cli-runtime' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/client-go' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/cloud-provider' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/cluster-bootstrap' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/code-generator' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/component-base' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/component-helpers' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/controller-manager' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/cri-api' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/cri-client' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/csi-translation-lib' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/dynamic-resource-allocation' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/endpointslice' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/externaljwt' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/kms' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/kube-aggregator' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/kube-controller-manager' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/kube-proxy' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/kube-scheduler' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/kubectl' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/kubelet' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/metrics' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/mount-utils' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/pod-security-admission' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/sample-apiserver' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/sample-cli-plugin' dep: updating required version to '1.34.1' (for information purposes) +Handling 'k8s.io/sample-controller' dep: updating required version to '1.34.1' (for information purposes) +go mod edit -require github.com/openshift/route-controller-manager@c337cf413bbbfc2154dc1d3c1bf8007ea1edfbc8 +go mod edit -require github.com/openshift/cluster-policy-controller@ef703966fe6e82f5f255b06bc5c758f105bf8b28 +for p in scripts/auto-rebase/rebase_patches/0001-Fix-CSI-initialization-conflict.patch scripts/auto-rebase/rebase_patches/0002-disable-APIrequestcount-controller.patch scripts/auto-rebase/rebase_patches/0003-disable-clusterQuotaMapping-controller.patch scripts/auto-rebase/rebase_patches/0004-remove-config-informer-and-cpu-partitioning-admission-plugin.patch scripts/auto-rebase/rebase_patches/0005-remove-user-informer.patch scripts/auto-rebase/rebase_patches/0006-kcm-no-panic.patch scripts/auto-rebase/rebase_patches/0020-klog-component-names.patch scripts/auto-rebase/rebase_patches/0030-kube-controller-manager-command-context.patch; do \ + echo "Applying patch $p"; \ + git mailinfo /dev/null /dev/stderr 2<&1- < $p | git apply --reject || exit 1; \ +done +Applying patch scripts/auto-rebase/rebase_patches/0001-Fix-CSI-initialization-conflict.patch +Checking patch deps/github.com/openshift/kubernetes/pkg/volume/csi/csi_plugin.go... +Hunk #1 succeeded at 347 (offset 2 lines). +Applied patch deps/github.com/openshift/kubernetes/pkg/volume/csi/csi_plugin.go cleanly. +Applying patch scripts/auto-rebase/rebase_patches/0002-disable-APIrequestcount-controller.patch +Checking patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/openshiftkubeapiserver/patch.go... +Hunk #2 succeeded at 33 (offset 1 line). +Hunk #3 succeeded at 86 (offset 2 lines). +Applied patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/openshiftkubeapiserver/patch.go cleanly. +Applying patch scripts/auto-rebase/rebase_patches/0003-disable-clusterQuotaMapping-controller.patch +Checking patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/openshiftkubeapiserver/patch.go... +Hunk #2 succeeded at 26 (offset 1 line). +Hunk #3 succeeded at 50 (offset 1 line). +Hunk #4 succeeded at 109 (offset 2 lines). +Hunk #5 succeeded at 127 (offset 2 lines). +Hunk #6 succeeded at 141 (offset 2 lines). +Hunk #7 succeeded at 157 (offset 2 lines). +Applied patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/openshiftkubeapiserver/patch.go cleanly. +Applying patch scripts/auto-rebase/rebase_patches/0004-remove-config-informer-and-cpu-partitioning-admission-plugin.patch +Checking patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/openshiftkubeapiserver/patch.go... +Checking patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/admission/admissionenablement/register.go... +Applied patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/openshiftkubeapiserver/patch.go cleanly. +Applied patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/admission/admissionenablement/register.go cleanly. +Applying patch scripts/auto-rebase/rebase_patches/0005-remove-user-informer.patch +Checking patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/openshiftkubeapiserver/patch.go... +Applied patch deps/github.com/openshift/kubernetes/openshift-kube-apiserver/openshiftkubeapiserver/patch.go cleanly. +Applying patch scripts/auto-rebase/rebase_patches/0006-kcm-no-panic.patch +Checking patch deps/github.com/openshift/kubernetes/cmd/kube-controller-manager/app/options/options.go... +Applied patch deps/github.com/openshift/kubernetes/cmd/kube-controller-manager/app/options/options.go cleanly. +Applying patch scripts/auto-rebase/rebase_patches/0020-klog-component-names.patch +Checking patch deps/k8s.io/klog/goroutine_labels.go... +Checking patch deps/k8s.io/klog/internal/buffer/buffer.go... +Hunk #1 succeeded at 144 (offset -5 lines). +Checking patch deps/k8s.io/klog/internal/buffer/goroutine_labels.go... +Applied patch deps/k8s.io/klog/goroutine_labels.go cleanly. +Applied patch deps/k8s.io/klog/internal/buffer/buffer.go cleanly. +Applied patch deps/k8s.io/klog/internal/buffer/goroutine_labels.go cleanly. +Applying patch scripts/auto-rebase/rebase_patches/0030-kube-controller-manager-command-context.patch +Checking patch deps/github.com/openshift/kubernetes/cmd/kube-controller-manager/app/controllermanager.go... +Applied patch deps/github.com/openshift/kubernetes/cmd/kube-controller-manager/app/controllermanager.go cleanly. +# Updating etcd/go.mod +go mod edit -require github.com/openshift/cluster-policy-controller@ef703966fe6e82f5f255b06bc5c758f105bf8b28 +go: downloading github.com/openshift/etcd/api/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 +go: downloading github.com/openshift/etcd/server/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 +go: downloading k8s.io/klog/v2 v2.130.1 +go: downloading google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 +go: downloading github.com/grpc-ecosystem/grpc-gateway v1.16.0 +go: downloading github.com/openshift/etcd/client/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 +go: downloading github.com/openshift/etcd/client/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 +go: downloading github.com/openshift/etcd/pkg/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 +go: downloading github.com/openshift/etcd/raft/v3 v3.5.1-0.20251001062325-e2b3dfdf0379 +go: downloading github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 +go: downloading github.com/golang-jwt/jwt/v4 v4.5.2 +go: downloading go.etcd.io/etcd/client/v2 v2.305.21 +go: downloading github.com/cockroachdb/datadriven v1.0.2 +skipping modulepath github.com/openshift/microshift: no or unknown command [] +skipping modulepath github.com/openshift/microshift/pkg/config: no or unknown command [] +skipping modulepath github.com/openshift/microshift/pkg/util/cryptomaterial: no or unknown command [] +go mod edit -replace github.com/onsi/ginkgo/v2=github.com/openshift/onsi-ginkgo/v2@v2.6.1-0.20251001123353-fd5b1fb35db1 +go mod edit -replace go.etcd.io/etcd/api/v3=github.com/openshift/etcd/api/v3@e2b3dfdf037938f7f0c489438eaa1138fd3fadba +go mod edit -replace go.etcd.io/etcd/client/pkg/v3=github.com/openshift/etcd/client/pkg/v3@v3.5.1-0.20251001062325-e2b3dfdf0379 +go mod edit -replace go.etcd.io/etcd/client/v3=github.com/openshift/etcd/client/v3@v3.5.1-0.20251001062325-e2b3dfdf0379 +go mod edit -replace go.etcd.io/etcd/pkg/v3=github.com/openshift/etcd/pkg/v3@v3.5.1-0.20251001062325-e2b3dfdf0379 +go mod edit -replace go.etcd.io/etcd/raft/v3=github.com/openshift/etcd/raft/v3@v3.5.1-0.20251001062325-e2b3dfdf0379 +go mod edit -replace go.etcd.io/etcd/server/v3=github.com/openshift/etcd/server/v3@v3.5.1-0.20251001062325-e2b3dfdf0379 +skipping modulepath k8s.io/api: no or unknown command [] +skipping modulepath k8s.io/apiextensions-apiserver: no or unknown command [] +skipping modulepath k8s.io/apimachinery: no or unknown command [] +skipping modulepath k8s.io/apiserver: no or unknown command [] +skipping modulepath k8s.io/cli-runtime: no or unknown command [] +skipping modulepath k8s.io/client-go: no or unknown command [] +skipping modulepath k8s.io/cloud-provider: no or unknown command [] +skipping modulepath k8s.io/cluster-bootstrap: no or unknown command [] +skipping modulepath k8s.io/code-generator: no or unknown command [] +skipping modulepath k8s.io/component-base: no or unknown command [] +skipping modulepath k8s.io/component-helpers: no or unknown command [] +skipping modulepath k8s.io/controller-manager: no or unknown command [] +skipping modulepath k8s.io/cri-api: no or unknown command [] +skipping modulepath k8s.io/cri-client: no or unknown command [] +skipping modulepath k8s.io/csi-translation-lib: no or unknown command [] +skipping modulepath k8s.io/dynamic-resource-allocation: no or unknown command [] +skipping modulepath k8s.io/endpointslice: no or unknown command [] +skipping modulepath k8s.io/externaljwt: no or unknown command [] +skipping modulepath k8s.io/kms: no or unknown command [] +skipping modulepath k8s.io/kube-aggregator: no or unknown command [] +skipping modulepath k8s.io/kube-controller-manager: no or unknown command [] +skipping modulepath k8s.io/kube-proxy: no or unknown command [] +skipping modulepath k8s.io/kube-scheduler: no or unknown command [] +skipping modulepath k8s.io/kubectl: no or unknown command [] +skipping modulepath k8s.io/kubelet: no or unknown command [] +skipping modulepath k8s.io/legacy-cloud-providers: no or unknown command [] +skipping modulepath k8s.io/metrics: no or unknown command [] +skipping modulepath k8s.io/mount-utils: no or unknown command [] +skipping modulepath k8s.io/pod-security-admission: no or unknown command [] +skipping modulepath k8s.io/sample-apiserver: no or unknown command [] +skipping modulepath k8s.io/sample-cli-plugin: no or unknown command [] +skipping modulepath k8s.io/sample-controller: no or unknown command [] +go mod edit -require github.com/openshift/route-controller-manager@c337cf413bbbfc2154dc1d3c1bf8007ea1edfbc8 +go mod edit -require github.com/openshift/cluster-policy-controller@ef703966fe6e82f5f255b06bc5c758f105bf8b28 +## Committing changes to microshift/go.mod +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 53ecde04e] update microshift/go.mod + 2 files changed, 3 insertions(+), 66 deletions(-) +## Updating deps/ directory +## Commiting changes to microshift/deps directory +warning: in the working copy of 'deps/github.com/openshift/kubernetes/vendor/github.com/MakeNowJust/heredoc/README.md', CRLF will be replaced by LF the next time Git touches it +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 c5799d054] update microshift/deps + 4 files changed, 11 insertions(+), 12 deletions(-) +## Updating microshift/vendor directory +/go/src/github.com/openshift/microshift /go/src/github.com/openshift/microshift +go mod vendor +/go/src/github.com/openshift/microshift +## Commiting changes to microshift/vendor directory +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 472937960] update microshift/vendor + 4 files changed, 8 insertions(+), 29 deletions(-) +Ensuring gofmt +Running `gofmt -s -l -w` on 853 file(s). +./deps/github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery/third_party/forked/golang/json/fields.go +./deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/third_party/forked/golang/template/exec.go +./deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go/third_party/forked/golang/template/funcs.go +./deps/github.com/openshift/kubernetes/staging/src/k8s.io/code-generator/third_party/forked/golang/reflect/type.go +## Commiting gofmt changes to deps directory +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 02821965b] update deps gofmt + 4 files changed, 12 insertions(+), 11 deletions(-) +## Committing changes to etcd/go.mod +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 b4913d986] update etcd/go.mod + 2 files changed, 6 insertions(+), 75 deletions(-) +## Updating deps/ directory +## Updating etcd/vendor directory +/go/src/github.com/openshift/microshift/etcd /go/src/github.com/openshift/microshift +go mod vendor +/go/src/github.com/openshift/microshift +## Commiting changes to etcd/vendor directory +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 fb3d80983] update etcd/vendor + 1 file changed, 26 deletions(-) +Ensuring gofmt +Running `gofmt -s -l -w` on 853 file(s). +Rebasing release_*.json +## Committing changes to pkg/release +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 a98b29d30] update component images + 2 files changed, 2 insertions(+), 2 deletions(-) +Copying manifests +2025-10-23 04:18:02,339 INFO Clearing directory assets/components/openshift-dns/dns/ +2025-10-23 04:18:02,340 DEBUG Copying assets/components/openshift-dns/dns/cluster-role-binding.yaml <- _output/staging/cluster-dns-operator/pkg/manifests/assets/dns/cluster-role-binding.yaml +2025-10-23 04:18:02,341 DEBUG Copying assets/components/openshift-dns/dns/cluster-role.yaml <- _output/staging/cluster-dns-operator/pkg/manifests/assets/dns/cluster-role.yaml +2025-10-23 04:18:02,341 INFO Restoring assets/components/openshift-dns/dns/configmap.yaml +2025-10-23 04:18:02,341 DEBUG Executing 'git restore assets/components/openshift-dns/dns/configmap.yaml' +2025-10-23 04:18:02,385 DEBUG Copying assets/components/openshift-dns/dns/daemonset.yaml <- _output/staging/cluster-dns-operator/pkg/manifests/assets/dns/daemonset.yaml +2025-10-23 04:18:02,386 DEBUG Copying assets/components/openshift-dns/dns/namespace.yaml <- _output/staging/cluster-dns-operator/pkg/manifests/assets/dns/namespace.yaml +2025-10-23 04:18:02,387 DEBUG Copying assets/components/openshift-dns/dns/service-account.yaml <- _output/staging/cluster-dns-operator/pkg/manifests/assets/dns/service-account.yaml +2025-10-23 04:18:02,388 DEBUG Copying assets/components/openshift-dns/dns/service.yaml <- _output/staging/cluster-dns-operator/pkg/manifests/assets/dns/service.yaml +2025-10-23 04:18:02,388 INFO Clearing directory assets/components/openshift-dns/node-resolver +2025-10-23 04:18:02,389 WARNING Ignoring components/openshift-dns/node-resolver/daemonset.yaml because it's created by processing daemonset.yaml.tmpl +2025-10-23 04:18:02,389 INFO Restoring assets/components/openshift-dns/node-resolver/daemonset.yaml.tmpl +2025-10-23 04:18:02,389 DEBUG Executing 'git restore assets/components/openshift-dns/node-resolver/daemonset.yaml.tmpl' +2025-10-23 04:18:02,429 DEBUG Copying assets/components/openshift-dns/node-resolver/service-account.yaml <- _output/staging/cluster-dns-operator/pkg/manifests/assets/node-resolver/service-account.yaml +2025-10-23 04:18:02,430 DEBUG Copying assets/components/openshift-dns/node-resolver/update-node-resolver.sh <- _output/staging/cluster-dns-operator/pkg/manifests/assets/node-resolver/update-node-resolver.sh +2025-10-23 04:18:02,431 INFO Clearing directory assets/components/openshift-router/ +2025-10-23 04:18:02,432 DEBUG Copying assets/components/openshift-router/cluster-role-binding.yaml <- _output/staging/cluster-ingress-operator/pkg/manifests/assets/router/cluster-role-binding.yaml +2025-10-23 04:18:02,433 DEBUG Copying assets/components/openshift-router/cluster-role.yaml <- _output/staging/cluster-ingress-operator/pkg/manifests/assets/router/cluster-role.yaml +2025-10-23 04:18:02,434 INFO Restoring assets/components/openshift-router/cluster-role-system-router.yaml +2025-10-23 04:18:02,434 DEBUG Executing 'git restore assets/components/openshift-router/cluster-role-system-router.yaml' +2025-10-23 04:18:02,474 INFO Restoring assets/components/openshift-router/configmap.yaml +2025-10-23 04:18:02,474 DEBUG Executing 'git restore assets/components/openshift-router/configmap.yaml' +2025-10-23 04:18:02,514 INFO Restoring assets/components/openshift-router/configmap-accesslog.yaml +2025-10-23 04:18:02,515 DEBUG Executing 'git restore assets/components/openshift-router/configmap-accesslog.yaml' +2025-10-23 04:18:02,555 DEBUG Copying assets/components/openshift-router/deployment.yaml <- _output/staging/cluster-ingress-operator/pkg/manifests/assets/router/deployment.yaml +2025-10-23 04:18:02,556 DEBUG Copying assets/components/openshift-router/namespace.yaml <- _output/staging/cluster-ingress-operator/pkg/manifests/assets/router/namespace.yaml +2025-10-23 04:18:02,557 DEBUG Copying assets/components/openshift-router/service-account.yaml <- _output/staging/cluster-ingress-operator/pkg/manifests/assets/router/service-account.yaml +2025-10-23 04:18:02,558 DEBUG Copying assets/components/openshift-router/service-internal.yaml <- _output/staging/cluster-ingress-operator/pkg/manifests/assets/router/service-internal.yaml +2025-10-23 04:18:02,559 DEBUG Copying assets/components/openshift-router/service-cloud.yaml <- _output/staging/cluster-ingress-operator/pkg/manifests/assets/router/service-cloud.yaml +2025-10-23 04:18:02,560 INFO Restoring assets/components/openshift-router/serving-certificate.yaml +2025-10-23 04:18:02,560 DEBUG Executing 'git restore assets/components/openshift-router/serving-certificate.yaml' +2025-10-23 04:18:02,600 INFO Restoring assets/components/openshift-router/cluster-role-aggregate-edit-route.yaml +2025-10-23 04:18:02,600 DEBUG Executing 'git restore assets/components/openshift-router/cluster-role-aggregate-edit-route.yaml' +2025-10-23 04:18:02,642 INFO Restoring assets/components/openshift-router/cluster-role-aggregate-admin-route.yaml +2025-10-23 04:18:02,642 DEBUG Executing 'git restore assets/components/openshift-router/cluster-role-aggregate-admin-route.yaml' +2025-10-23 04:18:02,683 WARNING Ignoring components/openshift-router/ingress-class.yaml because gets generated during image rebase +2025-10-23 04:18:02,683 WARNING Ignoring components/ovn/ because it's not covered by rebase script yet +2025-10-23 04:18:02,683 INFO Clearing directory assets/components/service-ca/ +2025-10-23 04:18:02,684 DEBUG Copying assets/components/service-ca/clusterrole.yaml <- _output/staging/service-ca-operator/bindata/v4.0.0/controller/clusterrole.yaml +2025-10-23 04:18:02,684 DEBUG Copying assets/components/service-ca/clusterrolebinding.yaml <- _output/staging/service-ca-operator/bindata/v4.0.0/controller/clusterrolebinding.yaml +2025-10-23 04:18:02,685 DEBUG Copying assets/components/service-ca/deployment.yaml <- _output/staging/service-ca-operator/bindata/v4.0.0/controller/deployment.yaml +2025-10-23 04:18:02,685 DEBUG Copying assets/components/service-ca/ns.yaml <- _output/staging/service-ca-operator/bindata/v4.0.0/controller/ns.yaml +2025-10-23 04:18:02,685 DEBUG Copying assets/components/service-ca/role.yaml <- _output/staging/service-ca-operator/bindata/v4.0.0/controller/role.yaml +2025-10-23 04:18:02,685 DEBUG Copying assets/components/service-ca/rolebinding.yaml <- _output/staging/service-ca-operator/bindata/v4.0.0/controller/rolebinding.yaml +2025-10-23 04:18:02,685 DEBUG Copying assets/components/service-ca/sa.yaml <- _output/staging/service-ca-operator/bindata/v4.0.0/controller/sa.yaml +2025-10-23 04:18:02,685 DEBUG Copying assets/components/service-ca/signing-cabundle.yaml <- _output/staging/service-ca-operator/bindata/v4.0.0/controller/signing-cabundle.yaml +2025-10-23 04:18:02,686 DEBUG Copying assets/components/service-ca/signing-secret.yaml <- _output/staging/service-ca-operator/bindata/v4.0.0/controller/signing-secret.yaml +2025-10-23 04:18:02,686 INFO Not clearing dir components/csi-snapshot-controller/ +2025-10-23 04:18:02,686 DEBUG Copying assets/components/csi-snapshot-controller/csi_controller_deployment.yaml <- _output/staging/cluster-csi-snapshot-controller-operator/assets/csi_controller_deployment.yaml +2025-10-23 04:18:02,687 DEBUG Copying assets/components/csi-snapshot-controller/serviceaccount.yaml <- _output/staging/cluster-csi-snapshot-controller-operator/assets/serviceaccount.yaml +2025-10-23 04:18:02,688 DEBUG Copying assets/components/csi-snapshot-controller/volumesnapshotclasses.yaml <- _output/staging/cluster-csi-snapshot-controller-operator/assets/volumesnapshotclasses.yaml +2025-10-23 04:18:02,689 DEBUG Copying assets/components/csi-snapshot-controller/volumesnapshotcontents.yaml <- _output/staging/cluster-csi-snapshot-controller-operator/assets/volumesnapshotcontents.yaml +2025-10-23 04:18:02,690 DEBUG Copying assets/components/csi-snapshot-controller/volumesnapshots.yaml <- _output/staging/cluster-csi-snapshot-controller-operator/assets/volumesnapshots.yaml +2025-10-23 04:18:02,691 DEBUG Copying assets/components/csi-snapshot-controller/05_operand_rbac.yaml <- _output/staging/cluster-csi-snapshot-controller-operator/assets/../manifests/05_operand_rbac.yaml +2025-10-23 04:18:02,692 WARNING Ignoring components/csi-snapshot-controller/clusterrole.yaml because extracted automatically from 05_operand_rbac.yaml +2025-10-23 04:18:02,692 WARNING Ignoring components/csi-snapshot-controller/clusterrolebinding.yaml because extracted automatically from 05_operand_rbac.yaml +2025-10-23 04:18:02,692 INFO Clearing directory assets/controllers/cluster-policy-controller/ +2025-10-23 04:18:02,693 DEBUG Copying assets/controllers/cluster-policy-controller/namespace-security-allocation-controller-clusterrole.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/namespace-security-allocation-controller-clusterrole.yaml +2025-10-23 04:18:02,693 DEBUG Copying assets/controllers/cluster-policy-controller/namespace-security-allocation-controller-clusterrolebinding.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/namespace-security-allocation-controller-clusterrolebinding.yaml +2025-10-23 04:18:02,694 DEBUG Copying assets/controllers/cluster-policy-controller/podsecurity-admission-label-syncer-controller-clusterrole.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/podsecurity-admission-label-syncer-controller-clusterrole.yaml +2025-10-23 04:18:02,695 DEBUG Copying assets/controllers/cluster-policy-controller/podsecurity-admission-label-syncer-controller-clusterrolebinding.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/podsecurity-admission-label-syncer-controller-clusterrolebinding.yaml +2025-10-23 04:18:02,696 DEBUG Copying assets/controllers/cluster-policy-controller/podsecurity-admission-label-privileged-namespaces-syncer-controller-clusterrole.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/podsecurity-admission-label-privileged-namespaces-syncer-controller-clusterrole.yaml +2025-10-23 04:18:02,697 DEBUG Copying assets/controllers/cluster-policy-controller/podsecurity-admission-label-privileged-namespaces-syncer-controller-clusterrolebinding.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/podsecurity-admission-label-privileged-namespaces-syncer-controller-clusterrolebinding.yaml +2025-10-23 04:18:02,698 INFO Clearing directory assets/controllers/kube-apiserver/ +2025-10-23 04:18:02,698 DEBUG Copying assets/controllers/kube-apiserver/config-overrides.yaml <- _output/staging/cluster-kube-apiserver-operator/bindata/assets/config/config-overrides.yaml +2025-10-23 04:18:02,698 DEBUG Copying assets/controllers/kube-apiserver/defaultconfig.yaml <- _output/staging/cluster-kube-apiserver-operator/bindata/assets/config/defaultconfig.yaml +2025-10-23 04:18:02,698 INFO Clearing directory assets/controllers/kube-controller-manager/ +2025-10-23 04:18:02,699 DEBUG Copying assets/controllers/kube-controller-manager/defaultconfig.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/../config/defaultconfig.yaml +2025-10-23 04:18:02,700 DEBUG Copying assets/controllers/kube-controller-manager/csr_approver_clusterrole.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/csr_approver_clusterrole.yaml +2025-10-23 04:18:02,700 DEBUG Copying assets/controllers/kube-controller-manager/csr_approver_clusterrolebinding.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/csr_approver_clusterrolebinding.yaml +2025-10-23 04:18:02,701 DEBUG Copying assets/controllers/kube-controller-manager/namespace-openshift-kube-controller-manager.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/ns.yaml +2025-10-23 04:18:02,702 INFO Clearing directory assets/controllers/openshift-default-scc-manager/ +2025-10-23 04:18:02,703 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-anyuid.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-anyuid.yaml +2025-10-23 04:18:02,704 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-hostaccess.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-hostaccess.yaml +2025-10-23 04:18:02,705 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-hostmount-anyuid.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-hostmount-anyuid.yaml +2025-10-23 04:18:02,706 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-hostnetwork-v2.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-hostnetwork-v2.yaml +2025-10-23 04:18:02,707 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-hostnetwork.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-hostnetwork.yaml +2025-10-23 04:18:02,707 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-nonroot-v2.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-nonroot-v2.yaml +2025-10-23 04:18:02,708 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-nonroot.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-nonroot.yaml +2025-10-23 04:18:02,709 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-privileged.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-privileged.yaml +2025-10-23 04:18:02,710 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-restricted-v2.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-restricted-v2.yaml +2025-10-23 04:18:02,711 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_cr-scc-restricted.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_cr-scc-restricted.yaml +2025-10-23 04:18:02,712 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v2.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v2.yaml +2025-10-23 04:18:02,712 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-anyuid.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-anyuid.yaml +2025-10-23 04:18:02,713 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-hostaccess.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-hostaccess.yaml +2025-10-23 04:18:02,714 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-hostmount-anyuid.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-hostmount-anyuid.yaml +2025-10-23 04:18:02,714 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-hostnetwork-v2.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-hostnetwork-v2.yaml +2025-10-23 04:18:02,715 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-hostnetwork.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-hostnetwork.yaml +2025-10-23 04:18:02,716 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-nonroot-v2.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-nonroot-v2.yaml +2025-10-23 04:18:02,716 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-nonroot.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-nonroot.yaml +2025-10-23 04:18:02,717 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-privileged.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-privileged.yaml +2025-10-23 04:18:02,718 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-restricted-v2.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-restricted-v2.yaml +2025-10-23 04:18:02,719 DEBUG Copying assets/controllers/openshift-default-scc-manager/0000_20_kube-apiserver-operator_00_scc-restricted.yaml <- _output/staging/release-manifests/0000_20_kube-apiserver-operator_00_scc-restricted.yaml +2025-10-23 04:18:02,719 INFO Clearing directory assets/controllers/route-controller-manager/ +2025-10-23 04:18:02,720 DEBUG Copying assets/controllers/route-controller-manager/ns.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/ns.yaml +2025-10-23 04:18:02,720 DEBUG Copying assets/controllers/route-controller-manager/sa.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/sa.yaml +2025-10-23 04:18:02,721 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-clusterrole.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-clusterrole.yaml +2025-10-23 04:18:02,721 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-clusterrolebinding.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-clusterrolebinding.yaml +2025-10-23 04:18:02,721 DEBUG Copying assets/controllers/route-controller-manager/informer-clusterrolebinding.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/informer-clusterrolebinding.yaml +2025-10-23 04:18:02,721 DEBUG Copying assets/controllers/route-controller-manager/informer-clusterrole.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/informer-clusterrole.yaml +2025-10-23 04:18:02,721 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-ingress-to-route-controller-clusterrolebinding.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-ingress-to-route-controller-clusterrolebinding.yaml +2025-10-23 04:18:02,721 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-ingress-to-route-controller-clusterrole.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-ingress-to-route-controller-clusterrole.yaml +2025-10-23 04:18:02,722 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-ns.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-ns.yaml +2025-10-23 04:18:02,722 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-sa.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-sa.yaml +2025-10-23 04:18:02,722 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-separate-sa-rolebinding.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-separate-sa-rolebinding.yaml +2025-10-23 04:18:02,722 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-separate-sa-role.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-separate-sa-role.yaml +2025-10-23 04:18:02,722 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-tokenreview-clusterrolebinding.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-tokenreview-clusterrolebinding.yaml +2025-10-23 04:18:02,722 DEBUG Copying assets/controllers/route-controller-manager/route-controller-manager-tokenreview-clusterrole.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/route-controller-manager-tokenreview-clusterrole.yaml +2025-10-23 04:18:02,723 INFO Restoring assets/controllers/route-controller-manager/route-controller-manager-authentication-reader-rolebinding.yaml +2025-10-23 04:18:02,723 DEBUG Executing 'git restore assets/controllers/route-controller-manager/route-controller-manager-authentication-reader-rolebinding.yaml' +2025-10-23 04:18:02,764 INFO Not clearing dir core/ +2025-10-23 04:18:02,764 DEBUG Copying assets/core/0000_50_cluster-openshift-controller-manager_00_namespace.yaml <- _output/staging/cluster-openshift-controller-manager-operator/bindata/assets/openshift-controller-manager/ns.yaml +2025-10-23 04:18:02,764 DEBUG Copying assets/core/namespace-openshift-infra.yaml <- _output/staging/cluster-kube-controller-manager-operator/bindata/assets/kube-controller-manager/namespace-openshift-infra.yaml +2025-10-23 04:18:02,765 WARNING Ignoring core/priority-class-openshift-user-critical.yaml because it's a priority class needed for oc debug node command - not available in any repo that rebase is using +2025-10-23 04:18:02,765 WARNING Ignoring core/securityv1-local-apiservice.yaml because it's a local API service for security API group, needed if OpenShift API server is not present +2025-10-23 04:18:02,765 DEBUG Copying assets/core/kubelet.yaml <- _output/staging/machine-config-operator/templates/master/01-master-kubelet/_base/files/kubelet.yaml +2025-10-23 04:18:02,766 WARNING Ignoring core/kubelet-client-ca.yaml because it's a template for ConfigMap processed during runtime +2025-10-23 04:18:02,766 INFO Clearing directory assets/crd/ +2025-10-23 04:18:02,766 DEBUG Copying assets/crd/0000_03_config-operator_01_securitycontextconstraints.crd.yaml <- _output/staging/release-manifests/0000_03_config-operator_01_securitycontextconstraints.crd.yaml +2025-10-23 04:18:02,767 DEBUG Copying assets/crd/0000_03_config-operator_02_rangeallocations.crd.yaml <- _output/staging/release-manifests/0000_03_config-operator_02_rangeallocations.crd.yaml +2025-10-23 04:18:02,768 DEBUG Copying assets/crd/storage_version_migration.crd.yaml <- _output/staging/release-manifests/0000_50_cluster-kube-storage-version-migrator-operator_01_storage_migration_crd.yaml +2025-10-23 04:18:02,769 DEBUG Copying assets/crd/route.crd.yaml <- _output/staging/api/route/v1/zz_generated.crd-manifests/routes.crd.yaml +2025-10-23 04:18:02,770 WARNING Ignoring release/ because it contains files generated during rebase procedure +2025-10-23 04:18:02,770 INFO Not clearing dir version/ +2025-10-23 04:18:02,771 WARNING Ignoring version/microshift-version.yaml because it's a template for ConfigMap processed during runtime +2025-10-23 04:18:02,771 WARNING Ignoring embed.go because it's a MicroShift specific Go file that embeds into a binary +2025-10-23 04:18:02,771 INFO Clearing directory assets/optional/operator-lifecycle-manager/ +2025-10-23 04:18:02,772 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-catalogsources.crd.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-catalogsources.crd.yaml +2025-10-23 04:18:02,772 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-clusterserviceversions.crd.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-clusterserviceversions.crd.yaml +2025-10-23 04:18:02,773 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-installplans.crd.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-installplans.crd.yaml +2025-10-23 04:18:02,773 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-namespace.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-namespace.yaml +2025-10-23 04:18:02,773 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-olmconfigs.crd.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-olmconfigs.crd.yaml +2025-10-23 04:18:02,773 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorconditions.crd.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-operatorconditions.crd.yaml +2025-10-23 04:18:02,774 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-operatorgroups.crd.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-operatorgroups.crd.yaml +2025-10-23 04:18:02,774 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-operators.crd.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-operators.crd.yaml +2025-10-23 04:18:02,774 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-packageserver.pdb.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-packageserver.pdb.yaml +2025-10-23 04:18:02,774 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-pprof-config.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-pprof-config.yaml +2025-10-23 04:18:02,774 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-pprof-rbac.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-pprof-rbac.yaml +2025-10-23 04:18:02,774 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-pprof-secret.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-pprof-secret.yaml +2025-10-23 04:18:02,775 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_00-subscriptions.crd.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_00-subscriptions.crd.yaml +2025-10-23 04:18:02,775 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_01-networkpolicies.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_01-networkpolicies.yaml +2025-10-23 04:18:02,775 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_02-olm-operator.serviceaccount.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_02-olm-operator.serviceaccount.yaml +2025-10-23 04:18:02,775 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_03-olmconfig.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_03-olmconfig.yaml +2025-10-23 04:18:02,776 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_03-services.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_03-services.yaml +2025-10-23 04:18:02,776 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_07-olm-operator.deployment.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_07-olm-operator.deployment.yaml +2025-10-23 04:18:02,776 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_08-catalog-operator.deployment.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_08-catalog-operator.deployment.yaml +2025-10-23 04:18:02,776 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_09-aggregated.clusterrole.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_09-aggregated.clusterrole.yaml +2025-10-23 04:18:02,776 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_13-operatorgroup-default.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_13-operatorgroup-default.yaml +2025-10-23 04:18:02,776 DEBUG Copying assets/optional/operator-lifecycle-manager/0000_50_olm_15-csv-viewer.rbac.yaml <- _output/staging/operator-framework-olm/microshift-manifests/0000_50_olm_15-csv-viewer.rbac.yaml +2025-10-23 04:18:02,777 DEBUG Copying assets/optional/operator-lifecycle-manager/image-references <- _output/staging/operator-framework-olm/microshift-manifests/image-references +2025-10-23 04:18:02,777 DEBUG Copying assets/optional/operator-lifecycle-manager/kustomization.yaml <- _output/staging/operator-framework-olm/microshift-manifests/kustomization.yaml +2025-10-23 04:18:02,777 WARNING Ignoring optional/operator-lifecycle-manager/kustomization.x86_64.yaml because gets generated during image rebase +2025-10-23 04:18:02,777 WARNING Ignoring optional/operator-lifecycle-manager/kustomization.aarch64.yaml because gets generated during image rebase +2025-10-23 04:18:02,777 WARNING Ignoring optional/operator-lifecycle-manager/release-olm-aarch64.json because gets generated during image rebase +2025-10-23 04:18:02,777 WARNING Ignoring optional/operator-lifecycle-manager/release-olm-x86_64.json because gets generated during image rebase +2025-10-23 04:18:02,777 WARNING Ignoring components/multus/ because they don't exist in upstream repository - only in microshift +2025-10-23 04:18:02,777 WARNING Ignoring optional/observability/ because they don't exist in upstream repository - only in microshift +Modifying OpenShift manifests +/go/src/github.com/openshift/microshift /go/src/github.com/openshift/microshift/_output/staging /go/src/github.com/openshift/microshift +Checking patch /go/src/github.com/openshift/microshift/scripts/auto-rebase/manifests_patches/010-ingress-deployment-clientCA.patch +/go/src/github.com/openshift/microshift/scripts/auto-rebase/manifests_patches/010-ingress-deployment-clientCA.patch - Patch applied +Checking patch /go/src/github.com/openshift/microshift/scripts/auto-rebase/manifests_patches/011-ingress-deployment-access-logging.patch +/go/src/github.com/openshift/microshift/scripts/auto-rebase/manifests_patches/011-ingress-deployment-access-logging.patch - Patch applied +Checking patch /go/src/github.com/openshift/microshift/scripts/auto-rebase/manifests_patches/012-ingress-class.patch +/go/src/github.com/openshift/microshift/scripts/auto-rebase/manifests_patches/012-ingress-class.patch - Patch applied +/go/src/github.com/openshift/microshift/_output/staging /go/src/github.com/openshift/microshift +Rebasing operator-lifecycle-manager manifests +Rebasing Multus images +## Committing changes to assets and pkg/assets +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 a4b9f77c5] update manifests + 11 files changed, 49 insertions(+), 47 deletions(-) +Rebasing Makefile +## Committing changes to buildfiles +[rebase-release-4.21-4.21.0-0.nightly-2025-10-22-123727_amd64-2025-10-22_arm64-2025-10-22 bbc290cbe] update buildfiles + 2 files changed, 2 insertions(+), 2 deletions(-) +# Removing staging directory +================================================== +rebase_ai_model_serving.sh: +Rebasing AI Model Serving for MicroShift to registry.redhat.io/rhoai/odh-operator-bundle:v2.22 +Fetching RHOAI CSV +Fetching RHOAI manifests +Updating last_rebase_ai_model_serving.sh +Updating rebase_job_entrypoint.sh +Copying manifests from staging dir to assets/ +2025-10-23 04:18:23,086 INFO Not clearing dir optional/ai-model-serving/ +2025-10-23 04:18:23,086 WARNING Ignoring optional/ai-model-serving/release-ai-model-serving-x86_64.json because Release info file +2025-10-23 04:18:23,086 INFO Not clearing dir optional/ai-model-serving/kserve/ +2025-10-23 04:18:23,086 WARNING Ignoring optional/ai-model-serving/kserve/kustomization.yaml because MicroShift specific overrides +2025-10-23 04:18:23,086 WARNING Ignoring optional/ai-model-serving/kserve/inferenceservice-config-microshift-patch.yaml because MicroShift specific overrides +2025-10-23 04:18:23,086 WARNING Ignoring optional/ai-model-serving/kserve/namespace.yaml because MicroShift specific overrides +2025-10-23 04:18:23,086 INFO Clearing directory assets/optional/ai-model-serving/kserve/overlays/odh/ +2025-10-23 04:18:23,087 DEBUG Copying assets/optional/ai-model-serving/kserve/overlays/odh/inferenceservice-config-patch.yaml <- _output/staging/rhoai/operator/kserve/overlays/odh/inferenceservice-config-patch.yaml +2025-10-23 04:18:23,087 DEBUG Copying assets/optional/ai-model-serving/kserve/overlays/odh/kustomization.yaml <- _output/staging/rhoai/operator/kserve/overlays/odh/kustomization.yaml +2025-10-23 04:18:23,087 DEBUG Copying assets/optional/ai-model-serving/kserve/overlays/odh/params.env <- _output/staging/rhoai/operator/kserve/overlays/odh/params.env +2025-10-23 04:18:23,087 DEBUG Copying assets/optional/ai-model-serving/kserve/overlays/odh/params.yaml <- _output/staging/rhoai/operator/kserve/overlays/odh/params.yaml +2025-10-23 04:18:23,087 DEBUG Copying assets/optional/ai-model-serving/kserve/overlays/odh/remove-namespace.yaml <- _output/staging/rhoai/operator/kserve/overlays/odh/remove-namespace.yaml +2025-10-23 04:18:23,088 DEBUG Copying assets/optional/ai-model-serving/kserve/overlays/odh/set-resources-manager-patch.yaml <- _output/staging/rhoai/operator/kserve/overlays/odh/set-resources-manager-patch.yaml +2025-10-23 04:18:23,088 DEBUG Copying assets/optional/ai-model-serving/kserve/overlays/odh/user-cluster-roles.yaml <- _output/staging/rhoai/operator/kserve/overlays/odh/user-cluster-roles.yaml +2025-10-23 04:18:23,088 INFO Clearing directory assets/optional/ai-model-serving/kserve/default/ +2025-10-23 04:18:23,089 DEBUG Copying assets/optional/ai-model-serving/kserve/default/cainjection_conversion_webhook.yaml <- _output/staging/rhoai/operator/kserve/default/cainjection_conversion_webhook.yaml +2025-10-23 04:18:23,089 DEBUG Copying assets/optional/ai-model-serving/kserve/default/clusterservingruntime_validatingwebhook_cainjection_patch.yaml <- _output/staging/rhoai/operator/kserve/default/clusterservingruntime_validatingwebhook_cainjection_patch.yaml +2025-10-23 04:18:23,089 DEBUG Copying assets/optional/ai-model-serving/kserve/default/inferencegraph_validatingwebhook_cainjection_patch.yaml <- _output/staging/rhoai/operator/kserve/default/inferencegraph_validatingwebhook_cainjection_patch.yaml +2025-10-23 04:18:23,089 DEBUG Copying assets/optional/ai-model-serving/kserve/default/isvc_mutatingwebhook_cainjection_patch.yaml <- _output/staging/rhoai/operator/kserve/default/isvc_mutatingwebhook_cainjection_patch.yaml +2025-10-23 04:18:23,089 DEBUG Copying assets/optional/ai-model-serving/kserve/default/isvc_validatingwebhook_cainjection_patch.yaml <- _output/staging/rhoai/operator/kserve/default/isvc_validatingwebhook_cainjection_patch.yaml +2025-10-23 04:18:23,090 DEBUG Copying assets/optional/ai-model-serving/kserve/default/kustomization.yaml <- _output/staging/rhoai/operator/kserve/default/kustomization.yaml +2025-10-23 04:18:23,090 DEBUG Copying assets/optional/ai-model-serving/kserve/default/localmodel_manager_image_patch.yaml <- _output/staging/rhoai/operator/kserve/default/localmodel_manager_image_patch.yaml +2025-10-23 04:18:23,090 DEBUG Copying assets/optional/ai-model-serving/kserve/default/manager_auth_proxy_patch.yaml <- _output/staging/rhoai/operator/kserve/default/manager_auth_proxy_patch.yaml +2025-10-23 04:18:23,090 DEBUG Copying assets/optional/ai-model-serving/kserve/default/manager_image_patch.yaml <- _output/staging/rhoai/operator/kserve/default/manager_image_patch.yaml +2025-10-23 04:18:23,090 DEBUG Copying assets/optional/ai-model-serving/kserve/default/manager_prometheus_metrics_patch.yaml <- _output/staging/rhoai/operator/kserve/default/manager_prometheus_metrics_patch.yaml +2025-10-23 04:18:23,091 DEBUG Copying assets/optional/ai-model-serving/kserve/default/manager_resources_patch.yaml <- _output/staging/rhoai/operator/kserve/default/manager_resources_patch.yaml +2025-10-23 04:18:23,091 DEBUG Copying assets/optional/ai-model-serving/kserve/default/network-policies.yaml <- _output/staging/rhoai/operator/kserve/default/network-policies.yaml +2025-10-23 04:18:23,091 DEBUG Copying assets/optional/ai-model-serving/kserve/default/servingruntime_validationwebhook_cainjection_patch.yaml <- _output/staging/rhoai/operator/kserve/default/servingruntime_validationwebhook_cainjection_patch.yaml +2025-10-23 04:18:23,091 DEBUG Copying assets/optional/ai-model-serving/kserve/default/svc_webhook_cainjection_patch.yaml <- _output/staging/rhoai/operator/kserve/default/svc_webhook_cainjection_patch.yaml +2025-10-23 04:18:23,091 DEBUG Copying assets/optional/ai-model-serving/kserve/default/trainedmodel_validatingwebhook_cainjection_patch.yaml <- _output/staging/rhoai/operator/kserve/default/trainedmodel_validatingwebhook_cainjection_patch.yaml +2025-10-23 04:18:23,091 INFO Clearing directory assets/optional/ai-model-serving/kserve/crd/ +2025-10-23 04:18:23,092 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/kustomization.yaml <- _output/staging/rhoai/operator/kserve/crd/kustomization.yaml +2025-10-23 04:18:23,093 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterlocalmodels.yaml <- _output/staging/rhoai/operator/kserve/crd/full/serving.kserve.io_clusterlocalmodels.yaml +2025-10-23 04:18:23,093 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterservingruntimes.yaml <- _output/staging/rhoai/operator/kserve/crd/full/serving.kserve.io_clusterservingruntimes.yaml +2025-10-23 04:18:23,093 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_clusterstoragecontainers.yaml <- _output/staging/rhoai/operator/kserve/crd/full/serving.kserve.io_clusterstoragecontainers.yaml +2025-10-23 04:18:23,093 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferencegraphs.yaml <- _output/staging/rhoai/operator/kserve/crd/full/serving.kserve.io_inferencegraphs.yaml +2025-10-23 04:18:23,093 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_inferenceservices.yaml <- _output/staging/rhoai/operator/kserve/crd/full/serving.kserve.io_inferenceservices.yaml +2025-10-23 04:18:23,094 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_localmodelnodegroups.yaml <- _output/staging/rhoai/operator/kserve/crd/full/serving.kserve.io_localmodelnodegroups.yaml +2025-10-23 04:18:23,094 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_servingruntimes.yaml <- _output/staging/rhoai/operator/kserve/crd/full/serving.kserve.io_servingruntimes.yaml +2025-10-23 04:18:23,095 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/full/serving.kserve.io_trainedmodels.yaml <- _output/staging/rhoai/operator/kserve/crd/full/serving.kserve.io_trainedmodels.yaml +2025-10-23 04:18:23,095 DEBUG Copying assets/optional/ai-model-serving/kserve/crd/patches/protocol.yaml <- _output/staging/rhoai/operator/kserve/crd/patches/protocol.yaml +2025-10-23 04:18:23,095 INFO Clearing directory assets/optional/ai-model-serving/kserve/configmap/ +2025-10-23 04:18:23,095 DEBUG Copying assets/optional/ai-model-serving/kserve/configmap/kustomization.yaml <- _output/staging/rhoai/operator/kserve/configmap/kustomization.yaml +2025-10-23 04:18:23,096 DEBUG Copying assets/optional/ai-model-serving/kserve/configmap/inferenceservice.yaml <- _output/staging/rhoai/operator/kserve/configmap/inferenceservice.yaml +2025-10-23 04:18:23,096 INFO Clearing directory assets/optional/ai-model-serving/kserve/rbac/ +2025-10-23 04:18:23,097 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/auth_proxy_role_binding.yaml <- _output/staging/rhoai/operator/kserve/rbac/auth_proxy_role_binding.yaml +2025-10-23 04:18:23,097 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/auth_proxy_role.yaml <- _output/staging/rhoai/operator/kserve/rbac/auth_proxy_role.yaml +2025-10-23 04:18:23,097 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/auth_proxy_service.yaml <- _output/staging/rhoai/operator/kserve/rbac/auth_proxy_service.yaml +2025-10-23 04:18:23,097 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/kustomization.yaml <- _output/staging/rhoai/operator/kserve/rbac/kustomization.yaml +2025-10-23 04:18:23,097 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/leader_election_role_binding.yaml <- _output/staging/rhoai/operator/kserve/rbac/leader_election_role_binding.yaml +2025-10-23 04:18:23,098 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/leader_election_role.yaml <- _output/staging/rhoai/operator/kserve/rbac/leader_election_role.yaml +2025-10-23 04:18:23,098 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/role_binding.yaml <- _output/staging/rhoai/operator/kserve/rbac/role_binding.yaml +2025-10-23 04:18:23,098 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/role.yaml <- _output/staging/rhoai/operator/kserve/rbac/role.yaml +2025-10-23 04:18:23,098 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/service_account.yaml <- _output/staging/rhoai/operator/kserve/rbac/service_account.yaml +2025-10-23 04:18:23,098 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/localmodel/role_binding.yaml <- _output/staging/rhoai/operator/kserve/rbac/localmodel/role_binding.yaml +2025-10-23 04:18:23,099 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/localmodel/role.yaml <- _output/staging/rhoai/operator/kserve/rbac/localmodel/role.yaml +2025-10-23 04:18:23,099 DEBUG Copying assets/optional/ai-model-serving/kserve/rbac/localmodel/service_account.yaml <- _output/staging/rhoai/operator/kserve/rbac/localmodel/service_account.yaml +2025-10-23 04:18:23,099 INFO Clearing directory assets/optional/ai-model-serving/kserve/manager/ +2025-10-23 04:18:23,099 DEBUG Copying assets/optional/ai-model-serving/kserve/manager/kustomization.yaml <- _output/staging/rhoai/operator/kserve/manager/kustomization.yaml +2025-10-23 04:18:23,100 DEBUG Copying assets/optional/ai-model-serving/kserve/manager/manager.yaml <- _output/staging/rhoai/operator/kserve/manager/manager.yaml +2025-10-23 04:18:23,100 DEBUG Copying assets/optional/ai-model-serving/kserve/manager/service.yaml <- _output/staging/rhoai/operator/kserve/manager/service.yaml +2025-10-23 04:18:23,100 INFO Clearing directory assets/optional/ai-model-serving/kserve/webhook/ +2025-10-23 04:18:23,100 DEBUG Copying assets/optional/ai-model-serving/kserve/webhook/kustomization.yaml <- _output/staging/rhoai/operator/kserve/webhook/kustomization.yaml +2025-10-23 04:18:23,100 DEBUG Copying assets/optional/ai-model-serving/kserve/webhook/manifests.yaml <- _output/staging/rhoai/operator/kserve/webhook/manifests.yaml +2025-10-23 04:18:23,101 DEBUG Copying assets/optional/ai-model-serving/kserve/webhook/service.yaml <- _output/staging/rhoai/operator/kserve/webhook/service.yaml +2025-10-23 04:18:23,101 INFO Clearing directory assets/optional/ai-model-serving/runtimes/ +2025-10-23 04:18:23,101 INFO Restoring assets/optional/ai-model-serving/runtimes/kustomization.yaml +2025-10-23 04:18:23,101 DEBUG Executing 'git restore assets/optional/ai-model-serving/runtimes/kustomization.yaml' +2025-10-23 04:18:23,140 WARNING Ignoring optional/ai-model-serving/runtimes/kustomization.x86_64.yaml because Generated during rebase +2025-10-23 04:18:23,140 DEBUG Copying assets/optional/ai-model-serving/runtimes/caikit-standalone.yaml <- _output/staging/rhoai/operator/modelcontroller/runtimes/caikit-standalone-template.yaml +2025-10-23 04:18:23,141 DEBUG Copying assets/optional/ai-model-serving/runtimes/caikit-tgis.yaml <- _output/staging/rhoai/operator/modelcontroller/runtimes/caikit-tgis-template.yaml +2025-10-23 04:18:23,141 DEBUG Copying assets/optional/ai-model-serving/runtimes/hf-detector.yaml <- _output/staging/rhoai/operator/modelcontroller/runtimes/hf-detector-template.yaml +2025-10-23 04:18:23,141 DEBUG Copying assets/optional/ai-model-serving/runtimes/ovms-kserve.yaml <- _output/staging/rhoai/operator/modelcontroller/runtimes/ovms-kserve-template.yaml +2025-10-23 04:18:23,141 DEBUG Copying assets/optional/ai-model-serving/runtimes/vllm-cuda.yaml <- _output/staging/rhoai/operator/modelcontroller/runtimes/vllm-cuda-template.yaml +2025-10-23 04:18:23,141 DEBUG Copying assets/optional/ai-model-serving/runtimes/vllm-gaudi.yaml <- _output/staging/rhoai/operator/modelcontroller/runtimes/vllm-gaudi-template.yaml +2025-10-23 04:18:23,141 DEBUG Copying assets/optional/ai-model-serving/runtimes/vllm-rocm.yaml <- _output/staging/rhoai/operator/modelcontroller/runtimes/vllm-rocm-template.yaml +Initializing release.json file +Dropping template containers from ServingRuntimes and changing them to ClusterServingRuntimes +Creating ClusterServingRuntimes images kustomization +No changes to assets/ or last_rebase_ai_model_serving.sh +Removing staging directory diff --git a/scripts/auto-rebase/assets.yaml b/scripts/auto-rebase/assets.yaml index 94730dc786..82f9803f42 100644 --- a/scripts/auto-rebase/assets.yaml +++ b/scripts/auto-rebase/assets.yaml @@ -10,6 +10,12 @@ assets: - file: namespace.yaml - file: service-account.yaml - file: service.yaml + - file: hosts-configmap-rolebinding.yaml + ignore: "RBAC rules for hosts customization" + git_restore: True + - file: hosts-configmap-role.yaml + ignore: "RBAC rules for hosts customization" + git_restore: True - dir: components/openshift-dns/node-resolver src: cluster-dns-operator/pkg/manifests/assets/node-resolver/ @@ -145,8 +151,10 @@ assets: - file: 0000_20_kube-apiserver-operator_00_cr-scc-nonroot.yaml - file: 0000_20_kube-apiserver-operator_00_cr-scc-privileged.yaml - file: 0000_20_kube-apiserver-operator_00_cr-scc-restricted-v2.yaml + - file: 0000_20_kube-apiserver-operator_00_cr-scc-restricted-v3.yaml - file: 0000_20_kube-apiserver-operator_00_cr-scc-restricted.yaml - file: 0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v2.yaml + - file: 0000_20_kube-apiserver-operator_00_crb-systemauthenticated-scc-restricted-v3.yaml - file: 0000_20_kube-apiserver-operator_00_scc-anyuid.yaml - file: 0000_20_kube-apiserver-operator_00_scc-hostaccess.yaml - file: 0000_20_kube-apiserver-operator_00_scc-hostmount-anyuid.yaml @@ -156,6 +164,7 @@ assets: - file: 0000_20_kube-apiserver-operator_00_scc-nonroot.yaml - file: 0000_20_kube-apiserver-operator_00_scc-privileged.yaml - file: 0000_20_kube-apiserver-operator_00_scc-restricted-v2.yaml + - file: 0000_20_kube-apiserver-operator_00_scc-restricted-v3.yaml - file: 0000_20_kube-apiserver-operator_00_scc-restricted.yaml - dir: controllers/route-controller-manager/ diff --git a/scripts/auto-rebase/assets_ai_model_serving.yaml b/scripts/auto-rebase/assets_ai_model_serving.yaml index b76ce580ac..3b90e38e2f 100644 --- a/scripts/auto-rebase/assets_ai_model_serving.yaml +++ b/scripts/auto-rebase/assets_ai_model_serving.yaml @@ -19,14 +19,23 @@ assets: - dir: optional/ai-model-serving/kserve/overlays/odh/ src: rhoai/operator/kserve/overlays/odh/ files: - - file: inferenceservice-config-patch.yaml - file: kustomization.yaml + - file: llm-svc-scc.yaml + - file: network-policies.yaml - file: params.env - file: params.yaml - - file: remove-namespace.yaml - - file: set-resources-manager-patch.yaml - file: user-cluster-roles.yaml + - dir: optional/ai-model-serving/kserve/overlays/odh/patches/ + src: rhoai/operator/kserve/overlays/odh/patches/ + files: + - file: patch-inferenceservice-config.yaml + - file: patch-set-resources-manager.yaml + - file: patch-webhook-svc-openshift-cert-injection.yaml + - file: remove-cert-manager.yaml + - file: remove-clusterservingruntime.yaml + - file: remove-local-model.yaml + - dir: optional/ai-model-serving/kserve/default/ src: rhoai/operator/kserve/default/ files: @@ -36,14 +45,16 @@ assets: - file: isvc_mutatingwebhook_cainjection_patch.yaml - file: isvc_validatingwebhook_cainjection_patch.yaml - file: kustomization.yaml + - file: llmisvcconfig_validatingwebhook_cainjection_patch.yaml + - file: llmisvc_validatingwebhook_cainjection_patch.yaml + - file: localmodelcache_validatingwebhook_cainjection_patch.yaml - file: localmodel_manager_image_patch.yaml + - file: localmodelnode_agent_image_patch.yaml - file: manager_auth_proxy_patch.yaml - file: manager_image_patch.yaml - file: manager_prometheus_metrics_patch.yaml - file: manager_resources_patch.yaml - - file: network-policies.yaml - file: servingruntime_validationwebhook_cainjection_patch.yaml - - file: svc_webhook_cainjection_patch.yaml - file: trainedmodel_validatingwebhook_cainjection_patch.yaml - dir: optional/ai-model-serving/kserve/crd/ @@ -51,15 +62,32 @@ assets: files: - file: kustomization.yaml + - dir: optional/ai-model-serving/kserve/crd/external/gateway-inference-extension/ + src: rhoai/operator/kserve/crd/external/gateway-inference-extension/ + files: + - file: kustomization.yaml + - file: gateway-inference-extension.yaml + + - dir: optional/ai-model-serving/kserve/crd/external/opendatahub-operator/ + src: rhoai/operator/kserve/crd/external/opendatahub-operator/ + files: + - file: kustomization.yaml + - file: datasciencecluster.opendatahub.io_datascienceclusters.yaml + - file: dscinitialization.opendatahub.io_dscinitializations.yaml + - dir: optional/ai-model-serving/kserve/crd/full/ src: rhoai/operator/kserve/crd/full/ files: - - file: serving.kserve.io_clusterlocalmodels.yaml + - file: kustomization.yaml - file: serving.kserve.io_clusterservingruntimes.yaml - file: serving.kserve.io_clusterstoragecontainers.yaml - file: serving.kserve.io_inferencegraphs.yaml - file: serving.kserve.io_inferenceservices.yaml + - file: serving.kserve.io_llminferenceserviceconfigs.yaml + - file: serving.kserve.io_llminferenceservices.yaml + - file: serving.kserve.io_localmodelcaches.yaml - file: serving.kserve.io_localmodelnodegroups.yaml + - file: serving.kserve.io_localmodelnodes.yaml - file: serving.kserve.io_servingruntimes.yaml - file: serving.kserve.io_trainedmodels.yaml @@ -94,6 +122,13 @@ assets: - file: role.yaml - file: service_account.yaml + - dir: optional/ai-model-serving/kserve/rbac/localmodelnode/ + src: rhoai/operator/kserve/rbac/localmodelnode/ + files: + - file: role_binding.yaml + - file: role.yaml + - file: service_account.yaml + - dir: optional/ai-model-serving/kserve/manager/ src: rhoai/operator/kserve/manager/ files: @@ -108,6 +143,44 @@ assets: - file: manifests.yaml - file: service.yaml + - dir: optional/ai-model-serving/kserve/localmodels/ + src: rhoai/operator/kserve/localmodels/ + files: + - file: kustomization.yaml + - file: manager.yaml + + - dir: optional/ai-model-serving/kserve/localmodelnodes/ + src: rhoai/operator/kserve/localmodelnodes/ + files: + - file: kustomization.yaml + - file: manager.yaml + + - dir: optional/ai-model-serving/kserve/llmisvc/ + src: rhoai/operator/kserve/llmisvc/ + files: + - file: config-llm-decode-template.yaml + - file: config-llm-decode-worker-data-parallel.yaml + - file: config-llm-prefill-template.yaml + - file: config-llm-prefill-worker-data-parallel.yaml + - file: config-llm-router-route.yaml + - file: config-llm-scheduler.yaml + - file: config-llm-template.yaml + - file: config-llm-worker-data-parallel.yaml + - file: kustomization.yaml + + - dir: optional/ai-model-serving/kserve/certmanager/ + src: rhoai/operator/kserve/certmanager/ + files: + - file: certificate.yaml + - file: kustomization.yaml + + - dir: optional/ai-model-serving/kserve/monitoring/llmisvc/ + src: rhoai/operator/kserve/monitoring/llmisvc/ + files: + - file: kustomization.yaml + - file: rbac.yaml + - file: istio_gateway_monitor.yaml + # Serving Runtimes - dir: optional/ai-model-serving/runtimes/ src: rhoai/operator/modelcontroller/runtimes/ diff --git a/scripts/auto-rebase/assets_sriov.yaml b/scripts/auto-rebase/assets_sriov.yaml new file mode 100644 index 0000000000..0575c3968f --- /dev/null +++ b/scripts/auto-rebase/assets_sriov.yaml @@ -0,0 +1,34 @@ +assets: + - dir: optional/sriov/ + no_clean: True + files: + - file: release-sriov-aarch64.json + ignore: "Provided by MicroShift" + - file: release-sriov-x86_64.json + ignore: "Provided by MicroShift" + - file: kustomization.yaml + ignore: "Provided by MicroShift" + + - dir: optional/sriov/crd/ + src: sriov + files: + - file: sriovnetwork.openshift.io_ovsnetworks.yaml + - file: sriovnetwork.openshift.io_sriovibnetworks.yaml + - file: sriovnetwork.openshift.io_sriovnetworknodepolicies.yaml + - file: sriovnetwork.openshift.io_sriovnetworknodestates.yaml + - file: sriovnetwork.openshift.io_sriovnetworkpoolconfigs.yaml + - file: sriovnetwork.openshift.io_sriovnetworks.yaml + - file: sriovnetwork.openshift.io_sriovoperatorconfigs.yaml + + - dir: optional/sriov/deploy/ + src: sriov + files: + - file: clusterrolebinding.yaml + - file: clusterrole.yaml + - file: namespace.yaml + - file: operator.yaml + - file: role.yaml + - file: rolebinding.yaml + - file: serviceaccount.yaml + - file: sriovoperatorconfig.yaml + - file: supported-nic-ids_v1_configmap.yaml diff --git a/scripts/auto-rebase/changelog.txt b/scripts/auto-rebase/changelog.txt index 458704cc8a..6009ea1b20 100644 --- a/scripts/auto-rebase/changelog.txt +++ b/scripts/auto-rebase/changelog.txt @@ -1,5138 +1,24 @@ -- api embedded-component fe48e8fd548bede3d7a38cc2dd1a9543b93e8a5e to 5050707b5937d28133772a29825169e578310d2c - - b618d5bd 2025-10-18T19:35:00-07:00 config/v1/types_cluster_version: Tighten force and rollback warnings - - 4e2fb13e 2025-10-16T08:56:43-04:00 promote ManagedBootImagesvSphere to default - - cd261409 2025-10-13T09:47:00-04:00 promote ManagedBootImagesAzure to default - - 14455544 2025-10-08T14:31:43-05:00 payload-command: remove authentication CR from hypershift payload - - ec8539c0 2025-09-23T14:34:32+01:00 network, virt: graduate preconfigured UDN addresses feature gate - - dcc007c7 2025-09-16T11:13:41-07:00 bump(k8s): make update - - e09bee69 2025-09-16T11:05:12-07:00 bump(k8s): go mod vendor - - d0e6cb88 2025-09-16T11:04:47-07:00 bump(k8s): tools: go mod vendor - - 92bcde98 2025-09-16T11:04:05-07:00 bump(k8s): update k8s.io/* dependencies to v1.34 - - e589cc1b 2025-09-16T11:03:03-07:00 bump(k8s): tools: update k8s.io/* dependencies to v1.34 +- cluster-kube-apiserver-operator embedded-component eecc8a9b87afa5ba882564cc4a352c93a555d7ab to 2c58d2f2bad129f0017ca194ae8a38711917c21c + - 5652b0b 2025-12-04T21:33:45-08:00 Update k8s version ranges for MutatingAdmissionPolicy -- cluster-ingress-operator embedded-component a35f1daf44c782ff89aa20a1446b9b4f196d1dc4 to 0cac97af560a68a5f5c0390a529726eb43556d51 - - 9f5aaf5 2025-10-14T13:30:05-04:00 Enhancement to add pull-secrets for brew and stage +- cluster-network-operator embedded-component 8bd3f1c3ea6055a49c14ece00a5b8779a100fc5d to 8d09651e31c64340865f7ec7f349786528805ebd + - b4c41d7 2025-12-04T23:56:54+01:00 Fix frr-k8s-statuscleaner crash: move $(LOG_LEVEL) to end of args -- cluster-kube-apiserver-operator embedded-component 3e3b6f604ac3c9089f1d2ff311c586e93f08ff62 to adc82f6188f4037a515eeeaa686ce1c1a80894da - - 5cf8821 2025-10-15T13:23:06-03:00 bump(k8s): align to upstream diff util changes - - 0f78d29 2025-10-15T13:20:07-03:00 bump(k8s): go mod vendor - - 847dfa3 2025-10-15T13:19:43-03:00 bump(k8s): update k8s.io/* dependencies to v1.34.1 +- kubernetes embedded-component 05182efbe79b0f9893cdffc9f76589cfd7419b39 to 9f57f51e3485ccc1cfd01ec94e9a0f5bef38eacb + - 873cd1d1b 2025-12-08T10:42:38+01:00 UPSTREAM: : make update + - 8d86655e3 2025-12-05T17:50:39+01:00 UPSTREAM: : pin cadvisor to downstream fork -- cluster-kube-controller-manager-operator embedded-component 52b7857076db0b649f8bede0018691466a19cbe6 to ffe5113eb88f384981fdeff599f22599e11a9d7c - - 6b9feeb 2025-10-15T13:53:17-03:00 bump(k8s): go mod vendor - - 18dda73 2025-10-15T13:52:52-03:00 bump(k8s): update k8s.io/* dependencies to v1.34.1 +- machine-config-operator embedded-component 00b8722ba3d4926f82541d781b3f6c1de7bd6b21 to e2f6042b4bd21ad64115fa5be529edc1cce8c451 + - d41f4bb5 2025-12-09T11:44:00+02:00 add missing ports in contaiterport on the daemoset + - 130d0ccd 2025-12-08T15:16:04-05:00 e2e test: update to wait until test node returns to ready + - ed3a3c85 2025-12-08T15:11:46-05:00 msbic: skip azure machinesets with securityType + - 92dda854 2025-12-08T09:53:35+02:00 add a relevant svc to the crio port -- cluster-kube-scheduler-operator embedded-component 75b90c6295999ac9e707532a0d77bbf257c77561 to 10d89b53f7ddcf0ee45f838c1a43e408074343e6 - - 867fc3a 2025-10-16T17:00:15-03:00 bump(k8s): react to library-go changes - - 14f9f27 2025-10-15T13:42:14-03:00 bump(k8s): align to upstream diff util changes - - 0299c1e 2025-10-15T13:40:13-03:00 bump(k8s): go mod vendor - - 35e02c5 2025-10-15T13:40:01-03:00 bump(k8s): update k8s.io/* dependencies to v1.34.1 +- kubernetes image-amd64 05182efbe79b0f9893cdffc9f76589cfd7419b39 to 9f57f51e3485ccc1cfd01ec94e9a0f5bef38eacb + - 873cd1d1b 2025-12-08T10:42:38+01:00 UPSTREAM: : make update + - 8d86655e3 2025-12-05T17:50:39+01:00 UPSTREAM: : pin cadvisor to downstream fork -- cluster-network-operator embedded-component 37d65252fe3e76946573da6ab6ddc7502e1c76fc to a5879759fb042f6c4b26931fa7ef8540244c8660 - - 2f74606 2025-10-01T08:39:28+01:00 api, l2udn: subnets must be masked - -- kubernetes embedded-component 00e7ec7a0db0b7e03c5ed2bc5b8b776fdc34f72a to 96593f323733d9ffc0fc70257ecad44a56df0ce3 - - 61114aa5a 2025-10-15T14:19:18-03:00 UPSTREAM: : hack/update-vendor.sh - - 30c13ce1b 2025-10-15T14:17:29-03:00 UPSTREAM: : make update - - b45907adb 2025-10-15T14:07:17-03:00 UPSTREAM: : hack/update-vendor.sh - - 25513888c 2025-10-15T14:03:12-03:00 UPSTREAM: 134199: Promote regression-issue-74839 to 1.4 - - 9ff0f3cae 2025-10-15T14:03:12-03:00 UPSTREAM: 134442: Fix ResourceQuota test for CRDs with long names - - 60ac34692 2025-10-15T14:03:12-03:00 UPSTREAM: revert: 133264: Revert "remove failing test that depends on expired credential, remove credential, add TODOs" - - ac1b24ee9 2025-10-15T14:03:12-03:00 UPSTREAM: 133905: kubelet/metrics: fix multiple Register call - - cd2e8b9ce 2025-10-15T14:03:12-03:00 UPSTREAM: 134376: Update hostpathplugin image version in DRA test driver manifest - - e5913956f 2025-10-15T14:03:11-03:00 UPSTREAM: 134327: test/e2e/apimachinery/watchlist: select only wellknown secrets for table test - - b392a7e3a 2025-10-15T14:03:11-03:00 UPSTREAM: 133421: e2e/watchlist: normalize dynamic Age column in Table test to prevent test flake - - 190966201 2025-10-15T14:03:11-03:00 UPSTREAM: 132791: Update pod resize test to accept new cpu.weight conversion. - - 6959e5211 2025-10-15T14:03:11-03:00 UPSTREAM: 132960: Configure JSON content type for generic webhook RESTClient. - - c21b863b5 2025-10-15T14:03:11-03:00 UPSTREAM: 134071: Wait for quota to report used before creating pvc - - 5a989b949 2025-10-15T14:03:11-03:00 UPSTREAM: 133959: Do not remove PVC ClaimRef to fix flaky VAC test - - cf73730d1 2025-10-15T14:03:11-03:00 UPSTREAM: 133682: Increase port-forward broken connection detection client timeout - - 06d238136 2025-10-15T14:03:11-03:00 UPSTREAM: : Add plugin for storage performant security policy - - b5ec7a566 2025-10-15T14:03:11-03:00 UPSTREAM: : unrevert: Mark admissionregistration.k8s.io/v1beta1 as deprecated." - - 71e26c8c5 2025-10-15T14:03:11-03:00 UPSTREAM: : allow TLS1.3 or modern profile to be specified - - 6803cc464 2025-10-15T14:03:11-03:00 UPSTREAM: : Add volume group snapshot test driver - - 22e63d2b8 2025-10-15T14:03:11-03:00 UPSTREAM: : admission: validate minimumKubeletVersion - - a743b1abe 2025-10-15T14:03:11-03:00 UPSTREAM: : log only deprecated api requests - - e87b794c6 2025-10-15T14:03:10-03:00 UPSTREAM: : disable etcd readiness checks by default - - 50b420aa6 2025-10-15T14:03:10-03:00 UPSTREAM: : add arbiter node role to known labels - - da795cb2c 2025-10-15T14:03:10-03:00 UPSTREAM: : Prefer local endpoint for cluster DNS service - - ecb7d7621 2025-10-15T14:03:10-03:00 UPSTREAM: : add etcd3RetryingProberMonitor for retrying etcd Unavailable errors for the etcd health checker client - - 06fe11ba2 2025-10-15T14:03:10-03:00 UPSTREAM: : annotate audit events for requests during unready phase and graceful termination phase - - 696bc0436 2025-10-15T14:03:10-03:00 UPSTREAM: : allow type mutation for specific secrets - - 0573d1831 2025-10-15T14:03:10-03:00 UPSTREAM: : Add openshift feature gates to kube-apiserver - inject openshift feature gates into pkg/features - - 3eb149a67 2025-10-15T14:03:10-03:00 UPSTREAM: : add new admission for handling shared cpus - - f3ef52744 2025-10-15T14:03:10-03:00 UPSTREAM: : temporarily disable reporting e2e text bugs and enforce 2nd labeling to make tests work - - db423d582 2025-10-15T14:03:10-03:00 UPSTREAM: : advertise shared cpus for mixed cpus feature - - 1994a6bff 2025-10-15T14:03:10-03:00 UPSTREAM: : Export cpu stats of ovs.slice via prometheus - - 57a39d46c 2025-10-15T14:03:10-03:00 UPSTREAM: : retry etcd Unavailable errors - - a4e802e80 2025-10-15T14:03:09-03:00 UPSTREAM: : selfsubjectaccessreview: grant user:full scope to self-SARs that have user:check-access - - 6cffd361e 2025-10-15T14:03:09-03:00 UPSTREAM: : merge v3 openapi discovery and specs for special groups - - e6b92109a 2025-10-15T14:03:09-03:00 UPSTREAM: : when only this kube-apiserver can fulfill the kubernetes.default.svc, don't wait for aggregated availability - - f42426e01 2025-10-15T14:03:09-03:00 UPSTREAM: : Export internal code from k8s.io/apimachinery/pkg/util/managedfields - - aa11b48c6 2025-10-15T14:03:09-03:00 UPSTREAM: : APISelfSubjectReview: only test v1beta1 API - - 4d0cd085e 2025-10-15T14:03:09-03:00 UPSTREAM: : disable load balancing on created cgroups when managed is enabled - - 283c592bc 2025-10-15T14:03:09-03:00 UPSTREAM: 115328: annotate early and late requests - - 967a1e568 2025-10-15T14:03:09-03:00 UPSTREAM: : PSa metrics: log platform namespaces in audit denies - - 788da1d88 2025-10-15T14:03:09-03:00 UPSTREAM: : make the PSA workload admission warnings honor the changes that SCC will eventually make to the pod - - 566fde9f6 2025-10-15T14:03:09-03:00 UPSTREAM: : optionally enable retry after until apiserver is ready - - 9c2fff44e 2025-10-15T14:03:09-03:00 UPSTREAM: : fix [sig-auth] ServiceAccounts no secret-based service account token should be auto-generated - - 93595fa11 2025-10-15T14:03:09-03:00 UPSTREAM: : use console-public config map for console redirect - - 3fab36613 2025-10-15T14:03:09-03:00 UPSTREAM: : Release lock on KCM and KS termination - - 927d3d922 2025-10-15T14:03:08-03:00 UPSTREAM: : sets X-OpenShift-Internal-If-Not-Ready HTTP Header for GC and Namespace controllers - - fc8db74d7 2025-10-15T14:03:08-03:00 UPSTREAM: : add max_housekeeping_interval - - ed28c08c4 2025-10-15T14:03:08-03:00 UPSTREAM: : send Retry-After when not ready with a caller opt in - - f7cdb220f 2025-10-15T14:03:08-03:00 UPSTREAM: : skip posting failures to aggregated APIs to avoid getting false positives until the server becomes ready - - 16f970296 2025-10-15T14:03:08-03:00 UPSTREAM: : add a way to inject a vulnerable, legacy service-ca.crt for migration compatibility - - 30a300bcb 2025-10-15T14:03:08-03:00 UPSTREAM: 103612: tolerate additional, but congruent, events for integration test - - 1780cd23f 2025-10-15T14:03:08-03:00 UPSTREAM: : crd: add ClusterOperator condition message table column - - ce1781131 2025-10-15T14:03:08-03:00 UPSTREAM: : emit event when readyz goes true - - 2d833691b 2025-10-15T14:03:08-03:00 UPSTREAM: : apiserver: add system_client=kube-{apiserver,cm,s} to apiserver_request_total - - b40e921b7 2025-10-15T14:03:08-03:00 UPSTREAM: : Ensure service ca is mounted for projected tokens - - dbcdc99b0 2025-10-15T14:03:08-03:00 UPSTREAM: : allows for switching KCM to talk to Kube API over localhost - - 4e71cfc7b 2025-10-15T14:03:07-03:00 UPSTREAM: : add management support to kubelet - - d859c8f35 2025-10-15T14:03:07-03:00 UPSTREAM: : allows for switching KS to talk to Kube API over localhost - - 2e380ce17 2025-10-15T14:03:07-03:00 UPSTREAM: : provide events, messages, and bodies for probe failures of important pods - - 63fc13858 2025-10-15T14:03:07-03:00 UPSTREAM: : allow kubelet to self-authorize metrics scraping - - 01f6a4ac1 2025-10-15T14:03:07-03:00 UPSTREAM: : use hardcoded metrics scraping authorizer for delegated apiservers - - ecbcaf656 2025-10-15T14:03:07-03:00 UPSTREAM: : kube-apiserver: ignore SIGTERM/INT after the first one - - 438c6cd39 2025-10-15T14:03:07-03:00 UPSTREAM: : noderestrictions: add node-role.kubernetes.io/* to allowed node labels - - 6b2289613 2025-10-15T14:03:07-03:00 UPSTREAM: : export HandleFlags - - fea2fa015 2025-10-15T14:03:07-03:00 UPSTREAM: : Add OpenShift tooling, images, configs and docs - - e162c7757 2025-10-15T14:03:06-03:00 UPSTREAM: : refactor/improve CRD publishing e2e tests in an HA setup - - c04050e15 2025-10-15T14:03:06-03:00 UPSTREAM: : conditionally fill the UserAgent from the currently running test - - f5ffc84dd 2025-10-15T14:03:06-03:00 UPSTREAM: : Remove excessive e2e logging - - 47631c08e 2025-10-15T14:03:06-03:00 UPSTREAM: : disable AES24, not supported by FIPS - - 673175cd6 2025-10-15T14:03:06-03:00 UPSTREAM: : warn only about unknown feature gates - - 49dbe59f1 2025-10-15T14:03:06-03:00 UPSTREAM: : bootstrap-rbac-policy: move over .well-known rules - - 42560b433 2025-10-15T14:03:06-03:00 UPSTREAM: : create termination events - - 3662118bf 2025-10-15T14:03:06-03:00 UPSTREAM: : kube-apiserver: priorize some CRD groups over others - - 6f7c7ec80 2025-10-15T14:03:06-03:00 UPSTREAM: : openshift-kube-apiserver: add openshift-kube-apiserver code - - d1c74dc85 2025-10-15T14:03:06-03:00 UPSTREAM: : openshift-kube-apiserver: add kube-apiserver patches - - 528cc99e6 2025-10-15T14:03:06-03:00 UPSTREAM: : kube-apiserver: add our immortal namespaces directly to admission plugin - - 72e349ebf 2025-10-15T14:03:06-03:00 UPSTREAM: : kube-controller-manager: exclude some origin resources from quota - - a0df69dbd 2025-10-15T14:03:05-03:00 UPSTREAM: : kube-controller-manager: allow running bare kube-controller-manager - - c90479ce1 2025-10-15T14:03:05-03:00 UPSTREAM: : kube-controller-manager: add service serving cert signer to token controller - - 75ec36f78 2025-10-15T14:03:05-03:00 UPSTREAM: : Extend NodeLogQuery feature - - 71f1dfcf8 2025-10-15T14:03:05-03:00 UPSTREAM: : hardcoded restmapper with a few entries to rebootstrap SDN when SDN is down - - fadd69ba4 2025-10-15T14:03:05-03:00 UPSTREAM: : remove apiservice from sync in CRD registration when it exists - - 4dd9038de 2025-10-15T14:03:05-03:00 UPSTREAM: : patch aggregator to allow delegating resources - - 898dd8cdf 2025-10-15T14:03:05-03:00 UPSTREAM: : filter out CustomResourceQuota paths from OpenAPI - - 91afdf9ce 2025-10-15T14:03:05-03:00 UPSTREAM: 93286: wait for apiservices on startup - - 96219fc21 2025-10-15T14:03:05-03:00 UPSTREAM: 74956: apiserver: switch authorization to use protobuf client - - 93248f9ae 2025-09-09T19:37:19Z Release commit for Kubernetes v1.34.1 - - 7bd2900b1 2025-09-05T03:53:40Z fix: Only warn for unrecognized formats on type=string - - f779cf638 2025-09-03T23:55:22+02:00 Disable estimating resource size for resources with watch cache disabled - - 96739661c 2025-09-03T09:23:47+02:00 Disable collecting stats for resources not setting prefix to prevent error logs - - 2631a5f21 2025-08-29T15:37:14+03:00 Fix linter - - 94c0e4788 2025-08-29T15:37:14+03:00 Fix completion of resource names - - 08515c751 2025-08-28T22:56:12+08:00 Fix missing control plane health check timeout - - a75938d9e 2025-08-28T18:07:40+08:00 Fix DaemonSet misscheduled status not updating on node taint changes - - 3ebbe5731 2025-08-28T10:29:24+02:00 Add a note about Conflicts return value - - 98dca817c 2025-08-28T10:29:24+02:00 Fix SELinux label comparison - - 3e75f3881 2025-08-28T10:29:24+02:00 Add missing cases to SELinuxMount tests - - d13374214 2025-08-27T10:36:11Z Update CHANGELOG/CHANGELOG-1.34.md for v1.34.0 - - f28b4c9ef 2025-08-27T10:09:04Z Release commit for Kubernetes v1.34.0 - - f2170bc6c 2025-08-26T16:11:12+01:00 kube-proxy: log but don't exit if ipv4 or ipv6 is not available - - f47e9696d 2025-08-20T17:40:32Z CHANGELOG: Update directory for v1.34.0-rc.2 release - - 78405b2c8 2025-08-20T17:40:32Z Update CHANGELOG/CHANGELOG-1.34.md for v1.34.0-rc.2 - - ed3ccdbe3 2025-08-20T17:17:54Z Release commit for Kubernetes v1.34.0-rc.2 - - db01f9403 2025-08-20T09:19:55-04:00 Remove patch/update from ServiceCIDR API conformance test - - d49e3d67c 2025-08-19T16:35:34+02:00 Fix storage counting all objects instead just objects for resource - - 747a295ca 2025-08-18T15:54:03-04:00 fix flake in dra test 'TestPlugin' - - 4ebe560c7 2025-08-18T13:44:26+02:00 DRA allocator: fix data race around `claimsToAllocate` - - 41013e7bf 2025-08-18T10:23:42+03:00 e2e_dra: use latest release if stable doesn't exist - - e49f6116f 2025-08-15T14:33:07-07:00 clarify that staging repos are automatically published - - ada2ed848 2025-08-15T10:17:18-07:00 add pointer to CONTRIBUTING.md for more details on contributing, clarify read-only - - 8919ac43c 2025-08-15T10:10:58-07:00 special case that kubectl staging repo is currently used to track issues, and only pull requests should be redirected back to the main repo. - - 011d50019 2025-08-15T10:10:26-07:00 link to what a staging repository is - - 7c43e6d2f 2025-08-15T10:08:16-07:00 docs: clarify that this is a staging repository and not for direct contributions - - f8bad82c2 2025-08-15T15:27:45+02:00 update go version for publishing bot rules - - bf6c86b56 2025-08-15T01:02:44-05:00 DRA: wait for stats to converge in "creates slices" e2e test - - 020b7052c 2025-08-14T09:46:06+02:00 Bump dependencies, images and versions used to Go 1.24.6 and distroless iptables - - c8ab780ed 2025-08-13T16:35:35-04:00 dra plugin: assume claim after api call in bindClaim - - 81affffa1 2025-08-13T19:49:57Z CHANGELOG: Update directory for v1.31.12 release - - 8311c1d3d 2025-08-13T19:46:23Z CHANGELOG: Update directory for v1.33.4 release - - edfa9a5bd 2025-08-13T17:57:33Z added WithFlaky() to the device plugin test case: supports extended resources together with ResourceClaim - - 48a496771 2025-08-13T14:49:49Z CHANGELOG: Update directory for v1.32.8 release - - 064b59161 2025-08-11T13:50:03+02:00 improve CRD handling in VolumePopulator test - - 944b0a492 2025-08-10T14:38:24-07:00 do not allow the node to update it's owner reference - - 0bd039e89 2025-08-08T21:01:46Z Update CHANGELOG/CHANGELOG-1.34.md for v1.34.0-rc.1 - - 4d6b49b3f 2025-08-08T21:01:45Z CHANGELOG: Update directory for v1.34.0-rc.1 release - - a956ef486 2025-08-08T20:39:54Z Release commit for Kubernetes v1.34.0-rc.1 - - e073a9125 2025-08-08T17:02:50+02:00 Add release-1.34 configuration - - cbd6fb867 2025-08-07T17:25:48-07:00 Remove DeprecatedVersion for apiserver_storage_objects, adjust help text - - 89b5034d5 2025-08-07T13:46:08+08:00 Make podcertificaterequestcleaner role feature-gated - - 2629fe25f 2025-08-06T21:24:27-07:00 Use Delete() instead of DeleteLabelValues() for etcd metrics - - 13ced7b7d 2025-08-06T20:20:05Z CHANGELOG: Update directory for v1.34.0-rc.0 release - - 40e8ad951 2025-08-06T13:26:10Z Release commit for Kubernetes v1.34.0-rc.0 - - b79691898 2025-08-06T07:42:31Z reduced numPods to 5 from 10 to fix flaky test (supports reusing resources) due to timeout. - - 2a026f6d6 2025-08-06T07:08:58Z 1/ added retries to AssumeClaimAfterAPICall for the object which is not present in the cache (dynamicresources.go) 2/ modified the assume cache verification to not error out as long as the expected claim is in the cache, no matter its latest and api object are different or not. (dynamicresources_test.go). 3/ fixed nil panic as seen from https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/133321/pull-kubernetes-integration/1952472629470302208 - - 01470d973 2025-08-01T09:56:51-07:00 Fix memory limit decrease test on cri-o - - aca402f25 2025-08-01T13:59:32+02:00 e2e: node: skip breaking tests - - 0fbc8cd44 2025-08-01T07:18:26Z Remove integration-test labels from long running scheduler_perf workloads - - e83e5815e 2025-08-01T00:55:10-04:00 always pull pause image for eviction tests - - 418e96bf1 2025-08-01T12:46:26+08:00 Update prerelease lifecycle to v1.34 - - 65fda6dd3 2025-07-31T18:15:55Z fixed exended resource scheduling performance test, added more nodes for scheduling the init pods - - 9eda4789c 2025-07-31T09:27:40Z Fix potential race in PodStatusPatchCall implementation - - dbfeb9c35 2025-07-30T11:57:26Z Fix potential race in closing API dispatcher - - c7db6362f 2025-07-30T10:47:38Z Move NominatedNodeName preemption-related integration tests to a new package - - 46b858aa1 2025-07-30T19:12:57+09:00 fix: return false to apply the patch - - 07c71097d 2025-07-30T09:06:34Z Split DRA scheduler_perf tests into multiple packages - - 988c9b03f 2025-07-30T15:48:26+09:00 Demote KEP-5278 feature gates ClearingNominatedNodeNameAfterBinding and NominatedNodeNameForExpectation to Alpha - - 0a12f00e9 2025-07-30T14:44:41+09:00 fix nil panic in hasBindingConditions, it cannot assume claim has allocations - - 7f052afae 2025-07-30T09:52:49+09:00 KEP 5075: implement scheduler - - 3e3b2447f 2025-07-29T17:28:26-07:00 Promote PodLevelResources to Beta (#132999) - - 59bba9271 2025-07-30T09:26:52+09:00 KEP-5075: generated codes from make update - - 5ad969588 2025-07-30T09:26:40+09:00 KEP-5075: API updates - - 29d1951eb 2025-07-29T12:34:35-07:00 fixes scheduler nil panic due to empty init container request&limit - - 23d6f73e7 2025-07-29T18:55:28Z extended resource backed by DRA: test - - 34a64db2c 2025-07-29T18:55:21Z extended resource backed by DRA: implementation - - a3a767b37 2025-07-29T20:20:08+02:00 WIP: fix e2e tests - - 4ca47255a 2025-07-29T20:19:40+02:00 node: disable resource managers when pod-level resources are enabled - - 3068b60b8 2025-07-29T17:17:20Z extended resource backed by DRA: codegen - - 1f2fd18ac 2025-07-29T17:17:19Z extended resource backed by DRA: API types.go - - 7fbf63a23 2025-07-29T09:02:26-07:00 HPA support for pod-level resource specifications (#132430) - - 6e9b60e3f 2025-07-29T11:06:39-04:00 Add / update kubelet and DRA API owners - - 60fa65db8 2025-07-29T23:48:11+09:00 Clear pod.Status.NominatedNodeName when pod is bound - - 15b1a7fd3 2025-07-29T16:41:37+02:00 Revert "CPU and Memory manager event when using pod level resources" - - aea0a3cca 2025-07-29T12:21:03Z Run all relevant test cases with the feature gate enabled and disabled - - 856e7d238 2025-07-29T12:21:03Z scheduler: Stop clearing NominatedNodeName on all cases - - 6653ef652 2025-07-29T11:36:07Z KEP-5007 DRA Device Binding Conditions: Add dra integration test - - 9e82c1330 2025-07-29T11:35:58Z KEP-5007 DRA Device Binding Conditions: Implement DRA logic - - e8c3af1f5 2025-07-29T11:34:30Z KEP-5007 DRA Device Binding Conditions: Implement scheduler logic - - ac81b829e 2025-07-29T11:34:03Z KEP-5007 DRA Device Binding Conditions: Run make update - - 987ad3951 2025-07-29T11:32:47Z KEP-5007 DRA Device Binding Conditions: API Related code Update - - 34c3b0938 2025-07-29T11:31:48Z KEP-5007 DRA Device Binding Conditions: API Update - - ac9fad603 2025-07-29T19:01:02+09:00 feat: trigger PreFilterPreBind in the binding cycle - - 48eef9ce9 2025-07-29T08:06:39Z test: fix TestStructuredAuthenticationConfigReload flake by handling expected network errors - - 4874d4166 2025-07-28T21:42:42-07:00 Pod Certs: Fix kubelet volume host arg order - - f9bb14fcf 2025-07-28T19:42:04-04:00 Fix apiserver service proxying e2e test flakiness - - 8ace0fb89 2025-07-28T15:43:43-07:00 remove failing test that depends on expired credential, remove credential, add TODOs - - f07dcd443 2025-07-28T22:06:48Z fix flake on TestStreamTranslator_WebSocketServerErrors - - 7ba22700b 2025-07-28T21:59:08Z websocket streamtranslator increament metrics before writing status - - 0aea6a1e4 2025-07-28T21:53:12Z TestStreamTranslator_BlockRedirects use subtests - - 4b698656b 2025-07-28T19:31:08Z Returning early if podResources is nil to avoid nil pointer dereferencing - - 766d011bb 2025-07-28T18:53:04Z E2E tests for no hints nor aligment of CPU and Memory managers - - 5672750e6 2025-07-28T18:53:03Z Unit tests for no hints nor aligment of CPU and Memory - - 7804b51f4 2025-07-28T18:53:03Z CPU and Memory manager event when using pod level resources - - fd206a0ef 2025-07-28T17:19:07Z Add comments for restart rules not used for unknown container status and probes - - 4b479da4b 2025-07-28T16:33:20Z Remove the feature from e2e test - - 6997fbd1e 2025-07-29T00:02:20+08:00 Fix incorrect validation on the kubelet - - 48f8458c4 2025-07-28T16:54:08+02:00 validation: Fix user-namespaces test case name - - 50a7a8af4 2025-07-28T16:54:08+02:00 validation: Align usage of hostUsers in error messages - - 5f7e611f7 2025-07-28T16:54:08+02:00 validation: Return error if hostUsers=false && volumeDevices - - f3466f8ad 2025-07-28T23:12:58+09:00 fix: flake integration test - - ed74d4cd5 2025-07-28T20:22:27+09:00 Revert "Revert "fix: handle corner cases in the async preemption"" - - e8dc272c5 2025-07-27T21:45:02-07:00 Update etcd to 3.6.4 - - 0f7cd1495 2025-07-28T11:52:12+08:00 Fix prerelease-lifecycle for volumeattributesclass - - 9c8dacb03 2025-07-27T23:14:12Z ContainerRestartRules feature gate should work with probes - - 48fd30113 2025-07-26T07:51:58+09:00 [PodLevelResources] Add missing label to Downward API test - - 57ceb56c6 2025-07-25T14:09:41-07:00 Bump etcd sdk to v3.6.4 - - b562335cb 2025-07-25T13:51:25-07:00 Build etcd v3.6.4 image - - 17d733e24 2025-07-25T15:35:36Z KEP-5229: Send API calls through dispatcher and cache - - 40a90df3b 2025-07-25T12:45:01+02:00 DRA E2E: remove stress test - - b956484c2 2025-07-25T19:29:14+09:00 KEP-5229: Add metrics for async API dispatcher - - 006d7620a 2025-07-25T10:38:34+08:00 Revert "fix: handle corner cases in the async preemption" - - 727a6e6db 2025-07-24T17:58:54-07:00 Reject pod when attachment limit is exceeded (#132933) - - a65289630 2025-07-24T17:58:33-07:00 Allow white-spaced CABundle during webhook client creation and validation (#132514) - - f1737db16 2025-07-24T18:58:24-05:00 Update DRA Pod spec comments - - b7de71f9c 2025-07-24T23:23:18Z feat(kubelet): Add ResourceHealthStatus for DRA pods - - d4a83b9a5 2025-07-24T21:41:28Z fix(golangci-lint): skip config verification when -c none is used - - 252513a1b 2025-07-24T21:40:08Z Add WithFeature and WithSerial, also check if cgroup v2 is used in test - - 1bc995c19 2025-07-24T21:29:04Z Generated files - - f925e5554 2025-07-24T21:29:04Z E2E tests for container hugepage resources immutability - - 9f5b09eb7 2025-07-24T21:29:04Z Unit test pod level hugepage Default and Validation logic - - 845e94d37 2025-07-24T21:29:01Z Validation logic and Defaulting update for pod level hugepages - - c15a54f8c 2025-07-24T14:08:14-07:00 draadminaccess: move metrics test from e2e to integration - - d176808d3 2025-07-24T12:12:59-07:00 Rename hack/*-yamlfmt to -owners-fmt - - 7adcd2114 2025-07-24T12:11:04-07:00 Replace cmd/yamlfmt with k-sigs/yaml/yamlfmt - - 79833578f 2025-07-24T18:52:34Z KEP-3695: add kubeletPodResources feature gate to Beta - - 2cb955d8c 2025-07-24T11:47:03-07:00 Add KYAML support to kubectl - - 8182a27f3 2025-07-24T11:46:03-07:00 Re-vendor sigs.k8s.io/yaml @ v1.6.0 - - 94bf8fc8a 2025-07-25T01:53:59+08:00 Promoted API `VolumeAttributesClass` and `VolumeAttributesClassList` to `storage.k8s.io/v1`. - - 8e3f93c87 2025-07-24T17:13:39Z Unit test propagate pod level hugepages to containers - - 52b457421 2025-07-24T17:13:39Z Pod level hugepage cgroup when unset in container - - add7132a6 2025-07-24T17:08:13Z E2E tests for pod level resources Kubelet Preemption - - 976a617d0 2025-07-24T17:07:09Z E2E tests for pod level resources eviction manager - - 13b122b6f 2025-07-24T17:07:09Z Unit tests for pod level resources eviction manager - - 9a3ca05f6 2025-07-24T17:07:05Z Use pod level resources for eviction manager - - b34f8782e 2025-07-24T16:49:54Z Add e2e tests - - 9086e52fe 2025-07-24T16:49:54Z Implement restart rules in kubelet - - af595a44a 2025-07-24T16:49:52Z Add container restart rules to API - - 5dc2030c0 2025-07-24T12:37:14-04:00 4033: GA KubeletCgroupDriverFromCRI feature gate - - 27e167515 2025-07-24T12:36:26-04:00 Make PSA host enforcement honor emulation version - - 32053b1d2 2025-07-25T00:07:30+08:00 chore: replace ptr caster with unified ptr.To - - 83a0d0c66 2025-07-24T11:42:59-04:00 kubelet: add metric for version CRI implementation will lose support - - ffe306d67 2025-07-24T07:56:27-07:00 client-go, kubectl: Replace deprecated ErrWaitTimeout with recommended method (#132718) - - cb33accc8 2025-07-24T06:46:28-07:00 JSON & YAML output for kubectl api-resources (#132604) - - 8a2db4da4 2025-07-24T22:45:39+09:00 fix: adjust the log level in the preemption - - 4c9bf4719 2025-07-24T22:44:39+09:00 fix: handle cornor cases in the async preepmtion - - bf98e45af 2025-07-24T21:20:12+08:00 Migrate pkg/kubelet/volumemanager to contextual logging - - aecd37e6f 2025-07-24T12:10:58Z Moving Scheduler interfaces to staging: Move PodInfo and NodeInfo interfaces (together with related types) to staging repo, leaving internal implementation in kubernetes/kubernetes/pkg/scheduler - - c954e1325 2025-07-24T14:04:08+02:00 Revert "DRAAdminAccess: add upgrade downgrade test" - - 12d675066 2025-07-24T13:50:05+02:00 client-go/metadata/fake: sets opts.Watch to true - - b37fd0cab 2025-07-24T11:49:51Z [KEP-4816] DRAPrioritizedList to Beta - - 6767d54bb 2025-07-24T19:46:51+09:00 Bump DRA API version to "v1" in "deviceattribute" package in "k8s.io/dynamic-resource-allocation" module - - 449763fb1 2025-07-24T12:35:45+02:00 e2e: podresources: disable memory manager integration - - b768c1d1d 2025-07-24T08:33:56+02:00 DRA API: bump storage version to v1beta2 - - 24de875ce 2025-07-24T08:33:56+02:00 DRA: graduate DynamicResourceAllocation feature to GA - - d8df1dc1b 2025-07-24T08:33:56+02:00 DRA RBAC: fix kube-scheduler bootstrap policy - - 21d929f59 2025-07-24T08:33:56+02:00 integration: use --runtime-config-emulation-forward-compatible - - 5c4f81743 2025-07-24T08:33:45+02:00 DRA: use v1 API - - cff91579e 2025-07-24T08:30:25+02:00 DRA API: v1 registration + tests - - 4e592f6c1 2025-07-24T08:30:24+02:00 DRA API: s/v1beta2/v1/ and generated files - - 1f2f433f7 2025-07-24T08:30:24+02:00 DRA API: verbatim copy v1beta2 -> v1 - - 837b7395d 2025-07-24T09:14:09+03:00 kubelet: DRA: Close gRPC connection when removing DRA plugin - - c7d6c0968 2025-07-23T21:44:27-07:00 List available endpoints for kube-apiserver (#132581) - - 5f4a1aa58 2025-07-24T09:11:09+08:00 chore: ptrTo util removal with ptr.To - - a82187cf1 2025-07-24T08:15:36+09:00 [PodLevelResources] Update Downward API defaulting for resource limits - - 4c87e60d0 2025-07-23T21:17:05+02:00 Tests using .host field in probes must be at priviledged level - - f94fcac86 2025-07-23T21:15:46+02:00 Add new fixture testData for 1.34 PSA - - fc0474d77 2025-07-23T21:15:46+02:00 Copy test fixtures to 1.34 from 1.32 - - 9540a9639 2025-07-23T21:15:46+02:00 Copy test fixtures to 1.33 from 1.32 - - 4a3ebf886 2025-07-23T21:15:46+02:00 update the minimal version to fix unit/fixture tests - - 333b19b44 2025-07-23T21:15:45+02:00 Add PSA for blocking .host field on pod probes and lifecycle - - c7bf3b81f 2025-07-23T13:51:18-04:00 Add flake debugging for admission test - - a806e069e 2025-07-23T17:40:53Z Remove WinDSR feature gate unit test - - 765d84e9b 2025-07-23T13:19:07-04:00 Test only EndpointSlices, not Endpoints, in dual-stack e2e tests - - 2cb48f77f 2025-07-23T18:58:57+02:00 schedule pod availability checks at the correct time in ReplicaSets - - 61cc6cf80 2025-07-23T09:13:13-07:00 draadminaccess test make it serial - - 33b45c838 2025-07-23T11:07:29-04:00 Update "should proxy through a service and a pod" to look at EndpointSlices - - d70e7e223 2025-07-23T11:07:29-04:00 Port aggregated apiserver discovery to EndpointSlices - - 41dc2d3b0 2025-07-23T11:07:28-04:00 Add utilities for getting EndpointSlices for a Service - - f7109ed28 2025-07-23T10:59:18-04:00 [KEP-3751] Allow PVC VACName to update to nil or empty when status.currentVAC is nil - - c35e4ad2b 2025-07-23T22:57:12+08:00 add codes for drop disabled pod fields - - 8d65e1e98 2025-07-23T22:57:11+08:00 Add e2e tests. - - f31aeca42 2025-07-23T22:57:11+08:00 Add code for overriding hostnames - - 88b762143 2025-07-23T22:57:08+08:00 Add validation for the HostnameOverride field. - - c889ee17a 2025-07-23T16:55:05+02:00 Convert kubelet plugin manager from gogo to protoc - - abb1b26d5 2025-07-23T16:50:23+02:00 DRA: Add experimental allocator variant - - 17cc5e9ec 2025-07-23T15:38:34+02:00 e2e: node: podresources: exercise with dynamicresources enabled - - ee8ef383b 2025-07-23T22:37:19+09:00 Update kubectl kustomize to kyaml/v0.20.1, cmd/config/v0.20.1, api/v0.20.1, kustomize/v5.7.1 - - af6c97bd1 2025-07-23T20:28:13+08:00 add Feature Gate. - - 8b3814c4a 2025-07-23T20:28:12+08:00 Add the HostnameOverride field to the Pod API - - c2a06e791 2025-07-23T11:06:11+03:00 DRA: skip flaky test case on Windows - - f6061605f 2025-07-23T09:12:46+02:00 DRA E2E: run multi-node control plane tests also with two nodes - - f0e292089 2025-07-23T09:10:45+02:00 DRA E2E: simplify "control plane" test names - - 603751ee8 2025-07-23T09:10:45+02:00 DRA E2E: remove redundant test - - 21ed19798 2025-07-23T09:58:14+03:00 kubelet: DRA: Handle grpc.ErrServerStopped in plugin tests - - 61bd5789b 2025-07-23T03:44:48Z Updated to not directly change the global variable `claim` - - 4f0a5771a 2025-07-23T10:19:20+08:00 test: add e2e case for mutating named port - - db9b9b5a4 2025-07-22T16:48:31-07:00 Build etcd v3.6.3 image - - 179551a7c 2025-07-22T23:24:32Z feat: Implement warnings for unrecognized formats in CRDs - - 437a2ad69 2025-07-22T23:23:55Z feat: Add func to export the supportedVersionedFormats - - d943239c5 2025-07-22T22:11:23Z added debug_redact to cri api secrets - - 88af8b606 2025-07-23T07:08:21+09:00 Add PodLevelResources to the Windows OS limitations in the API doc - - c2b26617b 2025-07-23T07:08:21+09:00 Check OS for PodLevelResources in kubelet - - e2c308aff 2025-07-23T07:08:14+09:00 Check OS for PodLevelResources in API server - - f6aee6369 2025-07-22T20:40:48Z add validation logic for APIVersion fields of HPA - - 6f3b6b91f 2025-07-22T13:40:42-07:00 KEP-3721: Support for env files (#132626) - - 0b60c1219 2025-07-22T15:15:18-04:00 KEP-4222: Adopt text and JSON transcoding support for CBOR. - - 917659269 2025-07-22T15:15:17-04:00 Bump to github.com/fxamacker/cbor/v2 v2.9.0. - - 216f7485b 2025-07-22T11:54:34-07:00 DRAAdminAccess: add upgrade downgrade test - - 303a7056f 2025-07-22T19:58:29+02:00 e2e: node: podresources: enable multi-container tests - - 38a9a8a59 2025-07-22T19:55:09+02:00 e2e: node: podresources: add tests for missing pod - - 19b00ecc9 2025-07-22T17:36:03Z update CCM image to v33.1.1 - - b070b0a5c 2025-07-23T00:57:50+08:00 chore: residual boolptr and intptr removal - - 407bcf886 2025-07-22T11:05:00-04:00 kubelet: add metrics for userns pods - - e5ccc31e7 2025-07-22T20:26:52+05:30 chore: replace float64Ptr with ptr.To helper in validation and integration tests - - 545b36ba2 2025-07-22T09:50:18-05:00 fix uncore e2e check - - b97decb7d 2025-07-22T15:58:22+02:00 client-go/dynamic/fake: sets opts.Watch true - - f626e847e 2025-07-22T20:44:53+08:00 Migrate pkg/kubelet/winstats to contextual logging - - ce2d97939 2025-07-22T17:35:48+08:00 Run Unschedulable scheduler_perf test case with SchedulerAsyncAPICalls feature gate enabled - - 0da0897c1 2025-07-22T16:38:20+08:00 Bump external snapshotter for vgs tests - - 78bf3410c 2025-07-22T09:21:58+02:00 DRA E2E: revisit conformance classification of tests - - 911df655d 2025-07-22T10:14:42+08:00 chore: migrate kubelet lifecycle to contextual logging. - - 872f0682d 2025-07-22T10:51:56+09:00 Use "k8s.io/api/resource/v1beta2" instead of "k8s.io/dynamic-resource-allocation/api" for resource API imports. - - 31d2de59d 2025-07-22T10:51:55+09:00 Split the symlink target error cases into for each condition - - a4fb1562f 2025-07-22T10:51:53+09:00 introduce resolvePCIeRoot instead of resolveSysDevicesPath - - f3d4b216f 2025-07-22T10:49:39+09:00 assign return value to a variable instead of using it directly - - 7f27c88d0 2025-07-22T10:25:17+09:00 Update staging/src/k8s.io/dynamic-resource-allocation/deviceattribute/pci_linux.go - - ee26a5837 2025-07-22T10:10:40+09:00 Update staging/src/k8s.io/dynamic-resource-allocation/deviceattribute/pci_linux.go - - 8b558a1bc 2025-07-21T22:54:24Z fix(validation-gen): correct typos in comments and documentation - - 63a958ff3 2025-07-21T22:54:24Z chore(validation-gen): remove TODO regarding ratcheting behavior for slices and maps - - c659b4182 2025-07-21T22:27:13Z e2e test for mirror pod with pod generation - - a5b9c7a79 2025-07-21T17:57:57-04:00 bump resource claim controller concurrent syncs to 50 - - 6d4000f84 2025-07-21T21:49:57Z Pod Certificates: make update - - 4624cb9bb 2025-07-21T21:49:57Z Pod Certificates: Basic implementation - - facbb6614 2025-07-21T17:00:45-04:00 Temporarily revert restart-on-node-IP-change behavior of proxy NodeManager - - e2d37f3cd 2025-07-21T17:00:44-04:00 kube-proxy: merge OnNodeAdd and OnNodeUpdate into OnNodeChange - - 0dc51b16f 2025-07-21T17:00:44-04:00 kube-proxy: merge NodeEligibleHandler with NodeManager - - d4892fef7 2025-07-21T17:00:44-04:00 kube-proxy: merge NodePodCIDRHandler with NodeManager - - 373fb487f 2025-07-21T17:00:44-04:00 kube-proxy: add NodeManager to manage life-cycle based on NodeIPs - - d21ca8674 2025-07-21T17:00:44-04:00 kube-proxy: add NodeTopologyConfig for tracking topology labels - - 8acda3631 2025-07-21T17:00:42-04:00 Belatedly add tests of proxy NodeConfig and ServiceCIDRConfig - - edf4654d7 2025-07-21T19:27:59Z generate proto - - 18918e200 2025-07-21T19:27:59Z add CSR declarative_validation_test.go tests - - 69a8a169d 2025-07-21T19:27:59Z add WithOrigin and MarkedByDeclarative, update hand-written to error at list instead of list item field, add additional tests for approved+denied case - - 6a2d5a1e6 2025-07-21T19:27:59Z feat: add CSR status.conditions approved+denied declarative validation tags and associated declarative validation tags to v1 and v1beta1 types.go - - 248ad2161 2025-07-21T13:55:32-05:00 graduate prefer-align-cpus-by-uncorecache to beta - - 6e77bff18 2025-07-21T18:51:07Z pod sandbox image is not being used by kubelet any longer - - 43706d6b7 2025-07-21T20:34:36+03:00 add warnings when creating headless service with specified load balancer ip,external ips and/or session affinity - - 53aa4332b 2025-07-21T16:50:16Z fix integration tests - - 8996e81fc 2025-07-21T16:46:07Z fix unit tests - - dd4dd3d8e 2025-07-21T16:32:25Z feat: Enabledeclarative validation in CertificateSigningRequest subresources updates - - ccc82775f 2025-07-21T11:19:25-05:00 expand test coverage for uncore alignment - - cb29414b4 2025-07-21T16:13:32Z Extend E2E test coverage for PSI metrics under pressure - - 4ed231da0 2025-07-21T17:16:16+02:00 kubelet/imagePullManager: add benchmarks for image pull record accessors - - 5486e6f44 2025-07-21T07:55:32-07:00 DRAAdminAccess: move to beta - - 5d4010d2d 2025-07-21T09:08:43-05:00 Mark KubeletServiceAccountTokenForCredentialProviders feature gate as beta - - 4fc9546e0 2025-07-21T14:00:34Z KEP-5229: Implement API dispatcher - - 549f7c4fc 2025-07-21T14:53:58+02:00 image pull manager: add in-memory LRU intents/pulled records caching - - ea326373e 2025-07-21T13:57:50+02:00 e2e: node: cpumanager cgroup v1 compatibility - - b8d74e75c 2025-07-21T12:56:51+01:00 Add test case to prove MaxElements correctly set on IntOrString - - 7e5aafcb1 2025-07-21T13:47:22+02:00 ci: remove unnecessary test harness - - 457df1cf9 2025-07-21T12:48:29+02:00 ci cleanup: make sure to remove test KUBECONFIGs - - 3026020b4 2025-07-21T10:04:01+02:00 Convert `k8s.io/kubelet/pkg/apis/deviceplugin` from gogo to protoc - - 4f9f6c053 2025-07-21T09:33:11+02:00 scheduler_perf: hide "metric ... not found" errors - - b8758ac31 2025-07-20T21:50:58+01:00 node: mm-mgr: migrate to contextual logging - - 2e756e741 2025-07-20T15:17:04-05:00 fix data race in OIDC integration tests by serializing test server starts - - 03acd266a 2025-07-20T22:16:45+08:00 chore: residual uint64ptr removal with ptr.To - - b84271a77 2025-07-19T21:54:47-07:00 DRAAdminAccess: add e2e - - ab839c93f 2025-07-20T09:47:50+09:00 feat(kubelet): migrate kuberuntime to contextual logging - - 30e5cdd64 2025-07-19T16:20:34+03:00 kubelet: don't fetch image credentials if the image is present and if we don't need to check if the pod is allowed to pull it - - cbba3281a 2025-07-19T11:46:32+02:00 integration: fix etcd output handling - - d0fc938a0 2025-07-19T11:38:21+02:00 DRA client: fix conversion of watch channel - - f77ce8951 2025-07-19T11:38:12+02:00 DRA: debug output for list/watch client - - 9d7d3a617 2025-07-19T14:41:04+05:30 Bump sample-device-plugin base image to alpine:3.22 - - 7ddb04262 2025-07-19T17:10:37+09:00 feat(cmd/kubelet): support structured and contextual logging - - fb4e25222 2025-07-19T14:13:59+08:00 test: add batch pod deletion for kubelet e2e tests - - 4b8dd9612 2025-07-19T13:08:34+09:00 cleanup: remove example plugins - - 067bd16b1 2025-07-19T03:37:37Z Add unit tests to check if right feature gate is checked based on resize request. - - f71080c93 2025-07-19T03:22:56Z Create separate feature gates for static CPU Manager and static Memory Manager support - - 07ef7842b 2025-07-19T03:20:26Z Change memory manager static policy to a public const - - ae5247afc 2025-07-19T00:07:22Z address feedback - - 659517445 2025-07-19T00:06:48Z unit test for HandlePodReconcile retrying pending resizes - - 0d24c3b57 2025-07-19T00:05:19Z add sourcesReady parameter to fakeKubelet constructor - - 6e86af48c 2025-07-19T00:05:17Z fix check if requests have shrunk - - 6a40bcb42 2025-07-19T00:03:46Z Retry pending resizes if a status update leads to aggregate requests shrinking - - 22d724969 2025-07-18T23:59:05Z kubelet: record container_resize_requests metric for all resize updates - - 13a6d2121 2025-07-18T23:30:54Z check a couple extra failure scenarios - - 8957109b7 2025-07-18T22:29:30Z only record resizes in progress and pending after all pods are added - - d51375dcc 2025-07-18T22:29:25Z record 'kubelet_pod_deferred_resize_accepted_total' metric - - b8fc1b675 2025-07-18T22:27:40Z record 'kubelet_pod_infeasible_resizes_total' metric - - d845e1fd6 2025-07-18T22:27:40Z record 'kubelet_pod_pending_resizes' metric - - 23005281f 2025-07-18T22:27:39Z record 'kubelet_pod_in_progress_resizes' metric - - 0595ddaaf 2025-07-18T22:27:39Z record 'kubelet_container_requested_resizes_total' metric - - 468aa5e30 2025-07-18T22:27:39Z record 'kubelet_pod_resize_duration_milliseconds' metric - - 129662763 2025-07-18T22:27:39Z define and register ippr metrics - - 3964fbeab 2025-07-18T17:00:17-05:00 kubelet: integrate sa creds in image pull manager - - f1728bd58 2025-07-18T16:38:27-05:00 Add ServiceAccount coordinates to ImagePullCredentials v1alpha1 - - b9dd2fdec 2025-07-18T16:38:23-05:00 credentialprovider: track service account cred source in ext provider keyring - - 9a4c0f9b2 2025-07-19T06:32:52+09:00 scheduler_perf: Add memory tracking to performance tests - - 8a42f4ccc 2025-07-18T11:55:23-07:00 Add support for CEL list library. - - 5d3186631 2025-07-18T17:50:07Z dedupe fetching allocatable and available resources in node test - - 79dc0b8a4 2025-07-18T19:38:56+02:00 Add jitter to priodically executed process in storage to avoid too concurrent executions - - a48420e3c 2025-07-18T16:57:41Z promote PodObservedGenerationTracking to beta - - 336b5aff4 2025-07-18T16:35:32Z Check for valid UID range when runasnonroot is true - - e9492239b 2025-07-18T16:29:31Z Promote windows graceful shutdown to Beta - - 00bf3b37a 2025-07-18T21:35:58+05:30 Graduate PodLifecycleSleepActionAllowZero to GA - - 99059895f 2025-07-18T17:53:23+02:00 Account for caching and maximum object size when estimating LIST request - - 2256f5747 2025-07-18T23:43:53+08:00 Add resize completed event after Inprogress conditionCleared is cleared - - d42a1d58d 2025-07-18T07:15:41-07:00 DRAAdminAccess: add metrics - - f5d12ed39 2025-07-18T14:10:45Z fix: Compare versions instead of pointer comparison - - 8dc20a0f6 2025-07-18T12:34:29+01:00 Fix IntOrString cost estimation when schema has a MaxLength constraint - - a2e9e9f66 2025-07-18T17:02:54+08:00 fix pass ctx into a revised HandleError function - - 729cd583a 2025-07-18T09:43:04+02:00 scheduler integration: fail test instead of existing - - bfa33b18a 2025-07-18T09:55:39+08:00 fix(kube-proxy) avoid add zero-masked loadBalancerSourceRanges to ipset - - d6e85b504 2025-07-17T20:30:06-05:00 Add kubelet_credential_provider_config_info metric - - 14a5ef56a 2025-07-17T23:21:26Z fix pipeline failure - - 21e2fcea9 2025-07-17T17:47:51-05:00 Add automatic_reload_last_config_info metric for auth configs - - 5f829195e 2025-07-17T14:46:47-07:00 Only warn when AppArmor annotation doesn't match pod field - - f2c48ffec 2025-07-17T16:32:47-05:00 Add generic config info custom collector - - 11921f758 2025-07-17T14:14:57-07:00 [KEP-5100] WinOverlay feature gate to GA - - e417232f9 2025-07-17T14:07:35-07:00 Warn when using AppArmor annotations with a pod field - - 4fdf09fdc 2025-07-17T14:07:35-07:00 Stop syncing AppArmor fields to annotations - - 3ecb3d230 2025-07-17T14:07:35-07:00 Remove unused appArmor*InUse functions - - 75ae2d727 2025-07-17T13:17:35-07:00 Add an E2E test for memory limit decrease usage check - - 2a9388c30 2025-07-17T13:17:35-07:00 Move memory limit decrease e2e test to success cases - - c7a78185c 2025-07-17T13:17:35-07:00 Remove the restriction on memory limit decrease - - d9c91127d 2025-07-17T13:17:35-07:00 Check memory usage before decreasing limits - - 465f72814 2025-07-17T20:09:05Z use gomega.BeComparableTo instead of Equal for resource quantity check in resize test - - cedcbfb94 2025-07-17T20:09:03Z Update cel-go to v0.26.0 - - 24065780e 2025-07-17T15:34:34-04:00 Add e2eendpointslice.WaitForEndpointPorts, use in some tests. - - f456a70bd 2025-07-17T19:19:05Z use CreateBatch and MakeResizePatch - - 5cea72d56 2025-07-17T21:18:28+02:00 DRA integration: add test case for FilterTimeout - - 241ac018e 2025-07-17T21:18:28+02:00 DRA integration: remove unnecessary anonymous import - - bc338e750 2025-07-17T21:18:28+02:00 DRA scheduler: implement filter timeout and cancellation - - 430c79b53 2025-07-17T19:03:35Z chore(validation-gen): hold uniqueness check of listmap - - 1745094c4 2025-07-17T18:40:01Z Update VolumeAttributesClass API Description - - 2cb30c779 2025-07-17T18:22:15Z Refactor target check - - 86bc1bf0a 2025-07-17T17:50:45Z more complex e2e test for deferred resizes - - 66de1960a 2025-07-17T18:13:10+02:00 Increase maxSeats for List requests - - 025c606e3 2025-07-17T16:47:47+02:00 DRA scheduler: add plugin configuration - - ee38a0013 2025-07-17T16:47:47+02:00 DRA scheduler: add DRASchedulerFilterTimeout feature gate - - 837ef29f5 2025-07-17T16:47:47+02:00 scheduler: enhance and document Filter cancellation - - 7910b43cd 2025-07-17T16:47:46+02:00 scheduler_perf: document benchstat usage - - b9ce92d50 2025-07-17T16:45:42+03:00 edit versioned_feature_list.yaml - - 070621bf7 2025-07-17T16:44:41+03:00 Remove unit tests that rely on feature gate enablement check - - 3f847d97c 2025-07-17T16:44:40+03:00 GA the NodeSwap feature gate - - 1a7630c09 2025-07-17T22:41:58+09:00 Remove deprecated LegacySidecarContainers feature gate - - 300c7b815 2025-07-17T22:33:32+09:00 set the timeout to Get method - - 2b13b87e6 2025-07-17T15:11:55+02:00 chore: replacing timer ptr with ptr.To - - 532d48fe6 2025-07-17T14:56:44+02:00 Convert `k8s.io/kubelet/pkg/apis/podresources` from gogo to protoc - - cf68f75fc 2025-07-17T14:30:16+02:00 Deprecate apiserver_storage_objects and replace it with apiserver_resource_objects metric using labels consistent with other metrics - - db342010f 2025-07-17T12:08:03+02:00 kube-controller-manager: enable WatchListClient - - cef9f9edb 2025-07-17T16:58:58+08:00 kubeadm: fix a bug where it should generate default etcd command based on etcd version when the etcd image tag supports semver - - ace2a2249 2025-07-17T10:17:30+02:00 drop rules for release-1.30 as it is EOL - - 6737c31d0 2025-07-17T10:12:19+02:00 update publishing bot go rules for release-1.31/1.32 - - a1a85ddb1 2025-07-17T09:56:28+02:00 SSA: test optional map keys - - 4d34975a4 2025-07-17T09:56:28+02:00 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 - - 3357e8fc0 2025-07-17T09:56:28+02:00 SSA: add integration tests - - a2a3839a8 2025-07-17T09:43:44+02:00 DRA scheduler: add pohly as approver - - 4bc2ad6ee 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/preemption to contextual logging - - b96e3cac7 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/pod to contextual logging - - 0cb31bc40 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/nodeshutdown to contextual logging - - 75ccd69ba 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/kubeletconfig to contextual logging - - 1d0fd5928 2025-07-17T00:16:01-07:00 kubectl: add port names to describe pod output - - 7dad9e2af 2025-07-17T10:15:58+03:00 migrate pkg/kubelet/apis to contextual logging - - f141907dd 2025-07-17T07:56:03+02:00 DRA kubelet: add v1 gRPC - - 1b5a08cbf 2025-07-17T09:51:42+08:00 cleanup: fetch individual PodResourceInfo from allocated resource state - - 6e7e6b37c 2025-07-17T01:37:22Z Fix the cost issue to match the bug fix for target being nil in CEL side. - - ad220eb6c 2025-07-17T09:08:12+08:00 chore: remove residual int64ptr usage with ptr.To - - a96446863 2025-07-16T15:59:55-07:00 Add PodCPUAndMemoryStats to stats.Provider interface - - 8f4a624a5 2025-07-16T22:56:59Z Fix pipeline errors - - e8536c019 2025-07-16T22:38:45Z add item + union and item + zeroroneof output tests - - be72d963b 2025-07-16T22:38:45Z add validate/zeroorone_test.go and add +k8s:zeroOrOneOfMember output tests - - 10b20852e 2025-07-16T22:38:45Z feat(validation-gen): add +k8s:zeroOrOneOfMember tag validator and associated validate method - - 81f18759e 2025-07-16T22:38:44Z add validate/union_test.go and add +k8s:unionMember and +k8s:unionDiscriminator output tests - - 5bc9b6911 2025-07-16T22:38:44Z feat(validation-gen): add +k8s:unionMember and +k8s:unionDiscriminator tag validators and associated validate methods - - bfb42fc31 2025-07-16T22:38:44Z refactor item.go with buildMatchConditions, make itemTagValidator a LateTagValidator - - 5d1c5ebd8 2025-07-16T22:38:32Z add ParentPath to context, remove Parent from context and plumb changes in validators - - c50da38aa 2025-07-16T22:33:58Z allow field validators to generate variables - - e7aeb4ff5 2025-07-16T21:23:13Z Promote MutableCSINodeAllocatableCount to Beta - - 9bcaa8c86 2025-07-16T15:11:21-04:00 Fix conversion-gen caching incorrect memory equality comparisons - - b35ad4e9b 2025-07-16T11:42:02-04:00 Add e2eendpointslice.WaitForEndpointPods, use in various test - - dbecdd187 2025-07-16T11:42:02-04:00 Use e2eendpointslice.WaitForEndpointCount in more network tests - - b7998a397 2025-07-16T11:42:00-04:00 Add e2eendpointslice.WaitForEndpointCount, use it in some network tests - - dd3691b16 2025-07-16T15:11:11Z refactor allocator, removed claimsToAllocate from NewAllocator(), instead, passed it through Allocate() - - 8e6651520 2025-07-16T16:46:39+02:00 Convert `k8s.io/kms/apis` from gogo to protoc - - 2f605f49f 2025-07-16T14:40:35Z CHANGELOG: Update directory for v1.34.0-beta.0 release - - 9cf00ec6d 2025-07-16T14:56:50+02:00 kube-apiserver: promote WatchList feature to beta - - e4320fe25 2025-07-16T15:49:41+03:00 e2e_node: DRA: test handling fatal serving failures - - ea05ad888 2025-07-16T15:49:41+03:00 e2e_node: DRA: add errorOnCloseListener - - fc21d3f37 2025-07-16T15:49:41+03:00 e2e: DRA: enable test plugin to cancel main context on error - - 1981c985b 2025-07-16T15:49:41+03:00 e2e: DRA: support test and public options - - d44b73744 2025-07-16T15:49:32+03:00 DRA: handle grpc.Server.Serve failures - - 169965350 2025-07-16T15:42:12+03:00 e2e_node: Refactor DRA tests to use variadic options - - 52fab5969 2025-07-16T21:33:33+09:00 Add NominatedNodeNameForExpectation feature flag - - fd23fa3d4 2025-07-16T12:52:01+02:00 Graduate ListFromCacheSnapshot to Beta - - 665599417 2025-07-16T06:17:34-04:00 Add e2eendpointslice.WaitForEndpointSlices, use it in a few places - - b5931f53d 2025-07-16T06:19:27Z Auto update openapi spec - - a100dfdfa 2025-07-16T05:11:52Z Using alpha as the stored version for one release. - - 6e9324453 2025-07-16T12:24:35+08:00 Add validation of volumeClaimTemplates in StatefulSet - - ae4a43de6 2025-07-16T11:01:37+08:00 Refactor: isolate flag registration to kube-apiserver to eliminate global state - - 5b4c1872a 2025-07-16T09:07:25+08:00 chore: residual intptr removal with ptr.To - - e9aab4648 2025-07-15T23:11:24Z CHANGELOG: Update directory for v1.31.11 release - - dc0ca0be3 2025-07-15T22:19:29Z CHANGELOG: Update directory for v1.33.3 release - - d6caa36dc 2025-07-15T22:18:25Z CHANGELOG: Update directory for v1.32.7 release - - d460611e7 2025-07-15T21:51:36Z Add more checks - - b69fd9d42 2025-07-15T16:03:07-04:00 Add egress selector support to JWT authenticator - - e9c1ca724 2025-07-15T15:38:13-04:00 Add conversion-gen memory equality test - - 62521d835 2025-07-15T18:23:30Z fix observedGeneration in pod resize conditions - - 386372602 2025-07-15T10:48:12-07:00 add unit-test for ensuring authn latency annotation - - 760eb7d5d 2025-07-15T10:39:08-07:00 fix: record authentication latency before audit filter wraps up - - 26c8ee7b8 2025-07-15T17:22:12Z DRA: Improve allocator with better backtracking - - d383c8e02 2025-07-15T17:46:28+02:00 Update history of checkpoint support in Kubelet - - 20914ef4e 2025-07-15T17:00:49+02:00 Prevent running two HPA cachers for different API versions - - bc5088cbf 2025-07-15T19:34:05+05:30 Revert "Kube proxy node manager" - - f8c7131b4 2025-07-15T15:32:13+02:00 Drop experimental- prefix from etcd flags - - d8747d716 2025-07-15T15:06:26+02:00 Use object size estimation for non-recursive list - - 05e1c4b48 2025-07-15T14:15:00+02:00 e2e: node: fix podresources API feature label - - 6e1875fac 2025-07-15T12:54:40+02:00 local-up-cluster.sh: don't require to be invoked in the root - - 356be5ae3 2025-07-15T12:54:40+02:00 DRA E2E: move upgrade/downgrade test into test/e2e_dra - - c8ca9249a 2025-07-15T12:54:40+02:00 DRA integration: add upgrade/downgrade testing with local-up-cluster.sh - - 60e9316c0 2025-07-15T12:54:40+02:00 DRA E2E: refactor helper code - - 2e3228e2c 2025-07-15T12:52:27+02:00 DRA E2E: support deploying driver on localhost - - e5f57d2cf 2025-07-15T12:52:27+02:00 ktesting: add WithoutCancel - - e01603b2e 2025-07-15T12:52:27+02:00 ktesting: document side effect of SetDefaultVerbosity during init - - 0b1bed1a1 2025-07-15T12:52:27+02:00 ktesting: WithCancel does not cancel on test completion anymore - - f381d7372 2025-07-15T12:52:27+02:00 DRA E2E: retry exec of hostpathplugin - - c2080e7e4 2025-07-15T12:52:27+02:00 DRA E2E: support using ktesting - - 906505281 2025-07-15T12:52:27+02:00 ktesting: add step Begin/End - - b7c2d6aba 2025-07-15T12:52:27+02:00 ktesting: skip logging error when capturing it - - 497716386 2025-07-15T12:52:26+02:00 DRA E2E: reduce port proxy verbosity - - 5721c927e 2025-07-15T12:52:26+02:00 DRA E2E: increase verbosity of resource claim controller - - 1a284472f 2025-07-15T12:52:26+02:00 E2E framework: retry also on EOF errors - - 6a7b9589f 2025-07-15T12:52:26+02:00 E2E framework: support setting REST config - - bd30b0ade 2025-07-15T16:55:12+08:00 remove general avaliable feature-gate DevicePluginCDIDevices - - 9c0e65b08 2025-07-15T10:11:23+02:00 test/apimachinery/watchlist: server supports sending resources in Table format - - 2dfc4e25a 2025-07-15T10:08:41+02:00 endpoints/handlers/respone: include metadata when IncludeNone and watchlist requested - - e1a0cf624 2025-07-15T14:56:43+08:00 handle stoppedCh and listenerStoppedCh returned by cc.SecureServing.Serve - - 6cd00cdcb 2025-07-15T04:48:13Z Auto gen - - a3ecea296 2025-07-15T01:44:13Z manual change - - 4f3334b7c 2025-07-15T01:44:13Z Promote feature gate - - 0d8fd61e6 2025-07-14T21:10:37Z address review comments - - 32afbd9ea 2025-07-14T23:02:18+02:00 Inconsistency resets cache snapshots and prevents collection of new ones until cache is marked consistent again - - 4f77a4618 2025-07-14T16:19:52-04:00 Generated files - - a04e7cf5e 2025-07-14T16:19:52-04:00 KEP-4601: Graduate selector authorization to stable - - 6f4be0d8c 2025-07-14T21:07:45+02:00 DRA allocator: skip unsupported test cases - - 740e56846 2025-07-14T18:13:00Z address review comments - - 61542e7a9 2025-07-14T18:13:00Z Cleanup: Remove field name from invalid field detail message - - 14f3c2684 2025-07-14T18:03:57Z Remove redundant metric field. - - ad03cb873 2025-07-15T00:31:20+08:00 chore: residual strPtr utility removal with ptr.To - - af249fb2e 2025-07-14T18:13:27+02:00 DRA E2E: test mixture of extended resources + ResourceClaim - - 9a7dddf5a 2025-07-15T01:07:43+09:00 fix test - - 09ec6f744 2025-07-15T01:07:25+09:00 chore - - 85adda5e6 2025-07-14T16:58:58+02:00 Use object size to estimate list cost assigning 1 sear per 100KB - - f20be4c09 2025-07-14T23:17:19+09:00 add test which checks release method calls Get - - 7d9eb2b3d 2025-07-14T16:09:29+02:00 test/apimachinery/watchlist: update tests that receive resources in Table format - - da7c55e0d 2025-07-14T15:42:57+02:00 reflector: detects unsupported meta.Table gvks for watchlist - - ebc1ccc49 2025-07-14T07:24:48-04:00 Bump k8s.io/kube-openapi to latest SHA (f3f2b991d03b) - - 8d1cbc83d 2025-07-14T13:02:14+02:00 endpoints/handlers/get: remove watchListEndpointRestrictions - - 14d1bbf36 2025-07-14T09:08:16+08:00 chore: maxPtr utility removal with ptr.To - - 6462ad918 2025-07-14T00:52:42+02:00 codegen tool: resolves GOBIN via `go env` - - 1073b3b90 2025-07-13T20:53:30Z Add unit tests for AddPod() - - fcb595a2d 2025-07-14T00:31:53+05:30 service-ip-alloc: delay ip processing on service recreate - - 8de14b526 2025-07-13T23:51:48+05:30 service-ip-alloc: make repair loop consumer clock interface - - e38361728 2025-07-13T12:42:45+02:00 Fix TestProgressNotify for etcd v3.6.2 - - e0f9914ef 2025-07-13T08:12:55+08:00 chore: replace int32Ptr usage with ptr.To - - cf4912eb4 2025-07-12T21:18:59Z chore(validation-gen): reorder imports - - 419e70b76 2025-07-12T21:18:59Z run update-codegen - - 4c8f489b8 2025-07-12T21:18:59Z add +k8s:neq tests - - fc1c832c4 2025-07-12T21:18:59Z feat: add +k8s:neq tag which enforces field is neq to a specified comparable value - - fb971325c 2025-07-12T21:18:59Z feat(validation-gen): add new test cases for item validation - - 5cc2721f6 2025-07-12T21:18:57Z feat(validation-gen): add k8s:item - - af05aa61d 2025-07-12T21:16:48Z feat: Add validation ratcheting for subfields tag - - daef13ecc 2025-07-12T21:16:48Z chore: improve error rendering and add unit tests for ErrorMatcher - - f40ee6f99 2025-07-12T21:16:48Z feat(validation-gen): add new test cases for validation of slices and maps - - b059bb551 2025-07-12T21:16:48Z feat(validation-gen): enhance validation functions for slices and maps - - 0b1fa64a9 2025-07-12T21:16:48Z refactor(validation-gen): streamline type validation logic - - 7ad89e199 2025-07-12T21:16:47Z feat(validation-gen): add FieldValidator - - ba45e37b2 2025-07-12T11:35:07+02:00 chore: removed boolPtrFn helpers with ptr package implementation - - 5971802fd 2025-07-12T16:44:39+08:00 chore: intPtr removal with ptr.To - - a091fa607 2025-07-11T22:58:00+02:00 Add apiserver_resource_size_estimate_bytes metric - - e6cf7dbf0 2025-07-11T22:19:55+02:00 Enable running cache inconsistency detection by default - - a06b3d356 2025-07-11T20:30:39+02:00 Bump dependencies, images and versions used to Go 1.24.5 and distroless iptables - - cba38b629 2025-07-11T20:20:48+02:00 DRA allocator: fix linter hint - - 5eab2b7a6 2025-07-11T10:59:20-07:00 Remove unuse runtimeCache parameter from stats.Provider - - 46e2c22fd 2025-07-11T23:06:44+05:30 kube-proxy: merge OnNodeAdd and OnNodeUpdate into OnNodeChange - - fa9e46694 2025-07-11T23:06:44+05:30 kube-proxy: merge NodeEligibleHandler with NodeManager - - c6735d9b3 2025-07-11T23:06:44+05:30 kube-proxy: merge NodePodCIDRHandler with NodeManager - - 45c355ca5 2025-07-11T19:48:11+03:00 Move unschedulablePods struct to a separate file - - bfeaae331 2025-07-11T18:25:46+02:00 Compact watch cache based on last observed etcd compaction - - c43104cbe 2025-07-11T21:48:52+05:30 kube-proxy: add NodeManager to manage life-cycle based on NodeIPs - - af7abde0e 2025-07-11T21:05:19+05:30 kube-proxy: add NodeTopologyConfig for tracking topology labels - - 98c4514ea 2025-07-11T10:32:01-05:00 add e2e_node tests for uncore alignment - - 70191dd21 2025-07-11T10:32:00-05:00 fix uncore cache alignment for odd integer cpus - - 65e0cff3c 2025-07-11T14:55:15+02:00 add Replicaset -> ReplicationController conversion test - - 9df4c35a6 2025-07-11T12:28:50Z Disable SchedulerAsyncPreemption feature correctly in integration tests - - 3636d5bd3 2025-07-11T08:23:44-04:00 Added NodeSelectors field to DriverDefinition - - 4f0d3eaa3 2025-07-11T18:59:14+08:00 enhance exec probe logging with pod and container context - - ffe908207 2025-07-11T08:34:39+02:00 DRA allocator: select tests based on supported features - - b1a35c640 2025-07-11T05:36:16Z Build etcd image v3.6.2 - - 7e37711d6 2025-07-10T23:20:27-05:00 kubelet: Add service account UID to token cache key for proper invalidation - - 45dfb4644 2025-07-10T23:20:23-05:00 Add TokenRequestServiceAccountUIDValidation feature gate with UID validation - - 237fbde8b 2025-07-10T22:30:21Z clean up e2e test and sorting code - - 4d2566eb5 2025-07-10T14:50:54-05:00 credentialprovider: wire in service account mode cache type - - 03db2278d 2025-07-10T14:50:51-05:00 kubelet: Add CacheType field to ServiceAccountTokenAttributes with validation - - ff4746af1 2025-07-10T19:19:13Z increase verbosity of kubelet preemption log - - f2de8897e 2025-07-10T12:13:40-07:00 Add metrics for mutation - - bfa7f38c6 2025-07-10T18:37:47Z fix TestPodResourceAllocationReset for windows - - e8b914c4b 2025-07-10T18:29:31Z address comments - - 6052c569d 2025-07-10T18:01:15Z prioritize resize requests by priorityClass and qos class - - c126870eb 2025-07-10T12:19:31-04:00 Bump RecoverVolumeExpansionFailure to GA - - 7b906f204 2025-07-10T17:34:21+02:00 DRA allocator: fork the code - - 5caf7bca1 2025-07-10T17:34:21+02:00 DRA allocator: refactor code - - 03e32bd26 2025-07-10T16:01:02+02:00 Expose compaction revision from compactor - - 5e3ea8e27 2025-07-10T16:00:12+02:00 Add test for compactor - - bbab59411 2025-07-10T15:30:56+02:00 local-up-cluster: stop running Docker - - f57662856 2025-07-10T15:30:56+02:00 local-up-cluster: store logs in artifacts directory - - 81b6e1d3a 2025-07-10T15:30:56+02:00 local-up-cluster: start containerd before Docker - - 27a77370d 2025-07-10T15:30:56+02:00 local-up-cluster: simplify installing packages - - ddda1dca3 2025-07-10T15:30:56+02:00 local-up-cluster.sh: add dry-run mode - - 0950b9ee5 2025-07-10T13:39:48+02:00 DRA allocator: export DeviceClassLister - - bc5aa94d8 2025-07-10T13:09:19+02:00 local-up-cluster.sh: allow configuring all ports - - a4b1d26b1 2025-07-10T13:09:18+02:00 local-up-cluster.sh: dump config on KUBE_VERBOSE >= 2 - - 5665bafaa 2025-07-09T23:12:11Z CHANGELOG: Update directory for v1.34.0-alpha.3 release - - 381b3f376 2025-07-09T21:44:08Z clear just the errors rather than the entire in-progress condition when a new resize is allocated - - b89ab301f 2025-07-09T20:50:07Z feedback round 2 - - 67aaa956d 2025-07-09T21:45:54+02:00 Update docs on shutdown and draining - - 7a6f6fdf7 2025-07-09T11:25:33-07:00 Delete unnecessary mutex - - 271233a62 2025-07-10T02:59:21+09:00 Prevent the failure of releasing the lock by updating the resource version in case of a resource conflict - - d9de590a2 2025-07-09T22:33:54+08:00 test: increase test coverage for pkg/kubelet/types - - 2dd07e924 2025-07-09T15:56:06+02:00 DRA E2E: ResourceSlice Controller test flake - - 26f54e5c0 2025-07-09T21:35:45+08:00 chore: replace int64ptr with ptr.To - - f2b24b984 2025-07-09T12:10:10Z Increase verbosity of frequently printed loglines in binder plugin - - 621482d68 2025-07-09T16:38:14+05:30 update pause version to 3.10.1 - - ce456c87f 2025-07-09T10:40:49+08:00 add SuccessCriteriaMet status for kubectl get job - - bb6bd5201 2025-07-08T23:49:34Z Add feature gate enable test for KubeletPodResourcesGet - - c92524377 2025-07-08T21:53:20Z address feedback - - c6fef9752 2025-07-08T13:25:26-07:00 fix: improve the pod level request validation (#132551) - - 89344dc23 2025-07-08T18:38:04Z feat(validation-gen): add k8s:enum validator - - 345641f10 2025-07-08T18:38:04Z feat(validation-gen): add Enum validator function - - adb71d041 2025-07-08T17:51:59Z Forcefully expire lease in integration test to fix flake - - 637bf55cb 2025-07-08T13:48:26-04:00 bump golang.org/x/vuln/cmd/govulncheck to v1.1.4 - - e0cc07af8 2025-07-08T17:43:52Z Promote PSI metrics feature to beta - - b46a124db 2025-07-08T17:14:49Z skip pending resize evaluation if sources aren't ready - - 35bf1522b 2025-07-08T17:14:48Z update allocation manager unit tests to cover push and retry of pending resizes - - e6d165b87 2025-07-08T17:14:47Z move resize allocation out of the sync loop - - 87fe2491a 2025-07-08T17:07:59Z add some additional helpers to kubelet status manager - - cb2baef91 2025-07-08T17:07:57Z move handlePodResourcesResize unit tests into allocation_manager_test - - 1a62ade74 2025-07-08T21:20:43+05:30 cleanup conntrack entries test for UDP service - - 8f92a8178 2025-07-08T17:18:34+02:00 node: e2e: podresources: add more e2e tests - - 380ed8d9b 2025-07-08T17:18:34+02:00 e2e: node: memory manager: build everywhere, run only on linux - - bc56d0e45 2025-07-08T17:18:34+02:00 podresources: list: use active pods in list - - 30a3bfdbc 2025-07-08T22:20:16+08:00 chore: remove residual uint64ptr usage with ptr package - - 006b2a3b5 2025-07-08T16:10:16+02:00 e2e: node: cpumanager: fix cpu quota non-regression tests - - 54f86a22e 2025-07-08T15:45:46+02:00 chore: removing redundant type conversion - - 25d9d8d9b 2025-07-08T15:48:35+03:00 refactor: use getLocalNode() to avoid code duplication - - bc9e8e1a9 2025-07-08T15:45:42+03:00 add a context argument to prePodCreationModificationFunc() - - 83584d13c 2025-07-08T20:27:34+08:00 fix: TestPatchResourceTimeout flaky test - - 994e106dc 2025-07-08T19:50:40+08:00 ci: update sample-apiserver version to v0.33.2 - - 3379d5ac4 2025-07-08T18:33:21+08:00 make sure all streams are created before starting demux websocket - - 1cec0aceb 2025-07-08T11:14:08+01:00 Short circuit CategorizeEndpoints when there are no endpoints - - c53b41e98 2025-07-08T11:41:36+02:00 Add testing compaction in storage List tests - - 1ac60e35e 2025-07-08T12:38:18+03:00 e2e test: Add a container_swap_limit_bytes metric - - bdd662f7c 2025-07-08T12:38:17+03:00 unit test: Add a container_swap_limit_bytes metric - - 341957a36 2025-07-08T12:36:59+03:00 Add a container_swap_limit_bytes metric - - c530b0225 2025-07-08T11:22:07+02:00 chore: depr. pointer pkg replacement for pkg/security and plugin/pkg - - dfe6a5c9c 2025-07-08T11:54:24+03:00 Clean up `unversioned_feature_list.yaml` file - - e909e0cf7 2025-07-08T09:48:56+02:00 chore: replacement of toPtr helper functions with ptr packge - - 841886df7 2025-07-08T08:08:30+02:00 Convert externaljwt from gogo to protoc - - 1b730abf8 2025-07-08T09:34:49+08:00 cleanup: use HandleErrorWithXXX instead of logger.Error where errors are intentionally ignored - - 075abb07a 2025-07-08T09:14:54+08:00 ci: redis removal for e2e test dependency simplicity - - 830a088d1 2025-07-08T09:03:38+08:00 chore: remove strPtr usage with ptr.To instead - - 838f3afc5 2025-07-07T17:37:36-07:00 storage/etcd3: add back missing errcheck - - 604cc2b51 2025-07-07T16:24:51-07:00 hack/update-openapi-spec.sh - - 5adc3bf08 2025-07-07T16:23:09-07:00 hack/update-codegen.sh - - ae7d637b8 2025-07-07T13:59:32-07:00 Delete unused ResizeContainerPatch function - - f1b35cae9 2025-07-07T13:58:40-07:00 Use MakeResizePatch instead of hand-written patch strings in resize E2Es - - 00c1c1a58 2025-07-07T13:57:48-07:00 Generate an E2E resize patch from original & desired ResizableContainerInfo - - cfd65c5f7 2025-07-07T21:28:54+02:00 chore: replacement of helper functions to ptr packge - - ff7c781e2 2025-07-07T18:34:01+02:00 Loop over all IP address from each node - - d9de37d93 2025-07-08T00:08:34+08:00 chore: typo invaILd occurrence replacement - - 1ae1964e8 2025-07-07T16:19:01+02:00 chore: depr. pointer pkg replacement for pkg/apis - - 311565141 2025-07-07T21:51:48+08:00 chore: remove uint64Ptr using ptr.To instead - - 38080c082 2025-07-07T13:30:48+02:00 kubeadm: use named ports in static pod manifests - - baf71997f 2025-07-07T13:22:36+02:00 chore: depr. pointer pkg replacement for pkg/controller - - 8abcdf088 2025-07-07T13:13:39+02:00 chore: depr. pointer pkg replacement for pkg/controller - - f966647b4 2025-07-07T12:54:05+02:00 chore: depr. pointer pkg replacement for pkg/apis - - 6cef8492e 2025-07-07T12:32:45+02:00 chore: depr. pointer pkg replacement for cli-runtime - - bc72fb81c 2025-07-07T12:25:55+02:00 chore: depr. pointer pkg replacement for test/e2e - - d193ffe57 2025-07-07T19:21:39+10:00 Use sets.Set instead of a local impl - - 277c665e8 2025-07-07T17:30:52+09:00 use early return - - 81be9065d 2025-07-07T17:17:11+09:00 improve the log message to clarify what users should do - - e74bbd5db 2025-07-06T22:32:21+02:00 chore: depr. pointer pkg replacement for test/e2e - - 2f7148782 2025-07-06T22:18:03+02:00 chore: depr. pointer pkg replacement for test/e2e and utils - - 1802c5565 2025-07-06T22:02:04+02:00 chore: depr. pointer pkg replacement for test integration - - b22ffdb48 2025-07-06T16:54:04+02:00 golangci-lint: exclude naming convention check for swagger docs - - 0e8424fcf 2025-07-06T11:27:16+02:00 chore: depr. pointer pkg replacement for the e2e_node - - bb24afe58 2025-07-06T11:20:53+02:00 chore: depr. pointer pkg replacement for component-base - - bd8d5f979 2025-07-06T11:14:15+02:00 chore: depr. pointer pkg replacement for controller-manager - - fe61e825e 2025-07-06T11:09:16+02:00 chore: second depr. pointer pkg replacement for apiserver - - 4a61b8170 2025-07-06T10:58:23+02:00 chore: first depr. pointer pkg replacement for apiserver - - 4625908a6 2025-07-06T15:58:06+08:00 remove unused file - - 995a7872c 2025-07-06T11:34:27+08:00 chore: remove utilpointer usage in pkg/api/pod - - ebae41933 2025-07-05T17:14:21-07:00 feat: add PreBindPreFlight and implement in in-tree plugins - - c5b0c9fdc 2025-07-05T12:23:02+02:00 chore: depr. pointer pkg replacement for psa policy - - 88d885e40 2025-07-05T12:13:28+02:00 chore: depr. pointer pkg replacement for psa admissiontest - - dc947510d 2025-07-05T12:09:17+02:00 chore: depr. pointer pkg replacement for psa tests - - 35e118a47 2025-07-05T09:51:57+02:00 chore: depr. pointer pkg replacement for apiext. apiservers validations - - 4a205cc7f 2025-07-05T09:50:03+02:00 chore: depr. pointer pkg replacement for apiext. pkg/cntroller - - 107c58eee 2025-07-05T09:47:37+02:00 chore: depr. pointer pkg replacement for apiextensions in general - - b8ec161d7 2025-07-05T09:39:02+02:00 chore: depr. pointer pkg replacement for apiext. integration - - ca1d7fff7 2025-07-05T11:45:52+08:00 chore: remove utilpointer usage in pkg/apis/autoscaling - - 0ad351281 2025-07-05T10:03:30+09:00 Cleanup duplicate function to get port number from named port - - 1ac5f661e 2025-07-04T11:10:55+01:00 Don't log irrelevant zone hints message on no endpoints - - 27812e44b 2025-07-04T10:47:12+02:00 chore: depr. pointer pkg replacement for apiext. pkg/registry - - b72ab8a4e 2025-07-04T09:51:22+02:00 chore: depr. pointer pkg replacement for the cloud-provider - - b464bbeb8 2025-07-04T08:55:57+02:00 Remove gogo-protobuf from CRI - - ce7b3694f 2025-07-04T12:54:52+08:00 chore: remove utilpointer usage in package test/integration/service/loadbancer_test.go - - 9016f9cb1 2025-07-04T09:29:47+08:00 chore: remove utilpointer usage in conversion package - - 90bbce56b 2025-07-03T21:14:44+03:00 PriorityMemoryEvictionOrdering: allocate more memory when swap is provisioned - - 25498cd34 2025-07-03T21:14:43+03:00 Eviction tests: small refactor - - 43b22a243 2025-07-03T05:07:24-07:00 Apply fix to namespace deletion test (#132691) - - 0766a3c6b 2025-07-03T11:58:42+02:00 chore: depr. pointer pkg replacement for the kube-aggregator apiregistration - - 6c3146e35 2025-07-03T11:34:13+02:00 chore: depr. pointer pkg replacement for the csr - - 934555227 2025-07-03T11:27:00+02:00 chore: depr. pointer pkg replacement for the reflactor - - ebea328f1 2025-07-03T10:46:45+02:00 Fix volume limit e2e test cleanup - - 38bf21327 2025-07-03T08:37:23+01:00 podtopologylabels: update topology.k8s.io->topology.kubernetes.io - - 2e966244e 2025-07-03T08:20:39+02:00 DRA resourceslice controller: fix recreation after quick delete - - fa3131700 2025-07-03T14:15:14+08:00 Remove unused PodIndexLabel feature reference - - 8c6c7df73 2025-07-03T09:57:15+08:00 remove apiserver_storage_objects metrics after crd deleted - - a7e8a505c 2025-07-02T18:53:24-07:00 Improve ignore-not-found behavior (#132542) - - 1c1f00a5f 2025-07-02T11:01:56-07:00 fix: add RV check on GC delete calls - - 84f6d742c 2025-07-02T09:50:33-07:00 Make dynamic and metadata clients plumb DeleteOptions - - ad0b2bf4f 2025-07-02T18:11:46+02:00 DRA E2E: serialize costly test - - 33cd2e1ba 2025-07-02T08:55:24-07:00 Fix AuthInfo godoc for Token / TokenFile precedence (#132659) - - c6f87f6e6 2025-07-02T10:17:26-04:00 Fix offline expansion tests for case where no node expansion tests is required - - b44b0fbf1 2025-07-02T08:00:43-04:00 Update github.com/emicklei/go-restful/v3 to v3.12.2 - - 58e620cc4 2025-07-02T07:37:06-04:00 Bump go.yaml.in/yaml/v3 to v3.0.4 - - 00f8cbae6 2025-07-02T07:32:24-04:00 Bump sigs.k8s.io/json to latest - no code changes - - 22138ef55 2025-07-02T12:57:33+02:00 Add DNS e2e test of NameIsDNSLabel validated Service names - - 97c1974e9 2025-07-02T12:57:32+02:00 Add integration test for RelaxedServiceNameValidation. - - 19e7e38af 2025-07-02T12:57:32+02:00 Add unit test for Ingress service ref relaxed validation - - 37a90b7c2 2025-07-02T12:57:32+02:00 Add unit test for Service relaxed validation - - b430159c8 2025-07-02T12:57:28+02:00 Allow Ingress service refs to be validated with apimachineryvalidation.NameIsDNSLabel - - 487eb8a9e 2025-07-02T12:55:53+02:00 Allow Service names to be validated with apimachineryvalidation.NameIsDNSLabel - - 9043afae6 2025-07-02T08:40:37+02:00 kubectl: Cache Verifier.HasSupport calls - - 179c4398f 2025-07-01T23:17:51-05:00 use defaultImage per OS - - 998776d80 2025-07-01T23:06:05-05:00 remove breaking test - - a17b0d7f6 2025-07-02T12:39:38+09:00 gofmt - - 1514568dd 2025-07-01T22:12:26-04:00 rename sortedfeatures -> sorted - - 9e1a21816 2025-07-01T22:03:22-04:00 update README - - 5cebe66b6 2025-07-01T21:57:50-04:00 update log line - - dcbed2fbd 2025-07-02T09:37:14+08:00 Graduate PodLifecycleSleepAction to GA - - 977c67073 2025-07-01T18:05:26-07:00 Add unit tests for minReady new behaviour - - 4b99dc5f1 2025-07-01T12:26:08-07:00 document hostnetwork <> port implications - - 952d2727a 2025-07-01T11:47:29-07:00 Add OrderedNamespaceDeletion to conformance. - - 12330a6c4 2025-07-01T12:49:16-04:00 Drop BoundedFrequencyRunner from pkg/util/async - - 5d4a85f9f 2025-07-01T16:13:56Z Enable versioned validation fuzz testing for certificates v1/v1alpha1/v1beta1 group - - 0fd4a0acc 2025-07-01T16:13:56Z CSR: Add declarative validation test suite - - 5db205668 2025-07-01T16:13:56Z CSR: Enable declarative validation - - eecba765d 2025-07-01T16:13:56Z Enable validation-gen on certificates/v1,v1alpha1&v1beta1 - - ec6471f63 2025-07-01T15:56:40Z Remove gnostic-models gopkg.in/yaml.v3 unwanted dependency - - d04ee27c9 2025-07-01T15:23:58Z Update vendor - - b41d375b8 2025-07-01T15:21:22Z pin kube-openapi to v0.0.0-20250628140032-d90c4fd18f59 - - 6d5e0bf2a 2025-07-01T16:59:19+02:00 review remarks - - 95b1151d2 2025-07-01T23:57:49+09:00 use format specifier - - 459188ce2 2025-07-01T08:54:14-04:00 Port BoundedFrequencyRunner from flowcontrol.RateLimiter to clock.Clock - - eae17c21b 2025-07-01T08:54:14-04:00 Change how BoundedFrequencyRunner retries work - - c16ee887e 2025-07-01T08:54:14-04:00 Remove burst syncs from BoundedFrequencyRunner - - 0298e04ea 2025-07-01T08:54:14-04:00 Updates to BoundedFrequencyRunner - - 6da9d363f 2025-07-01T08:53:54-04:00 Copy BoundedFrequencyRunner to kube-proxy - - 799aa8b2a 2025-07-01T13:04:40+02:00 Graduate streaming list encoding feature gates - - 5bae9fa89 2025-07-01T11:41:47+02:00 Graduate ConsistentListFromCache to GA - - d4e49b2ee 2025-07-01T02:25:37-07:00 Ensure Loadbalancer internal port is set to container port from endpointslice if the targetPort is not specified in service info creation. - - 6a25bdaac 2025-07-01T11:33:52+08:00 kubeadm: fix missing log of health check - - 764a8bc8b 2025-07-01T09:10:58+08:00 chore: remove utilpointer usage in package pkg/apis/admissionregistration - - a55318fe1 2025-06-30T23:11:49Z fix: versioned validation test avoid incorrect conversion - - 4c09aa907 2025-06-30T22:53:40Z review: feedback - - 776382daa 2025-06-30T21:19:21Z review: assert - - 43f6bd45f 2025-06-30T21:06:47Z review: assert - - fa87098ae 2025-06-30T17:00:27-04:00 fix: kubelet CRI portforward concurrent map write on error - - a0ea2569a 2025-06-30T20:50:51+08:00 chore: remove utilpointer usage in package staging/src/k8s.io/apiserver/pkg/registry/rest/delete - - 7236f3fc2 2025-06-30T12:35:58Z graduate APIServerTracing featuregate to GA - - 75fc2b1cf 2025-06-30T12:31:23Z promote TracingConfiguration to v1 - - a8068e27b 2025-06-30T21:31:21+09:00 scheduler_perf: Fix version emulation for empty featureGates map - - 5a20c38da 2025-06-30T12:30:47Z remove usage of KubeletTracing featuregate from kubelet - - 7faf797a9 2025-06-30T12:30:40Z promote KubeletTracing featuregate to GA - - d28791fa6 2025-06-30T20:59:13+09:00 Remove unused sysfsPath's methods - - 6e5c99dd0 2025-06-30T13:18:53+02:00 Review remarks - - ee8c265d3 2025-06-30T10:06:22Z Move Code and Status from pkg/scheduler/framework to k8s.io/kube-scheduler/framework - - 08dd9c47b 2025-06-30T18:27:55+09:00 improve the log message to clarify the cause of the failure - - a6e2cd4e8 2025-06-30T17:52:24+09:00 scheduler_perf: add logs to report the failure of measuring SchedulingThroughput - - 7e816ca9b 2025-06-30T16:14:50+09:00 Commented out for unused sysfspath methods - - 2bc45ca46 2025-06-30T16:14:44+09:00 Make test only helpers private (sysfspath methods, touchFile, createSymlink) - - 94973ba3f 2025-06-30T16:14:33+09:00 Fix typo: s/smock/mock/g - - ac86e67b7 2025-06-30T08:07:21+02:00 Commonize filtering of Pods by Owner with all orphans in namespace - - ca314b9f5 2025-06-30T07:58:04+02:00 Fix validation for Job with suspend=true,completions=0 to set Complete condition - - 1134220e0 2025-06-28T14:06:34+02:00 Add RelaxedServiceNameValidation feature gate - - f644e35d1 2025-06-28T11:21:54+02:00 kubeadm: cleanup after WaitForAllControlPlaneComponents GA - - cfe860450 2025-06-28T11:16:01+02:00 kubeadm: graduate WaitForAllControlPlaneComponents to GA - - f437aa4aa 2025-06-28T11:00:23+09:00 scheduler_perf: Set version emulation only when QueueingHints is disabled - - b2f27c064 2025-06-27T16:32:29-07:00 fix: Truncate too long Deployment name in RS name (#132560) - - d67e7937e 2025-06-27T17:57:16-04:00 Remove recovery related featuregates - - fa6f27c8f 2025-06-27T17:52:46-04:00 Add extra validations for newer resizing related fields - - 00dd610c9 2025-06-27T21:15:50+02:00 DRA E2E: run some tests without feature label - - f93b4408a 2025-06-27T15:02:34-04:00 Drop test that checks openAPI resource name since we currently don't guarantee name stability in the API - - 3eefb05a2 2025-06-27T11:49:41-07:00 Fix gRPC listener error message in kubeletplugin and some minor renaming - - e54e01e0a 2025-06-27T11:38:12-07:00 Enhance help text for the 'top' command - - 7d5ab7562 2025-06-27T14:30:58-04:00 Re-generate applyconfigurations - - 9af684ae0 2025-06-27T14:30:57-04:00 Applyconfig-gen: Only the root type is an applyconfiguration - - d50e1a684 2025-06-27T11:13:50-04:00 Ensure all the files have the updated sorting - - f2d8b7ec2 2025-06-27T11:05:13-04:00 Add linter to report on unsorted feature gates - - efcb03759 2025-06-27T16:10:38+02:00 E2E framework: sort tests in JUnit report - - dfd34a5b1 2025-06-27T16:30:51+08:00 fix pod template spec validation missing in sts - - a57f15e08 2025-06-27T10:06:50+02:00 DRA kubelet: remove v1alpha4 - - 005cef332 2025-06-27T09:30:28+02:00 DRA kubelet: API clarification - - f1845218e 2025-06-26T23:21:18-05:00 fixup! DRA: fix deleting orphaned ResourceClaim on startup - - 585ed0a5c 2025-06-26T22:00:41-04:00 [client-go #1415] Use transformer from provided store within internal stores in reflector to limit memory usage bursts - - 8632257c9 2025-06-26T21:24:43Z Cleanup: Remove redundant detail messages in field.Required - - e82d4f8e5 2025-06-26T18:25:42Z review: feedback - - 5cca03792 2025-06-27T00:49:02+09:00 resolve linter check - - ce86fca8c 2025-06-26T15:10:42Z Add warnings for use of Alpha features with Emulated Version Warn for both api and feature flag use of alpha features with emulated versions. This is an unsupported use case and users may run into issues. - - 00d375050 2025-06-26T08:06:29-07:00 Move ClusterEvent type to staging repo, leaving some functions (that contain logic internal to scheduler) in kubernetes/kubernetes (#132190) - - 74af3ac8a 2025-06-26T23:49:34+09:00 Revert "pop respects the context" - - 2dcce9333 2025-06-26T23:49:25+09:00 Revert "modify tests" - - 31667cc74 2025-06-26T09:15:02-04:00 Avoid killing kops etcd-manager - - 6d6a749c6 2025-06-26T14:31:03+02:00 DRA kubelet: add dra_resource_claims_in_use gauge vector - - 75432a141 2025-06-26T14:15:43+02:00 component-base metrics: allow usage of Prometheus types in tests - - 1639b0908 2025-06-26T11:09:24+02:00 Add benchmark for SizeBasedListCostEstimate feature - - c75d425ae 2025-06-26T07:44:13Z CHANGELOG: Update directory for v1.34.0-alpha.2 release - - 292679a28 2025-06-26T09:30:48+02:00 Handle consistent LIST in watch cache to avoid incorrect semantics while setting ResourceVersion on options - - c6c15bbe4 2025-06-26T00:11:20-04:00 bug: Remove duplicate DaemonSet update validations - - 39dda2b88 2025-06-26T00:59:34Z tests: runtime units - - 8bd8c1431 2025-06-25T22:00:40Z tests: add more units - - f9a5aec31 2025-06-25T23:59:44+05:30 Added unit tests - - 5390f7536 2025-06-25T23:59:26+05:30 Added podutil.HasAPIObjectReference to deny admission for static pods referencing API objects - - 8b2eb9090 2025-06-25T17:39:14Z chore: Remove vet target and associated script from Makefile and hack directory - - 7d85134ca 2025-06-25T17:18:07Z improve unit test coverage for pod observedGeneration - - 1a59c250e 2025-06-25T16:38:50Z feat: make CLE timers configurable - - ef117edf3 2025-06-25T11:11:43-05:00 DRA: fix deleting orphaned ResourceClaim on startup - - c5b4b133c 2025-06-25T11:42:12-04:00 switch to latest sigs.k8s.io/yaml v1.5.0 (run update-gofmt.sh as well) - - e2c6b7fdf 2025-06-25T17:25:58+02:00 Override getKeys when cacher is enabled - - 7cb241799 2025-06-25T17:25:58+02:00 Run background cleanup goroutine - - ec78b8305 2025-06-25T17:25:56+02:00 Estimate average size of objects in etcd and plug it into request cost estimator - - 190c8c7ab 2025-06-25T11:17:20-04:00 Use per-policy marker names for VAP integration tests. - - 6795d5366 2025-06-25T22:44:47+08:00 feature(kubectl): support mem-percent,cpu-value,cpu-average-value,mem-value,mem-average-value flag to kubectl autoscale - - 9de075def 2025-06-25T13:21:46+02:00 replacing deprecated pointer pkg with newer package version - - b8b398487 2025-06-25T04:04:29-07:00 client-go/reflector: stop exposing UseWatchList (#132453) - - 0028ea8e9 2025-06-25T08:51:29+02:00 Improve containers lifecycle test output parsing - - 7e0d71fc1 2025-06-25T08:51:20+02:00 apiserver/storage/cacher/listwatcher: error when the WatchList FG is disabled - - ec6ea2213 2025-06-25T13:39:12+08:00 test: code coverage increase for kubelet_client - - cb4014fb7 2025-06-24T22:25:41-04:00 cleanup: Migrate more usages of deprecated function ExtractCommentTags - - b50d50817 2025-06-25T08:23:53+08:00 bugfix(hpa): introduce buildQuantity helper for consistent resource quantity creation - - cbba973b6 2025-06-24T17:21:57-07:00 Fixing go-vet finding "call of reflect.DeepEqual copies lock value" by just asserting on the basic fields that should be reset when ClearState() is called - - 35ecb00f1 2025-06-24T22:19:35Z fix: Add wait for cache sync for customresourcediscovery tests - - d6d186ece 2025-06-24T20:56:44+02:00 Activly poll for namespace termination instead of sleeping - - e1daa69de 2025-06-24T14:52:37-04:00 Add printer column validation tests - - 369e6a25a 2025-06-24T14:52:27-04:00 Introduce k8s-short-name and k8s-long-name to the OpenAPI formats supported by CRDs - - 6f1295ae9 2025-06-24T11:04:25-07:00 fix: prevent SSA from creating CR while CRD terminating - - 3b0fd3281 2025-06-24T15:46:06+02:00 e2e: serial: cpumanager: continue on failure - - f76e1381d 2025-06-24T15:46:01+02:00 e2e: node: fix quota disablement testcases - - dc323756c 2025-06-24T09:24:27-04:00 Bump to latest kube-openapi - - d180fe28a 2025-06-24T09:23:39-04:00 Add json-patch v4 compatibility test - - 2ca4ffe65 2025-06-24T09:18:04-04:00 Add evanphx/json-patch/v5 to unwanted dependencies - - 5a7e04b6c 2025-06-24T21:12:56+08:00 feat: optimize ListAll and ListAllByNamespace to return directly when nothing to select - - ae13d1019 2025-06-24T12:41:42Z KEP-5229: Add SchedulerAsyncAPICalls feature gate - - dce69afad 2025-06-24T11:39:44+02:00 apiserver/cacher: properly wire listwatch options to the listwatcher - - 0276769c2 2025-06-24T11:07:47+02:00 kubectl: avoid logging during init - - 6040344a6 2025-06-24T10:42:46+02:00 kubelet: DRA: fix TestRegistrationHandler - - cc7893a42 2025-06-24T10:42:45+02:00 kubelet: DRA: fix unit test failure - - cf544da6f 2025-06-24T10:42:45+02:00 e2e_node: DRA: add tests for different socket setups - - 7f6389e77 2025-06-24T10:42:45+02:00 e2e_node: DRA: pass socket path as a parameter - - 3ae99f254 2025-06-24T10:42:45+02:00 kubelet: DRA: fix test failure on Windows - - c90c2e0d4 2025-06-24T10:42:45+02:00 kubelet: DRA: fix linter warnings - - 165bb1da5 2025-06-24T10:42:45+02:00 DRA kubelet: use TimedWorkersQueue - - 4ee7374b2 2025-06-24T10:42:41+02:00 DRA kubelet: add connection monitoring - - f927cd010 2025-06-24T09:05:43+02:00 DRA kubelet: simplify plugin creation and connection handling - - cfeab03ad 2025-06-24T11:50:18+08:00 remove kvh.exec - - 75862f3f4 2025-06-23T17:00:31-07:00 show namespace on delete (#126619) - - 56d97283a 2025-06-23T21:37:00Z fix: Improve error messaging on updating a deleted object - - fd8bf1c82 2025-06-23T14:58:57-04:00 e2e: retry getting status on restart policy tests - - c5f061e0d 2025-06-23T17:57:12Z Fix pod and container level swap metrics for CRI - - e1d74f1d3 2025-06-23T23:00:38+05:30 Update etcd image revision to 3.6.1-1 - - 7e3945808 2025-06-23T18:12:13+05:30 nftables: remove filter-output-post-dnat chain - - 91f2256b3 2025-06-23T18:12:13+05:30 update filter chains and priority - - 72305f82f 2025-06-23T13:06:19+02:00 Move UnsafeCorruptObjectDeletion outside of etcd3.New function - - 59dd2bd60 2025-06-23T17:57:59+08:00 ci: update test image base: nginx, nginx-new - - af89044a7 2025-06-23T00:37:28+05:30 conntrack: clean stale entries on endpoint port change - - 861e7b8fa 2025-06-20T12:30:51-07:00 fix unit test flake for authn config on windows - - 2fd93c089 2025-06-20T22:29:13+08:00 fix: data race for patchResource func - - ccdef28ac 2025-06-20T10:33:43+02:00 fixing large resourceversion and limit for storages - - fe8437745 2025-06-20T08:28:04+02:00 e2e/watchlist: new test for checking metadata informer - - d6ba9e1b9 2025-06-20T07:07:42+02:00 replacing depr. pointer pkg with new ptr pkg on src/apimachinery - - db32c4cf7 2025-06-20T09:11:35+10:00 fixing syntax issue for etcd builds - - 8454093f0 2025-06-19T15:19:00-05:00 DRA: add e2e test with initContainer using external claim - - 138e363e4 2025-06-19T11:48:15-04:00 cleanup shellcheck for temporary HOME directory - - 66c611125 2025-06-19T16:32:20+08:00 Add namespace-aware orphan pod indexing - - 5e54df3e7 2025-06-19T15:32:23+08:00 Fix [Failing test] [sig-node] [Feature:GPUDevicePlugin] [Serial]-related tests - - 280cecb8f 2025-06-19T17:07:32+10:00 fixing location to ensure the cp commands dont fail - - d2945a21f 2025-06-19T12:21:44+10:00 bumping revision - - fa1832484 2025-06-19T11:48:23+10:00 handling the etcd 3.6+ build directory location change - - e68d60134 2025-06-19T10:11:17+09:00 Don't panic in case of an unknown API error code - - 4ca91a030 2025-06-19T10:11:17+09:00 WIP: Fix tests - - 2b2c9adef 2025-06-19T10:11:16+09:00 Nicer value rendering in API errors - - cfff359b4 2025-06-18T18:01:28-04:00 fix for gimme when $HOME is not writable - - 6a654e5be 2025-06-18T21:15:30Z Deprecate StreamingConnectionIdleTimeout field, that is not being used for a long time - - b8cd05881 2025-06-18T14:13:47-07:00 Address PR comments - - 6f97f5bbf 2025-06-18T14:02:57-07:00 Use Mock CSI Driver for MutableCSINodeAllocatableCount storage e2e test (#132373) - - 176095ac3 2025-06-18T13:57:41-07:00 [KEP-5100] WinDSR feature gate to GA - - 64c44e1fa 2025-06-18T16:12:24-04:00 Test that generated applyconfigs are a runtime.ApplyConfig - - a5d42f569 2025-06-18T16:12:24-04:00 Re-Generate applyconfigs - - d5527b519 2025-06-18T16:12:24-04:00 Update applyconfiguration-gen so acs implement runtime.applyconfiguration - - 3fe4ea550 2025-06-18T16:12:24-04:00 Add an interface that all applyconfigs implement - - b0b52f4fb 2025-06-18T18:59:10Z CHANGELOG: Update directory for v1.30.14 release - - 2bc98f123 2025-06-18T18:36:13Z CHANGELOG: Update directory for v1.31.10 release - - 20e9f160c 2025-06-18T18:11:53Z CHANGELOG: Update directory for v1.32.6 release - - 9e126a377 2025-06-18T17:54:50Z CHANGELOG: Update directory for v1.33.2 release - - df32f10e0 2025-06-19T01:23:10+08:00 apimachinery/pkg/util/errors: deprecated MessageCountMap - - de2f22ee8 2025-06-18T17:43:58+02:00 e2e/watchlist: intro verifyStoreFor - - 017c9b94d 2025-06-18T17:34:05+02:00 e2e/watchlist: rename toSecretPointerSlice - - caa64afd0 2025-06-18T22:38:21+09:00 merge constants.go into attribute.go - - 73d65f830 2025-06-18T21:30:52+09:00 Put _linux suffix for linux specific go files - - 88b34ea1f 2025-06-18T21:28:41+09:00 Move bdfRegexp from global constant to local variable - - fc854a9a8 2025-06-18T21:26:15+09:00 Introduce DeviceAttribute{Name, Value} and change return type of 'GetPCIeRootAttributeByPCIBusID' with it - - 8ed8217e9 2025-06-18T21:26:13+09:00 Moved device attribute constants from api to deviceattribute package - - f7461a12d 2025-06-18T21:04:16+09:00 Revert "Add StandardDeviceAttributes and StandardPCIDeviceAttributes helper functions" - - 6b9ac7c51 2025-06-18T12:32:04+02:00 cluster/gce: rm KUBE_LIST_FROM_CACHE_INCONSISTENCY_DETECTOR - - 512563e7b 2025-06-18T14:22:26+05:30 pkg/proxy/conntrack: refactor - - 91b4816c2 2025-06-18T15:28:12+08:00 Optimize job controller performance: reduce work duration time & minimize cache locking - - 18dd1daae 2025-06-17T12:01:02-07:00 Add Windows Server 2025 (ltsc2025) to BASEIMAGEs (#132235) - - 44b4682a3 2025-06-17T22:38:10+05:30 Use jq docker image for pause windows build - - 3827d3bc4 2025-06-17T11:00:27-04:00 Drop usage of forked copies of goyaml.v2 and goyaml.v3 - - 2869b6f42 2025-06-17T23:04:43+09:00 Add StandardDeviceAttributes and StandardPCIDeviceAttributes helper functions - - a8ab9eb5f 2025-06-17T22:58:17+09:00 Simplify the implementation: just provide GetPCIeRootAttributeByPCIBusID - - d390902b9 2025-06-17T22:30:45+09:00 Verify scheduler resource metrics account for Pod Level Resources - - 32fcaf140 2025-06-17T15:05:46+02:00 client-go/util/consistencydetector: move IsDataConsistencyDetectionForWatchListEnabled - - 72654620a 2025-06-17T13:49:58+02:00 removing WaitIntervalString from iptables - - bad493904 2025-06-17T13:37:57+02:00 client-go/util/consistencydetector: remove CheckListFromCacheDataConsistencyIfRequested - - 15ca38b52 2025-06-17T12:01:02+02:00 apimachinery/meta/types.go: remove InitialEventsListBlueprintAnnotationKey const - - 690790257 2025-06-17T11:47:17+02:00 Add test verifying KUBECTL_KUBERC can be turned on and off - - 45449a78d 2025-06-17T11:14:47+02:00 Removing setting KUBECTL_KUBERC env var, now that it's on by default - - 3f32edeac 2025-06-17T15:45:44+08:00 chore: Remove the dependency of the volume manager on the container runtime. - - 3dc1810bb 2025-06-17T15:26:01+08:00 fix: failed unit test. - - b8a2127d2 2025-06-17T05:53:18Z Add random interval to nodeStatusReport interval every time after an actual node status change update or restart - - fbf4b47d1 2025-06-17T13:30:45+08:00 chore: clean up probemanager for shutdownnamager. - - 3fa23d06a 2025-06-17T06:39:33+02:00 Adjusting AdminAccess Type for API v1beta1 - - 2a5e4d558 2025-06-17T03:35:12Z add script for verifying dead code elimination - - 891e7fec6 2025-06-17T09:30:41+08:00 add seperate health check/probe for multi etcd override servers - grouping health checks for exclusion purposes & add exclude integration test - - 28573e373 2025-06-16T15:34:06-07:00 Add error prefixes for authn config load or validation failures - - 4cb6d3d77 2025-06-17T00:10:48+02:00 Validate requests sent to etcd in TestList "test List with limit" scenario - - 03afe6471 2025-06-16T17:10:42-04:00 Add a replacement for cmp.Diff using json+go-difflib - - 32ec4e68c 2025-06-16T21:51:24+02:00 adding omitempty tag and opt tag - - e654deba6 2025-06-16T18:44:59Z CHANGELOG: Update directory for v1.34.0-alpha.1 release - - f4a458625 2025-06-16T17:36:23Z fix APIServerTracing test data race - - 2004ee50f 2025-06-16T16:08:46Z Fix -Consistent paginated lists serve from cache - - bccc9fe47 2025-06-16T16:26:03+02:00 KEP-3939: Job Pod Replacement Policy; promote to GA - - fc198b92c 2025-06-16T07:02:59-07:00 apiserver/handlers/watch: stop encoding initialEventsListBlueprint (#132326) - - 854499f98 2025-06-16T20:51:17+08:00 clean: use correct pod template - - fae2fdd05 2025-06-15T23:49:43-05:00 DRA: wrap e2e finalizer update in retry - - 7a95f3e47 2025-06-16T00:11:48+09:00 Fix NetworkPolicy podSelector comments - - 233a0aeed 2025-06-15T13:04:25+02:00 DRA E2E: label tests which need a certain minimum kubelet, II - - 2cd5dbbda 2025-06-15T15:50:22+09:00 modify tests - - 59f0ab97c 2025-06-15T15:50:02+09:00 Add boilerplate header to go files - - 1c33d9876 2025-06-15T15:31:34+09:00 pop respects the context - - f67d30b35 2025-06-15T15:31:33+09:00 handle context in process loop - - 384240b4d 2025-06-14T17:50:38-07:00 Use "Invalid" errors rather than "TypeInvalid" - - bdfa8839b 2025-06-14T18:39:15+02:00 calculateStatus should use the same now time point for each pod - - ce44bcdf5 2025-06-14T16:10:04Z conformance servicecidr read status endpoint - - c2988884f 2025-06-15T00:01:29+08:00 fix kubeadm e2e tests - - cb26d065d 2025-06-14T15:57:48+09:00 Validate PCI Address (domain is 16 bits, bus is 8 bits, device is 5 bits, function is 3 bits) - - 752a04369 2025-06-14T15:57:46+09:00 fix lint: apply De Morgan's laws to simplify conditionals - - 76ef6a388 2025-06-14T14:45:29+08:00 fix kubeadm e2e tests - - 79601d135 2025-06-13T13:50:03-07:00 Fix CRI fake_runtime RemovePodSandbox - - 666f38f41 2025-06-14T04:19:00+09:00 DRA: Introduce a helper function producing standardized device attributes for DRA drivers - - 7a3af908c 2025-06-13T17:54:36Z add securitycontext OWNERS to be SIG Node as the package is mostly used and contributed by SIG Node - - 7f1dde2a0 2025-06-13T17:23:16+02:00 test/apimachinery/watchlist: properly wire modified config to informer for fallback case - - 40c718864 2025-06-13T15:28:55+02:00 chore(apiserver): avoid using html template which disables dce - - 6a3797684 2025-06-13T14:15:51+02:00 client-go/rest: rm watchlist - - 4372c59eb 2025-06-13T13:35:00+02:00 update go version for publishing bot rules - - e09b042d3 2025-06-13T16:28:35+05:30 Bump etcd to v3.6.1 - - 901441c66 2025-06-13T11:15:35+08:00 Promote SeparateTaintEvictionController to stable - - 85bc3cb09 2025-06-13T10:58:37+08:00 Remove GetExec method from VolumeHost - - 9251b2a7a 2025-06-12T16:02:19-04:00 Expand webhook test to check rejection metrics - - f8b4ea50e 2025-06-12T19:26:26+02:00 ./hack/update-internal-modules.sh - - 71b2f32d7 2025-06-12T18:16:04+02:00 DRA E2E: label tests which need a certain minimum kubelet - - 3908550c0 2025-06-12T11:20:39-04:00 Update to latest github.com/modern-go/reflect2 - - d8bfafe07 2025-06-12T16:02:10+02:00 test/apimachinery/watchlist: prove typed client's List method not streaming - - 601065a7c 2025-06-12T09:44:41-04:00 bug: Fix misleading response codes in admission control metrics - - 5882df8be 2025-06-12T21:43:03+08:00 promote env test to conformance - - 69a5bda83 2025-06-12T18:15:11+05:30 Bump base image used in nonewprivs to alpine:3.22 - - 04110fce1 2025-06-12T21:29:54+09:00 Correct error message to print `ResetConfigurationKind` - - 3443c1115 2025-06-12T13:54:57+02:00 make update - - 798c6ebab 2025-06-12T13:41:50+02:00 client-gen/code-generator: remove watchList - - db2555628 2025-06-12T07:35:07-04:00 Fix: HPA suppresses FailedRescale event on successful conflict retry - - 2f943293e 2025-06-12T13:13:02+02:00 client-go/gentype: remove watchlist - - f0dde3823 2025-06-12T17:29:17+08:00 Remove pluginName param from GetMounter and GetExec - - fb611f4c9 2025-06-12T11:27:51+03:00 kubectl delete: Update interactive delete to break on new line - - d46e13b9c 2025-06-12T16:06:50+08:00 change the command of the terminated container - - 226c0d109 2025-06-12T11:49:12+05:30 Bump ipc-utils base image to alpine:3.22 - - e75ccce83 2025-06-12T10:48:53+08:00 feat: optimize label selector match performance - - ac467d3ae 2025-06-11T23:44:52Z add ratcheting testcase for validateFalse tag - - 9384285c6 2025-06-11T23:44:52Z add ratcheting testcase for minimum tag - - 1574001a1 2025-06-11T23:44:52Z run update-codegen.sh - - f574115f1 2025-06-11T23:44:52Z feat: add default ratcheting support - - e9eabb200 2025-06-11T23:44:52Z feat(validation-gen): Refactor type handling and introduce utility functions - - 03c6e15f8 2025-06-11T16:35:44-07:00 bump to alpine 3.22 and bump apparmor-loader to 1.6 - - b86b4632b 2025-06-11T15:35:56-07:00 disable selinux relabeling when mounting sourcedir to shellcheck - - dc3836c49 2025-06-11T15:31:37-07:00 Remove deprecated encryption config controller metrics - - 5a2844a76 2025-06-11T16:46:03-04:00 Update to etcd v3.6.1 in vendor/ - - a9108e8f5 2025-06-11T15:52:40-04:00 Adding `grpcnotrace` tag for production (non-debug) builds - - 11abb0042 2025-06-11T17:14:39+02:00 Fix outdated links in VolumeSource godocs - - 4b2fe2a54 2025-06-11T22:35:08+08:00 pkg/kubeapiserver: use utils/ptr package instead of utils/pointer - - 69eddde89 2025-06-11T21:49:38+08:00 using finalizer - - 57d55fbb1 2025-06-11T21:29:24+09:00 test: Add test case for createNodeOp - - 1d69a2fbc 2025-06-11T12:04:53+02:00 ./hack/update-vendor.sh - - edadfee47 2025-06-11T12:04:48+02:00 test/apimachinery/watchlist: prove dynamic client's List method not streaming - - 348ff7497 2025-06-11T14:53:35+05:30 Build etcd image v3.6.1 - - 3038f3530 2025-06-11T09:58:05+02:00 client-go/dynamic: rm watchlist - - 86c709cd8 2025-06-11T12:34:18+05:30 skip nfacct test in IPv6 clusters - - e5f36796e 2025-06-11T08:24:35+02:00 Bump dependencies, images and versions used to Go 1.24.4 and distroless iptables - - 07151bb0f 2025-06-11T04:27:21Z chore: Add validation error for unsupported map of slices in validation-gen - - 89f5453e3 2025-06-10T23:16:41-04:00 Allow system:monitoring role to access kubelet metrics endpoints - - 2810f6e65 2025-06-10T20:10:02-07:00 add bentheelder to cmd/preferredimports *reviewers* - - 00a6d2c99 2025-06-10T20:09:57-07:00 add bentheelder to conformance related test *reviewers* - - 1dd055774 2025-06-10T20:05:40-07:00 backfill some sig-testing-reviewers (tech leads aojea and pohly) - - ad68a4b4c 2025-06-10T20:05:40-07:00 emeritus spiffxp - - 512f000d0 2025-06-10T14:11:30-07:00 Update tests for StructuredAuthenticationConfiguration feature gate GA - - efebfe9e3 2025-06-10T14:04:28-07:00 Set StructuredAuthenticationConfiguration feature gate to GA in v1.34 - - 769d71b30 2025-06-10T20:15:07Z Remove unused Expect methods in testscheme - - 105dd3b0a 2025-06-10T20:15:06Z Add ExpectMatches to ValidationTester - - 28e973c04 2025-06-10T18:08:45Z Better formatting of matcher errors - - b39741b50 2025-06-10T19:25:48+02:00 e2e: node: serial: fix cgroup path with crio - - 26b188aaa 2025-06-10T17:13:15Z KEP-4633: Graduate to Stable. - - fd5d7a18e 2025-06-10T19:58:36+03:00 reduce logspam when calculating sandbox resources - - 0baeccd32 2025-06-10T16:16:13Z KEP-740: promote ExternalJWTSigner feature to beta - - ef2c18a5a 2025-06-11T00:02:48+08:00 Add more test cases - - eb3c9a318 2025-06-10T15:41:50Z Promote feature OrderedNamespaceDeletion to GA. - - f8b701243 2025-06-10T16:56:58+02:00 Revert "improve display format" - - 449320a54 2025-06-10T10:50:54-04:00 update github.com/spf13/cobra v1.9.1 - - 260a720a8 2025-06-10T09:38:55-04:00 Rate-limit the LoadBalancer rolling update test - - 0a86ca406 2025-06-10T21:14:17+08:00 Add healthChecker to the kubeDeps - - dacafec88 2025-06-10T08:46:34-04:00 KEP-3015: PreferSameTrafficDistribution to Beta - - b2ab0ba19 2025-06-10T11:37:47+02:00 Drop unused testing manifest - - 96b39187c 2025-06-10T08:45:51+02:00 Add context to Count() - - 9d1bc51cb 2025-06-10T10:52:25+08:00 adjust durations for sleepAction - - c85ac59df 2025-06-09T17:41:41-04:00 Build k8s using latest commit of golang - - 4a7e68a35 2025-06-09T21:27:57+08:00 fix: Fix the issue where kubelet's slow startup causes it to be mistakenly killed by the watchdog. - - b02fba7e0 2025-06-09T14:30:05+08:00 Fix incorrect logging of insufficientResources in preemption - - fc7ba63ee 2025-06-08T16:48:09+05:30 support parsing of iperf 2.2.0 output - - 1755a9e54 2025-06-08T16:42:25+05:30 fix: iperf version in comments - - 0ca9c380a 2025-06-08T12:00:14+08:00 update all api files - - 32aa52adf 2025-06-07T19:52:48-04:00 tolerate newer golang/oauth2 version - - 3cfa73bc1 2025-06-07T17:42:29+03:00 add -q flag for git worktree - - 97ec8618d 2025-06-07T10:28:36-04:00 Fix kubelet iptables startup, clarify semantics of utiliptables calls. - - 6a4751da7 2025-06-07T20:32:03+08:00 Graduate RelaxedEnvironmentVariableValidation Feature gate to GA - - f4ab6c2be 2025-06-06T17:57:43-04:00 cleanup: Migrate deprecated function ExtractCommentTags - - 0d468f58c 2025-06-06T20:37:50Z kuberuntime_manager: don't log entire container spec. - - 858b88bce 2025-06-07T01:14:33+05:30 kube-proxy: log ipt errors during platformCheckSupported - - 1f46b3fdb 2025-06-06T18:31:38Z Clean backoff record earlier - - 7b1f49906 2025-06-06T18:24:33+02:00 DRA kubelet: rename Store + Plugin -> DRAPluginManager + DRAPlugin - - fad670c27 2025-06-06T18:24:33+02:00 DRA kubelet: move RegistrationHandler into Store - - 494a129d0 2025-06-06T18:24:33+02:00 DRA kubelet: clarify plugin vs, driver name - - 0d5578b83 2025-06-06T16:46:15+02:00 test/apimachinery/watchlist: prove metadata client's List method not streaming - - 5b0f0d2ef 2025-06-06T10:40:00-04:00 update pr template issue links section - - a38ad3a2c 2025-06-06T16:15:43+02:00 client-go/metadata: rm watchlist - - beb86a839 2025-06-06T16:15:30+02:00 KEP-3329: drop PodDisruptionConditions feature gate - - b5a8f5d0a 2025-06-06T16:08:21+02:00 KEP-3715: drop ElasticIndexedJob feature gate - - 10de6780c 2025-06-06T12:06:28+02:00 DRA API: remove obsolete types from v1alpha3 - - 089669369 2025-06-06T16:03:46+08:00 fix TestNodeAffinityPriority: calculate the priorities correctly even if PreScore is not called - - 087554448 2025-06-06T02:26:05Z Make nodeports scheduling plugin sidecar initContainer aware - - 1876c5445 2025-06-05T22:44:31Z Remove unsupported map of slice validation for non-byte elements in validation-gen - - 501393810 2025-06-05T18:24:06-04:00 Change option to a slice - - 990cb7547 2025-06-05T17:02:41-04:00 Use slice.Contains() - - 28e99ef2e 2025-06-05T16:51:11-04:00 Add type information to tag Docs() and use it to typecheck tags - - 31aa3c202 2025-06-05T15:29:12-04:00 Switch to using named args in output_tests - - 7892fd95f 2025-06-05T15:29:12-04:00 Use codetags in validation-gen - - 249801b7c 2025-06-06T00:42:58+05:30 Fix windows-pause-image-base:@ invalid reference format - - 2c4c3037b 2025-06-05T11:17:47-04:00 Fix field path for embedded fields in root types - - d1bddfd77 2025-06-05T18:03:56+03:00 Forbid github.com/pkg/errors in k/k - - efaaece0f 2025-06-05T17:58:09+03:00 go.mod: drop pkg/errors as a direct dep - - cbbfabe7f 2025-06-05T10:50:14-04:00 Support embedded fields properly - - d1a858ca9 2025-06-05T17:48:13+03:00 kubeadm: fix one missed pkg/errors location - - 036f4bfe2 2025-06-05T15:08:35+02:00 hack: fix KUBE_RACE in benchmark-dockerized.sh - - 5be254650 2025-06-05T16:05:02+03:00 kubeadm: start using util/errors - - f522d7cb8 2025-06-05T16:04:52+03:00 kubeadm: add a local implementation of wrapped errors - - 2bf3d8b73 2025-06-05T14:02:44+02:00 KEP-3335: drop StatefulSetStartOrdinal feature gate - - 1d1d0c154 2025-06-05T14:45:00+05:30 promote agnhost to v2.56 - - 258961cb3 2025-06-05T05:30:59Z pkg/appis/apps: use utils/ptr package instead of utils/pointer - - 7b664a113 2025-06-05T05:20:46Z pkg/volume: drop pointer wrapper functions. - - 253a08d7e 2025-06-05T04:48:25Z pkg/util: drop pointer wrapper functions. - - ac5cb2300 2025-06-04T22:39:08-04:00 Bump gengo/v2 to latest - - d6ec03a13 2025-06-04T13:28:20-07:00 Preempt based based on allocated resources rather than desired - - 7d47165e3 2025-06-04T13:48:11-05:00 Replace queue.FIFOs with k8s.io/utils/buffer.Ring - - 705e89b04 2025-06-04T11:45:12-07:00 Only set pod allocation if admission succeeds - - f8b893489 2025-06-04T20:36:15+02:00 Update pkg/kubelet/kubelet_test.go - - 147073102 2025-06-04T18:06:07Z fix: prevent data race in metric LabelValueAllowList initialization - - 8cdbbf5cd 2025-06-04T12:56:39-05:00 Update k8s.io/utils for new generic ring buffer - - daae472fe 2025-06-04T13:27:50-04:00 e2e_node: verify restart looping container correctly - - 109ae1bac 2025-06-04T10:08:00-07:00 feat: Allow leases to have custom labels set when a new holder has the lease - - 8d3fb9ee0 2025-06-04T07:10:38-07:00 [KEP-2400] kubectl top: add a --show-swap option (#129458) - - 4c7840ec5 2025-06-04T15:33:27+02:00 podResizeMutex cleanup - - c7fdf6abd 2025-06-04T11:47:03+05:30 Handler will return the server port number instead of address - - 6a495241e 2025-06-03T14:40:17-07:00 KEP-3331: Add test to simulate revocation via user validation rule using unique identifier (jti) - - 466fb8152 2025-06-03T15:58:41-03:00 test/e2e/apimachinery/namespace.go: make OrderedNamespaceDeletion test serial - - 7e7aa6d81 2025-06-03T18:22:48+02:00 e2e: node: cpumanager: require cgroup v2 - - 68efb079a 2025-06-03T16:17:25+02:00 kuberc: add tests for DefaultGetPreferences - - ad3a13e01 2025-06-03T19:28:20+08:00 Graduate NodeLocalCRISocket to beta - - b9d9dea03 2025-06-03T16:08:29+08:00 Update npd from v0.8.20 to v0.8.21 - - 47dead1c4 2025-06-02T22:46:55Z unexport allocationManager IsPodResizeInProgress - - de1d6fbf2 2025-06-03T01:12:31+03:00 fix: ResolverTypeProvider data race - - 9b8d7ce49 2025-06-02T17:51:03Z pr review feedback - - a512de6e0 2025-06-02T16:53:10Z Clarified the token scope and future plans for the next security scan to refer to it - - 032a9eaed 2025-06-02T18:30:04+02:00 DRA kubelet: code cleanup - - a6e226899 2025-06-02T14:29:38+02:00 Ensure github.com/pkg/errors is used only in kubeadm - - 7ccb9657f 2025-06-02T21:19:38+09:00 sched: Apply EnablePlugins to CoreResourceEnqueueTestCases - - 6cb14884b 2025-06-02T11:47:42+02:00 test-integration: allow enabling race detection - - 545fbc99c 2025-06-02T11:27:09+02:00 test: drop dependency on github.com/pkg/errors - - 899f76159 2025-06-01T00:48:16+08:00 add unit test for IsDNS1123SubdomainWithUnderscore function - - 0a7d9f9bf 2025-05-31T07:45:16+02:00 KEP-4427: Promote Relaxed DNS search string validation to GA - - 2aa7ef3d2 2025-05-30T22:20:30Z Address comments - - dbdd6a3b4 2025-05-30T15:33:42-04:00 FieldManagedObjectTracker: Fix to work with unstructured - - b7d16fea7 2025-05-30T21:08:12+02:00 disable terminatingReplicas reconciliation in ReplicationController - - ee33c1a9f 2025-05-30T13:32:52-04:00 e2e: fix userns test - - be049397d 2025-05-31T00:52:04+08:00 Fix IsDNS1123SubdomainWithUnderscore to return correct error message - - 4f91a69f2 2025-05-30T10:29:18+02:00 DRA integration: move and extend device status test - - 0a9661375 2025-05-30T16:13:06+08:00 proxy: remove iptables wait interval flag - - a5aabf9f7 2025-05-30T09:52:22+02:00 DRA kubelet: validation pass before changing claim info cache - - 5420dcec5 2025-05-29T20:22:34-04:00 Promote two more EndpointSlice tests to conformance - - b9496d1a9 2025-05-29T16:18:47-04:00 Update client-go template with backticks - - d70fcf731 2025-05-29T20:13:56Z Update client-go PR template - - d75af825f 2025-05-29T16:18:36Z Extract interface CycleState and move is to staging repo. CycleState implementation remains in k/k/pkg/scheduler/framework - - be6807e6a 2025-05-29T09:42:26-04:00 Allow specifying a directory for image credential providers json/yaml configuration - - aac00c1f0 2025-05-29T10:50:32+02:00 add orphanedPods parameter to getRSPods - - d13dcbbf9 2025-05-29T13:05:32+08:00 kube-dns bump to v1.26.4 - - 96b5ae792 2025-05-28T13:07:34-04:00 Add code for not expanding volume if it has NodeExpansionNotRequired annotation - - 2b0b34350 2025-05-28T15:44:09Z DRA: Improve implementation of counter management in allocator - - 1cd71cbb1 2025-05-28T11:27:01-04:00 ManagedFieldsObjectTracker: Reload scheme - - 4654496c3 2025-05-28T10:22:35-04:00 Add code to not expand certain types of volumes - - 741d0e2b8 2025-05-28T11:21:57+02:00 Gradute ResilientWatchCacheInitialization to GA - - c8f1a6530 2025-05-28T12:26:09+05:30 agnhost: added server address for conntrack cleanup entries - - 5058e385b 2025-05-27T21:19:25-07:00 DRAAdminAccess: update label key - - ee2d3b6a2 2025-05-28T01:08:24Z DRA: Exclude individual devices when PartitionableDevices feature is disabled - - ab6fdf46d 2025-05-27T13:36:16-07:00 Move the autoscaling e2e tests to be ran in parallel (#131091) - - 4e3634bbb 2025-05-27T16:51:51+02:00 Update security contacts for sig-cli owned repos - - b0847b476 2025-05-27T10:38:45-04:00 Add unit tests for fsGroupChangePolicy accessors - - 74167f904 2025-05-27T14:47:55+02:00 Fix typo in the `--anonymous-auth` flag name - - 6410329a0 2025-05-27T10:43:59+02:00 update go version for publishing bot rules - - 60b5338d4 2025-05-26T22:06:25-07:00 Promote automatic_reloads of authn config metrics to BETA - - f694c58c6 2025-05-26T21:23:46+02:00 feat: graduate QueueingHint to GA - - 1310fc027 2025-05-26T16:41:38+02:00 kubelet: drop dependency on github.com/pkg/errors - - 346fe182b 2025-05-26T15:30:39+02:00 DRA E2E: fail test when ResourceSlice publishing fails - - dc2f33f9d 2025-05-26T18:31:28+05:30 Update Perl to 5.40 - - 7c0f968ab 2025-05-26T08:32:09-04:00 Drop usages of deprecated otelgrpc methods - - 157903b09 2025-05-26T09:35:53Z Skip backoff when PodMaxBackoffDuration is set to zero - - 54b2fad03 2025-05-26T11:28:24+02:00 kubectl: drop dependency on github.com/pkg/errors - - b461d80f3 2025-05-26T15:06:50+08:00 etcd: update etcd image to v3.6.0 - - df2857e77 2025-05-26T12:16:48+09:00 Revert shorthand for kubectl explain --output - - 1d17ca9b7 2025-05-24T00:03:35-04:00 generate code - - 8ae717104 2025-05-24T00:03:28-04:00 Simplify subresource matching - - 9715c90b3 2025-05-23T21:47:09-04:00 Clarify errors and improve tests - - 4cac349f8 2025-05-23T21:47:08-04:00 Clarify group version lookup in validateDeclaratively - - c2eef42cf 2025-05-23T21:47:08-04:00 Add output_tests - - 6284a0f50 2025-05-23T21:47:08-04:00 Tag types with +k8s:isSubresource and +k8s:supportsSubresource for scale - - 7dc8660d0 2025-05-23T21:47:08-04:00 Update testing to fully track subresources - - 6ca6b7bb6 2025-05-23T21:47:08-04:00 Add +k8s:isSubresource and +k8s:supportsSubresource tags - - 105391403 2025-05-23T21:47:08-04:00 Enable scale subresource in generated validations - - a3eddf7d8 2025-05-23T21:47:07-04:00 Add declarative validation testing for replicationcontroller/scale - - 356f395f0 2025-05-23T21:47:07-04:00 Enable declarative validation for replicationcontroller/scale - - 030b4ab9c 2025-05-23T21:47:07-04:00 Add declarative validation testing to Scale.spec.replicas - - 48e1079cf 2025-05-23T21:47:07-04:00 Add subresource mapping support to ValidateDeclaratively and introduce configs - - 8c5c5fb76 2025-05-23T21:47:07-04:00 Add origin and use apivalidation.ValidateNonnegativeField for Scale.spec.replicas validation. - - d0f6fe30b 2025-05-23T21:47:07-04:00 Add k8s:minimum validation to Scale.spec.replicas - - ffb4e003f 2025-05-23T21:47:06-04:00 Enable validation-gen for scale group-versions - - e63019a87 2025-05-23T17:52:26+02:00 DRA integration: refactor code to support other tests - - 1ffda045c 2025-05-23T07:44:49-07:00 update to latest ishidawataru/sctp dependency - - 50f152440 2025-05-23T15:04:00+02:00 DRA integration: start scheduler on demand - - 488c94735 2025-05-23T08:58:13-04:00 Bump dependencies, images and versions used to Go 1.24.3 and distroless iptables - - 699dce0a5 2025-05-23T14:32:19+02:00 DRA kubelet: fix gRPC timeout flake - - 7215de79b 2025-05-23T13:05:42+02:00 DRA kubeletplugin: some doc updates - - 24c0e91d2 2025-05-23T12:54:26+02:00 DRA resource slice controller: disable resync - - 01820ff7c 2025-05-23T18:02:32+08:00 chore(scheduler): add filter integration tests for missing part plugins: NodeAffinity plugin - - 151d9d79f 2025-05-23T09:51:35Z Remove package protected field updatePodOther from ActionType. Make ActionType.None public - - 76f95271a 2025-05-23T11:02:58+02:00 kuberc: make update and update-vendor - - b8e6de08e 2025-05-23T10:56:59+02:00 kuberc: add API violation exceptions - - c29accaf5 2025-05-23T10:56:59+02:00 kuberc: introduce fuzzing for kuberc types - - b0370c483 2025-05-23T10:56:59+02:00 Promote kuberc to beta - - 1f355e5b4 2025-05-23T10:56:59+02:00 kuberc: pick the first known version when decoding + tests - - 0341b27c5 2025-05-23T10:56:59+02:00 kuberc: align internal and v1alpha1 go-types with v1beta1 - - 39195f9a4 2025-05-23T10:56:59+02:00 kuberc: add v1beta1 types - - 35870c480 2025-05-23T10:48:54+02:00 client-go remotecommand: avoid "unexpected error" log when there is no error - - 7287dcd2f 2025-05-23T09:18:33+03:00 vendor: update system-validators to v1.10.1 - - b35c5c0a3 2025-05-22T12:40:35-07:00 e2e: Fix shadowed error in reboot test and clean up containers after reboot test (#131699) - - f79012a0d 2025-05-21T20:45:01Z renamed SIG Node google groups - - 50fe29e52 2025-05-21T16:39:25-04:00 Add accessors for fsgroup change policy - - 17946fe79 2025-05-21T18:02:52Z Add Stress Tests for VolumeAttributesClass - - 32c45ecf1 2025-05-21T13:10:02+02:00 Bump github.com/vishvananda/netlink to v1.3.1 - - aea2743e4 2025-05-21T12:31:52+03:00 vendor: update system-validators to v1.10.0 - - 96e4cc65f 2025-05-21T09:09:46Z update baseimage - - c5f368522 2025-05-21T12:09:40+03:00 kubeadm: fix dryrun-latest e2e by updating cluster-info fixture - - d7b604909 2025-05-21T09:22:33+02:00 e2e: node: always declare testcase CPU requirements - - b571840d0 2025-05-20T23:05:17-04:00 bug: Remove duplicate ReplicaSet update validation - - 67345417c 2025-05-20T16:42:23-07:00 Update tests to use v1 for AuthenticationConfiguration - - aea874e5e 2025-05-20T16:28:49-07:00 Duplicate v1beta1 AuthenticationConfiguration to v1 - - c509e22d1 2025-05-20T18:05:57-04:00 Add a list of modules that should be pinned at current versions - - c4421fc13 2025-05-20T18:15:01Z address more feedback and some cleaning - - 637d234aa 2025-05-20T17:08:56Z feat: Add support for ECDSA-P384 encryption algorithm - - b98b86bd6 2025-05-20T09:57:16-07:00 DRA: Add scheduler perf test for partitionable devices (#131771) - - 4cc2bded9 2025-05-20T15:48:31Z DRA: Add an allocator test that uses an attribute selector - - 60c36432f 2025-05-20T17:43:30+02:00 DRA integration: set up nodes for scheduling - - 1c3beb47a 2025-05-20T22:41:19+08:00 Fix goroutine leak in unit tests - - f6fafba42 2025-05-20T21:57:44+08:00 fix flacky test: ResourceQuota should verify ResourceQuota with terminating scopes through scope selectors - - 8cf5e8db7 2025-05-20T13:31:57+02:00 Deprecate kubeconfig's preference field in favor of kuberc - - 1ce8503e9 2025-05-20T16:47:42+08:00 add UT for volumepathhandler - - a8ed33bc6 2025-05-20T08:41:01Z feat: add metrics for compatibility version - - c4a59afe9 2025-05-20T04:47:50Z Fix incorrect URL in build/dependencies.yaml file - - 5bb3f862a 2025-05-20T01:46:55Z DRA: Clean up allocator tests - - 583447668 2025-05-19T19:38:42Z fix lint and unit test failures - - 676978641 2025-05-19T19:38:42Z address feedback - - 88e1909e5 2025-05-19T19:38:42Z move pod admission and resize logic into the allocation manager - - 353073197 2025-05-19T10:19:14-07:00 Kubectl: check version skew (#127365) - - 3878f7e74 2025-05-19T18:23:49+02:00 E2E ResourceQuota: ensure consistent ResourceQuote during scope selector test - - 4a353d07e 2025-05-19T15:36:57+02:00 E2E ResourceQuota: fix pod creation flake - - 4b10ba9ee 2025-05-19T15:36:57+02:00 E2E ResourceQuota: dump last ResourceQuota - - f712b01dd 2025-05-19T13:07:42+02:00 Unify references to group resource in metrics - - d3afe8a87 2025-05-19T09:20:54+02:00 hack/local-up-cluster.sh: remove kubelet --cloud-config - - 772d01066 2025-05-19T08:02:43+02:00 client-go workqueue: clarify parallel reenqueuing - - d043beb22 2025-05-18T12:52:13-04:00 HealthChecker has a List method - - 9b3830fba 2025-05-18T12:52:05-04:00 Bump google.golang.org/grpc v1.72.1 - - be5d8c767 2025-05-18T18:38:16+10:00 Update cmd/kubeadm/app/cmd/upgrade/apply.go - - c0885e018 2025-05-18T18:36:45+10:00 Fix --config option from suggested kubeadm command - - 8f49fb5ce 2025-05-17T20:42:08-04:00 future-proof csi test mocks - - adc4916df 2025-05-17T12:39:58+02:00 feat: introduce pInfo.UnschedulableCount to make the backoff calculation more appropriate - - 968e19d1b 2025-05-17T09:30:09+02:00 docs: avoid broken link - - a271d3e53 2025-05-17T11:08:29+08:00 cleanup: remove error comment of AddIndexers func - - 5def7fadf 2025-05-16T20:46:55Z Drop dependency on x/exp package in mount_linux_test.go - - b9e2a1608 2025-05-16T21:53:35+03:00 e2e_node: dra: test plugin registration retry - - aef61622a 2025-05-16T21:53:35+03:00 e2e: dra: implement ResetGRPCCalls - - e8be3e575 2025-05-16T21:53:30+03:00 e2e: dra: simulate GetInfo failure - - 2f50d0a51 2025-05-16T16:04:15+01:00 Add kube-api-linter plugin to golangci-lint - - 0e5eab042 2025-05-16T08:04:07-07:00 test: Use sub-tests in watch tests - - 5da12b5ae 2025-05-16T08:16:24-04:00 Add tests that validate the return value of resize operation - - c369e3cd4 2025-05-16T19:06:09+08:00 etcd: build etcd image v3.6.0 - - 65a27eb97 2025-05-16T08:48:39Z restrict the use of scheme internally to client-go - - 671d1a07a 2025-05-16T13:28:37+05:30 Bump the busybox image - - 88b236054 2025-05-16T08:15:35+02:00 ResourceQuota E2E: more informative failure message - - ba77d2756 2025-05-16T07:52:55+02:00 DRA E2E: reduce risk of flake in ResourceSlice stress test - - 6b0ebedcc 2025-05-15T21:19:18-04:00 Set non-experimental WatchProgressNotifyInterval config field - - 079d4e52c 2025-05-15T21:19:18-04:00 Fix kubeadm etcd client interface - - cf0bbf117 2025-05-15T21:19:11-04:00 bump etcd client to 3.6 - - 7bccb1acb 2025-05-16T13:12:13+12:00 Update pkg/scheduler/framework/plugins/defaultpreemption/default_preemption.go - - 139fab0eb 2025-05-15T12:46:03-07:00 kubelet: don't import testing dependency in non-test code - - 90b256537 2025-05-15T11:21:54-07:00 Add suggestChangeEmulationVersion if setting locked feature. - - 5314fcece 2025-05-15T11:11:35-07:00 Promote automatic_reloads of authz config metrics to BETA - - 1b9bb3393 2025-05-15T14:01:18-04:00 test: Fix CURL download of Windows busybox test image - - b0ab168a7 2025-05-15T17:56:31Z CHANGELOG: Update directory for v1.30.13 release - - ec7e732cb 2025-05-15T20:55:17+03:00 e2e: dra: move gomega matchers to dedicated package - - fcfd87812 2025-05-15T17:52:37Z CHANGELOG: Update directory for v1.31.9 release - - 2b7f8e168 2025-05-15T17:51:41Z CHANGELOG: Update directory for v1.32.5 release - - 1ab54ffa6 2025-05-15T17:48:58Z CHANGELOG: Update directory for v1.33.1 release - - bba9c49e1 2025-05-15T19:31:16+03:00 e2e: DRA: test 2 claims with the same name - - 8d8fd9296 2025-05-15T19:31:16+03:00 DRA: test mismatched claim UIDs - - 96da66054 2025-05-15T19:31:16+03:00 DRA: genTestClaimInfo: add claimUID parameter - - 69e16d2f5 2025-05-15T19:31:11+03:00 DRA: kubelet: check for duplicate claim names - - b9fec8bf4 2025-05-15T13:46:48Z fix scheme import - - cf8acf5cb 2025-05-15T11:43:59Z package bootstrap matches dir - - e9fcdabcf 2025-05-15T18:23:30+07:00 feat: kubectl debug: add label for debugger pod - - b13cf0a65 2025-05-15T12:55:10+02:00 tests: userns: Add framework.WithFeatureGate() - - 9549c1115 2025-05-15T08:48:35Z fix e2e network test flake because of network programming latency - - ef0547741 2025-05-14T21:23:52-07:00 verify scripts: preserve exit code - - 0114d33c3 2025-05-14T17:44:00-07:00 datapol: compare types directly - - a1a4bc8fe 2025-05-15T02:23:51+02:00 fix: add BackoffExpiration to DeepCopy - - 2fe65bbf4 2025-05-14T19:10:10Z fix(kubelet): update lease duration when config changes - - 094466539 2025-05-14T18:44:04Z Add rotation and clean up for logging - - 125600e74 2025-05-14T11:05:46-07:00 Remove unused GetHostname method - - ee94ba913 2025-05-14T16:51:43+02:00 Run codegen - - 4eb9fb21b 2025-05-14T16:51:43+02:00 applyconfig-gen: handle non-pointer embedded members - - c374ab811 2025-05-14T16:51:43+02:00 Add a breaking example for applyconfig-gen - - 70e051326 2025-05-14T15:52:09+02:00 Separate getList and watch errors to prevent TestGetCacheBypass flakes - - 512111571 2025-05-14T11:39:04Z Add sig/scheduling label to scheduler integration tests and staging repo OWNERS - - 1ed6cf219 2025-05-14T13:06:03+03:00 Add e2e tests for kuberc - - 0ad8e65d9 2025-05-14T08:55:42Z e2e pod readiness gate network flake - - fe1b1fff7 2025-05-14T14:50:59+08:00 Remove unused GetHostIP method - - 504b681ae 2025-05-13T15:46:43-05:00 Adding Joel Speed - - 47f859606 2025-05-13T15:03:27-05:00 DRA: prevent admin access claims from getting duplicate devices - - c5e4cab9b 2025-05-13T13:14:47-04:00 e2e: add corresponding featuregate label to node features - - c4d6fcb19 2025-05-13T15:35:21Z Remove misleading comment from NodeTaint TimeAdded field - - d0b6ea36b 2025-05-13T15:35:18+02:00 update got to 1.23.8 for the active release branches - - 3043257b8 2025-05-13T15:34:38+02:00 remove release-1.29 as it is deprecated - - 9fd545bcc 2025-05-13T15:06:04+02:00 [sig-scheduling] SchedulerPreemption [Serial] validates various priority Pods preempt expectedly with the async preemption: replace finalizers with preStop hook and TerminationGracePeriodSeconds - - 74e9b27e5 2025-05-13T08:53:50-04:00 Port "Service endpoints latency should not be very high" to EndpointSlices - - e5f7fc25e 2025-05-13T16:18:19+09:00 TestNodeAffinityScoring: wait all nodes - - e42aba6c0 2025-05-12T19:56:46Z Optimize RS Controller Performance: Reduce Work Duration Time & Minimize Cache Locking - - 28602c66f 2025-05-13T06:56:27+12:00 Update pkg/scheduler/framework/plugins/defaultpreemption/default_preemption_test.go - - 52e7aa37d 2025-05-13T06:56:27+12:00 gofmt - - a507e64fe 2025-05-13T06:56:27+12:00 Have separate tests for custom selection vs ordering, add comments around system pod eligibility - - 283c5e6b6 2025-05-13T06:56:27+12:00 Have IsEligiblePod be supplemental to priority check, update tests - - 3ed73e058 2025-05-13T06:56:27+12:00 Clean up the affinity explanation, fix for new lint rule - - d4bc527a7 2025-05-13T06:56:27+12:00 Update comments: affinity info, default behavior, priority->importance - - 95ebc2c10 2025-05-13T06:56:27+12:00 Apply suggestions from code review - - 7f57c6e52 2025-05-13T06:56:27+12:00 Update factory to use generics, keep single New function - - 137da6a48 2025-05-13T06:56:27+12:00 Remove line about equal priority, fix typo - - b8ac17143 2025-05-13T06:56:27+12:00 Apply suggestions from code review - - 224e6a3a3 2025-05-13T06:56:27+12:00 Rename EligiblePod* to IsEligiblePod* - - 4bf684149 2025-05-13T06:56:27+12:00 Update the customizations to operate on individual pods, for more flexibility later - - c34f8db55 2025-05-13T06:56:27+12:00 Remove unnecessary context and typecheck, switch to cmp.Diff - - c6f2d3879 2025-05-13T06:56:26+12:00 Fix gofmt in default_preemption_test.go - - 78b059c06 2025-05-13T06:56:26+12:00 rename OrderedPods -> OrderPods - - 2616202ac 2025-05-13T06:56:26+12:00 Implement tests with example customizations, add direct constructor - - 760daaf11 2025-05-13T06:56:26+12:00 feature(scheduler): Custom pod selection/ordering in DefaultPreemption - - 721947a57 2025-05-12T14:11:19-04:00 Update staging/src/k8s.io/apiserver/pkg/audit/request_log_test.go - - 153233c67 2025-05-12T12:59:58-04:00 review from tallclair - - e418ee3a9 2025-05-12T12:11:38-04:00 Avoid encoding in LogResponseObject when we are not going to use it - - 26c198dc2 2025-05-12T16:08:15Z Some fixes - - 0b915a538 2025-05-12T16:02:11Z Cleanup after rebase - - a6586aa61 2025-05-12T16:01:01Z Addressed comments - - e262cccf2 2025-05-12T16:00:07Z Cleanup after rebase - - 861040435 2025-05-12T16:00:04Z Add e2e tests for Partitionable Devices - - ece35e588 2025-05-12T15:56:24Z Update DRA e2e test framework to allow publishing advanced ResourceSlices - - a437a269f 2025-05-12T11:22:18-04:00 Fix comments on ginkgo label functions - - 85734ac6b 2025-05-12T10:48:19+02:00 DRA E2E: don't run prioritized list tests twice - - 808a5cfd4 2025-05-12T11:57:27+08:00 e2e tests: remove all cloud provider calls in storage/volume_provisioning.go - - 514078682 2025-05-12T01:26:47+02:00 feat: improve the backoff calculation to o(1) - - cfe7d0424 2025-05-11T16:22:52-07:00 Account consumed newlines properly in YAML decoder - - d5a56739c 2025-05-11T13:12:29+08:00 use framework.ExpectNoError instead - - 699ec0a53 2025-05-10T13:15:12+02:00 Remove wrong comment - - f718096b7 2025-05-10T17:22:11+08:00 NoExecute taint should be added when a Node's ready condition becomes Unknown - - 3911b677b 2025-05-10T18:17:38+09:00 test: wait for nodes to be in scheduler's cache - - ea6b4ea7e 2025-05-10T16:16:04+08:00 kubeadm: bump supported etcd version - - 9d963298a 2025-05-09T14:29:06-07:00 test: Close response body in watch tests - - d1fb42a40 2025-05-09T22:26:33+01:00 fix: fixes a possible panic in `NewYAMLToJSONDecoder` - - 960a4939f 2025-05-09T14:26:13-04:00 Eliminate AuditContext`s SetEventLevel - - c39705281 2025-05-09T16:11:30+02:00 Self nominate adrianmoisey as sig-network reviewer - - b09d034a5 2025-05-09T11:33:04+02:00 DRA E2E: revise test labeling - - 13bd0b4ee 2025-05-09T11:07:05+02:00 e2e: node: rewrite the sidecar related tests - - f4265638b 2025-05-09T11:07:04+02:00 e2e: node: factor out reservedCPUs - - a8c8b0987 2025-05-09T11:07:04+02:00 e2e: node: dissolve skipIfNotEnoughAllocatableCPUs - - 32d4724ab 2025-05-09T11:07:04+02:00 e2e: node: add comment about reserved CPU - - daf2fc710 2025-05-09T11:07:04+02:00 e2e: node: rewrite multi-pod tests - - ccc662c22 2025-05-09T11:07:04+02:00 e2e: node: initial multi-container tests - - 2419d9ccc 2025-05-09T11:07:04+02:00 e2e: node: rewrite: multi-cpus single-container pods - - e4726719a 2025-05-09T11:07:04+02:00 e2e: node: rewrite more compatibility tests - - 74fda8c70 2025-05-09T11:07:04+02:00 e2e: node: rewrite compatibility tests - - dd3f9b607 2025-05-09T11:07:04+02:00 e2e: node: rewrite CFS quota tests - - b9ce058ab 2025-05-09T11:07:04+02:00 e2e: node: rewrite strict-cpu-reservation tests - - 3eb2e65fc 2025-05-09T11:07:04+02:00 e2e: node: rewrite cpumanager tests - - 94dd0b840 2025-05-09T14:15:17+08:00 Move test cases from mounted_volume_resize into testsuites/volume_expand.go - - 4aa3c968a 2025-05-09T10:25:25+08:00 Build etcd image v3.6.0-rc.5 - - 641834d03 2025-05-08T17:22:38-07:00 Fix broken recursion - - eb4641d65 2025-05-08T14:21:19-07:00 Add container Resources to the backoff key - - 080d6f9ea 2025-05-08T13:08:20-07:00 test: pass the test context to http requests - - 3f188e5d8 2025-05-08T12:54:06-07:00 refactor: Use http method constants in apimachinery - - 75afa1e0a 2025-05-08T15:31:16-04:00 Fix API server crash on concurrent map iteration and write - - f93e4645c 2025-05-08T11:28:52-07:00 refactor: Stop using ioutil in apiserver - - 9e3a1b0a9 2025-05-08T19:11:40+02:00 Add comment describing the feature gate with a link to KEP - - e3f3da5e7 2025-05-08T19:11:36+02:00 Swap KUBECTL_COMMAND_HEADERS to use the proper feature gate mechanism - - d1b5f268b 2025-05-08T19:04:58+02:00 Drop KUBECTL_ENABLE_CMD_SHADOW featgure gat entirely - - a6abd717e 2025-05-08T16:37:43Z DRA: Fix failure to allocate large number of devices - - 6cca37b36 2025-05-08T16:47:35+02:00 Add integration test for log verbosity - - 69682b75e 2025-05-08T16:47:29+02:00 Manually read verbosity before kubectl command construction - - ee4c6b90c 2025-05-08T21:15:24+08:00 add HirazawaUi to kubeadm approvers list - - 77b1236a5 2025-05-08T21:08:01+08:00 fix: Kubernetes versions in unit tests - - f40892f48 2025-05-08T14:33:11+02:00 client-go: call out WithContext inconsistency - - 871cabeed 2025-05-08T11:10:12+08:00 deflake e2e tests: StatefulSet Non-retain StatefulSetPersistentVolumeClaimPolicy should delete PVCs after adopting pod (WhenScaled) - - 8b81a3d88 2025-05-07T16:42:08-07:00 Rename GetStableKey to GetBackoffKey - - 861682235 2025-05-07T21:15:12Z DRA: Fix incorrect behavior for AllocationMode: All in ResourceClaim when used in subrequests - - a3097010f 2025-05-07T13:01:15-07:00 Change the implementation design of matchLabelKeys in PodTopologySpread to be aligned with PodAffinity (#129874) - - ce02da8da 2025-05-07T15:42:16-04:00 generate code - - 4821604f8 2025-05-07T15:42:09-04:00 Reorganize scheme type converter into apimachinery utils - - e81887276 2025-05-07T12:17:48-07:00 refactor: Add request method constants - - af1d60f30 2025-05-07T18:16:15Z Add hpa reviewers - - 0acc7bd4d 2025-05-07T16:26:27Z HPA: Fix int overflow in GetExternalPerPodMetricReplicas - - b9cb3cb33 2025-05-07T23:35:28+08:00 update klog flags - - 57218ac96 2025-05-07T19:53:45+05:30 Revert "kube-proxy: log errors during proxy boot" - - 9def40c9e 2025-05-07T15:41:27+02:00 DRA E2E: fix "must manage ResourceSlices" - - c71e29ff1 2025-05-07T15:41:27+02:00 DRA E2E: fix flaky "sequential update with pods replacing each other" - - d28c8cd48 2025-05-07T14:12:23+02:00 fix: not removing the plugin from the unsched plugins after PreEnqueue - - 47d296d62 2025-05-07T13:54:47+02:00 feat: introduce pInfo.GatingPlugin to filter out events more generally - - 441dd3051 2025-05-07T11:52:36+02:00 userns: Wrap more errors - - 43f61e80d 2025-05-07T11:52:36+02:00 userns: Improve error returned if userns is not supported - - c5efc843d 2025-05-06T15:56:29-04:00 Fix rudimentaryErrorBackoff to only be created once - - 97e64e80c 2025-05-06T12:43:17-07:00 Fix typo in comment - - 68f0204e3 2025-05-06T12:40:58-07:00 Better logs and debugging - - 8a571f7fb 2025-05-06T12:40:57-07:00 Rename discover() to discoverType() - - eb3c061ca 2025-05-06T12:40:57-07:00 Reorder and merge blocks handling named types - - 67bab26ea 2025-05-06T12:40:56-07:00 hasValidations should return cached values first - - bb10f55fd 2025-05-06T12:40:55-07:00 Fix lint warnings - - 22fa3c747 2025-05-06T18:33:25Z add retries to exec command in cgroup verification - - 8652b6ab2 2025-05-06T13:40:44-04:00 Update sig-network-approvers/reviewers - - b1bb9a588 2025-05-06T14:30:10-03:00 Kubelet: Randomize ClusterRole name in e2e - - 863168e47 2025-05-06T09:25:06-07:00 e2e: stabilize Windows memory pressure eviction test - - 4ed3768dc 2025-05-06T17:54:25+02:00 userns: Use len to handle empty non-nil slices - - 97a2cb39c 2025-05-06T15:37:57Z Make sig-scheduling-api-approvers actual approvers - - 6d927c3c2 2025-05-06T15:15:03Z Comment out sig-scheduling-api-reviewers, since it's currently empty. - - 038bb1a9a 2025-05-06T15:15:03Z Remove alculquicondor who is stepping down from sig-scheduling-api-reviewers - - 55b5827d8 2025-05-06T13:59:36Z integration: etcd data - - aa9f156d7 2025-05-06T13:59:09Z integration test for compatibility version - - 3be3051fb 2025-05-06T09:35:38-04:00 Adding test case for the webhook behavior change - - cf82fd7e9 2025-05-06T09:35:27-04:00 Treat error decoding a mutating webhook patch as error calling the webhook - - 9bcec340f 2025-05-06T13:29:55Z modify unit test for compatibility version - - 15ab88f88 2025-05-06T13:29:54Z remove networking v1alpha1 and make update - - 54b014be1 2025-05-06T13:29:54Z use networkingv1 as default storage for servicecidr and ipaddresses - - b2fe862ae 2025-05-06T13:29:45Z graduate disableAllocatorDualWrite and lock MultiCIDRServiceAllocator - - d2fa246b0 2025-05-06T09:00:38-04:00 Update codegen - - d78b295a8 2025-05-06T09:00:32-04:00 Reenable guard to only validat root and scale subresources until ratcheting merges. - - 94d043b14 2025-05-06T13:00:14+03:00 Drop KUBECTL_DEBUG_CUSTOM_PROFILE feature gate entirely - - d52f05dad 2025-05-06T15:26:20+08:00 remove hwdef from hack reviewer - - 2e6ec2414 2025-05-05T22:06:59-04:00 Remove unused function - - 2e8b409a5 2025-05-05T22:06:59-04:00 Rewrite Subresources godoc. - - 164fefa94 2025-05-05T22:06:59-04:00 Update codegen - - 2119555e0 2025-05-05T22:06:59-04:00 Add subresource to operation, do not special case subresources in validation-gen - - 2073ba237 2025-05-05T18:47:41-04:00 pkg/storage/cacher/cacher_whitebox_test: deflake TestWatchNotHangingOnStartupFailure when ResilientWatchCacheInitialization is on - - 2b3f2aa70 2025-05-05T19:31:48Z propogate error - - 10c5bdd6a 2025-05-05T15:03:11-04:00 Apply feedback - - 36685c6f1 2025-05-05T14:40:06-04:00 Add information about expected status - - 6c8904104 2025-05-05T22:08:05+08:00 fix(scheduler): node pre-check logic to consider NoExecute taint effect - - e36a168a6 2025-05-05T10:37:42-03:00 test/e2e/node/kubelet_authz.go: fix SAR to include service account groups - - aeb43eb22 2025-05-05T12:22:39Z Migrate ExtractCommentTags to ExtractFunctionStyleCommentTags - - 1ec7231f6 2025-05-05T14:21:25+02:00 DRA node: reject static pods which reference ResourceClaims - - 2ea4b1aba 2025-05-05T13:00:08+02:00 golangci-lint: don't warn about conversion and defaulting functions - - 15d9a93d7 2025-05-05T13:00:08+02:00 golangci-lint: redirecting stderr raced with termination of script - - 3b5cfeaf2 2025-05-05T08:49:09+02:00 DRA: use v1beta2 - - b262d5616 2025-05-05T08:41:21+02:00 DRA: client-go wrapper with latest API as types - - 8e9abfaf2 2025-05-05T08:41:21+02:00 DRA: v1beta1 <-> v1beta2 conversion - - d7a64d68b 2025-05-05T08:41:21+02:00 DRA resourceslices: clarify code - - a171795e3 2025-05-05T08:40:52+02:00 DRA resourceslices: better error reporting - - 6392b54e1 2025-05-05T08:30:26+02:00 DRA resourceslices: avoid update loop when partitionable devices feature is off - - 5af026120 2025-05-05T08:25:20+02:00 test: bump agnhost image to 2.54 - - e5ffec242 2025-05-04T20:27:09+02:00 Bump CNI to 1.7.1 - - 47fddb08f 2025-05-02T20:56:03-04:00 Expand has() tests for omitempty and omitzero - - c2c003a71 2025-05-02T23:11:30Z update k8s.io/utils to bring fakeClock.Waiters() - - b3bf5ed0e 2025-05-02T15:33:07-07:00 verify-shellcheck.sh: normalize KUBE_ROOT using pwd -P - - a1a620886 2025-05-02T15:33:07-07:00 use the minimal shellcheck image instead - - e0983dbee 2025-05-02T14:23:49-07:00 remove unused shell imports in verify-shellcheck - - 7b50c8a51 2025-05-02T17:18:24-04:00 jwt: support CEL expressions with escaped names - - 784c589a7 2025-05-02T16:29:04-04:00 Check for newer resizing related fields after expansion is successful - - 6bb6c9934 2025-05-02T15:38:40-04:00 Drop null creationTimestamp from test fixtures - - 41805aff9 2025-05-02T15:38:40-04:00 Update runtime convertor to honor IsZero() - - bc6051717 2025-05-02T15:38:38-04:00 bump cbor to add omitzero support - - 06b078406 2025-05-02T15:38:38-04:00 bump structured-merge-diff to add omitzero support - - fdf0bb41a 2025-05-02T15:38:37-04:00 Omit null metadata.creationTimestamp - - 79891eac8 2025-05-02T17:27:34+02:00 agnhost: bump version to 2.54 - - 09912f352 2025-05-02T10:03:51-04:00 Make ToUnstructured match stdlib omitempty and anonymous behavior - - 49f765e2b 2025-05-02T20:56:29+08:00 Remove redundant Required validation for IngressRules - - c78556fb4 2025-05-02T14:46:56+02:00 agnhost pause: report signal, support termination message - - a6549edd1 2025-05-02T15:41:01+03:00 kubeadm: use named ports for coredns probes - - 0faeb5a0d 2025-05-02T14:38:09+02:00 golangci-lint: move into hack/tools/golangci-lint - - 5d9a2f30f 2025-05-02T14:38:09+02:00 golangci-lint: finish migration to v2 - - 9bada79de 2025-05-02T12:51:02+02:00 DRA node test: fix useless gomega.Consistently - - 4adb58565 2025-05-02T12:51:02+02:00 chore: bump golangci-lint to v2 - - f6d049801 2025-05-02T13:23:22+03:00 Continue alias creation when __completion is used to enable completion - - dceae3b38 2025-05-02T10:52:56+02:00 DRA e2e: avoid terminationGracePeriodSeconds - - 56e533f4a 2025-05-02T08:26:17Z servicecidr: only patch status if necessary - - 7fedcc34e 2025-05-02T08:25:16Z refactor default service cidr sync status logic - - edda4b02d 2025-05-02T00:09:10-07:00 fixup! Introduce special handling for updates involving a single resource slice. - - 6d8b41fac 2025-05-01T22:24:23-07:00 Introduce special handling for updates involving a single resource slice. - - 2e98d87c5 2025-05-02T10:48:46+05:30 api: Fix typo in word "immediately" - - 5441f5fde 2025-05-01T12:32:20-04:00 jwt: add unit tests for using CEL with deeply nested claims - - 43ce37ed4 2025-05-01T14:56:28+02:00 Address feedback - - 7e1cec680 2025-05-01T14:53:26+02:00 e2e: Deduplicate cgroup verification - - cc4c14d4c 2025-04-30T15:11:05-04:00 Disable size check for xfs/ext3/ext4 filesystems before expansion - - 48054afd6 2025-04-30T13:41:22-04:00 Relax external signer path validation to allow relative paths - - 5712881ca 2025-04-30T11:43:36-04:00 Disable disk size checking when calling NeedsResize function - - e500f9451 2025-04-30T23:55:46+09:00 add missing space in string concatenation (kubeapiserver) - - c5a2c69b9 2025-04-30T23:51:11+09:00 add missing space in string concatenation (kubeadm) - - 43a0da588 2025-04-30T23:35:25+09:00 add missing space in string concatenation (kube-proxy) - - 66b8a8427 2025-04-30T09:24:39-04:00 Fix CEL equality bug for structs will nil field not marked as omitempty - - 1b9386aac 2025-04-30T12:17:33+02:00 Add comment explaining the metric sampling logic for plugin execution metrics - - 0a4ab9367 2025-04-30T17:07:43+08:00 fix incorrect comments - - 4d5d48da7 2025-04-30T13:41:27+08:00 Remove unused volume limit constants - - 3a5dda78a 2025-04-30T04:46:50Z e2e network: blue green deployments - - ea6441827 2025-04-29T15:37:26-04:00 Appease linters - - 43d6ea12e 2025-04-29T15:37:01-04:00 jwt: refactor CEL eval to drop unstructured and map[string]any - - 064074c07 2025-04-29T13:32:26-04:00 Add lazy reflective CEL object wrapper - - 903d6d4f0 2025-04-29T09:17:40-04:00 Don't reinitialize test framework during each test case - - a56378d9f 2025-04-29T16:15:41+08:00 Update UserNamespaceSupport feature gate name - - 3cadb6ff8 2025-04-29T09:55:05+02:00 DRA test: update examples - - c6f652d5f 2025-04-29T14:58:57+08:00 Refactor pod failure policy defaults - - 68b1a950f 2025-04-28T22:14:02-03:00 kube-proxy should check global IPv6 enablement - - 2080bafa1 2025-04-28T23:40:49Z Add sunnylovestiramisu as Reviewer - - d6b45bc98 2025-04-28T18:43:12+02:00 [FG:InPlacePodVerticalScaling] clean code resize test - - dddfeb4a0 2025-04-29T00:19:47+08:00 Handle unsupported node expansion for RWX volumes - - 62ddcfba5 2025-04-28T20:35:19+05:30 kube-proxy: conditionally skip e2e - - 8bb7b0563 2025-04-28T15:44:04+02:00 dependencies: github.com/client9/misspell -> github.com/golangci/misspell - - ad40bc885 2025-04-28T08:28:46+02:00 kubectl describe service: Add Traffic Distribution - - 28e7acf0f 2025-04-27T20:35:38+02:00 improve display format - - f30c23a78 2025-04-27T15:36:09+02:00 kubectl: sort configmaps alphabetically to avoid random order - - db960d100 2025-04-26T17:39:31-07:00 Fix openid discovery docs with external jwt signer. - - 1869f6f23 2025-04-26T14:36:33-07:00 Fix typo in service account config test. - - c7a870135 2025-04-27T01:05:45+05:30 nftables: cleanup service chain checks - - 494b2b563 2025-04-27T01:21:39+09:00 use testing.TempDir and delete helper function - - efcceee90 2025-04-27T00:33:07+09:00 reduce assignment - - f42ee7a2d 2025-04-26T23:08:02+09:00 use slices package to reduce the codes - - 9cb3dfb5d 2025-04-26T16:06:18+05:30 kube-proxy: log errors during proxy boot - - 2d337f515 2025-04-25T11:21:42-07:00 Retool validator utils realType and unaliasType - - 835bb2ecc 2025-04-25T11:13:03-07:00 Change v8n context.Type and Parent on typedefs - - 6ea1db51a 2025-04-25T11:13:03-07:00 Disallow pointers as listmap keys - - fc7f01735 2025-04-25T11:13:02-07:00 Handle typedef fields in optional validations - - 9d519c7c4 2025-04-25T11:13:02-07:00 Fix immutable validation for structs with pointers - - 0b190b817 2025-04-25T11:13:01-07:00 Add test cases for immutable to verify pointers - - 855918f75 2025-04-25T11:13:01-07:00 Add tests for optionalness of typedef fields - - 7a24c4ce5 2025-04-25T10:07:12+02:00 chore: update github.com/google/cel-go dependency to v0.25.0 - - addaf680a 2025-04-25T15:49:41+08:00 remove v1.31.0 api testdata - - 86a43f4b5 2025-04-25T15:49:16+08:00 Add v1.33.0 API testdata - - 89156452a 2025-04-25T15:38:14+08:00 fix nil pointer panic on windows node - - 00908ce2d 2025-04-25T01:09:08-05:00 Wait for resource quota status to be populated - - d5bf33e7d 2025-04-24T22:54:09-07:00 update-codegen.sh: automatically install protoc - - 8a2f367ec 2025-04-24T22:54:09-07:00 automatically install goimports when running update-codegen - - 1473aeaac 2025-04-24T22:54:09-07:00 add goimports to tools module - - 540ea5949 2025-04-24T22:40:05-07:00 skip kubectl proxy env tests when the host is localhost/loopback and would not be proxied - - 1214dc223 2025-04-25T03:15:42Z kubelet: Use node addresses from informer - - c0b2f341a 2025-04-25T10:19:05+08:00 clean up cloud provider code because cloud provider only supports empty or external and cloud is nil - - 187b43d5a 2025-04-24T17:17:27-07:00 enable dep-approvers for staging go.mod/go.sum - - f50ad91ed 2025-04-24T15:18:26-07:00 Create a single TypeDiscoverer for all inputs - - 08794974b 2025-04-24T15:02:29-07:00 track gopkg.in/yaml.v3 as an unwanted depdendency - - aee494525 2025-04-24T21:28:07Z alculquicondor stepping down from sig-scheduling approvers - - 58e5dfd45 2025-04-24T13:08:46-07:00 attempt to re-introduce dep-approvers for go.mod/go.sum - - 74e84dbf5 2025-04-24T12:00:50-07:00 Add more test cases to TestDescribeSecret test (#131422) - - 6eff9db0f 2025-04-24T11:01:03-07:00 chore: Add VeryShortWatchError typed error - - 92359cdc6 2025-04-24T16:05:01Z update godoc for and rename observedGeneration helpers - - 932cff5dd 2025-04-24T15:51:08Z add more error details to the failing cgroup check - - c3bb59d07 2025-04-24T17:06:27+02:00 Fix etcd3 watcher flake - - 0d3d2733f 2025-04-24T08:06:17-04:00 Update go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful to v0.44.0 - - a2281f97b 2025-04-24T17:01:00+08:00 bump fsnotify v1.9.0 - - 44d7132af 2025-04-24T00:45:27-07:00 Update hnslib version in Windows KubeProxy. - - 7c53a5aaa 2025-04-24T14:54:41+08:00 Remove feature label NodeOutOfServiceVolumeDetach - - f74424bd7 2025-04-24T08:54:13+02:00 etcd: better logging - - 24257f2d3 2025-04-24T11:45:38+08:00 Remove deprecated scheduler cache metrics - - 269d3ae51 2025-04-24T09:47:27+09:00 Fix comment for default gRPC log level in DRA plugin - - 2ea689207 2025-04-23T15:58:37-07:00 Always check for Immutable selector in Deployment Replicaset Daemonset (#131017) - - 947a9f26f 2025-04-23T14:02:36-07:00 Move pod resize e2e utilities out of e2e/framework - - 609e4a9ba 2025-04-23T13:31:14-07:00 Unhandled panic crash on rollout_history printer.PrintObj (#130503) - - fa8e37f78 2025-04-23T13:30:52-07:00 Allow disabling caching for webhook authorizers when using `apiserver.config.k8s.io/v1{alpha1,beta1}.AuthorizationConfiguration` (#129237) - - 1db2d6a01 2025-04-23T16:15:10-04:00 Mark NodeExpansion finsihed without featuregate check - - 70ebe90b1 2025-04-23T16:05:56-04:00 Also change final status by removing featuregate check - - 849924b6b 2025-04-23T11:56:12-07:00 Increase delay in kuberuntime termination order test to prevent time rounding flake. - - 0e40ed642 2025-04-23T11:37:22-04:00 Check for newer fields when deciding expansion recovery feature status - - 4fa090bd8 2025-04-23T14:03:19Z Remove alculquicondor from test framework OWNERS - - 6a17858ff 2025-04-23T13:24:19Z CHANGELOG: Update directory for v1.33.0 release - - 90de4b589 2025-04-22T10:30:51-04:00 Remove warning about resizing failed for unknown reason - - 418092840 2025-04-22T10:11:35+02:00 Update cri-tools to v1.33.0 - - f63702de0 2025-04-22T14:54:40+08:00 scheduler: return UnschedulableAndUnresolvable when node capacity is insufficient - - d10eb8692 2025-04-22T14:01:41+08:00 fix: Fix non-constant format string in framework.Logf call - - b9a6a257b 2025-04-21T13:34:37-07:00 add TODO for unifying .go-version - - 5c84ee07e 2025-04-21T13:34:35-07:00 test/images: read .go-version instead of duplicating - - 722581f5f 2025-04-21T17:34:42Z Expand etcd data test to n-3 - - c21f26895 2025-04-21T17:34:41Z Fix VAP test for v1.34 - - bfcee6645 2025-04-21T17:34:41Z Bump DefaultKubeBinaryVersion to 1.34 - - 27815acee 2025-04-21T13:58:58+08:00 remove outdate comment - - 64b4c96e2 2025-04-21T08:44:04+08:00 fix: use correct apiextensions v1 API instead of apiregistration v1 - - a53ea3357 2025-04-18T10:53:10+01:00 Updates prober_total_total to BETA and updates the list of stable metrics - - f844abfc6 2025-04-18T15:55:38+08:00 Fix typo in ResourceEncodingConfig comment - - ff108e72a 2025-04-17T17:16:23+02:00 DRA device taints: fix rare unit test flake - - 97dd6dc28 2025-04-17T15:02:29Z Add warning message for attach - - 8672956f7 2025-04-17T14:41:43+02:00 etcd: use Unix Domain socket for testserver - - 33f16a55b 2025-04-17T14:26:54+02:00 etcd: fix 5 second delay during shutdown - - ff2e6dddc 2025-04-17T10:57:27+02:00 DRA device taints: work around fake.ClientSet informer race - - 638abf033 2025-04-17T10:55:13+02:00 DRA device taints: more logging in test - - 40f2085d6 2025-04-17T10:55:13+02:00 DRA device taint: clean up test initialization - - 091d09b44 2025-04-17T16:40:27+08:00 deflake e2e tests: CustomResourcePublishOpenAPI works for multiple CRDs of same group and version but different kinds - - db1e10715 2025-04-17T00:42:26+09:00 Job: Fix API comments for SuccessCriteriaMet - - ac3274521 2025-04-16T17:24:08+08:00 scheduler: remove duplicate nominatedNodeName clearing in preemption - - 373866eee 2025-04-16T08:54:06Z Build etcd v3.6.0-rc.4 image - - 7fcc1bcf1 2025-04-15T17:23:32-07:00 chore: move watch handler tests to handlers pkg - - 3fcb26f01 2025-04-15T15:18:22-07:00 reduce etcd install log noise - - 3e609ecf6 2025-04-15T12:03:21-07:00 fix: Watcher deadlock from Stop not being called - - c704025a0 2025-04-15T11:27:26-04:00 Fix error handling and csi json file removal interaction - - 1654aa619 2025-04-15T15:33:40+08:00 deflake intergation test: TestEndpointHandlers - - 3d53bfec0 2025-04-14T17:19:50+02:00 Typo fix: watchActcion - - 4e3026fdb 2025-04-14T15:59:45+02:00 pr fix - - 7d6f86594 2025-04-14T15:55:57+02:00 kubectl: sort secrets alphabetically to avoid random order - - 8f1326251 2025-04-14T09:51:51+02:00 Improve Job API comment for the backoffLimit - - 9d5f78a99 2025-04-14T09:21:16+02:00 Update OWNERS_ALIASES add aojea to sig-network-api-reviews - - e8dbfc0b6 2025-04-14T09:07:51+08:00 add miss Shutdown call for selinux_warning controller - - 405b9e802 2025-04-13T13:56:37-05:00 Check expected emitted events with assert.Equal - - 5ebeb8def 2025-04-13T13:56:37-05:00 don't only run events in nested lists consecutively - - 614b1e901 2025-04-13T13:56:37-05:00 Run all permutations of events in ResourceSliceTracker tests - - 29b499e2b 2025-04-13T13:10:38-05:00 simplify applyEventPair - - 45b0ddff1 2025-04-13T13:07:14-05:00 make input events a slice - - 3883e050f 2025-04-12T22:02:06-05:00 Use shared test fixtures for ResourceSlice Tracker test cases - - 7f21df6ab 2025-04-13T00:53:57+09:00 resolved review comments - - 5928fc0e6 2025-04-11T13:36:37-07:00 Add ContainerIter utility for ranging over pod containers - - 3b2cd1234 2025-04-11T17:17:46Z fix(kubelet): acquire imageRecordsLock when removing image - - 6d6abaab7 2025-04-11T15:34:26+02:00 Simplify etcd3 watcher - - b82fd6c28 2025-04-11T16:42:44+08:00 add e2e test for healthz/ - - 8bc7e6c10 2025-04-11T16:42:44+08:00 add etcd server overrides to etcd probe factory for healthz and readyz - - b141ac6a2 2025-04-11T16:06:30+08:00 adjust container_spec_memory_limit_bytes e2e to range: ppc64le is 44*1024 less - - 2aa39a0c7 2025-04-10T22:38:18-07:00 Update the busybox test image to 1.37.0 - - f9c1876b4 2025-04-10T14:58:37-04:00 Make proxy CleanupLeftovers methods quieter - - b61ca041b 2025-04-10T14:58:35-04:00 Add some missing cleanup to "kube-proxy --cleanup" - - c1ff9cf4e 2025-04-10T21:16:47+08:00 chore: Upgrade the mockery version to v2.53.3. - - ffe235d2d 2025-04-10T15:07:18+02:00 replace context.TODO with context.Background in tests - - 4bd0c024e 2025-04-10T15:07:18+02:00 add goleak to kubelet vendor via hack/update-vendor.sh - - 161b44d04 2025-04-10T15:07:18+02:00 add missing header in httpstream_test.go; whitespace in imports - - 79150d1ec 2025-04-10T15:07:18+02:00 add unit tests to verify the fix - - 42d3716d7 2025-04-10T15:07:18+02:00 fixed the formatting - - 268033a51 2025-04-10T15:07:18+02:00 Fixed go routine leak in kubelet tests - - 30f1bcade 2025-04-10T09:05:23-04:00 Add a unit test for iptables.CleanupLeftovers, improve ipvs test - - 94530dad7 2025-04-10T09:03:25-04:00 Move iptables/ipvs/ipset interface creation into CleanupLeftovers - - 975e653af 2025-04-10T13:01:07+02:00 RWX tests should create RWX volumes - - 5ad90c3b6 2025-04-10T19:08:25+09:00 merge RunBenchmarkPerfScheduling and runBenchmarkPerfScheduling - - 780c0d672 2025-04-10T18:56:45+09:00 add license description in options.go - - 4f33b74a3 2025-04-10T09:25:08+02:00 Use Go 1.24 os.Root instead of filepath-securejoin - - 5677f7ab0 2025-04-09T16:16:48-04:00 Make Request#RequestURI honor configured context root - - b206264ff 2025-04-09T15:45:31+02:00 Shorten long directory names with e2e pod logs - - 2800c16c8 2025-04-09T15:00:16+02:00 Remove FlowSchemas handling non-leases-backed leader election - - 16f4a5c4e 2025-04-09T17:04:20+08:00 cleanup unneed code - - 88fbccd69 2025-04-09T16:21:38+08:00 Fix the allocatedResourceStatuses Field name mismatch in PVC status validation - - 302a85058 2025-04-09T13:08:21+05:30 Update coredns version to v1.12.1 - - d4fd41285 2025-04-08T10:21:02-07:00 update the log message to reflect success and failed jobs - - cc4284618 2025-04-08T07:10:13-07:00 Fix for HNS local endpoint was being deleted instead of the remote endpoint. - - 551f3c782 2025-04-07T17:37:19-07:00 merge the integration tests into a single one - - de98a71ff 2025-04-07T08:09:59-03:00 Update PodSecurityLevel used during Service CIDRs tests - - 58ff3129a 2025-04-03T15:57:08-05:00 update kubelet_authz.go to new test framework - - c7d0ed5c4 2025-04-01T12:38:15-07:00 add integration test for job failure event delay and remove the unit test - - 6747bf7a9 2025-04-01T13:59:32-04:00 Clean up leaked goroutines in cache unit tests - - 04d0715e6 2025-04-01T19:29:17+09:00 scheduler-perf: add option to enable api-server initialization - - 16af0d79d 2025-03-31T09:45:51-07:00 update sig-autoscaling maintainers - - 653f48d88 2025-03-30T10:46:59+08:00 Certificate store: ensure data is written to disk - - 5a14fdbf7 2025-03-28T11:18:33Z e2e: Keep original error when exec in container fails - - 9c228e81d 2025-03-28T12:39:01+03:00 Increase kubectl cp command timeout to 30 seconds - - 310b395a0 2025-03-27T17:56:06+01:00 [cloud-provider] respect the "exclude-from-external-load-balancers=false" label - - ae08504ca 2025-03-27T22:29:39+08:00 Remove unneeded return values - - 2c94112a0 2025-03-27T07:45:31Z Disable thresholds for PreemptionBasic and PreemptionPVs tests - - f7d885321 2025-03-27T10:07:25+09:00 Add dom4ha to SIG-Scheduling approvers - - 8e65a62b3 2025-03-26T16:50:26-07:00 Deduplicate MilliCPUToQuota function & constants - - 3067bbfe1 2025-03-26T12:10:23+01:00 hack/ginkgo-e2e.sh: fix misplaced brackets - - 5e4600e46 2025-03-26T07:55:40Z e2e service ip preservation test - - f7e82d805 2025-03-25T17:30:42-07:00 clarify mutual exclusivity of service account annotation keys in godoc - - 4fa963914 2025-03-25T15:08:34-07:00 kubectl http proxy e2e: do not append os.Environ() redundantly - - f7f4aa02b 2025-03-25T15:08:04-07:00 kubectl e2e: debug appended environment variables - - 5aa61f847 2025-03-24T18:27:50+01:00 Test tooling: fix agnhost pause command - - 65b8fba34 2025-03-24T12:53:50+01:00 Mask Linux thermal interrupt info in /proc and /sys. - - 0ff1e3778 2025-03-24T14:05:12+08:00 Remove general available feature-gate PodDisruptionConditions - - fe14689f2 2025-03-22T10:14:01+08:00 bump k8s.io/utils - - 1c3dc397a 2025-03-21T18:19:43-07:00 make update - - 8af1629f7 2025-03-21T18:19:29-07:00 remove inaccurate hostNetwork doc comment - - bad6c7e4c 2025-03-21T17:28:41Z Set LANGUAGE env variable in TestDiffProgram for consistent locale behavior - - c005b85d4 2025-03-21T15:23:08Z Reduce locking duration on cache to fetch data from Cache - - 252d584cb 2025-03-21T08:20:04-07:00 Implement validation-gen lint for CI - - 1a694bfd3 2025-03-21T08:19:49-07:00 Make validation-gen lint errors easier to read - - 8dc6806d2 2025-03-21T14:55:25+08:00 Expose NodeInfo to PreFilter plugins and Framework - - 5413d0edf 2025-03-21T12:37:19+09:00 chore: correct the comment on UnschedulablePlugins - - 8db5f0618 2025-03-20T22:46:38Z adding commits of the original PR - - 1b8bbcac4 2025-03-20T15:04:44-07:00 Add integration test - - 1402a5491 2025-03-20T14:51:54-07:00 Removed unused function UncompressLog. - - 88a3c000e 2025-03-20T14:33:38Z Implement CSI e2e test for MutableCSINodeAllocatableCount - - d868eeb08 2025-03-20T21:58:14+08:00 Migrate pkg/kubelet/status to contextual logging - - 7f263b057 2025-03-19T13:04:18-04:00 Tag api change instead of apimachinery on generated openapi. changes - - 4120ed1df 2025-03-19T16:06:30Z chore: `make update` for doc changes - - 356e14804 2025-03-19T15:46:30Z fix: comment on preferred PodAntiAffinity - - a2624f9c6 2025-03-19T15:09:26+08:00 make update - - 21f7026c2 2025-03-19T14:54:12+08:00 clean up CSIDriverRegistry - - a68501da7 2025-03-18T20:18:12Z Add check to see if promote worked within the retry loop - - 53499d97e 2025-03-13T16:15:24-07:00 prefer error over bool, prefer Should(gomega.Succeed()) - - d54ff7441 2025-03-13T13:57:55-07:00 test: don't panic during an Eventually retry loop - - cab6045a4 2025-03-13T17:36:25+01:00 hack: remove verify-e2e-suites.sh - - 73afab185 2025-03-10T14:01:29-07:00 handle review comments - - 51fdd55e8 2025-03-06T15:56:07-08:00 use sync map for the cache - - 3a5f8b4b9 2025-03-06T00:03:59-08:00 Update OWNERS_ALIASES for sig scalability - - 547c005cb 2025-03-04T14:42:13-08:00 handle job complete update delayed event - - 410ada002 2025-03-04T14:32:50+08:00 Made the unsupportedError msg more readable - - 780fac5a3 2025-02-28T09:45:42+08:00 chore(kubelet): migrate network to contextual logging - - 125b8d280 2025-02-25T14:43:53-08:00 Removed kubelet test duplicate line. - - c1efa2e16 2025-02-18T14:18:25+08:00 delete test/e2e/common/storage/volumes.go - - 429437962 2025-02-17T17:49:36+08:00 e2e storage test: intree driver adds the support for nfs v3 - - 6df869347 2025-02-17T14:13:48+08:00 remove outdate comment about pv controller - - 329990590 2025-02-14T20:23:30+01:00 Based on the issue #8304 add mfahlandt as ne Co Chair for Contributor Experience - - 9a60ea01f 2025-02-12T13:44:15+08:00 fix getPodMatches should call /runningpods endpoint - - 5da366e3e 2025-02-11T18:35:25+08:00 Update pkg/quota/v1/evaluator/core/resource_claims.go - - ce7d3ea00 2025-02-11T16:38:18+08:00 fix wrong api version in toExternalResourceClaimOrError - - 0f0f9d01c 2025-02-05T12:19:17+08:00 remove out-of-date comments about version - - c2b455f55 2025-01-25T23:02:41+08:00 remove unnecessary functions - - 44d31af29 2025-01-25T02:17:01Z Add example in etcd override flag help text - - 3dc611e66 2025-01-24T14:56:37+08:00 fix container lifecycle e2e tests - - 4a4fb0a11 2025-01-22T22:21:39+09:00 Fix LC_CTYPE for kubemark start scripts - - ea644981d 2025-01-14T14:19:16+08:00 Update pkg/controller/certificates/cleaner/cleaner.go - - 1e1e2dee9 2025-01-14T14:18:51+08:00 Update pkg/controller/certificates/cleaner/cleaner.go - - 006ebbc33 2025-01-07T21:18:25-06:00 Fix comment typos - - 4bf5f1a6b 2025-01-02T13:01:01-05:00 kubelet: add coverage for identical kubelet config and drop-in config content - - eae133919 2024-12-26T15:35:56+08:00 fix: killPodOptions support JSON serialization - - 55ba8f063 2024-12-10T16:18:57+02:00 kube-scheduler: Fix a misleading error message in the VolumeRestrictions plugin - - a52863827 2024-11-13T10:23:54+03:00 [kubectl] drain daemonSetFilter with other APIVersion - - 9f50740b7 2024-11-12T12:43:53-08:00 Simplify span handling - - c64b6f80e 2024-11-12T11:23:38-07:00 Trace across start handler invocations, nesting spans - - 6fd8954fe 2024-10-29T15:34:58+08:00 kube-controller-manager: also support context for record.NewBroadcaster - - bea35b1f5 2024-10-28T11:16:27+08:00 remove non-lease resource locks in tests. - - ff74405bd 2024-10-22T11:28:31+08:00 kubelet: remove --register-schedulable flag - - 05be83b38 2024-09-18T11:54:35+02:00 tracing: set audit-id on incoming requests - - eda71f9e9 2024-04-09T15:12:57+08:00 cleaner.go should use time.Until instead of t.Sub(time.Now()) - - 1354bb9e2 2023-11-20T17:54:16Z Update log verbosity for node health and taint checks - -- machine-config-operator embedded-component c6faace50b71d89f694e9f3a8ee7a6635ac36f7c to 7007a56217125f6b5ea358a520c080c4ac002575 - - b77f1c99 2025-10-09T15:23:22-04:00 controller, daemon, and upgrade monitor: update MachineConfigNode update flow to include image mode status reporting fields - - 749f9b72 2025-10-09T15:22:27-04:00 bump(api & client-go): bump api to commit 2acafd4 and client-go to commit 1bc0cb0 - - 0a6dfa5c 2025-10-09T19:07:57+02:00 add: fallback check for br-ex-br in ofport NM dispatcher script - - 1e8fc024 2025-10-09T17:58:47+02:00 Revert "ofport-request dispatcher script takes br-ex(-br) managed by nmstate into account" - - 5add8259 2025-10-09T17:58:22+02:00 Revert "improve of-port request so it uses a common path instead of retrying on NMS managed br-ex" - - 28a1a758 2025-09-30T12:31:11+02:00 improve of-port request so it uses a common path instead of retrying on NMS managed br-ex - - 2fdedfa0 2025-09-29T22:05:34Z Updating ose-machine-config-operator-container image to be consistent with ART for 4.21 Reconciling with https://github.com/openshift/ocp-build-data/tree/4fbe3fab45239dc4be6f5d9d98a0bf36e0274ec9/images/ose-machine-config-operator.yml - - 5a59b6c2 2025-09-24T14:19:13+02:00 ofport-request dispatcher script takes br-ex(-br) managed by nmstate into account - -- operator-framework-olm embedded-component 2c539ec14ba778ae4085be9af77231e32ff4005b to bdc0d750909a7cea17b087f53bcaa01d449638f1 - - e2870c7e 2025-10-14T13:39:43+08:00 support opm cases - -- service-ca-operator embedded-component a40d9a8ec60e0c6c1578300c372b6104130f2ecc to e5d65c6f6b1446b77e0e915d64825d97be9c06de - - 46bab7e 2025-10-15T03:03:14+08:00 Fix gofmt formatting after CA rotation logic fix - - 5edc600 2025-10-15T02:45:32+08:00 Fix CA rotation polling logic - - 5031339 2025-10-14T21:23:53+08:00 Fix gofmt formatting in e2e_test.go - - 911d3da 2025-10-14T19:08:52+08:00 Fix connection test in checkClientPodRcvdUpdatedServerCert - - c9f6900 2025-10-14T17:14:30+08:00 Merge fixes from commit 41d9ed12 - - 667d9c7 2025-10-14T16:32:54+08:00 Fix e2e test failures due to SCC UID range validation - - 6e9d853 2025-09-29T22:19:56Z Updating ose-service-ca-operator-container image to be consistent with ART for 4.21 Reconciling with https://github.com/openshift/ocp-build-data/tree/4fbe3fab45239dc4be6f5d9d98a0bf36e0274ec9/images/ose-service-ca-operator.yml - -- ovn-kubernetes image-amd64 53c8c29ad581831ace5ba3a3812f295bff080ab4 to 3f971b1c061a775aedee0e9a06ab2a2a31bc64cc - - 31a760d7 2025-10-08T15:00:45+02:00 kv, e2e: Add --wait to killall - - cedfc13e 2025-10-08T13:17:13+02:00 utils,multinet: GetPodNADToNetworkMappingWithActiveNetwork CUDN support - - e4835ab8 2025-10-08T13:17:13+02:00 e2e,kubevirt: Test MAC conflict detection - - f46a21c6 2025-10-08T13:17:11+02:00 e2e,net-seg default-net annot: Test MAC conflict detection - - 89d1696a 2025-10-08T13:14:17+02:00 clustermanager,allocator: Init MAC manager with pod MACs - - eb4789b7 2025-10-08T13:14:08+02:00 clustermanager,allocator: Init MAC manager with infra MACs - - b6965d94 2025-10-08T13:10:25+02:00 clustermanager,allocator: Release reserved MAC on pod deletion - - 0b38dd8a 2025-10-08T13:10:21+02:00 clustermanager,allocator: Emit pod event reflecting MAC conflicts - - 1d5045a8 2025-10-08T13:09:42+02:00 clustermanager,allocator: Detect MAC conflict on pod allocation - - c8b18bd7 2025-10-08T13:09:08+02:00 pod-allocator: Introduce MAC addresses manager - - 8db8ca1d 2025-10-02T09:41:44+02:00 Use "OVN-Kubernetes" consistently as project name for CNFC correctness - - aa188fb5 2025-10-02T09:41:03+02:00 [docs] Add instructions for CI failures. - - 33a4f8c5 2025-10-02T09:40:57+02:00 [docs] Move local testing guide to its own page from CI - - 845ec2d1 2025-09-30T23:21:58Z Updating ose-ovn-kubernetes-container image to be consistent with ART for 4.21 Reconciling with https://github.com/openshift/ocp-build-data/tree/4fbe3fab45239dc4be6f5d9d98a0bf36e0274ec9/images/ose-ovn-kubernetes.yml - -- kubernetes image-amd64 00e7ec7a0db0b7e03c5ed2bc5b8b776fdc34f72a to 96593f323733d9ffc0fc70257ecad44a56df0ce3 - - 61114aa5a 2025-10-15T14:19:18-03:00 UPSTREAM: : hack/update-vendor.sh - - 30c13ce1b 2025-10-15T14:17:29-03:00 UPSTREAM: : make update - - b45907adb 2025-10-15T14:07:17-03:00 UPSTREAM: : hack/update-vendor.sh - - 25513888c 2025-10-15T14:03:12-03:00 UPSTREAM: 134199: Promote regression-issue-74839 to 1.4 - - 9ff0f3cae 2025-10-15T14:03:12-03:00 UPSTREAM: 134442: Fix ResourceQuota test for CRDs with long names - - 60ac34692 2025-10-15T14:03:12-03:00 UPSTREAM: revert: 133264: Revert "remove failing test that depends on expired credential, remove credential, add TODOs" - - ac1b24ee9 2025-10-15T14:03:12-03:00 UPSTREAM: 133905: kubelet/metrics: fix multiple Register call - - cd2e8b9ce 2025-10-15T14:03:12-03:00 UPSTREAM: 134376: Update hostpathplugin image version in DRA test driver manifest - - e5913956f 2025-10-15T14:03:11-03:00 UPSTREAM: 134327: test/e2e/apimachinery/watchlist: select only wellknown secrets for table test - - b392a7e3a 2025-10-15T14:03:11-03:00 UPSTREAM: 133421: e2e/watchlist: normalize dynamic Age column in Table test to prevent test flake - - 190966201 2025-10-15T14:03:11-03:00 UPSTREAM: 132791: Update pod resize test to accept new cpu.weight conversion. - - 6959e5211 2025-10-15T14:03:11-03:00 UPSTREAM: 132960: Configure JSON content type for generic webhook RESTClient. - - c21b863b5 2025-10-15T14:03:11-03:00 UPSTREAM: 134071: Wait for quota to report used before creating pvc - - 5a989b949 2025-10-15T14:03:11-03:00 UPSTREAM: 133959: Do not remove PVC ClaimRef to fix flaky VAC test - - cf73730d1 2025-10-15T14:03:11-03:00 UPSTREAM: 133682: Increase port-forward broken connection detection client timeout - - 06d238136 2025-10-15T14:03:11-03:00 UPSTREAM: : Add plugin for storage performant security policy - - b5ec7a566 2025-10-15T14:03:11-03:00 UPSTREAM: : unrevert: Mark admissionregistration.k8s.io/v1beta1 as deprecated." - - 71e26c8c5 2025-10-15T14:03:11-03:00 UPSTREAM: : allow TLS1.3 or modern profile to be specified - - 6803cc464 2025-10-15T14:03:11-03:00 UPSTREAM: : Add volume group snapshot test driver - - 22e63d2b8 2025-10-15T14:03:11-03:00 UPSTREAM: : admission: validate minimumKubeletVersion - - a743b1abe 2025-10-15T14:03:11-03:00 UPSTREAM: : log only deprecated api requests - - e87b794c6 2025-10-15T14:03:10-03:00 UPSTREAM: : disable etcd readiness checks by default - - 50b420aa6 2025-10-15T14:03:10-03:00 UPSTREAM: : add arbiter node role to known labels - - da795cb2c 2025-10-15T14:03:10-03:00 UPSTREAM: : Prefer local endpoint for cluster DNS service - - ecb7d7621 2025-10-15T14:03:10-03:00 UPSTREAM: : add etcd3RetryingProberMonitor for retrying etcd Unavailable errors for the etcd health checker client - - 06fe11ba2 2025-10-15T14:03:10-03:00 UPSTREAM: : annotate audit events for requests during unready phase and graceful termination phase - - 696bc0436 2025-10-15T14:03:10-03:00 UPSTREAM: : allow type mutation for specific secrets - - 0573d1831 2025-10-15T14:03:10-03:00 UPSTREAM: : Add openshift feature gates to kube-apiserver - inject openshift feature gates into pkg/features - - 3eb149a67 2025-10-15T14:03:10-03:00 UPSTREAM: : add new admission for handling shared cpus - - f3ef52744 2025-10-15T14:03:10-03:00 UPSTREAM: : temporarily disable reporting e2e text bugs and enforce 2nd labeling to make tests work - - db423d582 2025-10-15T14:03:10-03:00 UPSTREAM: : advertise shared cpus for mixed cpus feature - - 1994a6bff 2025-10-15T14:03:10-03:00 UPSTREAM: : Export cpu stats of ovs.slice via prometheus - - 57a39d46c 2025-10-15T14:03:10-03:00 UPSTREAM: : retry etcd Unavailable errors - - a4e802e80 2025-10-15T14:03:09-03:00 UPSTREAM: : selfsubjectaccessreview: grant user:full scope to self-SARs that have user:check-access - - 6cffd361e 2025-10-15T14:03:09-03:00 UPSTREAM: : merge v3 openapi discovery and specs for special groups - - e6b92109a 2025-10-15T14:03:09-03:00 UPSTREAM: : when only this kube-apiserver can fulfill the kubernetes.default.svc, don't wait for aggregated availability - - f42426e01 2025-10-15T14:03:09-03:00 UPSTREAM: : Export internal code from k8s.io/apimachinery/pkg/util/managedfields - - aa11b48c6 2025-10-15T14:03:09-03:00 UPSTREAM: : APISelfSubjectReview: only test v1beta1 API - - 4d0cd085e 2025-10-15T14:03:09-03:00 UPSTREAM: : disable load balancing on created cgroups when managed is enabled - - 283c592bc 2025-10-15T14:03:09-03:00 UPSTREAM: 115328: annotate early and late requests - - 967a1e568 2025-10-15T14:03:09-03:00 UPSTREAM: : PSa metrics: log platform namespaces in audit denies - - 788da1d88 2025-10-15T14:03:09-03:00 UPSTREAM: : make the PSA workload admission warnings honor the changes that SCC will eventually make to the pod - - 566fde9f6 2025-10-15T14:03:09-03:00 UPSTREAM: : optionally enable retry after until apiserver is ready - - 9c2fff44e 2025-10-15T14:03:09-03:00 UPSTREAM: : fix [sig-auth] ServiceAccounts no secret-based service account token should be auto-generated - - 93595fa11 2025-10-15T14:03:09-03:00 UPSTREAM: : use console-public config map for console redirect - - 3fab36613 2025-10-15T14:03:09-03:00 UPSTREAM: : Release lock on KCM and KS termination - - 927d3d922 2025-10-15T14:03:08-03:00 UPSTREAM: : sets X-OpenShift-Internal-If-Not-Ready HTTP Header for GC and Namespace controllers - - fc8db74d7 2025-10-15T14:03:08-03:00 UPSTREAM: : add max_housekeeping_interval - - ed28c08c4 2025-10-15T14:03:08-03:00 UPSTREAM: : send Retry-After when not ready with a caller opt in - - f7cdb220f 2025-10-15T14:03:08-03:00 UPSTREAM: : skip posting failures to aggregated APIs to avoid getting false positives until the server becomes ready - - 16f970296 2025-10-15T14:03:08-03:00 UPSTREAM: : add a way to inject a vulnerable, legacy service-ca.crt for migration compatibility - - 30a300bcb 2025-10-15T14:03:08-03:00 UPSTREAM: 103612: tolerate additional, but congruent, events for integration test - - 1780cd23f 2025-10-15T14:03:08-03:00 UPSTREAM: : crd: add ClusterOperator condition message table column - - ce1781131 2025-10-15T14:03:08-03:00 UPSTREAM: : emit event when readyz goes true - - 2d833691b 2025-10-15T14:03:08-03:00 UPSTREAM: : apiserver: add system_client=kube-{apiserver,cm,s} to apiserver_request_total - - b40e921b7 2025-10-15T14:03:08-03:00 UPSTREAM: : Ensure service ca is mounted for projected tokens - - dbcdc99b0 2025-10-15T14:03:08-03:00 UPSTREAM: : allows for switching KCM to talk to Kube API over localhost - - 4e71cfc7b 2025-10-15T14:03:07-03:00 UPSTREAM: : add management support to kubelet - - d859c8f35 2025-10-15T14:03:07-03:00 UPSTREAM: : allows for switching KS to talk to Kube API over localhost - - 2e380ce17 2025-10-15T14:03:07-03:00 UPSTREAM: : provide events, messages, and bodies for probe failures of important pods - - 63fc13858 2025-10-15T14:03:07-03:00 UPSTREAM: : allow kubelet to self-authorize metrics scraping - - 01f6a4ac1 2025-10-15T14:03:07-03:00 UPSTREAM: : use hardcoded metrics scraping authorizer for delegated apiservers - - ecbcaf656 2025-10-15T14:03:07-03:00 UPSTREAM: : kube-apiserver: ignore SIGTERM/INT after the first one - - 438c6cd39 2025-10-15T14:03:07-03:00 UPSTREAM: : noderestrictions: add node-role.kubernetes.io/* to allowed node labels - - 6b2289613 2025-10-15T14:03:07-03:00 UPSTREAM: : export HandleFlags - - fea2fa015 2025-10-15T14:03:07-03:00 UPSTREAM: : Add OpenShift tooling, images, configs and docs - - e162c7757 2025-10-15T14:03:06-03:00 UPSTREAM: : refactor/improve CRD publishing e2e tests in an HA setup - - c04050e15 2025-10-15T14:03:06-03:00 UPSTREAM: : conditionally fill the UserAgent from the currently running test - - f5ffc84dd 2025-10-15T14:03:06-03:00 UPSTREAM: : Remove excessive e2e logging - - 47631c08e 2025-10-15T14:03:06-03:00 UPSTREAM: : disable AES24, not supported by FIPS - - 673175cd6 2025-10-15T14:03:06-03:00 UPSTREAM: : warn only about unknown feature gates - - 49dbe59f1 2025-10-15T14:03:06-03:00 UPSTREAM: : bootstrap-rbac-policy: move over .well-known rules - - 42560b433 2025-10-15T14:03:06-03:00 UPSTREAM: : create termination events - - 3662118bf 2025-10-15T14:03:06-03:00 UPSTREAM: : kube-apiserver: priorize some CRD groups over others - - 6f7c7ec80 2025-10-15T14:03:06-03:00 UPSTREAM: : openshift-kube-apiserver: add openshift-kube-apiserver code - - d1c74dc85 2025-10-15T14:03:06-03:00 UPSTREAM: : openshift-kube-apiserver: add kube-apiserver patches - - 528cc99e6 2025-10-15T14:03:06-03:00 UPSTREAM: : kube-apiserver: add our immortal namespaces directly to admission plugin - - 72e349ebf 2025-10-15T14:03:06-03:00 UPSTREAM: : kube-controller-manager: exclude some origin resources from quota - - a0df69dbd 2025-10-15T14:03:05-03:00 UPSTREAM: : kube-controller-manager: allow running bare kube-controller-manager - - c90479ce1 2025-10-15T14:03:05-03:00 UPSTREAM: : kube-controller-manager: add service serving cert signer to token controller - - 75ec36f78 2025-10-15T14:03:05-03:00 UPSTREAM: : Extend NodeLogQuery feature - - 71f1dfcf8 2025-10-15T14:03:05-03:00 UPSTREAM: : hardcoded restmapper with a few entries to rebootstrap SDN when SDN is down - - fadd69ba4 2025-10-15T14:03:05-03:00 UPSTREAM: : remove apiservice from sync in CRD registration when it exists - - 4dd9038de 2025-10-15T14:03:05-03:00 UPSTREAM: : patch aggregator to allow delegating resources - - 898dd8cdf 2025-10-15T14:03:05-03:00 UPSTREAM: : filter out CustomResourceQuota paths from OpenAPI - - 91afdf9ce 2025-10-15T14:03:05-03:00 UPSTREAM: 93286: wait for apiservices on startup - - 96219fc21 2025-10-15T14:03:05-03:00 UPSTREAM: 74956: apiserver: switch authorization to use protobuf client - - 93248f9ae 2025-09-09T19:37:19Z Release commit for Kubernetes v1.34.1 - - 7bd2900b1 2025-09-05T03:53:40Z fix: Only warn for unrecognized formats on type=string - - f779cf638 2025-09-03T23:55:22+02:00 Disable estimating resource size for resources with watch cache disabled - - 96739661c 2025-09-03T09:23:47+02:00 Disable collecting stats for resources not setting prefix to prevent error logs - - 2631a5f21 2025-08-29T15:37:14+03:00 Fix linter - - 94c0e4788 2025-08-29T15:37:14+03:00 Fix completion of resource names - - 08515c751 2025-08-28T22:56:12+08:00 Fix missing control plane health check timeout - - a75938d9e 2025-08-28T18:07:40+08:00 Fix DaemonSet misscheduled status not updating on node taint changes - - 3ebbe5731 2025-08-28T10:29:24+02:00 Add a note about Conflicts return value - - 98dca817c 2025-08-28T10:29:24+02:00 Fix SELinux label comparison - - 3e75f3881 2025-08-28T10:29:24+02:00 Add missing cases to SELinuxMount tests - - d13374214 2025-08-27T10:36:11Z Update CHANGELOG/CHANGELOG-1.34.md for v1.34.0 - - f28b4c9ef 2025-08-27T10:09:04Z Release commit for Kubernetes v1.34.0 - - f2170bc6c 2025-08-26T16:11:12+01:00 kube-proxy: log but don't exit if ipv4 or ipv6 is not available - - f47e9696d 2025-08-20T17:40:32Z CHANGELOG: Update directory for v1.34.0-rc.2 release - - 78405b2c8 2025-08-20T17:40:32Z Update CHANGELOG/CHANGELOG-1.34.md for v1.34.0-rc.2 - - ed3ccdbe3 2025-08-20T17:17:54Z Release commit for Kubernetes v1.34.0-rc.2 - - db01f9403 2025-08-20T09:19:55-04:00 Remove patch/update from ServiceCIDR API conformance test - - d49e3d67c 2025-08-19T16:35:34+02:00 Fix storage counting all objects instead just objects for resource - - 747a295ca 2025-08-18T15:54:03-04:00 fix flake in dra test 'TestPlugin' - - 4ebe560c7 2025-08-18T13:44:26+02:00 DRA allocator: fix data race around `claimsToAllocate` - - 41013e7bf 2025-08-18T10:23:42+03:00 e2e_dra: use latest release if stable doesn't exist - - e49f6116f 2025-08-15T14:33:07-07:00 clarify that staging repos are automatically published - - ada2ed848 2025-08-15T10:17:18-07:00 add pointer to CONTRIBUTING.md for more details on contributing, clarify read-only - - 8919ac43c 2025-08-15T10:10:58-07:00 special case that kubectl staging repo is currently used to track issues, and only pull requests should be redirected back to the main repo. - - 011d50019 2025-08-15T10:10:26-07:00 link to what a staging repository is - - 7c43e6d2f 2025-08-15T10:08:16-07:00 docs: clarify that this is a staging repository and not for direct contributions - - f8bad82c2 2025-08-15T15:27:45+02:00 update go version for publishing bot rules - - bf6c86b56 2025-08-15T01:02:44-05:00 DRA: wait for stats to converge in "creates slices" e2e test - - 020b7052c 2025-08-14T09:46:06+02:00 Bump dependencies, images and versions used to Go 1.24.6 and distroless iptables - - c8ab780ed 2025-08-13T16:35:35-04:00 dra plugin: assume claim after api call in bindClaim - - 81affffa1 2025-08-13T19:49:57Z CHANGELOG: Update directory for v1.31.12 release - - 8311c1d3d 2025-08-13T19:46:23Z CHANGELOG: Update directory for v1.33.4 release - - edfa9a5bd 2025-08-13T17:57:33Z added WithFlaky() to the device plugin test case: supports extended resources together with ResourceClaim - - 48a496771 2025-08-13T14:49:49Z CHANGELOG: Update directory for v1.32.8 release - - 064b59161 2025-08-11T13:50:03+02:00 improve CRD handling in VolumePopulator test - - 944b0a492 2025-08-10T14:38:24-07:00 do not allow the node to update it's owner reference - - 0bd039e89 2025-08-08T21:01:46Z Update CHANGELOG/CHANGELOG-1.34.md for v1.34.0-rc.1 - - 4d6b49b3f 2025-08-08T21:01:45Z CHANGELOG: Update directory for v1.34.0-rc.1 release - - a956ef486 2025-08-08T20:39:54Z Release commit for Kubernetes v1.34.0-rc.1 - - e073a9125 2025-08-08T17:02:50+02:00 Add release-1.34 configuration - - cbd6fb867 2025-08-07T17:25:48-07:00 Remove DeprecatedVersion for apiserver_storage_objects, adjust help text - - 89b5034d5 2025-08-07T13:46:08+08:00 Make podcertificaterequestcleaner role feature-gated - - 2629fe25f 2025-08-06T21:24:27-07:00 Use Delete() instead of DeleteLabelValues() for etcd metrics - - 13ced7b7d 2025-08-06T20:20:05Z CHANGELOG: Update directory for v1.34.0-rc.0 release - - 40e8ad951 2025-08-06T13:26:10Z Release commit for Kubernetes v1.34.0-rc.0 - - b79691898 2025-08-06T07:42:31Z reduced numPods to 5 from 10 to fix flaky test (supports reusing resources) due to timeout. - - 2a026f6d6 2025-08-06T07:08:58Z 1/ added retries to AssumeClaimAfterAPICall for the object which is not present in the cache (dynamicresources.go) 2/ modified the assume cache verification to not error out as long as the expected claim is in the cache, no matter its latest and api object are different or not. (dynamicresources_test.go). 3/ fixed nil panic as seen from https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/133321/pull-kubernetes-integration/1952472629470302208 - - 01470d973 2025-08-01T09:56:51-07:00 Fix memory limit decrease test on cri-o - - aca402f25 2025-08-01T13:59:32+02:00 e2e: node: skip breaking tests - - 0fbc8cd44 2025-08-01T07:18:26Z Remove integration-test labels from long running scheduler_perf workloads - - e83e5815e 2025-08-01T00:55:10-04:00 always pull pause image for eviction tests - - 418e96bf1 2025-08-01T12:46:26+08:00 Update prerelease lifecycle to v1.34 - - 65fda6dd3 2025-07-31T18:15:55Z fixed exended resource scheduling performance test, added more nodes for scheduling the init pods - - 9eda4789c 2025-07-31T09:27:40Z Fix potential race in PodStatusPatchCall implementation - - dbfeb9c35 2025-07-30T11:57:26Z Fix potential race in closing API dispatcher - - c7db6362f 2025-07-30T10:47:38Z Move NominatedNodeName preemption-related integration tests to a new package - - 46b858aa1 2025-07-30T19:12:57+09:00 fix: return false to apply the patch - - 07c71097d 2025-07-30T09:06:34Z Split DRA scheduler_perf tests into multiple packages - - 988c9b03f 2025-07-30T15:48:26+09:00 Demote KEP-5278 feature gates ClearingNominatedNodeNameAfterBinding and NominatedNodeNameForExpectation to Alpha - - 0a12f00e9 2025-07-30T14:44:41+09:00 fix nil panic in hasBindingConditions, it cannot assume claim has allocations - - 7f052afae 2025-07-30T09:52:49+09:00 KEP 5075: implement scheduler - - 3e3b2447f 2025-07-29T17:28:26-07:00 Promote PodLevelResources to Beta (#132999) - - 59bba9271 2025-07-30T09:26:52+09:00 KEP-5075: generated codes from make update - - 5ad969588 2025-07-30T09:26:40+09:00 KEP-5075: API updates - - 29d1951eb 2025-07-29T12:34:35-07:00 fixes scheduler nil panic due to empty init container request&limit - - 23d6f73e7 2025-07-29T18:55:28Z extended resource backed by DRA: test - - 34a64db2c 2025-07-29T18:55:21Z extended resource backed by DRA: implementation - - a3a767b37 2025-07-29T20:20:08+02:00 WIP: fix e2e tests - - 4ca47255a 2025-07-29T20:19:40+02:00 node: disable resource managers when pod-level resources are enabled - - 3068b60b8 2025-07-29T17:17:20Z extended resource backed by DRA: codegen - - 1f2fd18ac 2025-07-29T17:17:19Z extended resource backed by DRA: API types.go - - 7fbf63a23 2025-07-29T09:02:26-07:00 HPA support for pod-level resource specifications (#132430) - - 6e9b60e3f 2025-07-29T11:06:39-04:00 Add / update kubelet and DRA API owners - - 60fa65db8 2025-07-29T23:48:11+09:00 Clear pod.Status.NominatedNodeName when pod is bound - - 15b1a7fd3 2025-07-29T16:41:37+02:00 Revert "CPU and Memory manager event when using pod level resources" - - aea0a3cca 2025-07-29T12:21:03Z Run all relevant test cases with the feature gate enabled and disabled - - 856e7d238 2025-07-29T12:21:03Z scheduler: Stop clearing NominatedNodeName on all cases - - 6653ef652 2025-07-29T11:36:07Z KEP-5007 DRA Device Binding Conditions: Add dra integration test - - 9e82c1330 2025-07-29T11:35:58Z KEP-5007 DRA Device Binding Conditions: Implement DRA logic - - e8c3af1f5 2025-07-29T11:34:30Z KEP-5007 DRA Device Binding Conditions: Implement scheduler logic - - ac81b829e 2025-07-29T11:34:03Z KEP-5007 DRA Device Binding Conditions: Run make update - - 987ad3951 2025-07-29T11:32:47Z KEP-5007 DRA Device Binding Conditions: API Related code Update - - 34c3b0938 2025-07-29T11:31:48Z KEP-5007 DRA Device Binding Conditions: API Update - - ac9fad603 2025-07-29T19:01:02+09:00 feat: trigger PreFilterPreBind in the binding cycle - - 48eef9ce9 2025-07-29T08:06:39Z test: fix TestStructuredAuthenticationConfigReload flake by handling expected network errors - - 4874d4166 2025-07-28T21:42:42-07:00 Pod Certs: Fix kubelet volume host arg order - - f9bb14fcf 2025-07-28T19:42:04-04:00 Fix apiserver service proxying e2e test flakiness - - 8ace0fb89 2025-07-28T15:43:43-07:00 remove failing test that depends on expired credential, remove credential, add TODOs - - f07dcd443 2025-07-28T22:06:48Z fix flake on TestStreamTranslator_WebSocketServerErrors - - 7ba22700b 2025-07-28T21:59:08Z websocket streamtranslator increament metrics before writing status - - 0aea6a1e4 2025-07-28T21:53:12Z TestStreamTranslator_BlockRedirects use subtests - - 4b698656b 2025-07-28T19:31:08Z Returning early if podResources is nil to avoid nil pointer dereferencing - - 766d011bb 2025-07-28T18:53:04Z E2E tests for no hints nor aligment of CPU and Memory managers - - 5672750e6 2025-07-28T18:53:03Z Unit tests for no hints nor aligment of CPU and Memory - - 7804b51f4 2025-07-28T18:53:03Z CPU and Memory manager event when using pod level resources - - fd206a0ef 2025-07-28T17:19:07Z Add comments for restart rules not used for unknown container status and probes - - 4b479da4b 2025-07-28T16:33:20Z Remove the feature from e2e test - - 6997fbd1e 2025-07-29T00:02:20+08:00 Fix incorrect validation on the kubelet - - 48f8458c4 2025-07-28T16:54:08+02:00 validation: Fix user-namespaces test case name - - 50a7a8af4 2025-07-28T16:54:08+02:00 validation: Align usage of hostUsers in error messages - - 5f7e611f7 2025-07-28T16:54:08+02:00 validation: Return error if hostUsers=false && volumeDevices - - f3466f8ad 2025-07-28T23:12:58+09:00 fix: flake integration test - - ed74d4cd5 2025-07-28T20:22:27+09:00 Revert "Revert "fix: handle corner cases in the async preemption"" - - e8dc272c5 2025-07-27T21:45:02-07:00 Update etcd to 3.6.4 - - 0f7cd1495 2025-07-28T11:52:12+08:00 Fix prerelease-lifecycle for volumeattributesclass - - 9c8dacb03 2025-07-27T23:14:12Z ContainerRestartRules feature gate should work with probes - - 48fd30113 2025-07-26T07:51:58+09:00 [PodLevelResources] Add missing label to Downward API test - - 57ceb56c6 2025-07-25T14:09:41-07:00 Bump etcd sdk to v3.6.4 - - b562335cb 2025-07-25T13:51:25-07:00 Build etcd v3.6.4 image - - 17d733e24 2025-07-25T15:35:36Z KEP-5229: Send API calls through dispatcher and cache - - 40a90df3b 2025-07-25T12:45:01+02:00 DRA E2E: remove stress test - - b956484c2 2025-07-25T19:29:14+09:00 KEP-5229: Add metrics for async API dispatcher - - 006d7620a 2025-07-25T10:38:34+08:00 Revert "fix: handle corner cases in the async preemption" - - 727a6e6db 2025-07-24T17:58:54-07:00 Reject pod when attachment limit is exceeded (#132933) - - a65289630 2025-07-24T17:58:33-07:00 Allow white-spaced CABundle during webhook client creation and validation (#132514) - - f1737db16 2025-07-24T18:58:24-05:00 Update DRA Pod spec comments - - b7de71f9c 2025-07-24T23:23:18Z feat(kubelet): Add ResourceHealthStatus for DRA pods - - d4a83b9a5 2025-07-24T21:41:28Z fix(golangci-lint): skip config verification when -c none is used - - 252513a1b 2025-07-24T21:40:08Z Add WithFeature and WithSerial, also check if cgroup v2 is used in test - - 1bc995c19 2025-07-24T21:29:04Z Generated files - - f925e5554 2025-07-24T21:29:04Z E2E tests for container hugepage resources immutability - - 9f5b09eb7 2025-07-24T21:29:04Z Unit test pod level hugepage Default and Validation logic - - 845e94d37 2025-07-24T21:29:01Z Validation logic and Defaulting update for pod level hugepages - - c15a54f8c 2025-07-24T14:08:14-07:00 draadminaccess: move metrics test from e2e to integration - - d176808d3 2025-07-24T12:12:59-07:00 Rename hack/*-yamlfmt to -owners-fmt - - 7adcd2114 2025-07-24T12:11:04-07:00 Replace cmd/yamlfmt with k-sigs/yaml/yamlfmt - - 79833578f 2025-07-24T18:52:34Z KEP-3695: add kubeletPodResources feature gate to Beta - - 2cb955d8c 2025-07-24T11:47:03-07:00 Add KYAML support to kubectl - - 8182a27f3 2025-07-24T11:46:03-07:00 Re-vendor sigs.k8s.io/yaml @ v1.6.0 - - 94bf8fc8a 2025-07-25T01:53:59+08:00 Promoted API `VolumeAttributesClass` and `VolumeAttributesClassList` to `storage.k8s.io/v1`. - - 8e3f93c87 2025-07-24T17:13:39Z Unit test propagate pod level hugepages to containers - - 52b457421 2025-07-24T17:13:39Z Pod level hugepage cgroup when unset in container - - add7132a6 2025-07-24T17:08:13Z E2E tests for pod level resources Kubelet Preemption - - 976a617d0 2025-07-24T17:07:09Z E2E tests for pod level resources eviction manager - - 13b122b6f 2025-07-24T17:07:09Z Unit tests for pod level resources eviction manager - - 9a3ca05f6 2025-07-24T17:07:05Z Use pod level resources for eviction manager - - b34f8782e 2025-07-24T16:49:54Z Add e2e tests - - 9086e52fe 2025-07-24T16:49:54Z Implement restart rules in kubelet - - af595a44a 2025-07-24T16:49:52Z Add container restart rules to API - - 5dc2030c0 2025-07-24T12:37:14-04:00 4033: GA KubeletCgroupDriverFromCRI feature gate - - 27e167515 2025-07-24T12:36:26-04:00 Make PSA host enforcement honor emulation version - - 32053b1d2 2025-07-25T00:07:30+08:00 chore: replace ptr caster with unified ptr.To - - 83a0d0c66 2025-07-24T11:42:59-04:00 kubelet: add metric for version CRI implementation will lose support - - ffe306d67 2025-07-24T07:56:27-07:00 client-go, kubectl: Replace deprecated ErrWaitTimeout with recommended method (#132718) - - cb33accc8 2025-07-24T06:46:28-07:00 JSON & YAML output for kubectl api-resources (#132604) - - 8a2db4da4 2025-07-24T22:45:39+09:00 fix: adjust the log level in the preemption - - 4c9bf4719 2025-07-24T22:44:39+09:00 fix: handle cornor cases in the async preepmtion - - bf98e45af 2025-07-24T21:20:12+08:00 Migrate pkg/kubelet/volumemanager to contextual logging - - aecd37e6f 2025-07-24T12:10:58Z Moving Scheduler interfaces to staging: Move PodInfo and NodeInfo interfaces (together with related types) to staging repo, leaving internal implementation in kubernetes/kubernetes/pkg/scheduler - - c954e1325 2025-07-24T14:04:08+02:00 Revert "DRAAdminAccess: add upgrade downgrade test" - - 12d675066 2025-07-24T13:50:05+02:00 client-go/metadata/fake: sets opts.Watch to true - - b37fd0cab 2025-07-24T11:49:51Z [KEP-4816] DRAPrioritizedList to Beta - - 6767d54bb 2025-07-24T19:46:51+09:00 Bump DRA API version to "v1" in "deviceattribute" package in "k8s.io/dynamic-resource-allocation" module - - 449763fb1 2025-07-24T12:35:45+02:00 e2e: podresources: disable memory manager integration - - b768c1d1d 2025-07-24T08:33:56+02:00 DRA API: bump storage version to v1beta2 - - 24de875ce 2025-07-24T08:33:56+02:00 DRA: graduate DynamicResourceAllocation feature to GA - - d8df1dc1b 2025-07-24T08:33:56+02:00 DRA RBAC: fix kube-scheduler bootstrap policy - - 21d929f59 2025-07-24T08:33:56+02:00 integration: use --runtime-config-emulation-forward-compatible - - 5c4f81743 2025-07-24T08:33:45+02:00 DRA: use v1 API - - cff91579e 2025-07-24T08:30:25+02:00 DRA API: v1 registration + tests - - 4e592f6c1 2025-07-24T08:30:24+02:00 DRA API: s/v1beta2/v1/ and generated files - - 1f2f433f7 2025-07-24T08:30:24+02:00 DRA API: verbatim copy v1beta2 -> v1 - - 837b7395d 2025-07-24T09:14:09+03:00 kubelet: DRA: Close gRPC connection when removing DRA plugin - - c7d6c0968 2025-07-23T21:44:27-07:00 List available endpoints for kube-apiserver (#132581) - - 5f4a1aa58 2025-07-24T09:11:09+08:00 chore: ptrTo util removal with ptr.To - - a82187cf1 2025-07-24T08:15:36+09:00 [PodLevelResources] Update Downward API defaulting for resource limits - - 4c87e60d0 2025-07-23T21:17:05+02:00 Tests using .host field in probes must be at priviledged level - - f94fcac86 2025-07-23T21:15:46+02:00 Add new fixture testData for 1.34 PSA - - fc0474d77 2025-07-23T21:15:46+02:00 Copy test fixtures to 1.34 from 1.32 - - 9540a9639 2025-07-23T21:15:46+02:00 Copy test fixtures to 1.33 from 1.32 - - 4a3ebf886 2025-07-23T21:15:46+02:00 update the minimal version to fix unit/fixture tests - - 333b19b44 2025-07-23T21:15:45+02:00 Add PSA for blocking .host field on pod probes and lifecycle - - c7bf3b81f 2025-07-23T13:51:18-04:00 Add flake debugging for admission test - - a806e069e 2025-07-23T17:40:53Z Remove WinDSR feature gate unit test - - 765d84e9b 2025-07-23T13:19:07-04:00 Test only EndpointSlices, not Endpoints, in dual-stack e2e tests - - 2cb48f77f 2025-07-23T18:58:57+02:00 schedule pod availability checks at the correct time in ReplicaSets - - 61cc6cf80 2025-07-23T09:13:13-07:00 draadminaccess test make it serial - - 33b45c838 2025-07-23T11:07:29-04:00 Update "should proxy through a service and a pod" to look at EndpointSlices - - d70e7e223 2025-07-23T11:07:29-04:00 Port aggregated apiserver discovery to EndpointSlices - - 41dc2d3b0 2025-07-23T11:07:28-04:00 Add utilities for getting EndpointSlices for a Service - - f7109ed28 2025-07-23T10:59:18-04:00 [KEP-3751] Allow PVC VACName to update to nil or empty when status.currentVAC is nil - - c35e4ad2b 2025-07-23T22:57:12+08:00 add codes for drop disabled pod fields - - 8d65e1e98 2025-07-23T22:57:11+08:00 Add e2e tests. - - f31aeca42 2025-07-23T22:57:11+08:00 Add code for overriding hostnames - - 88b762143 2025-07-23T22:57:08+08:00 Add validation for the HostnameOverride field. - - c889ee17a 2025-07-23T16:55:05+02:00 Convert kubelet plugin manager from gogo to protoc - - abb1b26d5 2025-07-23T16:50:23+02:00 DRA: Add experimental allocator variant - - 17cc5e9ec 2025-07-23T15:38:34+02:00 e2e: node: podresources: exercise with dynamicresources enabled - - ee8ef383b 2025-07-23T22:37:19+09:00 Update kubectl kustomize to kyaml/v0.20.1, cmd/config/v0.20.1, api/v0.20.1, kustomize/v5.7.1 - - af6c97bd1 2025-07-23T20:28:13+08:00 add Feature Gate. - - 8b3814c4a 2025-07-23T20:28:12+08:00 Add the HostnameOverride field to the Pod API - - c2a06e791 2025-07-23T11:06:11+03:00 DRA: skip flaky test case on Windows - - f6061605f 2025-07-23T09:12:46+02:00 DRA E2E: run multi-node control plane tests also with two nodes - - f0e292089 2025-07-23T09:10:45+02:00 DRA E2E: simplify "control plane" test names - - 603751ee8 2025-07-23T09:10:45+02:00 DRA E2E: remove redundant test - - 21ed19798 2025-07-23T09:58:14+03:00 kubelet: DRA: Handle grpc.ErrServerStopped in plugin tests - - 61bd5789b 2025-07-23T03:44:48Z Updated to not directly change the global variable `claim` - - 4f0a5771a 2025-07-23T10:19:20+08:00 test: add e2e case for mutating named port - - db9b9b5a4 2025-07-22T16:48:31-07:00 Build etcd v3.6.3 image - - 179551a7c 2025-07-22T23:24:32Z feat: Implement warnings for unrecognized formats in CRDs - - 437a2ad69 2025-07-22T23:23:55Z feat: Add func to export the supportedVersionedFormats - - d943239c5 2025-07-22T22:11:23Z added debug_redact to cri api secrets - - 88af8b606 2025-07-23T07:08:21+09:00 Add PodLevelResources to the Windows OS limitations in the API doc - - c2b26617b 2025-07-23T07:08:21+09:00 Check OS for PodLevelResources in kubelet - - e2c308aff 2025-07-23T07:08:14+09:00 Check OS for PodLevelResources in API server - - f6aee6369 2025-07-22T20:40:48Z add validation logic for APIVersion fields of HPA - - 6f3b6b91f 2025-07-22T13:40:42-07:00 KEP-3721: Support for env files (#132626) - - 0b60c1219 2025-07-22T15:15:18-04:00 KEP-4222: Adopt text and JSON transcoding support for CBOR. - - 917659269 2025-07-22T15:15:17-04:00 Bump to github.com/fxamacker/cbor/v2 v2.9.0. - - 216f7485b 2025-07-22T11:54:34-07:00 DRAAdminAccess: add upgrade downgrade test - - 303a7056f 2025-07-22T19:58:29+02:00 e2e: node: podresources: enable multi-container tests - - 38a9a8a59 2025-07-22T19:55:09+02:00 e2e: node: podresources: add tests for missing pod - - 19b00ecc9 2025-07-22T17:36:03Z update CCM image to v33.1.1 - - b070b0a5c 2025-07-23T00:57:50+08:00 chore: residual boolptr and intptr removal - - 407bcf886 2025-07-22T11:05:00-04:00 kubelet: add metrics for userns pods - - e5ccc31e7 2025-07-22T20:26:52+05:30 chore: replace float64Ptr with ptr.To helper in validation and integration tests - - 545b36ba2 2025-07-22T09:50:18-05:00 fix uncore e2e check - - b97decb7d 2025-07-22T15:58:22+02:00 client-go/dynamic/fake: sets opts.Watch true - - f626e847e 2025-07-22T20:44:53+08:00 Migrate pkg/kubelet/winstats to contextual logging - - ce2d97939 2025-07-22T17:35:48+08:00 Run Unschedulable scheduler_perf test case with SchedulerAsyncAPICalls feature gate enabled - - 0da0897c1 2025-07-22T16:38:20+08:00 Bump external snapshotter for vgs tests - - 78bf3410c 2025-07-22T09:21:58+02:00 DRA E2E: revisit conformance classification of tests - - 911df655d 2025-07-22T10:14:42+08:00 chore: migrate kubelet lifecycle to contextual logging. - - 872f0682d 2025-07-22T10:51:56+09:00 Use "k8s.io/api/resource/v1beta2" instead of "k8s.io/dynamic-resource-allocation/api" for resource API imports. - - 31d2de59d 2025-07-22T10:51:55+09:00 Split the symlink target error cases into for each condition - - a4fb1562f 2025-07-22T10:51:53+09:00 introduce resolvePCIeRoot instead of resolveSysDevicesPath - - f3d4b216f 2025-07-22T10:49:39+09:00 assign return value to a variable instead of using it directly - - 7f27c88d0 2025-07-22T10:25:17+09:00 Update staging/src/k8s.io/dynamic-resource-allocation/deviceattribute/pci_linux.go - - ee26a5837 2025-07-22T10:10:40+09:00 Update staging/src/k8s.io/dynamic-resource-allocation/deviceattribute/pci_linux.go - - 8b558a1bc 2025-07-21T22:54:24Z fix(validation-gen): correct typos in comments and documentation - - 63a958ff3 2025-07-21T22:54:24Z chore(validation-gen): remove TODO regarding ratcheting behavior for slices and maps - - c659b4182 2025-07-21T22:27:13Z e2e test for mirror pod with pod generation - - a5b9c7a79 2025-07-21T17:57:57-04:00 bump resource claim controller concurrent syncs to 50 - - 6d4000f84 2025-07-21T21:49:57Z Pod Certificates: make update - - 4624cb9bb 2025-07-21T21:49:57Z Pod Certificates: Basic implementation - - facbb6614 2025-07-21T17:00:45-04:00 Temporarily revert restart-on-node-IP-change behavior of proxy NodeManager - - e2d37f3cd 2025-07-21T17:00:44-04:00 kube-proxy: merge OnNodeAdd and OnNodeUpdate into OnNodeChange - - 0dc51b16f 2025-07-21T17:00:44-04:00 kube-proxy: merge NodeEligibleHandler with NodeManager - - d4892fef7 2025-07-21T17:00:44-04:00 kube-proxy: merge NodePodCIDRHandler with NodeManager - - 373fb487f 2025-07-21T17:00:44-04:00 kube-proxy: add NodeManager to manage life-cycle based on NodeIPs - - d21ca8674 2025-07-21T17:00:44-04:00 kube-proxy: add NodeTopologyConfig for tracking topology labels - - 8acda3631 2025-07-21T17:00:42-04:00 Belatedly add tests of proxy NodeConfig and ServiceCIDRConfig - - edf4654d7 2025-07-21T19:27:59Z generate proto - - 18918e200 2025-07-21T19:27:59Z add CSR declarative_validation_test.go tests - - 69a8a169d 2025-07-21T19:27:59Z add WithOrigin and MarkedByDeclarative, update hand-written to error at list instead of list item field, add additional tests for approved+denied case - - 6a2d5a1e6 2025-07-21T19:27:59Z feat: add CSR status.conditions approved+denied declarative validation tags and associated declarative validation tags to v1 and v1beta1 types.go - - 248ad2161 2025-07-21T13:55:32-05:00 graduate prefer-align-cpus-by-uncorecache to beta - - 6e77bff18 2025-07-21T18:51:07Z pod sandbox image is not being used by kubelet any longer - - 43706d6b7 2025-07-21T20:34:36+03:00 add warnings when creating headless service with specified load balancer ip,external ips and/or session affinity - - 53aa4332b 2025-07-21T16:50:16Z fix integration tests - - 8996e81fc 2025-07-21T16:46:07Z fix unit tests - - dd4dd3d8e 2025-07-21T16:32:25Z feat: Enabledeclarative validation in CertificateSigningRequest subresources updates - - ccc82775f 2025-07-21T11:19:25-05:00 expand test coverage for uncore alignment - - cb29414b4 2025-07-21T16:13:32Z Extend E2E test coverage for PSI metrics under pressure - - 4ed231da0 2025-07-21T17:16:16+02:00 kubelet/imagePullManager: add benchmarks for image pull record accessors - - 5486e6f44 2025-07-21T07:55:32-07:00 DRAAdminAccess: move to beta - - 5d4010d2d 2025-07-21T09:08:43-05:00 Mark KubeletServiceAccountTokenForCredentialProviders feature gate as beta - - 4fc9546e0 2025-07-21T14:00:34Z KEP-5229: Implement API dispatcher - - 549f7c4fc 2025-07-21T14:53:58+02:00 image pull manager: add in-memory LRU intents/pulled records caching - - ea326373e 2025-07-21T13:57:50+02:00 e2e: node: cpumanager cgroup v1 compatibility - - b8d74e75c 2025-07-21T12:56:51+01:00 Add test case to prove MaxElements correctly set on IntOrString - - 7e5aafcb1 2025-07-21T13:47:22+02:00 ci: remove unnecessary test harness - - 457df1cf9 2025-07-21T12:48:29+02:00 ci cleanup: make sure to remove test KUBECONFIGs - - 3026020b4 2025-07-21T10:04:01+02:00 Convert `k8s.io/kubelet/pkg/apis/deviceplugin` from gogo to protoc - - 4f9f6c053 2025-07-21T09:33:11+02:00 scheduler_perf: hide "metric ... not found" errors - - b8758ac31 2025-07-20T21:50:58+01:00 node: mm-mgr: migrate to contextual logging - - 2e756e741 2025-07-20T15:17:04-05:00 fix data race in OIDC integration tests by serializing test server starts - - 03acd266a 2025-07-20T22:16:45+08:00 chore: residual uint64ptr removal with ptr.To - - b84271a77 2025-07-19T21:54:47-07:00 DRAAdminAccess: add e2e - - ab839c93f 2025-07-20T09:47:50+09:00 feat(kubelet): migrate kuberuntime to contextual logging - - 30e5cdd64 2025-07-19T16:20:34+03:00 kubelet: don't fetch image credentials if the image is present and if we don't need to check if the pod is allowed to pull it - - cbba3281a 2025-07-19T11:46:32+02:00 integration: fix etcd output handling - - d0fc938a0 2025-07-19T11:38:21+02:00 DRA client: fix conversion of watch channel - - f77ce8951 2025-07-19T11:38:12+02:00 DRA: debug output for list/watch client - - 9d7d3a617 2025-07-19T14:41:04+05:30 Bump sample-device-plugin base image to alpine:3.22 - - 7ddb04262 2025-07-19T17:10:37+09:00 feat(cmd/kubelet): support structured and contextual logging - - fb4e25222 2025-07-19T14:13:59+08:00 test: add batch pod deletion for kubelet e2e tests - - 4b8dd9612 2025-07-19T13:08:34+09:00 cleanup: remove example plugins - - 067bd16b1 2025-07-19T03:37:37Z Add unit tests to check if right feature gate is checked based on resize request. - - f71080c93 2025-07-19T03:22:56Z Create separate feature gates for static CPU Manager and static Memory Manager support - - 07ef7842b 2025-07-19T03:20:26Z Change memory manager static policy to a public const - - ae5247afc 2025-07-19T00:07:22Z address feedback - - 659517445 2025-07-19T00:06:48Z unit test for HandlePodReconcile retrying pending resizes - - 0d24c3b57 2025-07-19T00:05:19Z add sourcesReady parameter to fakeKubelet constructor - - 6e86af48c 2025-07-19T00:05:17Z fix check if requests have shrunk - - 6a40bcb42 2025-07-19T00:03:46Z Retry pending resizes if a status update leads to aggregate requests shrinking - - 22d724969 2025-07-18T23:59:05Z kubelet: record container_resize_requests metric for all resize updates - - 13a6d2121 2025-07-18T23:30:54Z check a couple extra failure scenarios - - 8957109b7 2025-07-18T22:29:30Z only record resizes in progress and pending after all pods are added - - d51375dcc 2025-07-18T22:29:25Z record 'kubelet_pod_deferred_resize_accepted_total' metric - - b8fc1b675 2025-07-18T22:27:40Z record 'kubelet_pod_infeasible_resizes_total' metric - - d845e1fd6 2025-07-18T22:27:40Z record 'kubelet_pod_pending_resizes' metric - - 23005281f 2025-07-18T22:27:39Z record 'kubelet_pod_in_progress_resizes' metric - - 0595ddaaf 2025-07-18T22:27:39Z record 'kubelet_container_requested_resizes_total' metric - - 468aa5e30 2025-07-18T22:27:39Z record 'kubelet_pod_resize_duration_milliseconds' metric - - 129662763 2025-07-18T22:27:39Z define and register ippr metrics - - 3964fbeab 2025-07-18T17:00:17-05:00 kubelet: integrate sa creds in image pull manager - - f1728bd58 2025-07-18T16:38:27-05:00 Add ServiceAccount coordinates to ImagePullCredentials v1alpha1 - - b9dd2fdec 2025-07-18T16:38:23-05:00 credentialprovider: track service account cred source in ext provider keyring - - 9a4c0f9b2 2025-07-19T06:32:52+09:00 scheduler_perf: Add memory tracking to performance tests - - 8a42f4ccc 2025-07-18T11:55:23-07:00 Add support for CEL list library. - - 5d3186631 2025-07-18T17:50:07Z dedupe fetching allocatable and available resources in node test - - 79dc0b8a4 2025-07-18T19:38:56+02:00 Add jitter to priodically executed process in storage to avoid too concurrent executions - - a48420e3c 2025-07-18T16:57:41Z promote PodObservedGenerationTracking to beta - - 336b5aff4 2025-07-18T16:35:32Z Check for valid UID range when runasnonroot is true - - e9492239b 2025-07-18T16:29:31Z Promote windows graceful shutdown to Beta - - 00bf3b37a 2025-07-18T21:35:58+05:30 Graduate PodLifecycleSleepActionAllowZero to GA - - 99059895f 2025-07-18T17:53:23+02:00 Account for caching and maximum object size when estimating LIST request - - 2256f5747 2025-07-18T23:43:53+08:00 Add resize completed event after Inprogress conditionCleared is cleared - - d42a1d58d 2025-07-18T07:15:41-07:00 DRAAdminAccess: add metrics - - f5d12ed39 2025-07-18T14:10:45Z fix: Compare versions instead of pointer comparison - - 8dc20a0f6 2025-07-18T12:34:29+01:00 Fix IntOrString cost estimation when schema has a MaxLength constraint - - a2e9e9f66 2025-07-18T17:02:54+08:00 fix pass ctx into a revised HandleError function - - 729cd583a 2025-07-18T09:43:04+02:00 scheduler integration: fail test instead of existing - - bfa33b18a 2025-07-18T09:55:39+08:00 fix(kube-proxy) avoid add zero-masked loadBalancerSourceRanges to ipset - - d6e85b504 2025-07-17T20:30:06-05:00 Add kubelet_credential_provider_config_info metric - - 14a5ef56a 2025-07-17T23:21:26Z fix pipeline failure - - 21e2fcea9 2025-07-17T17:47:51-05:00 Add automatic_reload_last_config_info metric for auth configs - - 5f829195e 2025-07-17T14:46:47-07:00 Only warn when AppArmor annotation doesn't match pod field - - f2c48ffec 2025-07-17T16:32:47-05:00 Add generic config info custom collector - - 11921f758 2025-07-17T14:14:57-07:00 [KEP-5100] WinOverlay feature gate to GA - - e417232f9 2025-07-17T14:07:35-07:00 Warn when using AppArmor annotations with a pod field - - 4fdf09fdc 2025-07-17T14:07:35-07:00 Stop syncing AppArmor fields to annotations - - 3ecb3d230 2025-07-17T14:07:35-07:00 Remove unused appArmor*InUse functions - - 75ae2d727 2025-07-17T13:17:35-07:00 Add an E2E test for memory limit decrease usage check - - 2a9388c30 2025-07-17T13:17:35-07:00 Move memory limit decrease e2e test to success cases - - c7a78185c 2025-07-17T13:17:35-07:00 Remove the restriction on memory limit decrease - - d9c91127d 2025-07-17T13:17:35-07:00 Check memory usage before decreasing limits - - 465f72814 2025-07-17T20:09:05Z use gomega.BeComparableTo instead of Equal for resource quantity check in resize test - - cedcbfb94 2025-07-17T20:09:03Z Update cel-go to v0.26.0 - - 24065780e 2025-07-17T15:34:34-04:00 Add e2eendpointslice.WaitForEndpointPorts, use in some tests. - - f456a70bd 2025-07-17T19:19:05Z use CreateBatch and MakeResizePatch - - 5cea72d56 2025-07-17T21:18:28+02:00 DRA integration: add test case for FilterTimeout - - 241ac018e 2025-07-17T21:18:28+02:00 DRA integration: remove unnecessary anonymous import - - bc338e750 2025-07-17T21:18:28+02:00 DRA scheduler: implement filter timeout and cancellation - - 430c79b53 2025-07-17T19:03:35Z chore(validation-gen): hold uniqueness check of listmap - - 1745094c4 2025-07-17T18:40:01Z Update VolumeAttributesClass API Description - - 2cb30c779 2025-07-17T18:22:15Z Refactor target check - - 86bc1bf0a 2025-07-17T17:50:45Z more complex e2e test for deferred resizes - - 66de1960a 2025-07-17T18:13:10+02:00 Increase maxSeats for List requests - - 025c606e3 2025-07-17T16:47:47+02:00 DRA scheduler: add plugin configuration - - ee38a0013 2025-07-17T16:47:47+02:00 DRA scheduler: add DRASchedulerFilterTimeout feature gate - - 837ef29f5 2025-07-17T16:47:47+02:00 scheduler: enhance and document Filter cancellation - - 7910b43cd 2025-07-17T16:47:46+02:00 scheduler_perf: document benchstat usage - - b9ce92d50 2025-07-17T16:45:42+03:00 edit versioned_feature_list.yaml - - 070621bf7 2025-07-17T16:44:41+03:00 Remove unit tests that rely on feature gate enablement check - - 3f847d97c 2025-07-17T16:44:40+03:00 GA the NodeSwap feature gate - - 1a7630c09 2025-07-17T22:41:58+09:00 Remove deprecated LegacySidecarContainers feature gate - - 300c7b815 2025-07-17T22:33:32+09:00 set the timeout to Get method - - 2b13b87e6 2025-07-17T15:11:55+02:00 chore: replacing timer ptr with ptr.To - - 532d48fe6 2025-07-17T14:56:44+02:00 Convert `k8s.io/kubelet/pkg/apis/podresources` from gogo to protoc - - cf68f75fc 2025-07-17T14:30:16+02:00 Deprecate apiserver_storage_objects and replace it with apiserver_resource_objects metric using labels consistent with other metrics - - db342010f 2025-07-17T12:08:03+02:00 kube-controller-manager: enable WatchListClient - - cef9f9edb 2025-07-17T16:58:58+08:00 kubeadm: fix a bug where it should generate default etcd command based on etcd version when the etcd image tag supports semver - - ace2a2249 2025-07-17T10:17:30+02:00 drop rules for release-1.30 as it is EOL - - 6737c31d0 2025-07-17T10:12:19+02:00 update publishing bot go rules for release-1.31/1.32 - - a1a85ddb1 2025-07-17T09:56:28+02:00 SSA: test optional map keys - - 4d34975a4 2025-07-17T09:56:28+02:00 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 - - 3357e8fc0 2025-07-17T09:56:28+02:00 SSA: add integration tests - - a2a3839a8 2025-07-17T09:43:44+02:00 DRA scheduler: add pohly as approver - - 4bc2ad6ee 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/preemption to contextual logging - - b96e3cac7 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/pod to contextual logging - - 0cb31bc40 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/nodeshutdown to contextual logging - - 75ccd69ba 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/kubeletconfig to contextual logging - - 1d0fd5928 2025-07-17T00:16:01-07:00 kubectl: add port names to describe pod output - - 7dad9e2af 2025-07-17T10:15:58+03:00 migrate pkg/kubelet/apis to contextual logging - - f141907dd 2025-07-17T07:56:03+02:00 DRA kubelet: add v1 gRPC - - 1b5a08cbf 2025-07-17T09:51:42+08:00 cleanup: fetch individual PodResourceInfo from allocated resource state - - 6e7e6b37c 2025-07-17T01:37:22Z Fix the cost issue to match the bug fix for target being nil in CEL side. - - ad220eb6c 2025-07-17T09:08:12+08:00 chore: remove residual int64ptr usage with ptr.To - - a96446863 2025-07-16T15:59:55-07:00 Add PodCPUAndMemoryStats to stats.Provider interface - - 8f4a624a5 2025-07-16T22:56:59Z Fix pipeline errors - - e8536c019 2025-07-16T22:38:45Z add item + union and item + zeroroneof output tests - - be72d963b 2025-07-16T22:38:45Z add validate/zeroorone_test.go and add +k8s:zeroOrOneOfMember output tests - - 10b20852e 2025-07-16T22:38:45Z feat(validation-gen): add +k8s:zeroOrOneOfMember tag validator and associated validate method - - 81f18759e 2025-07-16T22:38:44Z add validate/union_test.go and add +k8s:unionMember and +k8s:unionDiscriminator output tests - - 5bc9b6911 2025-07-16T22:38:44Z feat(validation-gen): add +k8s:unionMember and +k8s:unionDiscriminator tag validators and associated validate methods - - bfb42fc31 2025-07-16T22:38:44Z refactor item.go with buildMatchConditions, make itemTagValidator a LateTagValidator - - 5d1c5ebd8 2025-07-16T22:38:32Z add ParentPath to context, remove Parent from context and plumb changes in validators - - c50da38aa 2025-07-16T22:33:58Z allow field validators to generate variables - - e7aeb4ff5 2025-07-16T21:23:13Z Promote MutableCSINodeAllocatableCount to Beta - - 9bcaa8c86 2025-07-16T15:11:21-04:00 Fix conversion-gen caching incorrect memory equality comparisons - - b35ad4e9b 2025-07-16T11:42:02-04:00 Add e2eendpointslice.WaitForEndpointPods, use in various test - - dbecdd187 2025-07-16T11:42:02-04:00 Use e2eendpointslice.WaitForEndpointCount in more network tests - - b7998a397 2025-07-16T11:42:00-04:00 Add e2eendpointslice.WaitForEndpointCount, use it in some network tests - - dd3691b16 2025-07-16T15:11:11Z refactor allocator, removed claimsToAllocate from NewAllocator(), instead, passed it through Allocate() - - 8e6651520 2025-07-16T16:46:39+02:00 Convert `k8s.io/kms/apis` from gogo to protoc - - 2f605f49f 2025-07-16T14:40:35Z CHANGELOG: Update directory for v1.34.0-beta.0 release - - 9cf00ec6d 2025-07-16T14:56:50+02:00 kube-apiserver: promote WatchList feature to beta - - e4320fe25 2025-07-16T15:49:41+03:00 e2e_node: DRA: test handling fatal serving failures - - ea05ad888 2025-07-16T15:49:41+03:00 e2e_node: DRA: add errorOnCloseListener - - fc21d3f37 2025-07-16T15:49:41+03:00 e2e: DRA: enable test plugin to cancel main context on error - - 1981c985b 2025-07-16T15:49:41+03:00 e2e: DRA: support test and public options - - d44b73744 2025-07-16T15:49:32+03:00 DRA: handle grpc.Server.Serve failures - - 169965350 2025-07-16T15:42:12+03:00 e2e_node: Refactor DRA tests to use variadic options - - 52fab5969 2025-07-16T21:33:33+09:00 Add NominatedNodeNameForExpectation feature flag - - fd23fa3d4 2025-07-16T12:52:01+02:00 Graduate ListFromCacheSnapshot to Beta - - 665599417 2025-07-16T06:17:34-04:00 Add e2eendpointslice.WaitForEndpointSlices, use it in a few places - - b5931f53d 2025-07-16T06:19:27Z Auto update openapi spec - - a100dfdfa 2025-07-16T05:11:52Z Using alpha as the stored version for one release. - - 6e9324453 2025-07-16T12:24:35+08:00 Add validation of volumeClaimTemplates in StatefulSet - - ae4a43de6 2025-07-16T11:01:37+08:00 Refactor: isolate flag registration to kube-apiserver to eliminate global state - - 5b4c1872a 2025-07-16T09:07:25+08:00 chore: residual intptr removal with ptr.To - - e9aab4648 2025-07-15T23:11:24Z CHANGELOG: Update directory for v1.31.11 release - - dc0ca0be3 2025-07-15T22:19:29Z CHANGELOG: Update directory for v1.33.3 release - - d6caa36dc 2025-07-15T22:18:25Z CHANGELOG: Update directory for v1.32.7 release - - d460611e7 2025-07-15T21:51:36Z Add more checks - - b69fd9d42 2025-07-15T16:03:07-04:00 Add egress selector support to JWT authenticator - - e9c1ca724 2025-07-15T15:38:13-04:00 Add conversion-gen memory equality test - - 62521d835 2025-07-15T18:23:30Z fix observedGeneration in pod resize conditions - - 386372602 2025-07-15T10:48:12-07:00 add unit-test for ensuring authn latency annotation - - 760eb7d5d 2025-07-15T10:39:08-07:00 fix: record authentication latency before audit filter wraps up - - 26c8ee7b8 2025-07-15T17:22:12Z DRA: Improve allocator with better backtracking - - d383c8e02 2025-07-15T17:46:28+02:00 Update history of checkpoint support in Kubelet - - 20914ef4e 2025-07-15T17:00:49+02:00 Prevent running two HPA cachers for different API versions - - bc5088cbf 2025-07-15T19:34:05+05:30 Revert "Kube proxy node manager" - - f8c7131b4 2025-07-15T15:32:13+02:00 Drop experimental- prefix from etcd flags - - d8747d716 2025-07-15T15:06:26+02:00 Use object size estimation for non-recursive list - - 05e1c4b48 2025-07-15T14:15:00+02:00 e2e: node: fix podresources API feature label - - 6e1875fac 2025-07-15T12:54:40+02:00 local-up-cluster.sh: don't require to be invoked in the root - - 356be5ae3 2025-07-15T12:54:40+02:00 DRA E2E: move upgrade/downgrade test into test/e2e_dra - - c8ca9249a 2025-07-15T12:54:40+02:00 DRA integration: add upgrade/downgrade testing with local-up-cluster.sh - - 60e9316c0 2025-07-15T12:54:40+02:00 DRA E2E: refactor helper code - - 2e3228e2c 2025-07-15T12:52:27+02:00 DRA E2E: support deploying driver on localhost - - e5f57d2cf 2025-07-15T12:52:27+02:00 ktesting: add WithoutCancel - - e01603b2e 2025-07-15T12:52:27+02:00 ktesting: document side effect of SetDefaultVerbosity during init - - 0b1bed1a1 2025-07-15T12:52:27+02:00 ktesting: WithCancel does not cancel on test completion anymore - - f381d7372 2025-07-15T12:52:27+02:00 DRA E2E: retry exec of hostpathplugin - - c2080e7e4 2025-07-15T12:52:27+02:00 DRA E2E: support using ktesting - - 906505281 2025-07-15T12:52:27+02:00 ktesting: add step Begin/End - - b7c2d6aba 2025-07-15T12:52:27+02:00 ktesting: skip logging error when capturing it - - 497716386 2025-07-15T12:52:26+02:00 DRA E2E: reduce port proxy verbosity - - 5721c927e 2025-07-15T12:52:26+02:00 DRA E2E: increase verbosity of resource claim controller - - 1a284472f 2025-07-15T12:52:26+02:00 E2E framework: retry also on EOF errors - - 6a7b9589f 2025-07-15T12:52:26+02:00 E2E framework: support setting REST config - - bd30b0ade 2025-07-15T16:55:12+08:00 remove general avaliable feature-gate DevicePluginCDIDevices - - 9c0e65b08 2025-07-15T10:11:23+02:00 test/apimachinery/watchlist: server supports sending resources in Table format - - 2dfc4e25a 2025-07-15T10:08:41+02:00 endpoints/handlers/respone: include metadata when IncludeNone and watchlist requested - - e1a0cf624 2025-07-15T14:56:43+08:00 handle stoppedCh and listenerStoppedCh returned by cc.SecureServing.Serve - - 6cd00cdcb 2025-07-15T04:48:13Z Auto gen - - a3ecea296 2025-07-15T01:44:13Z manual change - - 4f3334b7c 2025-07-15T01:44:13Z Promote feature gate - - 0d8fd61e6 2025-07-14T21:10:37Z address review comments - - 32afbd9ea 2025-07-14T23:02:18+02:00 Inconsistency resets cache snapshots and prevents collection of new ones until cache is marked consistent again - - 4f77a4618 2025-07-14T16:19:52-04:00 Generated files - - a04e7cf5e 2025-07-14T16:19:52-04:00 KEP-4601: Graduate selector authorization to stable - - 6f4be0d8c 2025-07-14T21:07:45+02:00 DRA allocator: skip unsupported test cases - - 740e56846 2025-07-14T18:13:00Z address review comments - - 61542e7a9 2025-07-14T18:13:00Z Cleanup: Remove field name from invalid field detail message - - 14f3c2684 2025-07-14T18:03:57Z Remove redundant metric field. - - ad03cb873 2025-07-15T00:31:20+08:00 chore: residual strPtr utility removal with ptr.To - - af249fb2e 2025-07-14T18:13:27+02:00 DRA E2E: test mixture of extended resources + ResourceClaim - - 9a7dddf5a 2025-07-15T01:07:43+09:00 fix test - - 09ec6f744 2025-07-15T01:07:25+09:00 chore - - 85adda5e6 2025-07-14T16:58:58+02:00 Use object size to estimate list cost assigning 1 sear per 100KB - - f20be4c09 2025-07-14T23:17:19+09:00 add test which checks release method calls Get - - 7d9eb2b3d 2025-07-14T16:09:29+02:00 test/apimachinery/watchlist: update tests that receive resources in Table format - - da7c55e0d 2025-07-14T15:42:57+02:00 reflector: detects unsupported meta.Table gvks for watchlist - - ebc1ccc49 2025-07-14T07:24:48-04:00 Bump k8s.io/kube-openapi to latest SHA (f3f2b991d03b) - - 8d1cbc83d 2025-07-14T13:02:14+02:00 endpoints/handlers/get: remove watchListEndpointRestrictions - - 14d1bbf36 2025-07-14T09:08:16+08:00 chore: maxPtr utility removal with ptr.To - - 6462ad918 2025-07-14T00:52:42+02:00 codegen tool: resolves GOBIN via `go env` - - 1073b3b90 2025-07-13T20:53:30Z Add unit tests for AddPod() - - fcb595a2d 2025-07-14T00:31:53+05:30 service-ip-alloc: delay ip processing on service recreate - - 8de14b526 2025-07-13T23:51:48+05:30 service-ip-alloc: make repair loop consumer clock interface - - e38361728 2025-07-13T12:42:45+02:00 Fix TestProgressNotify for etcd v3.6.2 - - e0f9914ef 2025-07-13T08:12:55+08:00 chore: replace int32Ptr usage with ptr.To - - cf4912eb4 2025-07-12T21:18:59Z chore(validation-gen): reorder imports - - 419e70b76 2025-07-12T21:18:59Z run update-codegen - - 4c8f489b8 2025-07-12T21:18:59Z add +k8s:neq tests - - fc1c832c4 2025-07-12T21:18:59Z feat: add +k8s:neq tag which enforces field is neq to a specified comparable value - - fb971325c 2025-07-12T21:18:59Z feat(validation-gen): add new test cases for item validation - - 5cc2721f6 2025-07-12T21:18:57Z feat(validation-gen): add k8s:item - - af05aa61d 2025-07-12T21:16:48Z feat: Add validation ratcheting for subfields tag - - daef13ecc 2025-07-12T21:16:48Z chore: improve error rendering and add unit tests for ErrorMatcher - - f40ee6f99 2025-07-12T21:16:48Z feat(validation-gen): add new test cases for validation of slices and maps - - b059bb551 2025-07-12T21:16:48Z feat(validation-gen): enhance validation functions for slices and maps - - 0b1fa64a9 2025-07-12T21:16:48Z refactor(validation-gen): streamline type validation logic - - 7ad89e199 2025-07-12T21:16:47Z feat(validation-gen): add FieldValidator - - ba45e37b2 2025-07-12T11:35:07+02:00 chore: removed boolPtrFn helpers with ptr package implementation - - 5971802fd 2025-07-12T16:44:39+08:00 chore: intPtr removal with ptr.To - - a091fa607 2025-07-11T22:58:00+02:00 Add apiserver_resource_size_estimate_bytes metric - - e6cf7dbf0 2025-07-11T22:19:55+02:00 Enable running cache inconsistency detection by default - - a06b3d356 2025-07-11T20:30:39+02:00 Bump dependencies, images and versions used to Go 1.24.5 and distroless iptables - - cba38b629 2025-07-11T20:20:48+02:00 DRA allocator: fix linter hint - - 5eab2b7a6 2025-07-11T10:59:20-07:00 Remove unuse runtimeCache parameter from stats.Provider - - 46e2c22fd 2025-07-11T23:06:44+05:30 kube-proxy: merge OnNodeAdd and OnNodeUpdate into OnNodeChange - - fa9e46694 2025-07-11T23:06:44+05:30 kube-proxy: merge NodeEligibleHandler with NodeManager - - c6735d9b3 2025-07-11T23:06:44+05:30 kube-proxy: merge NodePodCIDRHandler with NodeManager - - 45c355ca5 2025-07-11T19:48:11+03:00 Move unschedulablePods struct to a separate file - - bfeaae331 2025-07-11T18:25:46+02:00 Compact watch cache based on last observed etcd compaction - - c43104cbe 2025-07-11T21:48:52+05:30 kube-proxy: add NodeManager to manage life-cycle based on NodeIPs - - af7abde0e 2025-07-11T21:05:19+05:30 kube-proxy: add NodeTopologyConfig for tracking topology labels - - 98c4514ea 2025-07-11T10:32:01-05:00 add e2e_node tests for uncore alignment - - 70191dd21 2025-07-11T10:32:00-05:00 fix uncore cache alignment for odd integer cpus - - 65e0cff3c 2025-07-11T14:55:15+02:00 add Replicaset -> ReplicationController conversion test - - 9df4c35a6 2025-07-11T12:28:50Z Disable SchedulerAsyncPreemption feature correctly in integration tests - - 3636d5bd3 2025-07-11T08:23:44-04:00 Added NodeSelectors field to DriverDefinition - - 4f0d3eaa3 2025-07-11T18:59:14+08:00 enhance exec probe logging with pod and container context - - ffe908207 2025-07-11T08:34:39+02:00 DRA allocator: select tests based on supported features - - b1a35c640 2025-07-11T05:36:16Z Build etcd image v3.6.2 - - 7e37711d6 2025-07-10T23:20:27-05:00 kubelet: Add service account UID to token cache key for proper invalidation - - 45dfb4644 2025-07-10T23:20:23-05:00 Add TokenRequestServiceAccountUIDValidation feature gate with UID validation - - 237fbde8b 2025-07-10T22:30:21Z clean up e2e test and sorting code - - 4d2566eb5 2025-07-10T14:50:54-05:00 credentialprovider: wire in service account mode cache type - - 03db2278d 2025-07-10T14:50:51-05:00 kubelet: Add CacheType field to ServiceAccountTokenAttributes with validation - - ff4746af1 2025-07-10T19:19:13Z increase verbosity of kubelet preemption log - - f2de8897e 2025-07-10T12:13:40-07:00 Add metrics for mutation - - bfa7f38c6 2025-07-10T18:37:47Z fix TestPodResourceAllocationReset for windows - - e8b914c4b 2025-07-10T18:29:31Z address comments - - 6052c569d 2025-07-10T18:01:15Z prioritize resize requests by priorityClass and qos class - - c126870eb 2025-07-10T12:19:31-04:00 Bump RecoverVolumeExpansionFailure to GA - - 7b906f204 2025-07-10T17:34:21+02:00 DRA allocator: fork the code - - 5caf7bca1 2025-07-10T17:34:21+02:00 DRA allocator: refactor code - - 03e32bd26 2025-07-10T16:01:02+02:00 Expose compaction revision from compactor - - 5e3ea8e27 2025-07-10T16:00:12+02:00 Add test for compactor - - bbab59411 2025-07-10T15:30:56+02:00 local-up-cluster: stop running Docker - - f57662856 2025-07-10T15:30:56+02:00 local-up-cluster: store logs in artifacts directory - - 81b6e1d3a 2025-07-10T15:30:56+02:00 local-up-cluster: start containerd before Docker - - 27a77370d 2025-07-10T15:30:56+02:00 local-up-cluster: simplify installing packages - - ddda1dca3 2025-07-10T15:30:56+02:00 local-up-cluster.sh: add dry-run mode - - 0950b9ee5 2025-07-10T13:39:48+02:00 DRA allocator: export DeviceClassLister - - bc5aa94d8 2025-07-10T13:09:19+02:00 local-up-cluster.sh: allow configuring all ports - - a4b1d26b1 2025-07-10T13:09:18+02:00 local-up-cluster.sh: dump config on KUBE_VERBOSE >= 2 - - 5665bafaa 2025-07-09T23:12:11Z CHANGELOG: Update directory for v1.34.0-alpha.3 release - - 381b3f376 2025-07-09T21:44:08Z clear just the errors rather than the entire in-progress condition when a new resize is allocated - - b89ab301f 2025-07-09T20:50:07Z feedback round 2 - - 67aaa956d 2025-07-09T21:45:54+02:00 Update docs on shutdown and draining - - 7a6f6fdf7 2025-07-09T11:25:33-07:00 Delete unnecessary mutex - - 271233a62 2025-07-10T02:59:21+09:00 Prevent the failure of releasing the lock by updating the resource version in case of a resource conflict - - d9de590a2 2025-07-09T22:33:54+08:00 test: increase test coverage for pkg/kubelet/types - - 2dd07e924 2025-07-09T15:56:06+02:00 DRA E2E: ResourceSlice Controller test flake - - 26f54e5c0 2025-07-09T21:35:45+08:00 chore: replace int64ptr with ptr.To - - f2b24b984 2025-07-09T12:10:10Z Increase verbosity of frequently printed loglines in binder plugin - - 621482d68 2025-07-09T16:38:14+05:30 update pause version to 3.10.1 - - ce456c87f 2025-07-09T10:40:49+08:00 add SuccessCriteriaMet status for kubectl get job - - bb6bd5201 2025-07-08T23:49:34Z Add feature gate enable test for KubeletPodResourcesGet - - c92524377 2025-07-08T21:53:20Z address feedback - - c6fef9752 2025-07-08T13:25:26-07:00 fix: improve the pod level request validation (#132551) - - 89344dc23 2025-07-08T18:38:04Z feat(validation-gen): add k8s:enum validator - - 345641f10 2025-07-08T18:38:04Z feat(validation-gen): add Enum validator function - - adb71d041 2025-07-08T17:51:59Z Forcefully expire lease in integration test to fix flake - - 637bf55cb 2025-07-08T13:48:26-04:00 bump golang.org/x/vuln/cmd/govulncheck to v1.1.4 - - e0cc07af8 2025-07-08T17:43:52Z Promote PSI metrics feature to beta - - b46a124db 2025-07-08T17:14:49Z skip pending resize evaluation if sources aren't ready - - 35bf1522b 2025-07-08T17:14:48Z update allocation manager unit tests to cover push and retry of pending resizes - - e6d165b87 2025-07-08T17:14:47Z move resize allocation out of the sync loop - - 87fe2491a 2025-07-08T17:07:59Z add some additional helpers to kubelet status manager - - cb2baef91 2025-07-08T17:07:57Z move handlePodResourcesResize unit tests into allocation_manager_test - - 1a62ade74 2025-07-08T21:20:43+05:30 cleanup conntrack entries test for UDP service - - 8f92a8178 2025-07-08T17:18:34+02:00 node: e2e: podresources: add more e2e tests - - 380ed8d9b 2025-07-08T17:18:34+02:00 e2e: node: memory manager: build everywhere, run only on linux - - bc56d0e45 2025-07-08T17:18:34+02:00 podresources: list: use active pods in list - - 30a3bfdbc 2025-07-08T22:20:16+08:00 chore: remove residual uint64ptr usage with ptr package - - 006b2a3b5 2025-07-08T16:10:16+02:00 e2e: node: cpumanager: fix cpu quota non-regression tests - - 54f86a22e 2025-07-08T15:45:46+02:00 chore: removing redundant type conversion - - 25d9d8d9b 2025-07-08T15:48:35+03:00 refactor: use getLocalNode() to avoid code duplication - - bc9e8e1a9 2025-07-08T15:45:42+03:00 add a context argument to prePodCreationModificationFunc() - - 83584d13c 2025-07-08T20:27:34+08:00 fix: TestPatchResourceTimeout flaky test - - 994e106dc 2025-07-08T19:50:40+08:00 ci: update sample-apiserver version to v0.33.2 - - 3379d5ac4 2025-07-08T18:33:21+08:00 make sure all streams are created before starting demux websocket - - 1cec0aceb 2025-07-08T11:14:08+01:00 Short circuit CategorizeEndpoints when there are no endpoints - - c53b41e98 2025-07-08T11:41:36+02:00 Add testing compaction in storage List tests - - 1ac60e35e 2025-07-08T12:38:18+03:00 e2e test: Add a container_swap_limit_bytes metric - - bdd662f7c 2025-07-08T12:38:17+03:00 unit test: Add a container_swap_limit_bytes metric - - 341957a36 2025-07-08T12:36:59+03:00 Add a container_swap_limit_bytes metric - - c530b0225 2025-07-08T11:22:07+02:00 chore: depr. pointer pkg replacement for pkg/security and plugin/pkg - - dfe6a5c9c 2025-07-08T11:54:24+03:00 Clean up `unversioned_feature_list.yaml` file - - e909e0cf7 2025-07-08T09:48:56+02:00 chore: replacement of toPtr helper functions with ptr packge - - 841886df7 2025-07-08T08:08:30+02:00 Convert externaljwt from gogo to protoc - - 1b730abf8 2025-07-08T09:34:49+08:00 cleanup: use HandleErrorWithXXX instead of logger.Error where errors are intentionally ignored - - 075abb07a 2025-07-08T09:14:54+08:00 ci: redis removal for e2e test dependency simplicity - - 830a088d1 2025-07-08T09:03:38+08:00 chore: remove strPtr usage with ptr.To instead - - 838f3afc5 2025-07-07T17:37:36-07:00 storage/etcd3: add back missing errcheck - - 604cc2b51 2025-07-07T16:24:51-07:00 hack/update-openapi-spec.sh - - 5adc3bf08 2025-07-07T16:23:09-07:00 hack/update-codegen.sh - - ae7d637b8 2025-07-07T13:59:32-07:00 Delete unused ResizeContainerPatch function - - f1b35cae9 2025-07-07T13:58:40-07:00 Use MakeResizePatch instead of hand-written patch strings in resize E2Es - - 00c1c1a58 2025-07-07T13:57:48-07:00 Generate an E2E resize patch from original & desired ResizableContainerInfo - - cfd65c5f7 2025-07-07T21:28:54+02:00 chore: replacement of helper functions to ptr packge - - ff7c781e2 2025-07-07T18:34:01+02:00 Loop over all IP address from each node - - d9de37d93 2025-07-08T00:08:34+08:00 chore: typo invaILd occurrence replacement - - 1ae1964e8 2025-07-07T16:19:01+02:00 chore: depr. pointer pkg replacement for pkg/apis - - 311565141 2025-07-07T21:51:48+08:00 chore: remove uint64Ptr using ptr.To instead - - 38080c082 2025-07-07T13:30:48+02:00 kubeadm: use named ports in static pod manifests - - baf71997f 2025-07-07T13:22:36+02:00 chore: depr. pointer pkg replacement for pkg/controller - - 8abcdf088 2025-07-07T13:13:39+02:00 chore: depr. pointer pkg replacement for pkg/controller - - f966647b4 2025-07-07T12:54:05+02:00 chore: depr. pointer pkg replacement for pkg/apis - - 6cef8492e 2025-07-07T12:32:45+02:00 chore: depr. pointer pkg replacement for cli-runtime - - bc72fb81c 2025-07-07T12:25:55+02:00 chore: depr. pointer pkg replacement for test/e2e - - d193ffe57 2025-07-07T19:21:39+10:00 Use sets.Set instead of a local impl - - 277c665e8 2025-07-07T17:30:52+09:00 use early return - - 81be9065d 2025-07-07T17:17:11+09:00 improve the log message to clarify what users should do - - e74bbd5db 2025-07-06T22:32:21+02:00 chore: depr. pointer pkg replacement for test/e2e - - 2f7148782 2025-07-06T22:18:03+02:00 chore: depr. pointer pkg replacement for test/e2e and utils - - 1802c5565 2025-07-06T22:02:04+02:00 chore: depr. pointer pkg replacement for test integration - - b22ffdb48 2025-07-06T16:54:04+02:00 golangci-lint: exclude naming convention check for swagger docs - - 0e8424fcf 2025-07-06T11:27:16+02:00 chore: depr. pointer pkg replacement for the e2e_node - - bb24afe58 2025-07-06T11:20:53+02:00 chore: depr. pointer pkg replacement for component-base - - bd8d5f979 2025-07-06T11:14:15+02:00 chore: depr. pointer pkg replacement for controller-manager - - fe61e825e 2025-07-06T11:09:16+02:00 chore: second depr. pointer pkg replacement for apiserver - - 4a61b8170 2025-07-06T10:58:23+02:00 chore: first depr. pointer pkg replacement for apiserver - - 4625908a6 2025-07-06T15:58:06+08:00 remove unused file - - 995a7872c 2025-07-06T11:34:27+08:00 chore: remove utilpointer usage in pkg/api/pod - - ebae41933 2025-07-05T17:14:21-07:00 feat: add PreBindPreFlight and implement in in-tree plugins - - c5b0c9fdc 2025-07-05T12:23:02+02:00 chore: depr. pointer pkg replacement for psa policy - - 88d885e40 2025-07-05T12:13:28+02:00 chore: depr. pointer pkg replacement for psa admissiontest - - dc947510d 2025-07-05T12:09:17+02:00 chore: depr. pointer pkg replacement for psa tests - - 35e118a47 2025-07-05T09:51:57+02:00 chore: depr. pointer pkg replacement for apiext. apiservers validations - - 4a205cc7f 2025-07-05T09:50:03+02:00 chore: depr. pointer pkg replacement for apiext. pkg/cntroller - - 107c58eee 2025-07-05T09:47:37+02:00 chore: depr. pointer pkg replacement for apiextensions in general - - b8ec161d7 2025-07-05T09:39:02+02:00 chore: depr. pointer pkg replacement for apiext. integration - - ca1d7fff7 2025-07-05T11:45:52+08:00 chore: remove utilpointer usage in pkg/apis/autoscaling - - 0ad351281 2025-07-05T10:03:30+09:00 Cleanup duplicate function to get port number from named port - - 1ac5f661e 2025-07-04T11:10:55+01:00 Don't log irrelevant zone hints message on no endpoints - - 27812e44b 2025-07-04T10:47:12+02:00 chore: depr. pointer pkg replacement for apiext. pkg/registry - - b72ab8a4e 2025-07-04T09:51:22+02:00 chore: depr. pointer pkg replacement for the cloud-provider - - b464bbeb8 2025-07-04T08:55:57+02:00 Remove gogo-protobuf from CRI - - ce7b3694f 2025-07-04T12:54:52+08:00 chore: remove utilpointer usage in package test/integration/service/loadbancer_test.go - - 9016f9cb1 2025-07-04T09:29:47+08:00 chore: remove utilpointer usage in conversion package - - 90bbce56b 2025-07-03T21:14:44+03:00 PriorityMemoryEvictionOrdering: allocate more memory when swap is provisioned - - 25498cd34 2025-07-03T21:14:43+03:00 Eviction tests: small refactor - - 43b22a243 2025-07-03T05:07:24-07:00 Apply fix to namespace deletion test (#132691) - - 0766a3c6b 2025-07-03T11:58:42+02:00 chore: depr. pointer pkg replacement for the kube-aggregator apiregistration - - 6c3146e35 2025-07-03T11:34:13+02:00 chore: depr. pointer pkg replacement for the csr - - 934555227 2025-07-03T11:27:00+02:00 chore: depr. pointer pkg replacement for the reflactor - - ebea328f1 2025-07-03T10:46:45+02:00 Fix volume limit e2e test cleanup - - 38bf21327 2025-07-03T08:37:23+01:00 podtopologylabels: update topology.k8s.io->topology.kubernetes.io - - 2e966244e 2025-07-03T08:20:39+02:00 DRA resourceslice controller: fix recreation after quick delete - - fa3131700 2025-07-03T14:15:14+08:00 Remove unused PodIndexLabel feature reference - - 8c6c7df73 2025-07-03T09:57:15+08:00 remove apiserver_storage_objects metrics after crd deleted - - a7e8a505c 2025-07-02T18:53:24-07:00 Improve ignore-not-found behavior (#132542) - - 1c1f00a5f 2025-07-02T11:01:56-07:00 fix: add RV check on GC delete calls - - 84f6d742c 2025-07-02T09:50:33-07:00 Make dynamic and metadata clients plumb DeleteOptions - - ad0b2bf4f 2025-07-02T18:11:46+02:00 DRA E2E: serialize costly test - - 33cd2e1ba 2025-07-02T08:55:24-07:00 Fix AuthInfo godoc for Token / TokenFile precedence (#132659) - - c6f87f6e6 2025-07-02T10:17:26-04:00 Fix offline expansion tests for case where no node expansion tests is required - - b44b0fbf1 2025-07-02T08:00:43-04:00 Update github.com/emicklei/go-restful/v3 to v3.12.2 - - 58e620cc4 2025-07-02T07:37:06-04:00 Bump go.yaml.in/yaml/v3 to v3.0.4 - - 00f8cbae6 2025-07-02T07:32:24-04:00 Bump sigs.k8s.io/json to latest - no code changes - - 22138ef55 2025-07-02T12:57:33+02:00 Add DNS e2e test of NameIsDNSLabel validated Service names - - 97c1974e9 2025-07-02T12:57:32+02:00 Add integration test for RelaxedServiceNameValidation. - - 19e7e38af 2025-07-02T12:57:32+02:00 Add unit test for Ingress service ref relaxed validation - - 37a90b7c2 2025-07-02T12:57:32+02:00 Add unit test for Service relaxed validation - - b430159c8 2025-07-02T12:57:28+02:00 Allow Ingress service refs to be validated with apimachineryvalidation.NameIsDNSLabel - - 487eb8a9e 2025-07-02T12:55:53+02:00 Allow Service names to be validated with apimachineryvalidation.NameIsDNSLabel - - 9043afae6 2025-07-02T08:40:37+02:00 kubectl: Cache Verifier.HasSupport calls - - 179c4398f 2025-07-01T23:17:51-05:00 use defaultImage per OS - - 998776d80 2025-07-01T23:06:05-05:00 remove breaking test - - a17b0d7f6 2025-07-02T12:39:38+09:00 gofmt - - 1514568dd 2025-07-01T22:12:26-04:00 rename sortedfeatures -> sorted - - 9e1a21816 2025-07-01T22:03:22-04:00 update README - - 5cebe66b6 2025-07-01T21:57:50-04:00 update log line - - dcbed2fbd 2025-07-02T09:37:14+08:00 Graduate PodLifecycleSleepAction to GA - - 977c67073 2025-07-01T18:05:26-07:00 Add unit tests for minReady new behaviour - - 4b99dc5f1 2025-07-01T12:26:08-07:00 document hostnetwork <> port implications - - 952d2727a 2025-07-01T11:47:29-07:00 Add OrderedNamespaceDeletion to conformance. - - 12330a6c4 2025-07-01T12:49:16-04:00 Drop BoundedFrequencyRunner from pkg/util/async - - 5d4a85f9f 2025-07-01T16:13:56Z Enable versioned validation fuzz testing for certificates v1/v1alpha1/v1beta1 group - - 0fd4a0acc 2025-07-01T16:13:56Z CSR: Add declarative validation test suite - - 5db205668 2025-07-01T16:13:56Z CSR: Enable declarative validation - - eecba765d 2025-07-01T16:13:56Z Enable validation-gen on certificates/v1,v1alpha1&v1beta1 - - ec6471f63 2025-07-01T15:56:40Z Remove gnostic-models gopkg.in/yaml.v3 unwanted dependency - - d04ee27c9 2025-07-01T15:23:58Z Update vendor - - b41d375b8 2025-07-01T15:21:22Z pin kube-openapi to v0.0.0-20250628140032-d90c4fd18f59 - - 6d5e0bf2a 2025-07-01T16:59:19+02:00 review remarks - - 95b1151d2 2025-07-01T23:57:49+09:00 use format specifier - - 459188ce2 2025-07-01T08:54:14-04:00 Port BoundedFrequencyRunner from flowcontrol.RateLimiter to clock.Clock - - eae17c21b 2025-07-01T08:54:14-04:00 Change how BoundedFrequencyRunner retries work - - c16ee887e 2025-07-01T08:54:14-04:00 Remove burst syncs from BoundedFrequencyRunner - - 0298e04ea 2025-07-01T08:54:14-04:00 Updates to BoundedFrequencyRunner - - 6da9d363f 2025-07-01T08:53:54-04:00 Copy BoundedFrequencyRunner to kube-proxy - - 799aa8b2a 2025-07-01T13:04:40+02:00 Graduate streaming list encoding feature gates - - 5bae9fa89 2025-07-01T11:41:47+02:00 Graduate ConsistentListFromCache to GA - - d4e49b2ee 2025-07-01T02:25:37-07:00 Ensure Loadbalancer internal port is set to container port from endpointslice if the targetPort is not specified in service info creation. - - 6a25bdaac 2025-07-01T11:33:52+08:00 kubeadm: fix missing log of health check - - 764a8bc8b 2025-07-01T09:10:58+08:00 chore: remove utilpointer usage in package pkg/apis/admissionregistration - - a55318fe1 2025-06-30T23:11:49Z fix: versioned validation test avoid incorrect conversion - - 4c09aa907 2025-06-30T22:53:40Z review: feedback - - 776382daa 2025-06-30T21:19:21Z review: assert - - 43f6bd45f 2025-06-30T21:06:47Z review: assert - - fa87098ae 2025-06-30T17:00:27-04:00 fix: kubelet CRI portforward concurrent map write on error - - a0ea2569a 2025-06-30T20:50:51+08:00 chore: remove utilpointer usage in package staging/src/k8s.io/apiserver/pkg/registry/rest/delete - - 7236f3fc2 2025-06-30T12:35:58Z graduate APIServerTracing featuregate to GA - - 75fc2b1cf 2025-06-30T12:31:23Z promote TracingConfiguration to v1 - - a8068e27b 2025-06-30T21:31:21+09:00 scheduler_perf: Fix version emulation for empty featureGates map - - 5a20c38da 2025-06-30T12:30:47Z remove usage of KubeletTracing featuregate from kubelet - - 7faf797a9 2025-06-30T12:30:40Z promote KubeletTracing featuregate to GA - - d28791fa6 2025-06-30T20:59:13+09:00 Remove unused sysfsPath's methods - - 6e5c99dd0 2025-06-30T13:18:53+02:00 Review remarks - - ee8c265d3 2025-06-30T10:06:22Z Move Code and Status from pkg/scheduler/framework to k8s.io/kube-scheduler/framework - - 08dd9c47b 2025-06-30T18:27:55+09:00 improve the log message to clarify the cause of the failure - - a6e2cd4e8 2025-06-30T17:52:24+09:00 scheduler_perf: add logs to report the failure of measuring SchedulingThroughput - - 7e816ca9b 2025-06-30T16:14:50+09:00 Commented out for unused sysfspath methods - - 2bc45ca46 2025-06-30T16:14:44+09:00 Make test only helpers private (sysfspath methods, touchFile, createSymlink) - - 94973ba3f 2025-06-30T16:14:33+09:00 Fix typo: s/smock/mock/g - - ac86e67b7 2025-06-30T08:07:21+02:00 Commonize filtering of Pods by Owner with all orphans in namespace - - ca314b9f5 2025-06-30T07:58:04+02:00 Fix validation for Job with suspend=true,completions=0 to set Complete condition - - 1134220e0 2025-06-28T14:06:34+02:00 Add RelaxedServiceNameValidation feature gate - - f644e35d1 2025-06-28T11:21:54+02:00 kubeadm: cleanup after WaitForAllControlPlaneComponents GA - - cfe860450 2025-06-28T11:16:01+02:00 kubeadm: graduate WaitForAllControlPlaneComponents to GA - - f437aa4aa 2025-06-28T11:00:23+09:00 scheduler_perf: Set version emulation only when QueueingHints is disabled - - b2f27c064 2025-06-27T16:32:29-07:00 fix: Truncate too long Deployment name in RS name (#132560) - - d67e7937e 2025-06-27T17:57:16-04:00 Remove recovery related featuregates - - fa6f27c8f 2025-06-27T17:52:46-04:00 Add extra validations for newer resizing related fields - - 00dd610c9 2025-06-27T21:15:50+02:00 DRA E2E: run some tests without feature label - - f93b4408a 2025-06-27T15:02:34-04:00 Drop test that checks openAPI resource name since we currently don't guarantee name stability in the API - - 3eefb05a2 2025-06-27T11:49:41-07:00 Fix gRPC listener error message in kubeletplugin and some minor renaming - - e54e01e0a 2025-06-27T11:38:12-07:00 Enhance help text for the 'top' command - - 7d5ab7562 2025-06-27T14:30:58-04:00 Re-generate applyconfigurations - - 9af684ae0 2025-06-27T14:30:57-04:00 Applyconfig-gen: Only the root type is an applyconfiguration - - d50e1a684 2025-06-27T11:13:50-04:00 Ensure all the files have the updated sorting - - f2d8b7ec2 2025-06-27T11:05:13-04:00 Add linter to report on unsorted feature gates - - efcb03759 2025-06-27T16:10:38+02:00 E2E framework: sort tests in JUnit report - - dfd34a5b1 2025-06-27T16:30:51+08:00 fix pod template spec validation missing in sts - - a57f15e08 2025-06-27T10:06:50+02:00 DRA kubelet: remove v1alpha4 - - 005cef332 2025-06-27T09:30:28+02:00 DRA kubelet: API clarification - - f1845218e 2025-06-26T23:21:18-05:00 fixup! DRA: fix deleting orphaned ResourceClaim on startup - - 585ed0a5c 2025-06-26T22:00:41-04:00 [client-go #1415] Use transformer from provided store within internal stores in reflector to limit memory usage bursts - - 8632257c9 2025-06-26T21:24:43Z Cleanup: Remove redundant detail messages in field.Required - - e82d4f8e5 2025-06-26T18:25:42Z review: feedback - - 5cca03792 2025-06-27T00:49:02+09:00 resolve linter check - - ce86fca8c 2025-06-26T15:10:42Z Add warnings for use of Alpha features with Emulated Version Warn for both api and feature flag use of alpha features with emulated versions. This is an unsupported use case and users may run into issues. - - 00d375050 2025-06-26T08:06:29-07:00 Move ClusterEvent type to staging repo, leaving some functions (that contain logic internal to scheduler) in kubernetes/kubernetes (#132190) - - 74af3ac8a 2025-06-26T23:49:34+09:00 Revert "pop respects the context" - - 2dcce9333 2025-06-26T23:49:25+09:00 Revert "modify tests" - - 31667cc74 2025-06-26T09:15:02-04:00 Avoid killing kops etcd-manager - - 6d6a749c6 2025-06-26T14:31:03+02:00 DRA kubelet: add dra_resource_claims_in_use gauge vector - - 75432a141 2025-06-26T14:15:43+02:00 component-base metrics: allow usage of Prometheus types in tests - - 1639b0908 2025-06-26T11:09:24+02:00 Add benchmark for SizeBasedListCostEstimate feature - - c75d425ae 2025-06-26T07:44:13Z CHANGELOG: Update directory for v1.34.0-alpha.2 release - - 292679a28 2025-06-26T09:30:48+02:00 Handle consistent LIST in watch cache to avoid incorrect semantics while setting ResourceVersion on options - - c6c15bbe4 2025-06-26T00:11:20-04:00 bug: Remove duplicate DaemonSet update validations - - 39dda2b88 2025-06-26T00:59:34Z tests: runtime units - - 8bd8c1431 2025-06-25T22:00:40Z tests: add more units - - f9a5aec31 2025-06-25T23:59:44+05:30 Added unit tests - - 5390f7536 2025-06-25T23:59:26+05:30 Added podutil.HasAPIObjectReference to deny admission for static pods referencing API objects - - 8b2eb9090 2025-06-25T17:39:14Z chore: Remove vet target and associated script from Makefile and hack directory - - 7d85134ca 2025-06-25T17:18:07Z improve unit test coverage for pod observedGeneration - - 1a59c250e 2025-06-25T16:38:50Z feat: make CLE timers configurable - - ef117edf3 2025-06-25T11:11:43-05:00 DRA: fix deleting orphaned ResourceClaim on startup - - c5b4b133c 2025-06-25T11:42:12-04:00 switch to latest sigs.k8s.io/yaml v1.5.0 (run update-gofmt.sh as well) - - e2c6b7fdf 2025-06-25T17:25:58+02:00 Override getKeys when cacher is enabled - - 7cb241799 2025-06-25T17:25:58+02:00 Run background cleanup goroutine - - ec78b8305 2025-06-25T17:25:56+02:00 Estimate average size of objects in etcd and plug it into request cost estimator - - 190c8c7ab 2025-06-25T11:17:20-04:00 Use per-policy marker names for VAP integration tests. - - 6795d5366 2025-06-25T22:44:47+08:00 feature(kubectl): support mem-percent,cpu-value,cpu-average-value,mem-value,mem-average-value flag to kubectl autoscale - - 9de075def 2025-06-25T13:21:46+02:00 replacing deprecated pointer pkg with newer package version - - b8b398487 2025-06-25T04:04:29-07:00 client-go/reflector: stop exposing UseWatchList (#132453) - - 0028ea8e9 2025-06-25T08:51:29+02:00 Improve containers lifecycle test output parsing - - 7e0d71fc1 2025-06-25T08:51:20+02:00 apiserver/storage/cacher/listwatcher: error when the WatchList FG is disabled - - ec6ea2213 2025-06-25T13:39:12+08:00 test: code coverage increase for kubelet_client - - cb4014fb7 2025-06-24T22:25:41-04:00 cleanup: Migrate more usages of deprecated function ExtractCommentTags - - b50d50817 2025-06-25T08:23:53+08:00 bugfix(hpa): introduce buildQuantity helper for consistent resource quantity creation - - cbba973b6 2025-06-24T17:21:57-07:00 Fixing go-vet finding "call of reflect.DeepEqual copies lock value" by just asserting on the basic fields that should be reset when ClearState() is called - - 35ecb00f1 2025-06-24T22:19:35Z fix: Add wait for cache sync for customresourcediscovery tests - - d6d186ece 2025-06-24T20:56:44+02:00 Activly poll for namespace termination instead of sleeping - - e1daa69de 2025-06-24T14:52:37-04:00 Add printer column validation tests - - 369e6a25a 2025-06-24T14:52:27-04:00 Introduce k8s-short-name and k8s-long-name to the OpenAPI formats supported by CRDs - - 6f1295ae9 2025-06-24T11:04:25-07:00 fix: prevent SSA from creating CR while CRD terminating - - 3b0fd3281 2025-06-24T15:46:06+02:00 e2e: serial: cpumanager: continue on failure - - f76e1381d 2025-06-24T15:46:01+02:00 e2e: node: fix quota disablement testcases - - dc323756c 2025-06-24T09:24:27-04:00 Bump to latest kube-openapi - - d180fe28a 2025-06-24T09:23:39-04:00 Add json-patch v4 compatibility test - - 2ca4ffe65 2025-06-24T09:18:04-04:00 Add evanphx/json-patch/v5 to unwanted dependencies - - 5a7e04b6c 2025-06-24T21:12:56+08:00 feat: optimize ListAll and ListAllByNamespace to return directly when nothing to select - - ae13d1019 2025-06-24T12:41:42Z KEP-5229: Add SchedulerAsyncAPICalls feature gate - - dce69afad 2025-06-24T11:39:44+02:00 apiserver/cacher: properly wire listwatch options to the listwatcher - - 0276769c2 2025-06-24T11:07:47+02:00 kubectl: avoid logging during init - - 6040344a6 2025-06-24T10:42:46+02:00 kubelet: DRA: fix TestRegistrationHandler - - cc7893a42 2025-06-24T10:42:45+02:00 kubelet: DRA: fix unit test failure - - cf544da6f 2025-06-24T10:42:45+02:00 e2e_node: DRA: add tests for different socket setups - - 7f6389e77 2025-06-24T10:42:45+02:00 e2e_node: DRA: pass socket path as a parameter - - 3ae99f254 2025-06-24T10:42:45+02:00 kubelet: DRA: fix test failure on Windows - - c90c2e0d4 2025-06-24T10:42:45+02:00 kubelet: DRA: fix linter warnings - - 165bb1da5 2025-06-24T10:42:45+02:00 DRA kubelet: use TimedWorkersQueue - - 4ee7374b2 2025-06-24T10:42:41+02:00 DRA kubelet: add connection monitoring - - f927cd010 2025-06-24T09:05:43+02:00 DRA kubelet: simplify plugin creation and connection handling - - cfeab03ad 2025-06-24T11:50:18+08:00 remove kvh.exec - - 75862f3f4 2025-06-23T17:00:31-07:00 show namespace on delete (#126619) - - 56d97283a 2025-06-23T21:37:00Z fix: Improve error messaging on updating a deleted object - - fd8bf1c82 2025-06-23T14:58:57-04:00 e2e: retry getting status on restart policy tests - - c5f061e0d 2025-06-23T17:57:12Z Fix pod and container level swap metrics for CRI - - e1d74f1d3 2025-06-23T23:00:38+05:30 Update etcd image revision to 3.6.1-1 - - 7e3945808 2025-06-23T18:12:13+05:30 nftables: remove filter-output-post-dnat chain - - 91f2256b3 2025-06-23T18:12:13+05:30 update filter chains and priority - - 72305f82f 2025-06-23T13:06:19+02:00 Move UnsafeCorruptObjectDeletion outside of etcd3.New function - - 59dd2bd60 2025-06-23T17:57:59+08:00 ci: update test image base: nginx, nginx-new - - af89044a7 2025-06-23T00:37:28+05:30 conntrack: clean stale entries on endpoint port change - - 861e7b8fa 2025-06-20T12:30:51-07:00 fix unit test flake for authn config on windows - - 2fd93c089 2025-06-20T22:29:13+08:00 fix: data race for patchResource func - - ccdef28ac 2025-06-20T10:33:43+02:00 fixing large resourceversion and limit for storages - - fe8437745 2025-06-20T08:28:04+02:00 e2e/watchlist: new test for checking metadata informer - - d6ba9e1b9 2025-06-20T07:07:42+02:00 replacing depr. pointer pkg with new ptr pkg on src/apimachinery - - db32c4cf7 2025-06-20T09:11:35+10:00 fixing syntax issue for etcd builds - - 8454093f0 2025-06-19T15:19:00-05:00 DRA: add e2e test with initContainer using external claim - - 138e363e4 2025-06-19T11:48:15-04:00 cleanup shellcheck for temporary HOME directory - - 66c611125 2025-06-19T16:32:20+08:00 Add namespace-aware orphan pod indexing - - 5e54df3e7 2025-06-19T15:32:23+08:00 Fix [Failing test] [sig-node] [Feature:GPUDevicePlugin] [Serial]-related tests - - 280cecb8f 2025-06-19T17:07:32+10:00 fixing location to ensure the cp commands dont fail - - d2945a21f 2025-06-19T12:21:44+10:00 bumping revision - - fa1832484 2025-06-19T11:48:23+10:00 handling the etcd 3.6+ build directory location change - - e68d60134 2025-06-19T10:11:17+09:00 Don't panic in case of an unknown API error code - - 4ca91a030 2025-06-19T10:11:17+09:00 WIP: Fix tests - - 2b2c9adef 2025-06-19T10:11:16+09:00 Nicer value rendering in API errors - - cfff359b4 2025-06-18T18:01:28-04:00 fix for gimme when $HOME is not writable - - 6a654e5be 2025-06-18T21:15:30Z Deprecate StreamingConnectionIdleTimeout field, that is not being used for a long time - - b8cd05881 2025-06-18T14:13:47-07:00 Address PR comments - - 6f97f5bbf 2025-06-18T14:02:57-07:00 Use Mock CSI Driver for MutableCSINodeAllocatableCount storage e2e test (#132373) - - 176095ac3 2025-06-18T13:57:41-07:00 [KEP-5100] WinDSR feature gate to GA - - 64c44e1fa 2025-06-18T16:12:24-04:00 Test that generated applyconfigs are a runtime.ApplyConfig - - a5d42f569 2025-06-18T16:12:24-04:00 Re-Generate applyconfigs - - d5527b519 2025-06-18T16:12:24-04:00 Update applyconfiguration-gen so acs implement runtime.applyconfiguration - - 3fe4ea550 2025-06-18T16:12:24-04:00 Add an interface that all applyconfigs implement - - b0b52f4fb 2025-06-18T18:59:10Z CHANGELOG: Update directory for v1.30.14 release - - 2bc98f123 2025-06-18T18:36:13Z CHANGELOG: Update directory for v1.31.10 release - - 20e9f160c 2025-06-18T18:11:53Z CHANGELOG: Update directory for v1.32.6 release - - 9e126a377 2025-06-18T17:54:50Z CHANGELOG: Update directory for v1.33.2 release - - df32f10e0 2025-06-19T01:23:10+08:00 apimachinery/pkg/util/errors: deprecated MessageCountMap - - de2f22ee8 2025-06-18T17:43:58+02:00 e2e/watchlist: intro verifyStoreFor - - 017c9b94d 2025-06-18T17:34:05+02:00 e2e/watchlist: rename toSecretPointerSlice - - caa64afd0 2025-06-18T22:38:21+09:00 merge constants.go into attribute.go - - 73d65f830 2025-06-18T21:30:52+09:00 Put _linux suffix for linux specific go files - - 88b34ea1f 2025-06-18T21:28:41+09:00 Move bdfRegexp from global constant to local variable - - fc854a9a8 2025-06-18T21:26:15+09:00 Introduce DeviceAttribute{Name, Value} and change return type of 'GetPCIeRootAttributeByPCIBusID' with it - - 8ed8217e9 2025-06-18T21:26:13+09:00 Moved device attribute constants from api to deviceattribute package - - f7461a12d 2025-06-18T21:04:16+09:00 Revert "Add StandardDeviceAttributes and StandardPCIDeviceAttributes helper functions" - - 6b9ac7c51 2025-06-18T12:32:04+02:00 cluster/gce: rm KUBE_LIST_FROM_CACHE_INCONSISTENCY_DETECTOR - - 512563e7b 2025-06-18T14:22:26+05:30 pkg/proxy/conntrack: refactor - - 91b4816c2 2025-06-18T15:28:12+08:00 Optimize job controller performance: reduce work duration time & minimize cache locking - - 18dd1daae 2025-06-17T12:01:02-07:00 Add Windows Server 2025 (ltsc2025) to BASEIMAGEs (#132235) - - 44b4682a3 2025-06-17T22:38:10+05:30 Use jq docker image for pause windows build - - 3827d3bc4 2025-06-17T11:00:27-04:00 Drop usage of forked copies of goyaml.v2 and goyaml.v3 - - 2869b6f42 2025-06-17T23:04:43+09:00 Add StandardDeviceAttributes and StandardPCIDeviceAttributes helper functions - - a8ab9eb5f 2025-06-17T22:58:17+09:00 Simplify the implementation: just provide GetPCIeRootAttributeByPCIBusID - - d390902b9 2025-06-17T22:30:45+09:00 Verify scheduler resource metrics account for Pod Level Resources - - 32fcaf140 2025-06-17T15:05:46+02:00 client-go/util/consistencydetector: move IsDataConsistencyDetectionForWatchListEnabled - - 72654620a 2025-06-17T13:49:58+02:00 removing WaitIntervalString from iptables - - bad493904 2025-06-17T13:37:57+02:00 client-go/util/consistencydetector: remove CheckListFromCacheDataConsistencyIfRequested - - 15ca38b52 2025-06-17T12:01:02+02:00 apimachinery/meta/types.go: remove InitialEventsListBlueprintAnnotationKey const - - 690790257 2025-06-17T11:47:17+02:00 Add test verifying KUBECTL_KUBERC can be turned on and off - - 45449a78d 2025-06-17T11:14:47+02:00 Removing setting KUBECTL_KUBERC env var, now that it's on by default - - 3f32edeac 2025-06-17T15:45:44+08:00 chore: Remove the dependency of the volume manager on the container runtime. - - 3dc1810bb 2025-06-17T15:26:01+08:00 fix: failed unit test. - - b8a2127d2 2025-06-17T05:53:18Z Add random interval to nodeStatusReport interval every time after an actual node status change update or restart - - fbf4b47d1 2025-06-17T13:30:45+08:00 chore: clean up probemanager for shutdownnamager. - - 3fa23d06a 2025-06-17T06:39:33+02:00 Adjusting AdminAccess Type for API v1beta1 - - 2a5e4d558 2025-06-17T03:35:12Z add script for verifying dead code elimination - - 891e7fec6 2025-06-17T09:30:41+08:00 add seperate health check/probe for multi etcd override servers - grouping health checks for exclusion purposes & add exclude integration test - - 28573e373 2025-06-16T15:34:06-07:00 Add error prefixes for authn config load or validation failures - - 4cb6d3d77 2025-06-17T00:10:48+02:00 Validate requests sent to etcd in TestList "test List with limit" scenario - - 03afe6471 2025-06-16T17:10:42-04:00 Add a replacement for cmp.Diff using json+go-difflib - - 32ec4e68c 2025-06-16T21:51:24+02:00 adding omitempty tag and opt tag - - e654deba6 2025-06-16T18:44:59Z CHANGELOG: Update directory for v1.34.0-alpha.1 release - - f4a458625 2025-06-16T17:36:23Z fix APIServerTracing test data race - - 2004ee50f 2025-06-16T16:08:46Z Fix -Consistent paginated lists serve from cache - - bccc9fe47 2025-06-16T16:26:03+02:00 KEP-3939: Job Pod Replacement Policy; promote to GA - - fc198b92c 2025-06-16T07:02:59-07:00 apiserver/handlers/watch: stop encoding initialEventsListBlueprint (#132326) - - 854499f98 2025-06-16T20:51:17+08:00 clean: use correct pod template - - fae2fdd05 2025-06-15T23:49:43-05:00 DRA: wrap e2e finalizer update in retry - - 7a95f3e47 2025-06-16T00:11:48+09:00 Fix NetworkPolicy podSelector comments - - 233a0aeed 2025-06-15T13:04:25+02:00 DRA E2E: label tests which need a certain minimum kubelet, II - - 2cd5dbbda 2025-06-15T15:50:22+09:00 modify tests - - 59f0ab97c 2025-06-15T15:50:02+09:00 Add boilerplate header to go files - - 1c33d9876 2025-06-15T15:31:34+09:00 pop respects the context - - f67d30b35 2025-06-15T15:31:33+09:00 handle context in process loop - - 384240b4d 2025-06-14T17:50:38-07:00 Use "Invalid" errors rather than "TypeInvalid" - - bdfa8839b 2025-06-14T18:39:15+02:00 calculateStatus should use the same now time point for each pod - - ce44bcdf5 2025-06-14T16:10:04Z conformance servicecidr read status endpoint - - c2988884f 2025-06-15T00:01:29+08:00 fix kubeadm e2e tests - - cb26d065d 2025-06-14T15:57:48+09:00 Validate PCI Address (domain is 16 bits, bus is 8 bits, device is 5 bits, function is 3 bits) - - 752a04369 2025-06-14T15:57:46+09:00 fix lint: apply De Morgan's laws to simplify conditionals - - 76ef6a388 2025-06-14T14:45:29+08:00 fix kubeadm e2e tests - - 79601d135 2025-06-13T13:50:03-07:00 Fix CRI fake_runtime RemovePodSandbox - - 666f38f41 2025-06-14T04:19:00+09:00 DRA: Introduce a helper function producing standardized device attributes for DRA drivers - - 7a3af908c 2025-06-13T17:54:36Z add securitycontext OWNERS to be SIG Node as the package is mostly used and contributed by SIG Node - - 7f1dde2a0 2025-06-13T17:23:16+02:00 test/apimachinery/watchlist: properly wire modified config to informer for fallback case - - 40c718864 2025-06-13T15:28:55+02:00 chore(apiserver): avoid using html template which disables dce - - 6a3797684 2025-06-13T14:15:51+02:00 client-go/rest: rm watchlist - - 4372c59eb 2025-06-13T13:35:00+02:00 update go version for publishing bot rules - - e09b042d3 2025-06-13T16:28:35+05:30 Bump etcd to v3.6.1 - - 901441c66 2025-06-13T11:15:35+08:00 Promote SeparateTaintEvictionController to stable - - 85bc3cb09 2025-06-13T10:58:37+08:00 Remove GetExec method from VolumeHost - - 9251b2a7a 2025-06-12T16:02:19-04:00 Expand webhook test to check rejection metrics - - f8b4ea50e 2025-06-12T19:26:26+02:00 ./hack/update-internal-modules.sh - - 71b2f32d7 2025-06-12T18:16:04+02:00 DRA E2E: label tests which need a certain minimum kubelet - - 3908550c0 2025-06-12T11:20:39-04:00 Update to latest github.com/modern-go/reflect2 - - d8bfafe07 2025-06-12T16:02:10+02:00 test/apimachinery/watchlist: prove typed client's List method not streaming - - 601065a7c 2025-06-12T09:44:41-04:00 bug: Fix misleading response codes in admission control metrics - - 5882df8be 2025-06-12T21:43:03+08:00 promote env test to conformance - - 69a5bda83 2025-06-12T18:15:11+05:30 Bump base image used in nonewprivs to alpine:3.22 - - 04110fce1 2025-06-12T21:29:54+09:00 Correct error message to print `ResetConfigurationKind` - - 3443c1115 2025-06-12T13:54:57+02:00 make update - - 798c6ebab 2025-06-12T13:41:50+02:00 client-gen/code-generator: remove watchList - - db2555628 2025-06-12T07:35:07-04:00 Fix: HPA suppresses FailedRescale event on successful conflict retry - - 2f943293e 2025-06-12T13:13:02+02:00 client-go/gentype: remove watchlist - - f0dde3823 2025-06-12T17:29:17+08:00 Remove pluginName param from GetMounter and GetExec - - fb611f4c9 2025-06-12T11:27:51+03:00 kubectl delete: Update interactive delete to break on new line - - d46e13b9c 2025-06-12T16:06:50+08:00 change the command of the terminated container - - 226c0d109 2025-06-12T11:49:12+05:30 Bump ipc-utils base image to alpine:3.22 - - e75ccce83 2025-06-12T10:48:53+08:00 feat: optimize label selector match performance - - ac467d3ae 2025-06-11T23:44:52Z add ratcheting testcase for validateFalse tag - - 9384285c6 2025-06-11T23:44:52Z add ratcheting testcase for minimum tag - - 1574001a1 2025-06-11T23:44:52Z run update-codegen.sh - - f574115f1 2025-06-11T23:44:52Z feat: add default ratcheting support - - e9eabb200 2025-06-11T23:44:52Z feat(validation-gen): Refactor type handling and introduce utility functions - - 03c6e15f8 2025-06-11T16:35:44-07:00 bump to alpine 3.22 and bump apparmor-loader to 1.6 - - b86b4632b 2025-06-11T15:35:56-07:00 disable selinux relabeling when mounting sourcedir to shellcheck - - dc3836c49 2025-06-11T15:31:37-07:00 Remove deprecated encryption config controller metrics - - 5a2844a76 2025-06-11T16:46:03-04:00 Update to etcd v3.6.1 in vendor/ - - a9108e8f5 2025-06-11T15:52:40-04:00 Adding `grpcnotrace` tag for production (non-debug) builds - - 11abb0042 2025-06-11T17:14:39+02:00 Fix outdated links in VolumeSource godocs - - 4b2fe2a54 2025-06-11T22:35:08+08:00 pkg/kubeapiserver: use utils/ptr package instead of utils/pointer - - 69eddde89 2025-06-11T21:49:38+08:00 using finalizer - - 57d55fbb1 2025-06-11T21:29:24+09:00 test: Add test case for createNodeOp - - 1d69a2fbc 2025-06-11T12:04:53+02:00 ./hack/update-vendor.sh - - edadfee47 2025-06-11T12:04:48+02:00 test/apimachinery/watchlist: prove dynamic client's List method not streaming - - 348ff7497 2025-06-11T14:53:35+05:30 Build etcd image v3.6.1 - - 3038f3530 2025-06-11T09:58:05+02:00 client-go/dynamic: rm watchlist - - 86c709cd8 2025-06-11T12:34:18+05:30 skip nfacct test in IPv6 clusters - - e5f36796e 2025-06-11T08:24:35+02:00 Bump dependencies, images and versions used to Go 1.24.4 and distroless iptables - - 07151bb0f 2025-06-11T04:27:21Z chore: Add validation error for unsupported map of slices in validation-gen - - 89f5453e3 2025-06-10T23:16:41-04:00 Allow system:monitoring role to access kubelet metrics endpoints - - 2810f6e65 2025-06-10T20:10:02-07:00 add bentheelder to cmd/preferredimports *reviewers* - - 00a6d2c99 2025-06-10T20:09:57-07:00 add bentheelder to conformance related test *reviewers* - - 1dd055774 2025-06-10T20:05:40-07:00 backfill some sig-testing-reviewers (tech leads aojea and pohly) - - ad68a4b4c 2025-06-10T20:05:40-07:00 emeritus spiffxp - - 512f000d0 2025-06-10T14:11:30-07:00 Update tests for StructuredAuthenticationConfiguration feature gate GA - - efebfe9e3 2025-06-10T14:04:28-07:00 Set StructuredAuthenticationConfiguration feature gate to GA in v1.34 - - 769d71b30 2025-06-10T20:15:07Z Remove unused Expect methods in testscheme - - 105dd3b0a 2025-06-10T20:15:06Z Add ExpectMatches to ValidationTester - - 28e973c04 2025-06-10T18:08:45Z Better formatting of matcher errors - - b39741b50 2025-06-10T19:25:48+02:00 e2e: node: serial: fix cgroup path with crio - - 26b188aaa 2025-06-10T17:13:15Z KEP-4633: Graduate to Stable. - - fd5d7a18e 2025-06-10T19:58:36+03:00 reduce logspam when calculating sandbox resources - - 0baeccd32 2025-06-10T16:16:13Z KEP-740: promote ExternalJWTSigner feature to beta - - ef2c18a5a 2025-06-11T00:02:48+08:00 Add more test cases - - eb3c9a318 2025-06-10T15:41:50Z Promote feature OrderedNamespaceDeletion to GA. - - f8b701243 2025-06-10T16:56:58+02:00 Revert "improve display format" - - 449320a54 2025-06-10T10:50:54-04:00 update github.com/spf13/cobra v1.9.1 - - 260a720a8 2025-06-10T09:38:55-04:00 Rate-limit the LoadBalancer rolling update test - - 0a86ca406 2025-06-10T21:14:17+08:00 Add healthChecker to the kubeDeps - - dacafec88 2025-06-10T08:46:34-04:00 KEP-3015: PreferSameTrafficDistribution to Beta - - b2ab0ba19 2025-06-10T11:37:47+02:00 Drop unused testing manifest - - 96b39187c 2025-06-10T08:45:51+02:00 Add context to Count() - - 9d1bc51cb 2025-06-10T10:52:25+08:00 adjust durations for sleepAction - - c85ac59df 2025-06-09T17:41:41-04:00 Build k8s using latest commit of golang - - 4a7e68a35 2025-06-09T21:27:57+08:00 fix: Fix the issue where kubelet's slow startup causes it to be mistakenly killed by the watchdog. - - b02fba7e0 2025-06-09T14:30:05+08:00 Fix incorrect logging of insufficientResources in preemption - - fc7ba63ee 2025-06-08T16:48:09+05:30 support parsing of iperf 2.2.0 output - - 1755a9e54 2025-06-08T16:42:25+05:30 fix: iperf version in comments - - 0ca9c380a 2025-06-08T12:00:14+08:00 update all api files - - 32aa52adf 2025-06-07T19:52:48-04:00 tolerate newer golang/oauth2 version - - 3cfa73bc1 2025-06-07T17:42:29+03:00 add -q flag for git worktree - - 97ec8618d 2025-06-07T10:28:36-04:00 Fix kubelet iptables startup, clarify semantics of utiliptables calls. - - 6a4751da7 2025-06-07T20:32:03+08:00 Graduate RelaxedEnvironmentVariableValidation Feature gate to GA - - f4ab6c2be 2025-06-06T17:57:43-04:00 cleanup: Migrate deprecated function ExtractCommentTags - - 0d468f58c 2025-06-06T20:37:50Z kuberuntime_manager: don't log entire container spec. - - 858b88bce 2025-06-07T01:14:33+05:30 kube-proxy: log ipt errors during platformCheckSupported - - 1f46b3fdb 2025-06-06T18:31:38Z Clean backoff record earlier - - 7b1f49906 2025-06-06T18:24:33+02:00 DRA kubelet: rename Store + Plugin -> DRAPluginManager + DRAPlugin - - fad670c27 2025-06-06T18:24:33+02:00 DRA kubelet: move RegistrationHandler into Store - - 494a129d0 2025-06-06T18:24:33+02:00 DRA kubelet: clarify plugin vs, driver name - - 0d5578b83 2025-06-06T16:46:15+02:00 test/apimachinery/watchlist: prove metadata client's List method not streaming - - 5b0f0d2ef 2025-06-06T10:40:00-04:00 update pr template issue links section - - a38ad3a2c 2025-06-06T16:15:43+02:00 client-go/metadata: rm watchlist - - beb86a839 2025-06-06T16:15:30+02:00 KEP-3329: drop PodDisruptionConditions feature gate - - b5a8f5d0a 2025-06-06T16:08:21+02:00 KEP-3715: drop ElasticIndexedJob feature gate - - 10de6780c 2025-06-06T12:06:28+02:00 DRA API: remove obsolete types from v1alpha3 - - 089669369 2025-06-06T16:03:46+08:00 fix TestNodeAffinityPriority: calculate the priorities correctly even if PreScore is not called - - 087554448 2025-06-06T02:26:05Z Make nodeports scheduling plugin sidecar initContainer aware - - 1876c5445 2025-06-05T22:44:31Z Remove unsupported map of slice validation for non-byte elements in validation-gen - - 501393810 2025-06-05T18:24:06-04:00 Change option to a slice - - 990cb7547 2025-06-05T17:02:41-04:00 Use slice.Contains() - - 28e99ef2e 2025-06-05T16:51:11-04:00 Add type information to tag Docs() and use it to typecheck tags - - 31aa3c202 2025-06-05T15:29:12-04:00 Switch to using named args in output_tests - - 7892fd95f 2025-06-05T15:29:12-04:00 Use codetags in validation-gen - - 249801b7c 2025-06-06T00:42:58+05:30 Fix windows-pause-image-base:@ invalid reference format - - 2c4c3037b 2025-06-05T11:17:47-04:00 Fix field path for embedded fields in root types - - d1bddfd77 2025-06-05T18:03:56+03:00 Forbid github.com/pkg/errors in k/k - - efaaece0f 2025-06-05T17:58:09+03:00 go.mod: drop pkg/errors as a direct dep - - cbbfabe7f 2025-06-05T10:50:14-04:00 Support embedded fields properly - - d1a858ca9 2025-06-05T17:48:13+03:00 kubeadm: fix one missed pkg/errors location - - 036f4bfe2 2025-06-05T15:08:35+02:00 hack: fix KUBE_RACE in benchmark-dockerized.sh - - 5be254650 2025-06-05T16:05:02+03:00 kubeadm: start using util/errors - - f522d7cb8 2025-06-05T16:04:52+03:00 kubeadm: add a local implementation of wrapped errors - - 2bf3d8b73 2025-06-05T14:02:44+02:00 KEP-3335: drop StatefulSetStartOrdinal feature gate - - 1d1d0c154 2025-06-05T14:45:00+05:30 promote agnhost to v2.56 - - 258961cb3 2025-06-05T05:30:59Z pkg/appis/apps: use utils/ptr package instead of utils/pointer - - 7b664a113 2025-06-05T05:20:46Z pkg/volume: drop pointer wrapper functions. - - 253a08d7e 2025-06-05T04:48:25Z pkg/util: drop pointer wrapper functions. - - ac5cb2300 2025-06-04T22:39:08-04:00 Bump gengo/v2 to latest - - d6ec03a13 2025-06-04T13:28:20-07:00 Preempt based based on allocated resources rather than desired - - 7d47165e3 2025-06-04T13:48:11-05:00 Replace queue.FIFOs with k8s.io/utils/buffer.Ring - - 705e89b04 2025-06-04T11:45:12-07:00 Only set pod allocation if admission succeeds - - f8b893489 2025-06-04T20:36:15+02:00 Update pkg/kubelet/kubelet_test.go - - 147073102 2025-06-04T18:06:07Z fix: prevent data race in metric LabelValueAllowList initialization - - 8cdbbf5cd 2025-06-04T12:56:39-05:00 Update k8s.io/utils for new generic ring buffer - - daae472fe 2025-06-04T13:27:50-04:00 e2e_node: verify restart looping container correctly - - 109ae1bac 2025-06-04T10:08:00-07:00 feat: Allow leases to have custom labels set when a new holder has the lease - - 8d3fb9ee0 2025-06-04T07:10:38-07:00 [KEP-2400] kubectl top: add a --show-swap option (#129458) - - 4c7840ec5 2025-06-04T15:33:27+02:00 podResizeMutex cleanup - - c7fdf6abd 2025-06-04T11:47:03+05:30 Handler will return the server port number instead of address - - 6a495241e 2025-06-03T14:40:17-07:00 KEP-3331: Add test to simulate revocation via user validation rule using unique identifier (jti) - - 466fb8152 2025-06-03T15:58:41-03:00 test/e2e/apimachinery/namespace.go: make OrderedNamespaceDeletion test serial - - 7e7aa6d81 2025-06-03T18:22:48+02:00 e2e: node: cpumanager: require cgroup v2 - - 68efb079a 2025-06-03T16:17:25+02:00 kuberc: add tests for DefaultGetPreferences - - ad3a13e01 2025-06-03T19:28:20+08:00 Graduate NodeLocalCRISocket to beta - - b9d9dea03 2025-06-03T16:08:29+08:00 Update npd from v0.8.20 to v0.8.21 - - 47dead1c4 2025-06-02T22:46:55Z unexport allocationManager IsPodResizeInProgress - - de1d6fbf2 2025-06-03T01:12:31+03:00 fix: ResolverTypeProvider data race - - 9b8d7ce49 2025-06-02T17:51:03Z pr review feedback - - a512de6e0 2025-06-02T16:53:10Z Clarified the token scope and future plans for the next security scan to refer to it - - 032a9eaed 2025-06-02T18:30:04+02:00 DRA kubelet: code cleanup - - a6e226899 2025-06-02T14:29:38+02:00 Ensure github.com/pkg/errors is used only in kubeadm - - 7ccb9657f 2025-06-02T21:19:38+09:00 sched: Apply EnablePlugins to CoreResourceEnqueueTestCases - - 6cb14884b 2025-06-02T11:47:42+02:00 test-integration: allow enabling race detection - - 545fbc99c 2025-06-02T11:27:09+02:00 test: drop dependency on github.com/pkg/errors - - 899f76159 2025-06-01T00:48:16+08:00 add unit test for IsDNS1123SubdomainWithUnderscore function - - 0a7d9f9bf 2025-05-31T07:45:16+02:00 KEP-4427: Promote Relaxed DNS search string validation to GA - - 2aa7ef3d2 2025-05-30T22:20:30Z Address comments - - dbdd6a3b4 2025-05-30T15:33:42-04:00 FieldManagedObjectTracker: Fix to work with unstructured - - b7d16fea7 2025-05-30T21:08:12+02:00 disable terminatingReplicas reconciliation in ReplicationController - - ee33c1a9f 2025-05-30T13:32:52-04:00 e2e: fix userns test - - be049397d 2025-05-31T00:52:04+08:00 Fix IsDNS1123SubdomainWithUnderscore to return correct error message - - 4f91a69f2 2025-05-30T10:29:18+02:00 DRA integration: move and extend device status test - - 0a9661375 2025-05-30T16:13:06+08:00 proxy: remove iptables wait interval flag - - a5aabf9f7 2025-05-30T09:52:22+02:00 DRA kubelet: validation pass before changing claim info cache - - 5420dcec5 2025-05-29T20:22:34-04:00 Promote two more EndpointSlice tests to conformance - - b9496d1a9 2025-05-29T16:18:47-04:00 Update client-go template with backticks - - d70fcf731 2025-05-29T20:13:56Z Update client-go PR template - - d75af825f 2025-05-29T16:18:36Z Extract interface CycleState and move is to staging repo. CycleState implementation remains in k/k/pkg/scheduler/framework - - be6807e6a 2025-05-29T09:42:26-04:00 Allow specifying a directory for image credential providers json/yaml configuration - - aac00c1f0 2025-05-29T10:50:32+02:00 add orphanedPods parameter to getRSPods - - d13dcbbf9 2025-05-29T13:05:32+08:00 kube-dns bump to v1.26.4 - - 96b5ae792 2025-05-28T13:07:34-04:00 Add code for not expanding volume if it has NodeExpansionNotRequired annotation - - 2b0b34350 2025-05-28T15:44:09Z DRA: Improve implementation of counter management in allocator - - 1cd71cbb1 2025-05-28T11:27:01-04:00 ManagedFieldsObjectTracker: Reload scheme - - 4654496c3 2025-05-28T10:22:35-04:00 Add code to not expand certain types of volumes - - 741d0e2b8 2025-05-28T11:21:57+02:00 Gradute ResilientWatchCacheInitialization to GA - - c8f1a6530 2025-05-28T12:26:09+05:30 agnhost: added server address for conntrack cleanup entries - - 5058e385b 2025-05-27T21:19:25-07:00 DRAAdminAccess: update label key - - ee2d3b6a2 2025-05-28T01:08:24Z DRA: Exclude individual devices when PartitionableDevices feature is disabled - - ab6fdf46d 2025-05-27T13:36:16-07:00 Move the autoscaling e2e tests to be ran in parallel (#131091) - - 4e3634bbb 2025-05-27T16:51:51+02:00 Update security contacts for sig-cli owned repos - - b0847b476 2025-05-27T10:38:45-04:00 Add unit tests for fsGroupChangePolicy accessors - - 74167f904 2025-05-27T14:47:55+02:00 Fix typo in the `--anonymous-auth` flag name - - 6410329a0 2025-05-27T10:43:59+02:00 update go version for publishing bot rules - - 60b5338d4 2025-05-26T22:06:25-07:00 Promote automatic_reloads of authn config metrics to BETA - - f694c58c6 2025-05-26T21:23:46+02:00 feat: graduate QueueingHint to GA - - 1310fc027 2025-05-26T16:41:38+02:00 kubelet: drop dependency on github.com/pkg/errors - - 346fe182b 2025-05-26T15:30:39+02:00 DRA E2E: fail test when ResourceSlice publishing fails - - dc2f33f9d 2025-05-26T18:31:28+05:30 Update Perl to 5.40 - - 7c0f968ab 2025-05-26T08:32:09-04:00 Drop usages of deprecated otelgrpc methods - - 157903b09 2025-05-26T09:35:53Z Skip backoff when PodMaxBackoffDuration is set to zero - - 54b2fad03 2025-05-26T11:28:24+02:00 kubectl: drop dependency on github.com/pkg/errors - - b461d80f3 2025-05-26T15:06:50+08:00 etcd: update etcd image to v3.6.0 - - df2857e77 2025-05-26T12:16:48+09:00 Revert shorthand for kubectl explain --output - - 1d17ca9b7 2025-05-24T00:03:35-04:00 generate code - - 8ae717104 2025-05-24T00:03:28-04:00 Simplify subresource matching - - 9715c90b3 2025-05-23T21:47:09-04:00 Clarify errors and improve tests - - 4cac349f8 2025-05-23T21:47:08-04:00 Clarify group version lookup in validateDeclaratively - - c2eef42cf 2025-05-23T21:47:08-04:00 Add output_tests - - 6284a0f50 2025-05-23T21:47:08-04:00 Tag types with +k8s:isSubresource and +k8s:supportsSubresource for scale - - 7dc8660d0 2025-05-23T21:47:08-04:00 Update testing to fully track subresources - - 6ca6b7bb6 2025-05-23T21:47:08-04:00 Add +k8s:isSubresource and +k8s:supportsSubresource tags - - 105391403 2025-05-23T21:47:08-04:00 Enable scale subresource in generated validations - - a3eddf7d8 2025-05-23T21:47:07-04:00 Add declarative validation testing for replicationcontroller/scale - - 356f395f0 2025-05-23T21:47:07-04:00 Enable declarative validation for replicationcontroller/scale - - 030b4ab9c 2025-05-23T21:47:07-04:00 Add declarative validation testing to Scale.spec.replicas - - 48e1079cf 2025-05-23T21:47:07-04:00 Add subresource mapping support to ValidateDeclaratively and introduce configs - - 8c5c5fb76 2025-05-23T21:47:07-04:00 Add origin and use apivalidation.ValidateNonnegativeField for Scale.spec.replicas validation. - - d0f6fe30b 2025-05-23T21:47:07-04:00 Add k8s:minimum validation to Scale.spec.replicas - - ffb4e003f 2025-05-23T21:47:06-04:00 Enable validation-gen for scale group-versions - - e63019a87 2025-05-23T17:52:26+02:00 DRA integration: refactor code to support other tests - - 1ffda045c 2025-05-23T07:44:49-07:00 update to latest ishidawataru/sctp dependency - - 50f152440 2025-05-23T15:04:00+02:00 DRA integration: start scheduler on demand - - 488c94735 2025-05-23T08:58:13-04:00 Bump dependencies, images and versions used to Go 1.24.3 and distroless iptables - - 699dce0a5 2025-05-23T14:32:19+02:00 DRA kubelet: fix gRPC timeout flake - - 7215de79b 2025-05-23T13:05:42+02:00 DRA kubeletplugin: some doc updates - - 24c0e91d2 2025-05-23T12:54:26+02:00 DRA resource slice controller: disable resync - - 01820ff7c 2025-05-23T18:02:32+08:00 chore(scheduler): add filter integration tests for missing part plugins: NodeAffinity plugin - - 151d9d79f 2025-05-23T09:51:35Z Remove package protected field updatePodOther from ActionType. Make ActionType.None public - - 76f95271a 2025-05-23T11:02:58+02:00 kuberc: make update and update-vendor - - b8e6de08e 2025-05-23T10:56:59+02:00 kuberc: add API violation exceptions - - c29accaf5 2025-05-23T10:56:59+02:00 kuberc: introduce fuzzing for kuberc types - - b0370c483 2025-05-23T10:56:59+02:00 Promote kuberc to beta - - 1f355e5b4 2025-05-23T10:56:59+02:00 kuberc: pick the first known version when decoding + tests - - 0341b27c5 2025-05-23T10:56:59+02:00 kuberc: align internal and v1alpha1 go-types with v1beta1 - - 39195f9a4 2025-05-23T10:56:59+02:00 kuberc: add v1beta1 types - - 35870c480 2025-05-23T10:48:54+02:00 client-go remotecommand: avoid "unexpected error" log when there is no error - - 7287dcd2f 2025-05-23T09:18:33+03:00 vendor: update system-validators to v1.10.1 - - b35c5c0a3 2025-05-22T12:40:35-07:00 e2e: Fix shadowed error in reboot test and clean up containers after reboot test (#131699) - - f79012a0d 2025-05-21T20:45:01Z renamed SIG Node google groups - - 50fe29e52 2025-05-21T16:39:25-04:00 Add accessors for fsgroup change policy - - 17946fe79 2025-05-21T18:02:52Z Add Stress Tests for VolumeAttributesClass - - 32c45ecf1 2025-05-21T13:10:02+02:00 Bump github.com/vishvananda/netlink to v1.3.1 - - aea2743e4 2025-05-21T12:31:52+03:00 vendor: update system-validators to v1.10.0 - - 96e4cc65f 2025-05-21T09:09:46Z update baseimage - - c5f368522 2025-05-21T12:09:40+03:00 kubeadm: fix dryrun-latest e2e by updating cluster-info fixture - - d7b604909 2025-05-21T09:22:33+02:00 e2e: node: always declare testcase CPU requirements - - b571840d0 2025-05-20T23:05:17-04:00 bug: Remove duplicate ReplicaSet update validation - - 67345417c 2025-05-20T16:42:23-07:00 Update tests to use v1 for AuthenticationConfiguration - - aea874e5e 2025-05-20T16:28:49-07:00 Duplicate v1beta1 AuthenticationConfiguration to v1 - - c509e22d1 2025-05-20T18:05:57-04:00 Add a list of modules that should be pinned at current versions - - c4421fc13 2025-05-20T18:15:01Z address more feedback and some cleaning - - 637d234aa 2025-05-20T17:08:56Z feat: Add support for ECDSA-P384 encryption algorithm - - b98b86bd6 2025-05-20T09:57:16-07:00 DRA: Add scheduler perf test for partitionable devices (#131771) - - 4cc2bded9 2025-05-20T15:48:31Z DRA: Add an allocator test that uses an attribute selector - - 60c36432f 2025-05-20T17:43:30+02:00 DRA integration: set up nodes for scheduling - - 1c3beb47a 2025-05-20T22:41:19+08:00 Fix goroutine leak in unit tests - - f6fafba42 2025-05-20T21:57:44+08:00 fix flacky test: ResourceQuota should verify ResourceQuota with terminating scopes through scope selectors - - 8cf5e8db7 2025-05-20T13:31:57+02:00 Deprecate kubeconfig's preference field in favor of kuberc - - 1ce8503e9 2025-05-20T16:47:42+08:00 add UT for volumepathhandler - - a8ed33bc6 2025-05-20T08:41:01Z feat: add metrics for compatibility version - - c4a59afe9 2025-05-20T04:47:50Z Fix incorrect URL in build/dependencies.yaml file - - 5bb3f862a 2025-05-20T01:46:55Z DRA: Clean up allocator tests - - 583447668 2025-05-19T19:38:42Z fix lint and unit test failures - - 676978641 2025-05-19T19:38:42Z address feedback - - 88e1909e5 2025-05-19T19:38:42Z move pod admission and resize logic into the allocation manager - - 353073197 2025-05-19T10:19:14-07:00 Kubectl: check version skew (#127365) - - 3878f7e74 2025-05-19T18:23:49+02:00 E2E ResourceQuota: ensure consistent ResourceQuote during scope selector test - - 4a353d07e 2025-05-19T15:36:57+02:00 E2E ResourceQuota: fix pod creation flake - - 4b10ba9ee 2025-05-19T15:36:57+02:00 E2E ResourceQuota: dump last ResourceQuota - - f712b01dd 2025-05-19T13:07:42+02:00 Unify references to group resource in metrics - - d3afe8a87 2025-05-19T09:20:54+02:00 hack/local-up-cluster.sh: remove kubelet --cloud-config - - 772d01066 2025-05-19T08:02:43+02:00 client-go workqueue: clarify parallel reenqueuing - - d043beb22 2025-05-18T12:52:13-04:00 HealthChecker has a List method - - 9b3830fba 2025-05-18T12:52:05-04:00 Bump google.golang.org/grpc v1.72.1 - - be5d8c767 2025-05-18T18:38:16+10:00 Update cmd/kubeadm/app/cmd/upgrade/apply.go - - c0885e018 2025-05-18T18:36:45+10:00 Fix --config option from suggested kubeadm command - - 8f49fb5ce 2025-05-17T20:42:08-04:00 future-proof csi test mocks - - adc4916df 2025-05-17T12:39:58+02:00 feat: introduce pInfo.UnschedulableCount to make the backoff calculation more appropriate - - 968e19d1b 2025-05-17T09:30:09+02:00 docs: avoid broken link - - a271d3e53 2025-05-17T11:08:29+08:00 cleanup: remove error comment of AddIndexers func - - 5def7fadf 2025-05-16T20:46:55Z Drop dependency on x/exp package in mount_linux_test.go - - b9e2a1608 2025-05-16T21:53:35+03:00 e2e_node: dra: test plugin registration retry - - aef61622a 2025-05-16T21:53:35+03:00 e2e: dra: implement ResetGRPCCalls - - e8be3e575 2025-05-16T21:53:30+03:00 e2e: dra: simulate GetInfo failure - - 2f50d0a51 2025-05-16T16:04:15+01:00 Add kube-api-linter plugin to golangci-lint - - 0e5eab042 2025-05-16T08:04:07-07:00 test: Use sub-tests in watch tests - - 5da12b5ae 2025-05-16T08:16:24-04:00 Add tests that validate the return value of resize operation - - c369e3cd4 2025-05-16T19:06:09+08:00 etcd: build etcd image v3.6.0 - - 65a27eb97 2025-05-16T08:48:39Z restrict the use of scheme internally to client-go - - 671d1a07a 2025-05-16T13:28:37+05:30 Bump the busybox image - - 88b236054 2025-05-16T08:15:35+02:00 ResourceQuota E2E: more informative failure message - - ba77d2756 2025-05-16T07:52:55+02:00 DRA E2E: reduce risk of flake in ResourceSlice stress test - - 6b0ebedcc 2025-05-15T21:19:18-04:00 Set non-experimental WatchProgressNotifyInterval config field - - 079d4e52c 2025-05-15T21:19:18-04:00 Fix kubeadm etcd client interface - - cf0bbf117 2025-05-15T21:19:11-04:00 bump etcd client to 3.6 - - 7bccb1acb 2025-05-16T13:12:13+12:00 Update pkg/scheduler/framework/plugins/defaultpreemption/default_preemption.go - - 139fab0eb 2025-05-15T12:46:03-07:00 kubelet: don't import testing dependency in non-test code - - 90b256537 2025-05-15T11:21:54-07:00 Add suggestChangeEmulationVersion if setting locked feature. - - 5314fcece 2025-05-15T11:11:35-07:00 Promote automatic_reloads of authz config metrics to BETA - - 1b9bb3393 2025-05-15T14:01:18-04:00 test: Fix CURL download of Windows busybox test image - - b0ab168a7 2025-05-15T17:56:31Z CHANGELOG: Update directory for v1.30.13 release - - ec7e732cb 2025-05-15T20:55:17+03:00 e2e: dra: move gomega matchers to dedicated package - - fcfd87812 2025-05-15T17:52:37Z CHANGELOG: Update directory for v1.31.9 release - - 2b7f8e168 2025-05-15T17:51:41Z CHANGELOG: Update directory for v1.32.5 release - - 1ab54ffa6 2025-05-15T17:48:58Z CHANGELOG: Update directory for v1.33.1 release - - bba9c49e1 2025-05-15T19:31:16+03:00 e2e: DRA: test 2 claims with the same name - - 8d8fd9296 2025-05-15T19:31:16+03:00 DRA: test mismatched claim UIDs - - 96da66054 2025-05-15T19:31:16+03:00 DRA: genTestClaimInfo: add claimUID parameter - - 69e16d2f5 2025-05-15T19:31:11+03:00 DRA: kubelet: check for duplicate claim names - - b9fec8bf4 2025-05-15T13:46:48Z fix scheme import - - cf8acf5cb 2025-05-15T11:43:59Z package bootstrap matches dir - - e9fcdabcf 2025-05-15T18:23:30+07:00 feat: kubectl debug: add label for debugger pod - - b13cf0a65 2025-05-15T12:55:10+02:00 tests: userns: Add framework.WithFeatureGate() - - 9549c1115 2025-05-15T08:48:35Z fix e2e network test flake because of network programming latency - - ef0547741 2025-05-14T21:23:52-07:00 verify scripts: preserve exit code - - 0114d33c3 2025-05-14T17:44:00-07:00 datapol: compare types directly - - a1a4bc8fe 2025-05-15T02:23:51+02:00 fix: add BackoffExpiration to DeepCopy - - 2fe65bbf4 2025-05-14T19:10:10Z fix(kubelet): update lease duration when config changes - - 094466539 2025-05-14T18:44:04Z Add rotation and clean up for logging - - 125600e74 2025-05-14T11:05:46-07:00 Remove unused GetHostname method - - ee94ba913 2025-05-14T16:51:43+02:00 Run codegen - - 4eb9fb21b 2025-05-14T16:51:43+02:00 applyconfig-gen: handle non-pointer embedded members - - c374ab811 2025-05-14T16:51:43+02:00 Add a breaking example for applyconfig-gen - - 70e051326 2025-05-14T15:52:09+02:00 Separate getList and watch errors to prevent TestGetCacheBypass flakes - - 512111571 2025-05-14T11:39:04Z Add sig/scheduling label to scheduler integration tests and staging repo OWNERS - - 1ed6cf219 2025-05-14T13:06:03+03:00 Add e2e tests for kuberc - - 0ad8e65d9 2025-05-14T08:55:42Z e2e pod readiness gate network flake - - fe1b1fff7 2025-05-14T14:50:59+08:00 Remove unused GetHostIP method - - 504b681ae 2025-05-13T15:46:43-05:00 Adding Joel Speed - - 47f859606 2025-05-13T15:03:27-05:00 DRA: prevent admin access claims from getting duplicate devices - - c5e4cab9b 2025-05-13T13:14:47-04:00 e2e: add corresponding featuregate label to node features - - c4d6fcb19 2025-05-13T15:35:21Z Remove misleading comment from NodeTaint TimeAdded field - - d0b6ea36b 2025-05-13T15:35:18+02:00 update got to 1.23.8 for the active release branches - - 3043257b8 2025-05-13T15:34:38+02:00 remove release-1.29 as it is deprecated - - 9fd545bcc 2025-05-13T15:06:04+02:00 [sig-scheduling] SchedulerPreemption [Serial] validates various priority Pods preempt expectedly with the async preemption: replace finalizers with preStop hook and TerminationGracePeriodSeconds - - 74e9b27e5 2025-05-13T08:53:50-04:00 Port "Service endpoints latency should not be very high" to EndpointSlices - - e5f7fc25e 2025-05-13T16:18:19+09:00 TestNodeAffinityScoring: wait all nodes - - e42aba6c0 2025-05-12T19:56:46Z Optimize RS Controller Performance: Reduce Work Duration Time & Minimize Cache Locking - - 28602c66f 2025-05-13T06:56:27+12:00 Update pkg/scheduler/framework/plugins/defaultpreemption/default_preemption_test.go - - 52e7aa37d 2025-05-13T06:56:27+12:00 gofmt - - a507e64fe 2025-05-13T06:56:27+12:00 Have separate tests for custom selection vs ordering, add comments around system pod eligibility - - 283c5e6b6 2025-05-13T06:56:27+12:00 Have IsEligiblePod be supplemental to priority check, update tests - - 3ed73e058 2025-05-13T06:56:27+12:00 Clean up the affinity explanation, fix for new lint rule - - d4bc527a7 2025-05-13T06:56:27+12:00 Update comments: affinity info, default behavior, priority->importance - - 95ebc2c10 2025-05-13T06:56:27+12:00 Apply suggestions from code review - - 7f57c6e52 2025-05-13T06:56:27+12:00 Update factory to use generics, keep single New function - - 137da6a48 2025-05-13T06:56:27+12:00 Remove line about equal priority, fix typo - - b8ac17143 2025-05-13T06:56:27+12:00 Apply suggestions from code review - - 224e6a3a3 2025-05-13T06:56:27+12:00 Rename EligiblePod* to IsEligiblePod* - - 4bf684149 2025-05-13T06:56:27+12:00 Update the customizations to operate on individual pods, for more flexibility later - - c34f8db55 2025-05-13T06:56:27+12:00 Remove unnecessary context and typecheck, switch to cmp.Diff - - c6f2d3879 2025-05-13T06:56:26+12:00 Fix gofmt in default_preemption_test.go - - 78b059c06 2025-05-13T06:56:26+12:00 rename OrderedPods -> OrderPods - - 2616202ac 2025-05-13T06:56:26+12:00 Implement tests with example customizations, add direct constructor - - 760daaf11 2025-05-13T06:56:26+12:00 feature(scheduler): Custom pod selection/ordering in DefaultPreemption - - 721947a57 2025-05-12T14:11:19-04:00 Update staging/src/k8s.io/apiserver/pkg/audit/request_log_test.go - - 153233c67 2025-05-12T12:59:58-04:00 review from tallclair - - e418ee3a9 2025-05-12T12:11:38-04:00 Avoid encoding in LogResponseObject when we are not going to use it - - 26c198dc2 2025-05-12T16:08:15Z Some fixes - - 0b915a538 2025-05-12T16:02:11Z Cleanup after rebase - - a6586aa61 2025-05-12T16:01:01Z Addressed comments - - e262cccf2 2025-05-12T16:00:07Z Cleanup after rebase - - 861040435 2025-05-12T16:00:04Z Add e2e tests for Partitionable Devices - - ece35e588 2025-05-12T15:56:24Z Update DRA e2e test framework to allow publishing advanced ResourceSlices - - a437a269f 2025-05-12T11:22:18-04:00 Fix comments on ginkgo label functions - - 85734ac6b 2025-05-12T10:48:19+02:00 DRA E2E: don't run prioritized list tests twice - - 808a5cfd4 2025-05-12T11:57:27+08:00 e2e tests: remove all cloud provider calls in storage/volume_provisioning.go - - 514078682 2025-05-12T01:26:47+02:00 feat: improve the backoff calculation to o(1) - - cfe7d0424 2025-05-11T16:22:52-07:00 Account consumed newlines properly in YAML decoder - - d5a56739c 2025-05-11T13:12:29+08:00 use framework.ExpectNoError instead - - 699ec0a53 2025-05-10T13:15:12+02:00 Remove wrong comment - - f718096b7 2025-05-10T17:22:11+08:00 NoExecute taint should be added when a Node's ready condition becomes Unknown - - 3911b677b 2025-05-10T18:17:38+09:00 test: wait for nodes to be in scheduler's cache - - ea6b4ea7e 2025-05-10T16:16:04+08:00 kubeadm: bump supported etcd version - - 9d963298a 2025-05-09T14:29:06-07:00 test: Close response body in watch tests - - d1fb42a40 2025-05-09T22:26:33+01:00 fix: fixes a possible panic in `NewYAMLToJSONDecoder` - - 960a4939f 2025-05-09T14:26:13-04:00 Eliminate AuditContext`s SetEventLevel - - c39705281 2025-05-09T16:11:30+02:00 Self nominate adrianmoisey as sig-network reviewer - - b09d034a5 2025-05-09T11:33:04+02:00 DRA E2E: revise test labeling - - 13bd0b4ee 2025-05-09T11:07:05+02:00 e2e: node: rewrite the sidecar related tests - - f4265638b 2025-05-09T11:07:04+02:00 e2e: node: factor out reservedCPUs - - a8c8b0987 2025-05-09T11:07:04+02:00 e2e: node: dissolve skipIfNotEnoughAllocatableCPUs - - 32d4724ab 2025-05-09T11:07:04+02:00 e2e: node: add comment about reserved CPU - - daf2fc710 2025-05-09T11:07:04+02:00 e2e: node: rewrite multi-pod tests - - ccc662c22 2025-05-09T11:07:04+02:00 e2e: node: initial multi-container tests - - 2419d9ccc 2025-05-09T11:07:04+02:00 e2e: node: rewrite: multi-cpus single-container pods - - e4726719a 2025-05-09T11:07:04+02:00 e2e: node: rewrite more compatibility tests - - 74fda8c70 2025-05-09T11:07:04+02:00 e2e: node: rewrite compatibility tests - - dd3f9b607 2025-05-09T11:07:04+02:00 e2e: node: rewrite CFS quota tests - - b9ce058ab 2025-05-09T11:07:04+02:00 e2e: node: rewrite strict-cpu-reservation tests - - 3eb2e65fc 2025-05-09T11:07:04+02:00 e2e: node: rewrite cpumanager tests - - 94dd0b840 2025-05-09T14:15:17+08:00 Move test cases from mounted_volume_resize into testsuites/volume_expand.go - - 4aa3c968a 2025-05-09T10:25:25+08:00 Build etcd image v3.6.0-rc.5 - - 641834d03 2025-05-08T17:22:38-07:00 Fix broken recursion - - eb4641d65 2025-05-08T14:21:19-07:00 Add container Resources to the backoff key - - 080d6f9ea 2025-05-08T13:08:20-07:00 test: pass the test context to http requests - - 3f188e5d8 2025-05-08T12:54:06-07:00 refactor: Use http method constants in apimachinery - - 75afa1e0a 2025-05-08T15:31:16-04:00 Fix API server crash on concurrent map iteration and write - - f93e4645c 2025-05-08T11:28:52-07:00 refactor: Stop using ioutil in apiserver - - 9e3a1b0a9 2025-05-08T19:11:40+02:00 Add comment describing the feature gate with a link to KEP - - e3f3da5e7 2025-05-08T19:11:36+02:00 Swap KUBECTL_COMMAND_HEADERS to use the proper feature gate mechanism - - d1b5f268b 2025-05-08T19:04:58+02:00 Drop KUBECTL_ENABLE_CMD_SHADOW featgure gat entirely - - a6abd717e 2025-05-08T16:37:43Z DRA: Fix failure to allocate large number of devices - - 6cca37b36 2025-05-08T16:47:35+02:00 Add integration test for log verbosity - - 69682b75e 2025-05-08T16:47:29+02:00 Manually read verbosity before kubectl command construction - - ee4c6b90c 2025-05-08T21:15:24+08:00 add HirazawaUi to kubeadm approvers list - - 77b1236a5 2025-05-08T21:08:01+08:00 fix: Kubernetes versions in unit tests - - f40892f48 2025-05-08T14:33:11+02:00 client-go: call out WithContext inconsistency - - 871cabeed 2025-05-08T11:10:12+08:00 deflake e2e tests: StatefulSet Non-retain StatefulSetPersistentVolumeClaimPolicy should delete PVCs after adopting pod (WhenScaled) - - 8b81a3d88 2025-05-07T16:42:08-07:00 Rename GetStableKey to GetBackoffKey - - 861682235 2025-05-07T21:15:12Z DRA: Fix incorrect behavior for AllocationMode: All in ResourceClaim when used in subrequests - - a3097010f 2025-05-07T13:01:15-07:00 Change the implementation design of matchLabelKeys in PodTopologySpread to be aligned with PodAffinity (#129874) - - ce02da8da 2025-05-07T15:42:16-04:00 generate code - - 4821604f8 2025-05-07T15:42:09-04:00 Reorganize scheme type converter into apimachinery utils - - e81887276 2025-05-07T12:17:48-07:00 refactor: Add request method constants - - af1d60f30 2025-05-07T18:16:15Z Add hpa reviewers - - 0acc7bd4d 2025-05-07T16:26:27Z HPA: Fix int overflow in GetExternalPerPodMetricReplicas - - b9cb3cb33 2025-05-07T23:35:28+08:00 update klog flags - - 57218ac96 2025-05-07T19:53:45+05:30 Revert "kube-proxy: log errors during proxy boot" - - 9def40c9e 2025-05-07T15:41:27+02:00 DRA E2E: fix "must manage ResourceSlices" - - c71e29ff1 2025-05-07T15:41:27+02:00 DRA E2E: fix flaky "sequential update with pods replacing each other" - - d28c8cd48 2025-05-07T14:12:23+02:00 fix: not removing the plugin from the unsched plugins after PreEnqueue - - 47d296d62 2025-05-07T13:54:47+02:00 feat: introduce pInfo.GatingPlugin to filter out events more generally - - 441dd3051 2025-05-07T11:52:36+02:00 userns: Wrap more errors - - 43f61e80d 2025-05-07T11:52:36+02:00 userns: Improve error returned if userns is not supported - - c5efc843d 2025-05-06T15:56:29-04:00 Fix rudimentaryErrorBackoff to only be created once - - 97e64e80c 2025-05-06T12:43:17-07:00 Fix typo in comment - - 68f0204e3 2025-05-06T12:40:58-07:00 Better logs and debugging - - 8a571f7fb 2025-05-06T12:40:57-07:00 Rename discover() to discoverType() - - eb3c061ca 2025-05-06T12:40:57-07:00 Reorder and merge blocks handling named types - - 67bab26ea 2025-05-06T12:40:56-07:00 hasValidations should return cached values first - - bb10f55fd 2025-05-06T12:40:55-07:00 Fix lint warnings - - 22fa3c747 2025-05-06T18:33:25Z add retries to exec command in cgroup verification - - 8652b6ab2 2025-05-06T13:40:44-04:00 Update sig-network-approvers/reviewers - - b1bb9a588 2025-05-06T14:30:10-03:00 Kubelet: Randomize ClusterRole name in e2e - - 863168e47 2025-05-06T09:25:06-07:00 e2e: stabilize Windows memory pressure eviction test - - 4ed3768dc 2025-05-06T17:54:25+02:00 userns: Use len to handle empty non-nil slices - - 97a2cb39c 2025-05-06T15:37:57Z Make sig-scheduling-api-approvers actual approvers - - 6d927c3c2 2025-05-06T15:15:03Z Comment out sig-scheduling-api-reviewers, since it's currently empty. - - 038bb1a9a 2025-05-06T15:15:03Z Remove alculquicondor who is stepping down from sig-scheduling-api-reviewers - - 55b5827d8 2025-05-06T13:59:36Z integration: etcd data - - aa9f156d7 2025-05-06T13:59:09Z integration test for compatibility version - - 3be3051fb 2025-05-06T09:35:38-04:00 Adding test case for the webhook behavior change - - cf82fd7e9 2025-05-06T09:35:27-04:00 Treat error decoding a mutating webhook patch as error calling the webhook - - 9bcec340f 2025-05-06T13:29:55Z modify unit test for compatibility version - - 15ab88f88 2025-05-06T13:29:54Z remove networking v1alpha1 and make update - - 54b014be1 2025-05-06T13:29:54Z use networkingv1 as default storage for servicecidr and ipaddresses - - b2fe862ae 2025-05-06T13:29:45Z graduate disableAllocatorDualWrite and lock MultiCIDRServiceAllocator - - d2fa246b0 2025-05-06T09:00:38-04:00 Update codegen - - d78b295a8 2025-05-06T09:00:32-04:00 Reenable guard to only validat root and scale subresources until ratcheting merges. - - 94d043b14 2025-05-06T13:00:14+03:00 Drop KUBECTL_DEBUG_CUSTOM_PROFILE feature gate entirely - - d52f05dad 2025-05-06T15:26:20+08:00 remove hwdef from hack reviewer - - 2e6ec2414 2025-05-05T22:06:59-04:00 Remove unused function - - 2e8b409a5 2025-05-05T22:06:59-04:00 Rewrite Subresources godoc. - - 164fefa94 2025-05-05T22:06:59-04:00 Update codegen - - 2119555e0 2025-05-05T22:06:59-04:00 Add subresource to operation, do not special case subresources in validation-gen - - 2073ba237 2025-05-05T18:47:41-04:00 pkg/storage/cacher/cacher_whitebox_test: deflake TestWatchNotHangingOnStartupFailure when ResilientWatchCacheInitialization is on - - 2b3f2aa70 2025-05-05T19:31:48Z propogate error - - 10c5bdd6a 2025-05-05T15:03:11-04:00 Apply feedback - - 36685c6f1 2025-05-05T14:40:06-04:00 Add information about expected status - - 6c8904104 2025-05-05T22:08:05+08:00 fix(scheduler): node pre-check logic to consider NoExecute taint effect - - e36a168a6 2025-05-05T10:37:42-03:00 test/e2e/node/kubelet_authz.go: fix SAR to include service account groups - - aeb43eb22 2025-05-05T12:22:39Z Migrate ExtractCommentTags to ExtractFunctionStyleCommentTags - - 1ec7231f6 2025-05-05T14:21:25+02:00 DRA node: reject static pods which reference ResourceClaims - - 2ea4b1aba 2025-05-05T13:00:08+02:00 golangci-lint: don't warn about conversion and defaulting functions - - 15d9a93d7 2025-05-05T13:00:08+02:00 golangci-lint: redirecting stderr raced with termination of script - - 3b5cfeaf2 2025-05-05T08:49:09+02:00 DRA: use v1beta2 - - b262d5616 2025-05-05T08:41:21+02:00 DRA: client-go wrapper with latest API as types - - 8e9abfaf2 2025-05-05T08:41:21+02:00 DRA: v1beta1 <-> v1beta2 conversion - - d7a64d68b 2025-05-05T08:41:21+02:00 DRA resourceslices: clarify code - - a171795e3 2025-05-05T08:40:52+02:00 DRA resourceslices: better error reporting - - 6392b54e1 2025-05-05T08:30:26+02:00 DRA resourceslices: avoid update loop when partitionable devices feature is off - - 5af026120 2025-05-05T08:25:20+02:00 test: bump agnhost image to 2.54 - - e5ffec242 2025-05-04T20:27:09+02:00 Bump CNI to 1.7.1 - - 47fddb08f 2025-05-02T20:56:03-04:00 Expand has() tests for omitempty and omitzero - - c2c003a71 2025-05-02T23:11:30Z update k8s.io/utils to bring fakeClock.Waiters() - - b3bf5ed0e 2025-05-02T15:33:07-07:00 verify-shellcheck.sh: normalize KUBE_ROOT using pwd -P - - a1a620886 2025-05-02T15:33:07-07:00 use the minimal shellcheck image instead - - e0983dbee 2025-05-02T14:23:49-07:00 remove unused shell imports in verify-shellcheck - - 7b50c8a51 2025-05-02T17:18:24-04:00 jwt: support CEL expressions with escaped names - - 784c589a7 2025-05-02T16:29:04-04:00 Check for newer resizing related fields after expansion is successful - - 6bb6c9934 2025-05-02T15:38:40-04:00 Drop null creationTimestamp from test fixtures - - 41805aff9 2025-05-02T15:38:40-04:00 Update runtime convertor to honor IsZero() - - bc6051717 2025-05-02T15:38:38-04:00 bump cbor to add omitzero support - - 06b078406 2025-05-02T15:38:38-04:00 bump structured-merge-diff to add omitzero support - - fdf0bb41a 2025-05-02T15:38:37-04:00 Omit null metadata.creationTimestamp - - 79891eac8 2025-05-02T17:27:34+02:00 agnhost: bump version to 2.54 - - 09912f352 2025-05-02T10:03:51-04:00 Make ToUnstructured match stdlib omitempty and anonymous behavior - - 49f765e2b 2025-05-02T20:56:29+08:00 Remove redundant Required validation for IngressRules - - c78556fb4 2025-05-02T14:46:56+02:00 agnhost pause: report signal, support termination message - - a6549edd1 2025-05-02T15:41:01+03:00 kubeadm: use named ports for coredns probes - - 0faeb5a0d 2025-05-02T14:38:09+02:00 golangci-lint: move into hack/tools/golangci-lint - - 5d9a2f30f 2025-05-02T14:38:09+02:00 golangci-lint: finish migration to v2 - - 9bada79de 2025-05-02T12:51:02+02:00 DRA node test: fix useless gomega.Consistently - - 4adb58565 2025-05-02T12:51:02+02:00 chore: bump golangci-lint to v2 - - f6d049801 2025-05-02T13:23:22+03:00 Continue alias creation when __completion is used to enable completion - - dceae3b38 2025-05-02T10:52:56+02:00 DRA e2e: avoid terminationGracePeriodSeconds - - 56e533f4a 2025-05-02T08:26:17Z servicecidr: only patch status if necessary - - 7fedcc34e 2025-05-02T08:25:16Z refactor default service cidr sync status logic - - edda4b02d 2025-05-02T00:09:10-07:00 fixup! Introduce special handling for updates involving a single resource slice. - - 6d8b41fac 2025-05-01T22:24:23-07:00 Introduce special handling for updates involving a single resource slice. - - 2e98d87c5 2025-05-02T10:48:46+05:30 api: Fix typo in word "immediately" - - 5441f5fde 2025-05-01T12:32:20-04:00 jwt: add unit tests for using CEL with deeply nested claims - - 43ce37ed4 2025-05-01T14:56:28+02:00 Address feedback - - 7e1cec680 2025-05-01T14:53:26+02:00 e2e: Deduplicate cgroup verification - - cc4c14d4c 2025-04-30T15:11:05-04:00 Disable size check for xfs/ext3/ext4 filesystems before expansion - - 48054afd6 2025-04-30T13:41:22-04:00 Relax external signer path validation to allow relative paths - - 5712881ca 2025-04-30T11:43:36-04:00 Disable disk size checking when calling NeedsResize function - - e500f9451 2025-04-30T23:55:46+09:00 add missing space in string concatenation (kubeapiserver) - - c5a2c69b9 2025-04-30T23:51:11+09:00 add missing space in string concatenation (kubeadm) - - 43a0da588 2025-04-30T23:35:25+09:00 add missing space in string concatenation (kube-proxy) - - 66b8a8427 2025-04-30T09:24:39-04:00 Fix CEL equality bug for structs will nil field not marked as omitempty - - 1b9386aac 2025-04-30T12:17:33+02:00 Add comment explaining the metric sampling logic for plugin execution metrics - - 0a4ab9367 2025-04-30T17:07:43+08:00 fix incorrect comments - - 4d5d48da7 2025-04-30T13:41:27+08:00 Remove unused volume limit constants - - 3a5dda78a 2025-04-30T04:46:50Z e2e network: blue green deployments - - ea6441827 2025-04-29T15:37:26-04:00 Appease linters - - 43d6ea12e 2025-04-29T15:37:01-04:00 jwt: refactor CEL eval to drop unstructured and map[string]any - - 064074c07 2025-04-29T13:32:26-04:00 Add lazy reflective CEL object wrapper - - 903d6d4f0 2025-04-29T09:17:40-04:00 Don't reinitialize test framework during each test case - - a56378d9f 2025-04-29T16:15:41+08:00 Update UserNamespaceSupport feature gate name - - 3cadb6ff8 2025-04-29T09:55:05+02:00 DRA test: update examples - - c6f652d5f 2025-04-29T14:58:57+08:00 Refactor pod failure policy defaults - - 68b1a950f 2025-04-28T22:14:02-03:00 kube-proxy should check global IPv6 enablement - - 2080bafa1 2025-04-28T23:40:49Z Add sunnylovestiramisu as Reviewer - - d6b45bc98 2025-04-28T18:43:12+02:00 [FG:InPlacePodVerticalScaling] clean code resize test - - dddfeb4a0 2025-04-29T00:19:47+08:00 Handle unsupported node expansion for RWX volumes - - 62ddcfba5 2025-04-28T20:35:19+05:30 kube-proxy: conditionally skip e2e - - 8bb7b0563 2025-04-28T15:44:04+02:00 dependencies: github.com/client9/misspell -> github.com/golangci/misspell - - ad40bc885 2025-04-28T08:28:46+02:00 kubectl describe service: Add Traffic Distribution - - 28e7acf0f 2025-04-27T20:35:38+02:00 improve display format - - f30c23a78 2025-04-27T15:36:09+02:00 kubectl: sort configmaps alphabetically to avoid random order - - db960d100 2025-04-26T17:39:31-07:00 Fix openid discovery docs with external jwt signer. - - 1869f6f23 2025-04-26T14:36:33-07:00 Fix typo in service account config test. - - c7a870135 2025-04-27T01:05:45+05:30 nftables: cleanup service chain checks - - 494b2b563 2025-04-27T01:21:39+09:00 use testing.TempDir and delete helper function - - efcceee90 2025-04-27T00:33:07+09:00 reduce assignment - - f42ee7a2d 2025-04-26T23:08:02+09:00 use slices package to reduce the codes - - 9cb3dfb5d 2025-04-26T16:06:18+05:30 kube-proxy: log errors during proxy boot - - 2d337f515 2025-04-25T11:21:42-07:00 Retool validator utils realType and unaliasType - - 835bb2ecc 2025-04-25T11:13:03-07:00 Change v8n context.Type and Parent on typedefs - - 6ea1db51a 2025-04-25T11:13:03-07:00 Disallow pointers as listmap keys - - fc7f01735 2025-04-25T11:13:02-07:00 Handle typedef fields in optional validations - - 9d519c7c4 2025-04-25T11:13:02-07:00 Fix immutable validation for structs with pointers - - 0b190b817 2025-04-25T11:13:01-07:00 Add test cases for immutable to verify pointers - - 855918f75 2025-04-25T11:13:01-07:00 Add tests for optionalness of typedef fields - - 7a24c4ce5 2025-04-25T10:07:12+02:00 chore: update github.com/google/cel-go dependency to v0.25.0 - - addaf680a 2025-04-25T15:49:41+08:00 remove v1.31.0 api testdata - - 86a43f4b5 2025-04-25T15:49:16+08:00 Add v1.33.0 API testdata - - 89156452a 2025-04-25T15:38:14+08:00 fix nil pointer panic on windows node - - 00908ce2d 2025-04-25T01:09:08-05:00 Wait for resource quota status to be populated - - d5bf33e7d 2025-04-24T22:54:09-07:00 update-codegen.sh: automatically install protoc - - 8a2f367ec 2025-04-24T22:54:09-07:00 automatically install goimports when running update-codegen - - 1473aeaac 2025-04-24T22:54:09-07:00 add goimports to tools module - - 540ea5949 2025-04-24T22:40:05-07:00 skip kubectl proxy env tests when the host is localhost/loopback and would not be proxied - - 1214dc223 2025-04-25T03:15:42Z kubelet: Use node addresses from informer - - c0b2f341a 2025-04-25T10:19:05+08:00 clean up cloud provider code because cloud provider only supports empty or external and cloud is nil - - 187b43d5a 2025-04-24T17:17:27-07:00 enable dep-approvers for staging go.mod/go.sum - - f50ad91ed 2025-04-24T15:18:26-07:00 Create a single TypeDiscoverer for all inputs - - 08794974b 2025-04-24T15:02:29-07:00 track gopkg.in/yaml.v3 as an unwanted depdendency - - aee494525 2025-04-24T21:28:07Z alculquicondor stepping down from sig-scheduling approvers - - 58e5dfd45 2025-04-24T13:08:46-07:00 attempt to re-introduce dep-approvers for go.mod/go.sum - - 74e84dbf5 2025-04-24T12:00:50-07:00 Add more test cases to TestDescribeSecret test (#131422) - - 6eff9db0f 2025-04-24T11:01:03-07:00 chore: Add VeryShortWatchError typed error - - 92359cdc6 2025-04-24T16:05:01Z update godoc for and rename observedGeneration helpers - - 932cff5dd 2025-04-24T15:51:08Z add more error details to the failing cgroup check - - c3bb59d07 2025-04-24T17:06:27+02:00 Fix etcd3 watcher flake - - 0d3d2733f 2025-04-24T08:06:17-04:00 Update go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful to v0.44.0 - - a2281f97b 2025-04-24T17:01:00+08:00 bump fsnotify v1.9.0 - - 44d7132af 2025-04-24T00:45:27-07:00 Update hnslib version in Windows KubeProxy. - - 7c53a5aaa 2025-04-24T14:54:41+08:00 Remove feature label NodeOutOfServiceVolumeDetach - - f74424bd7 2025-04-24T08:54:13+02:00 etcd: better logging - - 24257f2d3 2025-04-24T11:45:38+08:00 Remove deprecated scheduler cache metrics - - 269d3ae51 2025-04-24T09:47:27+09:00 Fix comment for default gRPC log level in DRA plugin - - 2ea689207 2025-04-23T15:58:37-07:00 Always check for Immutable selector in Deployment Replicaset Daemonset (#131017) - - 947a9f26f 2025-04-23T14:02:36-07:00 Move pod resize e2e utilities out of e2e/framework - - 609e4a9ba 2025-04-23T13:31:14-07:00 Unhandled panic crash on rollout_history printer.PrintObj (#130503) - - fa8e37f78 2025-04-23T13:30:52-07:00 Allow disabling caching for webhook authorizers when using `apiserver.config.k8s.io/v1{alpha1,beta1}.AuthorizationConfiguration` (#129237) - - 1db2d6a01 2025-04-23T16:15:10-04:00 Mark NodeExpansion finsihed without featuregate check - - 70ebe90b1 2025-04-23T16:05:56-04:00 Also change final status by removing featuregate check - - 849924b6b 2025-04-23T11:56:12-07:00 Increase delay in kuberuntime termination order test to prevent time rounding flake. - - 0e40ed642 2025-04-23T11:37:22-04:00 Check for newer fields when deciding expansion recovery feature status - - 4fa090bd8 2025-04-23T14:03:19Z Remove alculquicondor from test framework OWNERS - - 6a17858ff 2025-04-23T13:24:19Z CHANGELOG: Update directory for v1.33.0 release - - 90de4b589 2025-04-22T10:30:51-04:00 Remove warning about resizing failed for unknown reason - - 418092840 2025-04-22T10:11:35+02:00 Update cri-tools to v1.33.0 - - f63702de0 2025-04-22T14:54:40+08:00 scheduler: return UnschedulableAndUnresolvable when node capacity is insufficient - - d10eb8692 2025-04-22T14:01:41+08:00 fix: Fix non-constant format string in framework.Logf call - - b9a6a257b 2025-04-21T13:34:37-07:00 add TODO for unifying .go-version - - 5c84ee07e 2025-04-21T13:34:35-07:00 test/images: read .go-version instead of duplicating - - 722581f5f 2025-04-21T17:34:42Z Expand etcd data test to n-3 - - c21f26895 2025-04-21T17:34:41Z Fix VAP test for v1.34 - - bfcee6645 2025-04-21T17:34:41Z Bump DefaultKubeBinaryVersion to 1.34 - - 27815acee 2025-04-21T13:58:58+08:00 remove outdate comment - - 64b4c96e2 2025-04-21T08:44:04+08:00 fix: use correct apiextensions v1 API instead of apiregistration v1 - - a53ea3357 2025-04-18T10:53:10+01:00 Updates prober_total_total to BETA and updates the list of stable metrics - - f844abfc6 2025-04-18T15:55:38+08:00 Fix typo in ResourceEncodingConfig comment - - ff108e72a 2025-04-17T17:16:23+02:00 DRA device taints: fix rare unit test flake - - 97dd6dc28 2025-04-17T15:02:29Z Add warning message for attach - - 8672956f7 2025-04-17T14:41:43+02:00 etcd: use Unix Domain socket for testserver - - 33f16a55b 2025-04-17T14:26:54+02:00 etcd: fix 5 second delay during shutdown - - ff2e6dddc 2025-04-17T10:57:27+02:00 DRA device taints: work around fake.ClientSet informer race - - 638abf033 2025-04-17T10:55:13+02:00 DRA device taints: more logging in test - - 40f2085d6 2025-04-17T10:55:13+02:00 DRA device taint: clean up test initialization - - 091d09b44 2025-04-17T16:40:27+08:00 deflake e2e tests: CustomResourcePublishOpenAPI works for multiple CRDs of same group and version but different kinds - - db1e10715 2025-04-17T00:42:26+09:00 Job: Fix API comments for SuccessCriteriaMet - - ac3274521 2025-04-16T17:24:08+08:00 scheduler: remove duplicate nominatedNodeName clearing in preemption - - 373866eee 2025-04-16T08:54:06Z Build etcd v3.6.0-rc.4 image - - 7fcc1bcf1 2025-04-15T17:23:32-07:00 chore: move watch handler tests to handlers pkg - - 3fcb26f01 2025-04-15T15:18:22-07:00 reduce etcd install log noise - - 3e609ecf6 2025-04-15T12:03:21-07:00 fix: Watcher deadlock from Stop not being called - - c704025a0 2025-04-15T11:27:26-04:00 Fix error handling and csi json file removal interaction - - 1654aa619 2025-04-15T15:33:40+08:00 deflake intergation test: TestEndpointHandlers - - 3d53bfec0 2025-04-14T17:19:50+02:00 Typo fix: watchActcion - - 4e3026fdb 2025-04-14T15:59:45+02:00 pr fix - - 7d6f86594 2025-04-14T15:55:57+02:00 kubectl: sort secrets alphabetically to avoid random order - - 8f1326251 2025-04-14T09:51:51+02:00 Improve Job API comment for the backoffLimit - - 9d5f78a99 2025-04-14T09:21:16+02:00 Update OWNERS_ALIASES add aojea to sig-network-api-reviews - - e8dbfc0b6 2025-04-14T09:07:51+08:00 add miss Shutdown call for selinux_warning controller - - 405b9e802 2025-04-13T13:56:37-05:00 Check expected emitted events with assert.Equal - - 5ebeb8def 2025-04-13T13:56:37-05:00 don't only run events in nested lists consecutively - - 614b1e901 2025-04-13T13:56:37-05:00 Run all permutations of events in ResourceSliceTracker tests - - 29b499e2b 2025-04-13T13:10:38-05:00 simplify applyEventPair - - 45b0ddff1 2025-04-13T13:07:14-05:00 make input events a slice - - 3883e050f 2025-04-12T22:02:06-05:00 Use shared test fixtures for ResourceSlice Tracker test cases - - 7f21df6ab 2025-04-13T00:53:57+09:00 resolved review comments - - 5928fc0e6 2025-04-11T13:36:37-07:00 Add ContainerIter utility for ranging over pod containers - - 3b2cd1234 2025-04-11T17:17:46Z fix(kubelet): acquire imageRecordsLock when removing image - - 6d6abaab7 2025-04-11T15:34:26+02:00 Simplify etcd3 watcher - - b82fd6c28 2025-04-11T16:42:44+08:00 add e2e test for healthz/ - - 8bc7e6c10 2025-04-11T16:42:44+08:00 add etcd server overrides to etcd probe factory for healthz and readyz - - b141ac6a2 2025-04-11T16:06:30+08:00 adjust container_spec_memory_limit_bytes e2e to range: ppc64le is 44*1024 less - - 2aa39a0c7 2025-04-10T22:38:18-07:00 Update the busybox test image to 1.37.0 - - f9c1876b4 2025-04-10T14:58:37-04:00 Make proxy CleanupLeftovers methods quieter - - b61ca041b 2025-04-10T14:58:35-04:00 Add some missing cleanup to "kube-proxy --cleanup" - - c1ff9cf4e 2025-04-10T21:16:47+08:00 chore: Upgrade the mockery version to v2.53.3. - - ffe235d2d 2025-04-10T15:07:18+02:00 replace context.TODO with context.Background in tests - - 4bd0c024e 2025-04-10T15:07:18+02:00 add goleak to kubelet vendor via hack/update-vendor.sh - - 161b44d04 2025-04-10T15:07:18+02:00 add missing header in httpstream_test.go; whitespace in imports - - 79150d1ec 2025-04-10T15:07:18+02:00 add unit tests to verify the fix - - 42d3716d7 2025-04-10T15:07:18+02:00 fixed the formatting - - 268033a51 2025-04-10T15:07:18+02:00 Fixed go routine leak in kubelet tests - - 30f1bcade 2025-04-10T09:05:23-04:00 Add a unit test for iptables.CleanupLeftovers, improve ipvs test - - 94530dad7 2025-04-10T09:03:25-04:00 Move iptables/ipvs/ipset interface creation into CleanupLeftovers - - 975e653af 2025-04-10T13:01:07+02:00 RWX tests should create RWX volumes - - 5ad90c3b6 2025-04-10T19:08:25+09:00 merge RunBenchmarkPerfScheduling and runBenchmarkPerfScheduling - - 780c0d672 2025-04-10T18:56:45+09:00 add license description in options.go - - 4f33b74a3 2025-04-10T09:25:08+02:00 Use Go 1.24 os.Root instead of filepath-securejoin - - 5677f7ab0 2025-04-09T16:16:48-04:00 Make Request#RequestURI honor configured context root - - b206264ff 2025-04-09T15:45:31+02:00 Shorten long directory names with e2e pod logs - - 2800c16c8 2025-04-09T15:00:16+02:00 Remove FlowSchemas handling non-leases-backed leader election - - 16f4a5c4e 2025-04-09T17:04:20+08:00 cleanup unneed code - - 88fbccd69 2025-04-09T16:21:38+08:00 Fix the allocatedResourceStatuses Field name mismatch in PVC status validation - - 302a85058 2025-04-09T13:08:21+05:30 Update coredns version to v1.12.1 - - d4fd41285 2025-04-08T10:21:02-07:00 update the log message to reflect success and failed jobs - - cc4284618 2025-04-08T07:10:13-07:00 Fix for HNS local endpoint was being deleted instead of the remote endpoint. - - 551f3c782 2025-04-07T17:37:19-07:00 merge the integration tests into a single one - - de98a71ff 2025-04-07T08:09:59-03:00 Update PodSecurityLevel used during Service CIDRs tests - - 58ff3129a 2025-04-03T15:57:08-05:00 update kubelet_authz.go to new test framework - - c7d0ed5c4 2025-04-01T12:38:15-07:00 add integration test for job failure event delay and remove the unit test - - 6747bf7a9 2025-04-01T13:59:32-04:00 Clean up leaked goroutines in cache unit tests - - 04d0715e6 2025-04-01T19:29:17+09:00 scheduler-perf: add option to enable api-server initialization - - 16af0d79d 2025-03-31T09:45:51-07:00 update sig-autoscaling maintainers - - 653f48d88 2025-03-30T10:46:59+08:00 Certificate store: ensure data is written to disk - - 5a14fdbf7 2025-03-28T11:18:33Z e2e: Keep original error when exec in container fails - - 9c228e81d 2025-03-28T12:39:01+03:00 Increase kubectl cp command timeout to 30 seconds - - 310b395a0 2025-03-27T17:56:06+01:00 [cloud-provider] respect the "exclude-from-external-load-balancers=false" label - - ae08504ca 2025-03-27T22:29:39+08:00 Remove unneeded return values - - 2c94112a0 2025-03-27T07:45:31Z Disable thresholds for PreemptionBasic and PreemptionPVs tests - - f7d885321 2025-03-27T10:07:25+09:00 Add dom4ha to SIG-Scheduling approvers - - 8e65a62b3 2025-03-26T16:50:26-07:00 Deduplicate MilliCPUToQuota function & constants - - 3067bbfe1 2025-03-26T12:10:23+01:00 hack/ginkgo-e2e.sh: fix misplaced brackets - - 5e4600e46 2025-03-26T07:55:40Z e2e service ip preservation test - - f7e82d805 2025-03-25T17:30:42-07:00 clarify mutual exclusivity of service account annotation keys in godoc - - 4fa963914 2025-03-25T15:08:34-07:00 kubectl http proxy e2e: do not append os.Environ() redundantly - - f7f4aa02b 2025-03-25T15:08:04-07:00 kubectl e2e: debug appended environment variables - - 5aa61f847 2025-03-24T18:27:50+01:00 Test tooling: fix agnhost pause command - - 65b8fba34 2025-03-24T12:53:50+01:00 Mask Linux thermal interrupt info in /proc and /sys. - - 0ff1e3778 2025-03-24T14:05:12+08:00 Remove general available feature-gate PodDisruptionConditions - - fe14689f2 2025-03-22T10:14:01+08:00 bump k8s.io/utils - - 1c3dc397a 2025-03-21T18:19:43-07:00 make update - - 8af1629f7 2025-03-21T18:19:29-07:00 remove inaccurate hostNetwork doc comment - - bad6c7e4c 2025-03-21T17:28:41Z Set LANGUAGE env variable in TestDiffProgram for consistent locale behavior - - c005b85d4 2025-03-21T15:23:08Z Reduce locking duration on cache to fetch data from Cache - - 252d584cb 2025-03-21T08:20:04-07:00 Implement validation-gen lint for CI - - 1a694bfd3 2025-03-21T08:19:49-07:00 Make validation-gen lint errors easier to read - - 8dc6806d2 2025-03-21T14:55:25+08:00 Expose NodeInfo to PreFilter plugins and Framework - - 5413d0edf 2025-03-21T12:37:19+09:00 chore: correct the comment on UnschedulablePlugins - - 8db5f0618 2025-03-20T22:46:38Z adding commits of the original PR - - 1b8bbcac4 2025-03-20T15:04:44-07:00 Add integration test - - 1402a5491 2025-03-20T14:51:54-07:00 Removed unused function UncompressLog. - - 88a3c000e 2025-03-20T14:33:38Z Implement CSI e2e test for MutableCSINodeAllocatableCount - - d868eeb08 2025-03-20T21:58:14+08:00 Migrate pkg/kubelet/status to contextual logging - - 7f263b057 2025-03-19T13:04:18-04:00 Tag api change instead of apimachinery on generated openapi. changes - - 4120ed1df 2025-03-19T16:06:30Z chore: `make update` for doc changes - - 356e14804 2025-03-19T15:46:30Z fix: comment on preferred PodAntiAffinity - - a2624f9c6 2025-03-19T15:09:26+08:00 make update - - 21f7026c2 2025-03-19T14:54:12+08:00 clean up CSIDriverRegistry - - a68501da7 2025-03-18T20:18:12Z Add check to see if promote worked within the retry loop - - 53499d97e 2025-03-13T16:15:24-07:00 prefer error over bool, prefer Should(gomega.Succeed()) - - d54ff7441 2025-03-13T13:57:55-07:00 test: don't panic during an Eventually retry loop - - cab6045a4 2025-03-13T17:36:25+01:00 hack: remove verify-e2e-suites.sh - - 73afab185 2025-03-10T14:01:29-07:00 handle review comments - - 51fdd55e8 2025-03-06T15:56:07-08:00 use sync map for the cache - - 3a5f8b4b9 2025-03-06T00:03:59-08:00 Update OWNERS_ALIASES for sig scalability - - 547c005cb 2025-03-04T14:42:13-08:00 handle job complete update delayed event - - 410ada002 2025-03-04T14:32:50+08:00 Made the unsupportedError msg more readable - - 780fac5a3 2025-02-28T09:45:42+08:00 chore(kubelet): migrate network to contextual logging - - 125b8d280 2025-02-25T14:43:53-08:00 Removed kubelet test duplicate line. - - c1efa2e16 2025-02-18T14:18:25+08:00 delete test/e2e/common/storage/volumes.go - - 429437962 2025-02-17T17:49:36+08:00 e2e storage test: intree driver adds the support for nfs v3 - - 6df869347 2025-02-17T14:13:48+08:00 remove outdate comment about pv controller - - 329990590 2025-02-14T20:23:30+01:00 Based on the issue #8304 add mfahlandt as ne Co Chair for Contributor Experience - - 9a60ea01f 2025-02-12T13:44:15+08:00 fix getPodMatches should call /runningpods endpoint - - 5da366e3e 2025-02-11T18:35:25+08:00 Update pkg/quota/v1/evaluator/core/resource_claims.go - - ce7d3ea00 2025-02-11T16:38:18+08:00 fix wrong api version in toExternalResourceClaimOrError - - 0f0f9d01c 2025-02-05T12:19:17+08:00 remove out-of-date comments about version - - c2b455f55 2025-01-25T23:02:41+08:00 remove unnecessary functions - - 44d31af29 2025-01-25T02:17:01Z Add example in etcd override flag help text - - 3dc611e66 2025-01-24T14:56:37+08:00 fix container lifecycle e2e tests - - 4a4fb0a11 2025-01-22T22:21:39+09:00 Fix LC_CTYPE for kubemark start scripts - - ea644981d 2025-01-14T14:19:16+08:00 Update pkg/controller/certificates/cleaner/cleaner.go - - 1e1e2dee9 2025-01-14T14:18:51+08:00 Update pkg/controller/certificates/cleaner/cleaner.go - - 006ebbc33 2025-01-07T21:18:25-06:00 Fix comment typos - - 4bf5f1a6b 2025-01-02T13:01:01-05:00 kubelet: add coverage for identical kubelet config and drop-in config content - - eae133919 2024-12-26T15:35:56+08:00 fix: killPodOptions support JSON serialization - - 55ba8f063 2024-12-10T16:18:57+02:00 kube-scheduler: Fix a misleading error message in the VolumeRestrictions plugin - - a52863827 2024-11-13T10:23:54+03:00 [kubectl] drain daemonSetFilter with other APIVersion - - 9f50740b7 2024-11-12T12:43:53-08:00 Simplify span handling - - c64b6f80e 2024-11-12T11:23:38-07:00 Trace across start handler invocations, nesting spans - - 6fd8954fe 2024-10-29T15:34:58+08:00 kube-controller-manager: also support context for record.NewBroadcaster - - bea35b1f5 2024-10-28T11:16:27+08:00 remove non-lease resource locks in tests. - - ff74405bd 2024-10-22T11:28:31+08:00 kubelet: remove --register-schedulable flag - - 05be83b38 2024-09-18T11:54:35+02:00 tracing: set audit-id on incoming requests - - eda71f9e9 2024-04-09T15:12:57+08:00 cleaner.go should use time.Until instead of t.Sub(time.Now()) - - 1354bb9e2 2023-11-20T17:54:16Z Update log verbosity for node health and taint checks - -- service-ca-operator image-amd64 a40d9a8ec60e0c6c1578300c372b6104130f2ecc to e5d65c6f6b1446b77e0e915d64825d97be9c06de - - 46bab7e 2025-10-15T03:03:14+08:00 Fix gofmt formatting after CA rotation logic fix - - 5edc600 2025-10-15T02:45:32+08:00 Fix CA rotation polling logic - - 5031339 2025-10-14T21:23:53+08:00 Fix gofmt formatting in e2e_test.go - - 911d3da 2025-10-14T19:08:52+08:00 Fix connection test in checkClientPodRcvdUpdatedServerCert - - c9f6900 2025-10-14T17:14:30+08:00 Merge fixes from commit 41d9ed12 - - 667d9c7 2025-10-14T16:32:54+08:00 Fix e2e test failures due to SCC UID range validation - - 6e9d853 2025-09-29T22:19:56Z Updating ose-service-ca-operator-container image to be consistent with ART for 4.21 Reconciling with https://github.com/openshift/ocp-build-data/tree/4fbe3fab45239dc4be6f5d9d98a0bf36e0274ec9/images/ose-service-ca-operator.yml - -- ovn-kubernetes image-arm64 a7a531f167aa3e8ef14b7c258debf0c709ddcd09 to 3f971b1c061a775aedee0e9a06ab2a2a31bc64cc - - 31a760d7 2025-10-08T15:00:45+02:00 kv, e2e: Add --wait to killall - - cedfc13e 2025-10-08T13:17:13+02:00 utils,multinet: GetPodNADToNetworkMappingWithActiveNetwork CUDN support - - e4835ab8 2025-10-08T13:17:13+02:00 e2e,kubevirt: Test MAC conflict detection - - f46a21c6 2025-10-08T13:17:11+02:00 e2e,net-seg default-net annot: Test MAC conflict detection - - 89d1696a 2025-10-08T13:14:17+02:00 clustermanager,allocator: Init MAC manager with pod MACs - - eb4789b7 2025-10-08T13:14:08+02:00 clustermanager,allocator: Init MAC manager with infra MACs - - b6965d94 2025-10-08T13:10:25+02:00 clustermanager,allocator: Release reserved MAC on pod deletion - - 0b38dd8a 2025-10-08T13:10:21+02:00 clustermanager,allocator: Emit pod event reflecting MAC conflicts - - 1d5045a8 2025-10-08T13:09:42+02:00 clustermanager,allocator: Detect MAC conflict on pod allocation - - c8b18bd7 2025-10-08T13:09:08+02:00 pod-allocator: Introduce MAC addresses manager - - 8db8ca1d 2025-10-02T09:41:44+02:00 Use "OVN-Kubernetes" consistently as project name for CNFC correctness - - aa188fb5 2025-10-02T09:41:03+02:00 [docs] Add instructions for CI failures. - - 33a4f8c5 2025-10-02T09:40:57+02:00 [docs] Move local testing guide to its own page from CI - -- kubernetes image-arm64 00e7ec7a0db0b7e03c5ed2bc5b8b776fdc34f72a to 96593f323733d9ffc0fc70257ecad44a56df0ce3 - - 61114aa5a 2025-10-15T14:19:18-03:00 UPSTREAM: : hack/update-vendor.sh - - 30c13ce1b 2025-10-15T14:17:29-03:00 UPSTREAM: : make update - - b45907adb 2025-10-15T14:07:17-03:00 UPSTREAM: : hack/update-vendor.sh - - 25513888c 2025-10-15T14:03:12-03:00 UPSTREAM: 134199: Promote regression-issue-74839 to 1.4 - - 9ff0f3cae 2025-10-15T14:03:12-03:00 UPSTREAM: 134442: Fix ResourceQuota test for CRDs with long names - - 60ac34692 2025-10-15T14:03:12-03:00 UPSTREAM: revert: 133264: Revert "remove failing test that depends on expired credential, remove credential, add TODOs" - - ac1b24ee9 2025-10-15T14:03:12-03:00 UPSTREAM: 133905: kubelet/metrics: fix multiple Register call - - cd2e8b9ce 2025-10-15T14:03:12-03:00 UPSTREAM: 134376: Update hostpathplugin image version in DRA test driver manifest - - e5913956f 2025-10-15T14:03:11-03:00 UPSTREAM: 134327: test/e2e/apimachinery/watchlist: select only wellknown secrets for table test - - b392a7e3a 2025-10-15T14:03:11-03:00 UPSTREAM: 133421: e2e/watchlist: normalize dynamic Age column in Table test to prevent test flake - - 190966201 2025-10-15T14:03:11-03:00 UPSTREAM: 132791: Update pod resize test to accept new cpu.weight conversion. - - 6959e5211 2025-10-15T14:03:11-03:00 UPSTREAM: 132960: Configure JSON content type for generic webhook RESTClient. - - c21b863b5 2025-10-15T14:03:11-03:00 UPSTREAM: 134071: Wait for quota to report used before creating pvc - - 5a989b949 2025-10-15T14:03:11-03:00 UPSTREAM: 133959: Do not remove PVC ClaimRef to fix flaky VAC test - - cf73730d1 2025-10-15T14:03:11-03:00 UPSTREAM: 133682: Increase port-forward broken connection detection client timeout - - 06d238136 2025-10-15T14:03:11-03:00 UPSTREAM: : Add plugin for storage performant security policy - - b5ec7a566 2025-10-15T14:03:11-03:00 UPSTREAM: : unrevert: Mark admissionregistration.k8s.io/v1beta1 as deprecated." - - 71e26c8c5 2025-10-15T14:03:11-03:00 UPSTREAM: : allow TLS1.3 or modern profile to be specified - - 6803cc464 2025-10-15T14:03:11-03:00 UPSTREAM: : Add volume group snapshot test driver - - 22e63d2b8 2025-10-15T14:03:11-03:00 UPSTREAM: : admission: validate minimumKubeletVersion - - a743b1abe 2025-10-15T14:03:11-03:00 UPSTREAM: : log only deprecated api requests - - e87b794c6 2025-10-15T14:03:10-03:00 UPSTREAM: : disable etcd readiness checks by default - - 50b420aa6 2025-10-15T14:03:10-03:00 UPSTREAM: : add arbiter node role to known labels - - da795cb2c 2025-10-15T14:03:10-03:00 UPSTREAM: : Prefer local endpoint for cluster DNS service - - ecb7d7621 2025-10-15T14:03:10-03:00 UPSTREAM: : add etcd3RetryingProberMonitor for retrying etcd Unavailable errors for the etcd health checker client - - 06fe11ba2 2025-10-15T14:03:10-03:00 UPSTREAM: : annotate audit events for requests during unready phase and graceful termination phase - - 696bc0436 2025-10-15T14:03:10-03:00 UPSTREAM: : allow type mutation for specific secrets - - 0573d1831 2025-10-15T14:03:10-03:00 UPSTREAM: : Add openshift feature gates to kube-apiserver - inject openshift feature gates into pkg/features - - 3eb149a67 2025-10-15T14:03:10-03:00 UPSTREAM: : add new admission for handling shared cpus - - f3ef52744 2025-10-15T14:03:10-03:00 UPSTREAM: : temporarily disable reporting e2e text bugs and enforce 2nd labeling to make tests work - - db423d582 2025-10-15T14:03:10-03:00 UPSTREAM: : advertise shared cpus for mixed cpus feature - - 1994a6bff 2025-10-15T14:03:10-03:00 UPSTREAM: : Export cpu stats of ovs.slice via prometheus - - 57a39d46c 2025-10-15T14:03:10-03:00 UPSTREAM: : retry etcd Unavailable errors - - a4e802e80 2025-10-15T14:03:09-03:00 UPSTREAM: : selfsubjectaccessreview: grant user:full scope to self-SARs that have user:check-access - - 6cffd361e 2025-10-15T14:03:09-03:00 UPSTREAM: : merge v3 openapi discovery and specs for special groups - - e6b92109a 2025-10-15T14:03:09-03:00 UPSTREAM: : when only this kube-apiserver can fulfill the kubernetes.default.svc, don't wait for aggregated availability - - f42426e01 2025-10-15T14:03:09-03:00 UPSTREAM: : Export internal code from k8s.io/apimachinery/pkg/util/managedfields - - aa11b48c6 2025-10-15T14:03:09-03:00 UPSTREAM: : APISelfSubjectReview: only test v1beta1 API - - 4d0cd085e 2025-10-15T14:03:09-03:00 UPSTREAM: : disable load balancing on created cgroups when managed is enabled - - 283c592bc 2025-10-15T14:03:09-03:00 UPSTREAM: 115328: annotate early and late requests - - 967a1e568 2025-10-15T14:03:09-03:00 UPSTREAM: : PSa metrics: log platform namespaces in audit denies - - 788da1d88 2025-10-15T14:03:09-03:00 UPSTREAM: : make the PSA workload admission warnings honor the changes that SCC will eventually make to the pod - - 566fde9f6 2025-10-15T14:03:09-03:00 UPSTREAM: : optionally enable retry after until apiserver is ready - - 9c2fff44e 2025-10-15T14:03:09-03:00 UPSTREAM: : fix [sig-auth] ServiceAccounts no secret-based service account token should be auto-generated - - 93595fa11 2025-10-15T14:03:09-03:00 UPSTREAM: : use console-public config map for console redirect - - 3fab36613 2025-10-15T14:03:09-03:00 UPSTREAM: : Release lock on KCM and KS termination - - 927d3d922 2025-10-15T14:03:08-03:00 UPSTREAM: : sets X-OpenShift-Internal-If-Not-Ready HTTP Header for GC and Namespace controllers - - fc8db74d7 2025-10-15T14:03:08-03:00 UPSTREAM: : add max_housekeeping_interval - - ed28c08c4 2025-10-15T14:03:08-03:00 UPSTREAM: : send Retry-After when not ready with a caller opt in - - f7cdb220f 2025-10-15T14:03:08-03:00 UPSTREAM: : skip posting failures to aggregated APIs to avoid getting false positives until the server becomes ready - - 16f970296 2025-10-15T14:03:08-03:00 UPSTREAM: : add a way to inject a vulnerable, legacy service-ca.crt for migration compatibility - - 30a300bcb 2025-10-15T14:03:08-03:00 UPSTREAM: 103612: tolerate additional, but congruent, events for integration test - - 1780cd23f 2025-10-15T14:03:08-03:00 UPSTREAM: : crd: add ClusterOperator condition message table column - - ce1781131 2025-10-15T14:03:08-03:00 UPSTREAM: : emit event when readyz goes true - - 2d833691b 2025-10-15T14:03:08-03:00 UPSTREAM: : apiserver: add system_client=kube-{apiserver,cm,s} to apiserver_request_total - - b40e921b7 2025-10-15T14:03:08-03:00 UPSTREAM: : Ensure service ca is mounted for projected tokens - - dbcdc99b0 2025-10-15T14:03:08-03:00 UPSTREAM: : allows for switching KCM to talk to Kube API over localhost - - 4e71cfc7b 2025-10-15T14:03:07-03:00 UPSTREAM: : add management support to kubelet - - d859c8f35 2025-10-15T14:03:07-03:00 UPSTREAM: : allows for switching KS to talk to Kube API over localhost - - 2e380ce17 2025-10-15T14:03:07-03:00 UPSTREAM: : provide events, messages, and bodies for probe failures of important pods - - 63fc13858 2025-10-15T14:03:07-03:00 UPSTREAM: : allow kubelet to self-authorize metrics scraping - - 01f6a4ac1 2025-10-15T14:03:07-03:00 UPSTREAM: : use hardcoded metrics scraping authorizer for delegated apiservers - - ecbcaf656 2025-10-15T14:03:07-03:00 UPSTREAM: : kube-apiserver: ignore SIGTERM/INT after the first one - - 438c6cd39 2025-10-15T14:03:07-03:00 UPSTREAM: : noderestrictions: add node-role.kubernetes.io/* to allowed node labels - - 6b2289613 2025-10-15T14:03:07-03:00 UPSTREAM: : export HandleFlags - - fea2fa015 2025-10-15T14:03:07-03:00 UPSTREAM: : Add OpenShift tooling, images, configs and docs - - e162c7757 2025-10-15T14:03:06-03:00 UPSTREAM: : refactor/improve CRD publishing e2e tests in an HA setup - - c04050e15 2025-10-15T14:03:06-03:00 UPSTREAM: : conditionally fill the UserAgent from the currently running test - - f5ffc84dd 2025-10-15T14:03:06-03:00 UPSTREAM: : Remove excessive e2e logging - - 47631c08e 2025-10-15T14:03:06-03:00 UPSTREAM: : disable AES24, not supported by FIPS - - 673175cd6 2025-10-15T14:03:06-03:00 UPSTREAM: : warn only about unknown feature gates - - 49dbe59f1 2025-10-15T14:03:06-03:00 UPSTREAM: : bootstrap-rbac-policy: move over .well-known rules - - 42560b433 2025-10-15T14:03:06-03:00 UPSTREAM: : create termination events - - 3662118bf 2025-10-15T14:03:06-03:00 UPSTREAM: : kube-apiserver: priorize some CRD groups over others - - 6f7c7ec80 2025-10-15T14:03:06-03:00 UPSTREAM: : openshift-kube-apiserver: add openshift-kube-apiserver code - - d1c74dc85 2025-10-15T14:03:06-03:00 UPSTREAM: : openshift-kube-apiserver: add kube-apiserver patches - - 528cc99e6 2025-10-15T14:03:06-03:00 UPSTREAM: : kube-apiserver: add our immortal namespaces directly to admission plugin - - 72e349ebf 2025-10-15T14:03:06-03:00 UPSTREAM: : kube-controller-manager: exclude some origin resources from quota - - a0df69dbd 2025-10-15T14:03:05-03:00 UPSTREAM: : kube-controller-manager: allow running bare kube-controller-manager - - c90479ce1 2025-10-15T14:03:05-03:00 UPSTREAM: : kube-controller-manager: add service serving cert signer to token controller - - 75ec36f78 2025-10-15T14:03:05-03:00 UPSTREAM: : Extend NodeLogQuery feature - - 71f1dfcf8 2025-10-15T14:03:05-03:00 UPSTREAM: : hardcoded restmapper with a few entries to rebootstrap SDN when SDN is down - - fadd69ba4 2025-10-15T14:03:05-03:00 UPSTREAM: : remove apiservice from sync in CRD registration when it exists - - 4dd9038de 2025-10-15T14:03:05-03:00 UPSTREAM: : patch aggregator to allow delegating resources - - 898dd8cdf 2025-10-15T14:03:05-03:00 UPSTREAM: : filter out CustomResourceQuota paths from OpenAPI - - 91afdf9ce 2025-10-15T14:03:05-03:00 UPSTREAM: 93286: wait for apiservices on startup - - 96219fc21 2025-10-15T14:03:05-03:00 UPSTREAM: 74956: apiserver: switch authorization to use protobuf client - - 93248f9ae 2025-09-09T19:37:19Z Release commit for Kubernetes v1.34.1 - - 7bd2900b1 2025-09-05T03:53:40Z fix: Only warn for unrecognized formats on type=string - - f779cf638 2025-09-03T23:55:22+02:00 Disable estimating resource size for resources with watch cache disabled - - 96739661c 2025-09-03T09:23:47+02:00 Disable collecting stats for resources not setting prefix to prevent error logs - - 2631a5f21 2025-08-29T15:37:14+03:00 Fix linter - - 94c0e4788 2025-08-29T15:37:14+03:00 Fix completion of resource names - - 08515c751 2025-08-28T22:56:12+08:00 Fix missing control plane health check timeout - - a75938d9e 2025-08-28T18:07:40+08:00 Fix DaemonSet misscheduled status not updating on node taint changes - - 3ebbe5731 2025-08-28T10:29:24+02:00 Add a note about Conflicts return value - - 98dca817c 2025-08-28T10:29:24+02:00 Fix SELinux label comparison - - 3e75f3881 2025-08-28T10:29:24+02:00 Add missing cases to SELinuxMount tests - - d13374214 2025-08-27T10:36:11Z Update CHANGELOG/CHANGELOG-1.34.md for v1.34.0 - - f28b4c9ef 2025-08-27T10:09:04Z Release commit for Kubernetes v1.34.0 - - f2170bc6c 2025-08-26T16:11:12+01:00 kube-proxy: log but don't exit if ipv4 or ipv6 is not available - - f47e9696d 2025-08-20T17:40:32Z CHANGELOG: Update directory for v1.34.0-rc.2 release - - 78405b2c8 2025-08-20T17:40:32Z Update CHANGELOG/CHANGELOG-1.34.md for v1.34.0-rc.2 - - ed3ccdbe3 2025-08-20T17:17:54Z Release commit for Kubernetes v1.34.0-rc.2 - - db01f9403 2025-08-20T09:19:55-04:00 Remove patch/update from ServiceCIDR API conformance test - - d49e3d67c 2025-08-19T16:35:34+02:00 Fix storage counting all objects instead just objects for resource - - 747a295ca 2025-08-18T15:54:03-04:00 fix flake in dra test 'TestPlugin' - - 4ebe560c7 2025-08-18T13:44:26+02:00 DRA allocator: fix data race around `claimsToAllocate` - - 41013e7bf 2025-08-18T10:23:42+03:00 e2e_dra: use latest release if stable doesn't exist - - e49f6116f 2025-08-15T14:33:07-07:00 clarify that staging repos are automatically published - - ada2ed848 2025-08-15T10:17:18-07:00 add pointer to CONTRIBUTING.md for more details on contributing, clarify read-only - - 8919ac43c 2025-08-15T10:10:58-07:00 special case that kubectl staging repo is currently used to track issues, and only pull requests should be redirected back to the main repo. - - 011d50019 2025-08-15T10:10:26-07:00 link to what a staging repository is - - 7c43e6d2f 2025-08-15T10:08:16-07:00 docs: clarify that this is a staging repository and not for direct contributions - - f8bad82c2 2025-08-15T15:27:45+02:00 update go version for publishing bot rules - - bf6c86b56 2025-08-15T01:02:44-05:00 DRA: wait for stats to converge in "creates slices" e2e test - - 020b7052c 2025-08-14T09:46:06+02:00 Bump dependencies, images and versions used to Go 1.24.6 and distroless iptables - - c8ab780ed 2025-08-13T16:35:35-04:00 dra plugin: assume claim after api call in bindClaim - - 81affffa1 2025-08-13T19:49:57Z CHANGELOG: Update directory for v1.31.12 release - - 8311c1d3d 2025-08-13T19:46:23Z CHANGELOG: Update directory for v1.33.4 release - - edfa9a5bd 2025-08-13T17:57:33Z added WithFlaky() to the device plugin test case: supports extended resources together with ResourceClaim - - 48a496771 2025-08-13T14:49:49Z CHANGELOG: Update directory for v1.32.8 release - - 064b59161 2025-08-11T13:50:03+02:00 improve CRD handling in VolumePopulator test - - 944b0a492 2025-08-10T14:38:24-07:00 do not allow the node to update it's owner reference - - 0bd039e89 2025-08-08T21:01:46Z Update CHANGELOG/CHANGELOG-1.34.md for v1.34.0-rc.1 - - 4d6b49b3f 2025-08-08T21:01:45Z CHANGELOG: Update directory for v1.34.0-rc.1 release - - a956ef486 2025-08-08T20:39:54Z Release commit for Kubernetes v1.34.0-rc.1 - - e073a9125 2025-08-08T17:02:50+02:00 Add release-1.34 configuration - - cbd6fb867 2025-08-07T17:25:48-07:00 Remove DeprecatedVersion for apiserver_storage_objects, adjust help text - - 89b5034d5 2025-08-07T13:46:08+08:00 Make podcertificaterequestcleaner role feature-gated - - 2629fe25f 2025-08-06T21:24:27-07:00 Use Delete() instead of DeleteLabelValues() for etcd metrics - - 13ced7b7d 2025-08-06T20:20:05Z CHANGELOG: Update directory for v1.34.0-rc.0 release - - 40e8ad951 2025-08-06T13:26:10Z Release commit for Kubernetes v1.34.0-rc.0 - - b79691898 2025-08-06T07:42:31Z reduced numPods to 5 from 10 to fix flaky test (supports reusing resources) due to timeout. - - 2a026f6d6 2025-08-06T07:08:58Z 1/ added retries to AssumeClaimAfterAPICall for the object which is not present in the cache (dynamicresources.go) 2/ modified the assume cache verification to not error out as long as the expected claim is in the cache, no matter its latest and api object are different or not. (dynamicresources_test.go). 3/ fixed nil panic as seen from https://prow.k8s.io/view/gs/kubernetes-ci-logs/pr-logs/pull/133321/pull-kubernetes-integration/1952472629470302208 - - 01470d973 2025-08-01T09:56:51-07:00 Fix memory limit decrease test on cri-o - - aca402f25 2025-08-01T13:59:32+02:00 e2e: node: skip breaking tests - - 0fbc8cd44 2025-08-01T07:18:26Z Remove integration-test labels from long running scheduler_perf workloads - - e83e5815e 2025-08-01T00:55:10-04:00 always pull pause image for eviction tests - - 418e96bf1 2025-08-01T12:46:26+08:00 Update prerelease lifecycle to v1.34 - - 65fda6dd3 2025-07-31T18:15:55Z fixed exended resource scheduling performance test, added more nodes for scheduling the init pods - - 9eda4789c 2025-07-31T09:27:40Z Fix potential race in PodStatusPatchCall implementation - - dbfeb9c35 2025-07-30T11:57:26Z Fix potential race in closing API dispatcher - - c7db6362f 2025-07-30T10:47:38Z Move NominatedNodeName preemption-related integration tests to a new package - - 46b858aa1 2025-07-30T19:12:57+09:00 fix: return false to apply the patch - - 07c71097d 2025-07-30T09:06:34Z Split DRA scheduler_perf tests into multiple packages - - 988c9b03f 2025-07-30T15:48:26+09:00 Demote KEP-5278 feature gates ClearingNominatedNodeNameAfterBinding and NominatedNodeNameForExpectation to Alpha - - 0a12f00e9 2025-07-30T14:44:41+09:00 fix nil panic in hasBindingConditions, it cannot assume claim has allocations - - 7f052afae 2025-07-30T09:52:49+09:00 KEP 5075: implement scheduler - - 3e3b2447f 2025-07-29T17:28:26-07:00 Promote PodLevelResources to Beta (#132999) - - 59bba9271 2025-07-30T09:26:52+09:00 KEP-5075: generated codes from make update - - 5ad969588 2025-07-30T09:26:40+09:00 KEP-5075: API updates - - 29d1951eb 2025-07-29T12:34:35-07:00 fixes scheduler nil panic due to empty init container request&limit - - 23d6f73e7 2025-07-29T18:55:28Z extended resource backed by DRA: test - - 34a64db2c 2025-07-29T18:55:21Z extended resource backed by DRA: implementation - - a3a767b37 2025-07-29T20:20:08+02:00 WIP: fix e2e tests - - 4ca47255a 2025-07-29T20:19:40+02:00 node: disable resource managers when pod-level resources are enabled - - 3068b60b8 2025-07-29T17:17:20Z extended resource backed by DRA: codegen - - 1f2fd18ac 2025-07-29T17:17:19Z extended resource backed by DRA: API types.go - - 7fbf63a23 2025-07-29T09:02:26-07:00 HPA support for pod-level resource specifications (#132430) - - 6e9b60e3f 2025-07-29T11:06:39-04:00 Add / update kubelet and DRA API owners - - 60fa65db8 2025-07-29T23:48:11+09:00 Clear pod.Status.NominatedNodeName when pod is bound - - 15b1a7fd3 2025-07-29T16:41:37+02:00 Revert "CPU and Memory manager event when using pod level resources" - - aea0a3cca 2025-07-29T12:21:03Z Run all relevant test cases with the feature gate enabled and disabled - - 856e7d238 2025-07-29T12:21:03Z scheduler: Stop clearing NominatedNodeName on all cases - - 6653ef652 2025-07-29T11:36:07Z KEP-5007 DRA Device Binding Conditions: Add dra integration test - - 9e82c1330 2025-07-29T11:35:58Z KEP-5007 DRA Device Binding Conditions: Implement DRA logic - - e8c3af1f5 2025-07-29T11:34:30Z KEP-5007 DRA Device Binding Conditions: Implement scheduler logic - - ac81b829e 2025-07-29T11:34:03Z KEP-5007 DRA Device Binding Conditions: Run make update - - 987ad3951 2025-07-29T11:32:47Z KEP-5007 DRA Device Binding Conditions: API Related code Update - - 34c3b0938 2025-07-29T11:31:48Z KEP-5007 DRA Device Binding Conditions: API Update - - ac9fad603 2025-07-29T19:01:02+09:00 feat: trigger PreFilterPreBind in the binding cycle - - 48eef9ce9 2025-07-29T08:06:39Z test: fix TestStructuredAuthenticationConfigReload flake by handling expected network errors - - 4874d4166 2025-07-28T21:42:42-07:00 Pod Certs: Fix kubelet volume host arg order - - f9bb14fcf 2025-07-28T19:42:04-04:00 Fix apiserver service proxying e2e test flakiness - - 8ace0fb89 2025-07-28T15:43:43-07:00 remove failing test that depends on expired credential, remove credential, add TODOs - - f07dcd443 2025-07-28T22:06:48Z fix flake on TestStreamTranslator_WebSocketServerErrors - - 7ba22700b 2025-07-28T21:59:08Z websocket streamtranslator increament metrics before writing status - - 0aea6a1e4 2025-07-28T21:53:12Z TestStreamTranslator_BlockRedirects use subtests - - 4b698656b 2025-07-28T19:31:08Z Returning early if podResources is nil to avoid nil pointer dereferencing - - 766d011bb 2025-07-28T18:53:04Z E2E tests for no hints nor aligment of CPU and Memory managers - - 5672750e6 2025-07-28T18:53:03Z Unit tests for no hints nor aligment of CPU and Memory - - 7804b51f4 2025-07-28T18:53:03Z CPU and Memory manager event when using pod level resources - - fd206a0ef 2025-07-28T17:19:07Z Add comments for restart rules not used for unknown container status and probes - - 4b479da4b 2025-07-28T16:33:20Z Remove the feature from e2e test - - 6997fbd1e 2025-07-29T00:02:20+08:00 Fix incorrect validation on the kubelet - - 48f8458c4 2025-07-28T16:54:08+02:00 validation: Fix user-namespaces test case name - - 50a7a8af4 2025-07-28T16:54:08+02:00 validation: Align usage of hostUsers in error messages - - 5f7e611f7 2025-07-28T16:54:08+02:00 validation: Return error if hostUsers=false && volumeDevices - - f3466f8ad 2025-07-28T23:12:58+09:00 fix: flake integration test - - ed74d4cd5 2025-07-28T20:22:27+09:00 Revert "Revert "fix: handle corner cases in the async preemption"" - - e8dc272c5 2025-07-27T21:45:02-07:00 Update etcd to 3.6.4 - - 0f7cd1495 2025-07-28T11:52:12+08:00 Fix prerelease-lifecycle for volumeattributesclass - - 9c8dacb03 2025-07-27T23:14:12Z ContainerRestartRules feature gate should work with probes - - 48fd30113 2025-07-26T07:51:58+09:00 [PodLevelResources] Add missing label to Downward API test - - 57ceb56c6 2025-07-25T14:09:41-07:00 Bump etcd sdk to v3.6.4 - - b562335cb 2025-07-25T13:51:25-07:00 Build etcd v3.6.4 image - - 17d733e24 2025-07-25T15:35:36Z KEP-5229: Send API calls through dispatcher and cache - - 40a90df3b 2025-07-25T12:45:01+02:00 DRA E2E: remove stress test - - b956484c2 2025-07-25T19:29:14+09:00 KEP-5229: Add metrics for async API dispatcher - - 006d7620a 2025-07-25T10:38:34+08:00 Revert "fix: handle corner cases in the async preemption" - - 727a6e6db 2025-07-24T17:58:54-07:00 Reject pod when attachment limit is exceeded (#132933) - - a65289630 2025-07-24T17:58:33-07:00 Allow white-spaced CABundle during webhook client creation and validation (#132514) - - f1737db16 2025-07-24T18:58:24-05:00 Update DRA Pod spec comments - - b7de71f9c 2025-07-24T23:23:18Z feat(kubelet): Add ResourceHealthStatus for DRA pods - - d4a83b9a5 2025-07-24T21:41:28Z fix(golangci-lint): skip config verification when -c none is used - - 252513a1b 2025-07-24T21:40:08Z Add WithFeature and WithSerial, also check if cgroup v2 is used in test - - 1bc995c19 2025-07-24T21:29:04Z Generated files - - f925e5554 2025-07-24T21:29:04Z E2E tests for container hugepage resources immutability - - 9f5b09eb7 2025-07-24T21:29:04Z Unit test pod level hugepage Default and Validation logic - - 845e94d37 2025-07-24T21:29:01Z Validation logic and Defaulting update for pod level hugepages - - c15a54f8c 2025-07-24T14:08:14-07:00 draadminaccess: move metrics test from e2e to integration - - d176808d3 2025-07-24T12:12:59-07:00 Rename hack/*-yamlfmt to -owners-fmt - - 7adcd2114 2025-07-24T12:11:04-07:00 Replace cmd/yamlfmt with k-sigs/yaml/yamlfmt - - 79833578f 2025-07-24T18:52:34Z KEP-3695: add kubeletPodResources feature gate to Beta - - 2cb955d8c 2025-07-24T11:47:03-07:00 Add KYAML support to kubectl - - 8182a27f3 2025-07-24T11:46:03-07:00 Re-vendor sigs.k8s.io/yaml @ v1.6.0 - - 94bf8fc8a 2025-07-25T01:53:59+08:00 Promoted API `VolumeAttributesClass` and `VolumeAttributesClassList` to `storage.k8s.io/v1`. - - 8e3f93c87 2025-07-24T17:13:39Z Unit test propagate pod level hugepages to containers - - 52b457421 2025-07-24T17:13:39Z Pod level hugepage cgroup when unset in container - - add7132a6 2025-07-24T17:08:13Z E2E tests for pod level resources Kubelet Preemption - - 976a617d0 2025-07-24T17:07:09Z E2E tests for pod level resources eviction manager - - 13b122b6f 2025-07-24T17:07:09Z Unit tests for pod level resources eviction manager - - 9a3ca05f6 2025-07-24T17:07:05Z Use pod level resources for eviction manager - - b34f8782e 2025-07-24T16:49:54Z Add e2e tests - - 9086e52fe 2025-07-24T16:49:54Z Implement restart rules in kubelet - - af595a44a 2025-07-24T16:49:52Z Add container restart rules to API - - 5dc2030c0 2025-07-24T12:37:14-04:00 4033: GA KubeletCgroupDriverFromCRI feature gate - - 27e167515 2025-07-24T12:36:26-04:00 Make PSA host enforcement honor emulation version - - 32053b1d2 2025-07-25T00:07:30+08:00 chore: replace ptr caster with unified ptr.To - - 83a0d0c66 2025-07-24T11:42:59-04:00 kubelet: add metric for version CRI implementation will lose support - - ffe306d67 2025-07-24T07:56:27-07:00 client-go, kubectl: Replace deprecated ErrWaitTimeout with recommended method (#132718) - - cb33accc8 2025-07-24T06:46:28-07:00 JSON & YAML output for kubectl api-resources (#132604) - - 8a2db4da4 2025-07-24T22:45:39+09:00 fix: adjust the log level in the preemption - - 4c9bf4719 2025-07-24T22:44:39+09:00 fix: handle cornor cases in the async preepmtion - - bf98e45af 2025-07-24T21:20:12+08:00 Migrate pkg/kubelet/volumemanager to contextual logging - - aecd37e6f 2025-07-24T12:10:58Z Moving Scheduler interfaces to staging: Move PodInfo and NodeInfo interfaces (together with related types) to staging repo, leaving internal implementation in kubernetes/kubernetes/pkg/scheduler - - c954e1325 2025-07-24T14:04:08+02:00 Revert "DRAAdminAccess: add upgrade downgrade test" - - 12d675066 2025-07-24T13:50:05+02:00 client-go/metadata/fake: sets opts.Watch to true - - b37fd0cab 2025-07-24T11:49:51Z [KEP-4816] DRAPrioritizedList to Beta - - 6767d54bb 2025-07-24T19:46:51+09:00 Bump DRA API version to "v1" in "deviceattribute" package in "k8s.io/dynamic-resource-allocation" module - - 449763fb1 2025-07-24T12:35:45+02:00 e2e: podresources: disable memory manager integration - - b768c1d1d 2025-07-24T08:33:56+02:00 DRA API: bump storage version to v1beta2 - - 24de875ce 2025-07-24T08:33:56+02:00 DRA: graduate DynamicResourceAllocation feature to GA - - d8df1dc1b 2025-07-24T08:33:56+02:00 DRA RBAC: fix kube-scheduler bootstrap policy - - 21d929f59 2025-07-24T08:33:56+02:00 integration: use --runtime-config-emulation-forward-compatible - - 5c4f81743 2025-07-24T08:33:45+02:00 DRA: use v1 API - - cff91579e 2025-07-24T08:30:25+02:00 DRA API: v1 registration + tests - - 4e592f6c1 2025-07-24T08:30:24+02:00 DRA API: s/v1beta2/v1/ and generated files - - 1f2f433f7 2025-07-24T08:30:24+02:00 DRA API: verbatim copy v1beta2 -> v1 - - 837b7395d 2025-07-24T09:14:09+03:00 kubelet: DRA: Close gRPC connection when removing DRA plugin - - c7d6c0968 2025-07-23T21:44:27-07:00 List available endpoints for kube-apiserver (#132581) - - 5f4a1aa58 2025-07-24T09:11:09+08:00 chore: ptrTo util removal with ptr.To - - a82187cf1 2025-07-24T08:15:36+09:00 [PodLevelResources] Update Downward API defaulting for resource limits - - 4c87e60d0 2025-07-23T21:17:05+02:00 Tests using .host field in probes must be at priviledged level - - f94fcac86 2025-07-23T21:15:46+02:00 Add new fixture testData for 1.34 PSA - - fc0474d77 2025-07-23T21:15:46+02:00 Copy test fixtures to 1.34 from 1.32 - - 9540a9639 2025-07-23T21:15:46+02:00 Copy test fixtures to 1.33 from 1.32 - - 4a3ebf886 2025-07-23T21:15:46+02:00 update the minimal version to fix unit/fixture tests - - 333b19b44 2025-07-23T21:15:45+02:00 Add PSA for blocking .host field on pod probes and lifecycle - - c7bf3b81f 2025-07-23T13:51:18-04:00 Add flake debugging for admission test - - a806e069e 2025-07-23T17:40:53Z Remove WinDSR feature gate unit test - - 765d84e9b 2025-07-23T13:19:07-04:00 Test only EndpointSlices, not Endpoints, in dual-stack e2e tests - - 2cb48f77f 2025-07-23T18:58:57+02:00 schedule pod availability checks at the correct time in ReplicaSets - - 61cc6cf80 2025-07-23T09:13:13-07:00 draadminaccess test make it serial - - 33b45c838 2025-07-23T11:07:29-04:00 Update "should proxy through a service and a pod" to look at EndpointSlices - - d70e7e223 2025-07-23T11:07:29-04:00 Port aggregated apiserver discovery to EndpointSlices - - 41dc2d3b0 2025-07-23T11:07:28-04:00 Add utilities for getting EndpointSlices for a Service - - f7109ed28 2025-07-23T10:59:18-04:00 [KEP-3751] Allow PVC VACName to update to nil or empty when status.currentVAC is nil - - c35e4ad2b 2025-07-23T22:57:12+08:00 add codes for drop disabled pod fields - - 8d65e1e98 2025-07-23T22:57:11+08:00 Add e2e tests. - - f31aeca42 2025-07-23T22:57:11+08:00 Add code for overriding hostnames - - 88b762143 2025-07-23T22:57:08+08:00 Add validation for the HostnameOverride field. - - c889ee17a 2025-07-23T16:55:05+02:00 Convert kubelet plugin manager from gogo to protoc - - abb1b26d5 2025-07-23T16:50:23+02:00 DRA: Add experimental allocator variant - - 17cc5e9ec 2025-07-23T15:38:34+02:00 e2e: node: podresources: exercise with dynamicresources enabled - - ee8ef383b 2025-07-23T22:37:19+09:00 Update kubectl kustomize to kyaml/v0.20.1, cmd/config/v0.20.1, api/v0.20.1, kustomize/v5.7.1 - - af6c97bd1 2025-07-23T20:28:13+08:00 add Feature Gate. - - 8b3814c4a 2025-07-23T20:28:12+08:00 Add the HostnameOverride field to the Pod API - - c2a06e791 2025-07-23T11:06:11+03:00 DRA: skip flaky test case on Windows - - f6061605f 2025-07-23T09:12:46+02:00 DRA E2E: run multi-node control plane tests also with two nodes - - f0e292089 2025-07-23T09:10:45+02:00 DRA E2E: simplify "control plane" test names - - 603751ee8 2025-07-23T09:10:45+02:00 DRA E2E: remove redundant test - - 21ed19798 2025-07-23T09:58:14+03:00 kubelet: DRA: Handle grpc.ErrServerStopped in plugin tests - - 61bd5789b 2025-07-23T03:44:48Z Updated to not directly change the global variable `claim` - - 4f0a5771a 2025-07-23T10:19:20+08:00 test: add e2e case for mutating named port - - db9b9b5a4 2025-07-22T16:48:31-07:00 Build etcd v3.6.3 image - - 179551a7c 2025-07-22T23:24:32Z feat: Implement warnings for unrecognized formats in CRDs - - 437a2ad69 2025-07-22T23:23:55Z feat: Add func to export the supportedVersionedFormats - - d943239c5 2025-07-22T22:11:23Z added debug_redact to cri api secrets - - 88af8b606 2025-07-23T07:08:21+09:00 Add PodLevelResources to the Windows OS limitations in the API doc - - c2b26617b 2025-07-23T07:08:21+09:00 Check OS for PodLevelResources in kubelet - - e2c308aff 2025-07-23T07:08:14+09:00 Check OS for PodLevelResources in API server - - f6aee6369 2025-07-22T20:40:48Z add validation logic for APIVersion fields of HPA - - 6f3b6b91f 2025-07-22T13:40:42-07:00 KEP-3721: Support for env files (#132626) - - 0b60c1219 2025-07-22T15:15:18-04:00 KEP-4222: Adopt text and JSON transcoding support for CBOR. - - 917659269 2025-07-22T15:15:17-04:00 Bump to github.com/fxamacker/cbor/v2 v2.9.0. - - 216f7485b 2025-07-22T11:54:34-07:00 DRAAdminAccess: add upgrade downgrade test - - 303a7056f 2025-07-22T19:58:29+02:00 e2e: node: podresources: enable multi-container tests - - 38a9a8a59 2025-07-22T19:55:09+02:00 e2e: node: podresources: add tests for missing pod - - 19b00ecc9 2025-07-22T17:36:03Z update CCM image to v33.1.1 - - b070b0a5c 2025-07-23T00:57:50+08:00 chore: residual boolptr and intptr removal - - 407bcf886 2025-07-22T11:05:00-04:00 kubelet: add metrics for userns pods - - e5ccc31e7 2025-07-22T20:26:52+05:30 chore: replace float64Ptr with ptr.To helper in validation and integration tests - - 545b36ba2 2025-07-22T09:50:18-05:00 fix uncore e2e check - - b97decb7d 2025-07-22T15:58:22+02:00 client-go/dynamic/fake: sets opts.Watch true - - f626e847e 2025-07-22T20:44:53+08:00 Migrate pkg/kubelet/winstats to contextual logging - - ce2d97939 2025-07-22T17:35:48+08:00 Run Unschedulable scheduler_perf test case with SchedulerAsyncAPICalls feature gate enabled - - 0da0897c1 2025-07-22T16:38:20+08:00 Bump external snapshotter for vgs tests - - 78bf3410c 2025-07-22T09:21:58+02:00 DRA E2E: revisit conformance classification of tests - - 911df655d 2025-07-22T10:14:42+08:00 chore: migrate kubelet lifecycle to contextual logging. - - 872f0682d 2025-07-22T10:51:56+09:00 Use "k8s.io/api/resource/v1beta2" instead of "k8s.io/dynamic-resource-allocation/api" for resource API imports. - - 31d2de59d 2025-07-22T10:51:55+09:00 Split the symlink target error cases into for each condition - - a4fb1562f 2025-07-22T10:51:53+09:00 introduce resolvePCIeRoot instead of resolveSysDevicesPath - - f3d4b216f 2025-07-22T10:49:39+09:00 assign return value to a variable instead of using it directly - - 7f27c88d0 2025-07-22T10:25:17+09:00 Update staging/src/k8s.io/dynamic-resource-allocation/deviceattribute/pci_linux.go - - ee26a5837 2025-07-22T10:10:40+09:00 Update staging/src/k8s.io/dynamic-resource-allocation/deviceattribute/pci_linux.go - - 8b558a1bc 2025-07-21T22:54:24Z fix(validation-gen): correct typos in comments and documentation - - 63a958ff3 2025-07-21T22:54:24Z chore(validation-gen): remove TODO regarding ratcheting behavior for slices and maps - - c659b4182 2025-07-21T22:27:13Z e2e test for mirror pod with pod generation - - a5b9c7a79 2025-07-21T17:57:57-04:00 bump resource claim controller concurrent syncs to 50 - - 6d4000f84 2025-07-21T21:49:57Z Pod Certificates: make update - - 4624cb9bb 2025-07-21T21:49:57Z Pod Certificates: Basic implementation - - facbb6614 2025-07-21T17:00:45-04:00 Temporarily revert restart-on-node-IP-change behavior of proxy NodeManager - - e2d37f3cd 2025-07-21T17:00:44-04:00 kube-proxy: merge OnNodeAdd and OnNodeUpdate into OnNodeChange - - 0dc51b16f 2025-07-21T17:00:44-04:00 kube-proxy: merge NodeEligibleHandler with NodeManager - - d4892fef7 2025-07-21T17:00:44-04:00 kube-proxy: merge NodePodCIDRHandler with NodeManager - - 373fb487f 2025-07-21T17:00:44-04:00 kube-proxy: add NodeManager to manage life-cycle based on NodeIPs - - d21ca8674 2025-07-21T17:00:44-04:00 kube-proxy: add NodeTopologyConfig for tracking topology labels - - 8acda3631 2025-07-21T17:00:42-04:00 Belatedly add tests of proxy NodeConfig and ServiceCIDRConfig - - edf4654d7 2025-07-21T19:27:59Z generate proto - - 18918e200 2025-07-21T19:27:59Z add CSR declarative_validation_test.go tests - - 69a8a169d 2025-07-21T19:27:59Z add WithOrigin and MarkedByDeclarative, update hand-written to error at list instead of list item field, add additional tests for approved+denied case - - 6a2d5a1e6 2025-07-21T19:27:59Z feat: add CSR status.conditions approved+denied declarative validation tags and associated declarative validation tags to v1 and v1beta1 types.go - - 248ad2161 2025-07-21T13:55:32-05:00 graduate prefer-align-cpus-by-uncorecache to beta - - 6e77bff18 2025-07-21T18:51:07Z pod sandbox image is not being used by kubelet any longer - - 43706d6b7 2025-07-21T20:34:36+03:00 add warnings when creating headless service with specified load balancer ip,external ips and/or session affinity - - 53aa4332b 2025-07-21T16:50:16Z fix integration tests - - 8996e81fc 2025-07-21T16:46:07Z fix unit tests - - dd4dd3d8e 2025-07-21T16:32:25Z feat: Enabledeclarative validation in CertificateSigningRequest subresources updates - - ccc82775f 2025-07-21T11:19:25-05:00 expand test coverage for uncore alignment - - cb29414b4 2025-07-21T16:13:32Z Extend E2E test coverage for PSI metrics under pressure - - 4ed231da0 2025-07-21T17:16:16+02:00 kubelet/imagePullManager: add benchmarks for image pull record accessors - - 5486e6f44 2025-07-21T07:55:32-07:00 DRAAdminAccess: move to beta - - 5d4010d2d 2025-07-21T09:08:43-05:00 Mark KubeletServiceAccountTokenForCredentialProviders feature gate as beta - - 4fc9546e0 2025-07-21T14:00:34Z KEP-5229: Implement API dispatcher - - 549f7c4fc 2025-07-21T14:53:58+02:00 image pull manager: add in-memory LRU intents/pulled records caching - - ea326373e 2025-07-21T13:57:50+02:00 e2e: node: cpumanager cgroup v1 compatibility - - b8d74e75c 2025-07-21T12:56:51+01:00 Add test case to prove MaxElements correctly set on IntOrString - - 7e5aafcb1 2025-07-21T13:47:22+02:00 ci: remove unnecessary test harness - - 457df1cf9 2025-07-21T12:48:29+02:00 ci cleanup: make sure to remove test KUBECONFIGs - - 3026020b4 2025-07-21T10:04:01+02:00 Convert `k8s.io/kubelet/pkg/apis/deviceplugin` from gogo to protoc - - 4f9f6c053 2025-07-21T09:33:11+02:00 scheduler_perf: hide "metric ... not found" errors - - b8758ac31 2025-07-20T21:50:58+01:00 node: mm-mgr: migrate to contextual logging - - 2e756e741 2025-07-20T15:17:04-05:00 fix data race in OIDC integration tests by serializing test server starts - - 03acd266a 2025-07-20T22:16:45+08:00 chore: residual uint64ptr removal with ptr.To - - b84271a77 2025-07-19T21:54:47-07:00 DRAAdminAccess: add e2e - - ab839c93f 2025-07-20T09:47:50+09:00 feat(kubelet): migrate kuberuntime to contextual logging - - 30e5cdd64 2025-07-19T16:20:34+03:00 kubelet: don't fetch image credentials if the image is present and if we don't need to check if the pod is allowed to pull it - - cbba3281a 2025-07-19T11:46:32+02:00 integration: fix etcd output handling - - d0fc938a0 2025-07-19T11:38:21+02:00 DRA client: fix conversion of watch channel - - f77ce8951 2025-07-19T11:38:12+02:00 DRA: debug output for list/watch client - - 9d7d3a617 2025-07-19T14:41:04+05:30 Bump sample-device-plugin base image to alpine:3.22 - - 7ddb04262 2025-07-19T17:10:37+09:00 feat(cmd/kubelet): support structured and contextual logging - - fb4e25222 2025-07-19T14:13:59+08:00 test: add batch pod deletion for kubelet e2e tests - - 4b8dd9612 2025-07-19T13:08:34+09:00 cleanup: remove example plugins - - 067bd16b1 2025-07-19T03:37:37Z Add unit tests to check if right feature gate is checked based on resize request. - - f71080c93 2025-07-19T03:22:56Z Create separate feature gates for static CPU Manager and static Memory Manager support - - 07ef7842b 2025-07-19T03:20:26Z Change memory manager static policy to a public const - - ae5247afc 2025-07-19T00:07:22Z address feedback - - 659517445 2025-07-19T00:06:48Z unit test for HandlePodReconcile retrying pending resizes - - 0d24c3b57 2025-07-19T00:05:19Z add sourcesReady parameter to fakeKubelet constructor - - 6e86af48c 2025-07-19T00:05:17Z fix check if requests have shrunk - - 6a40bcb42 2025-07-19T00:03:46Z Retry pending resizes if a status update leads to aggregate requests shrinking - - 22d724969 2025-07-18T23:59:05Z kubelet: record container_resize_requests metric for all resize updates - - 13a6d2121 2025-07-18T23:30:54Z check a couple extra failure scenarios - - 8957109b7 2025-07-18T22:29:30Z only record resizes in progress and pending after all pods are added - - d51375dcc 2025-07-18T22:29:25Z record 'kubelet_pod_deferred_resize_accepted_total' metric - - b8fc1b675 2025-07-18T22:27:40Z record 'kubelet_pod_infeasible_resizes_total' metric - - d845e1fd6 2025-07-18T22:27:40Z record 'kubelet_pod_pending_resizes' metric - - 23005281f 2025-07-18T22:27:39Z record 'kubelet_pod_in_progress_resizes' metric - - 0595ddaaf 2025-07-18T22:27:39Z record 'kubelet_container_requested_resizes_total' metric - - 468aa5e30 2025-07-18T22:27:39Z record 'kubelet_pod_resize_duration_milliseconds' metric - - 129662763 2025-07-18T22:27:39Z define and register ippr metrics - - 3964fbeab 2025-07-18T17:00:17-05:00 kubelet: integrate sa creds in image pull manager - - f1728bd58 2025-07-18T16:38:27-05:00 Add ServiceAccount coordinates to ImagePullCredentials v1alpha1 - - b9dd2fdec 2025-07-18T16:38:23-05:00 credentialprovider: track service account cred source in ext provider keyring - - 9a4c0f9b2 2025-07-19T06:32:52+09:00 scheduler_perf: Add memory tracking to performance tests - - 8a42f4ccc 2025-07-18T11:55:23-07:00 Add support for CEL list library. - - 5d3186631 2025-07-18T17:50:07Z dedupe fetching allocatable and available resources in node test - - 79dc0b8a4 2025-07-18T19:38:56+02:00 Add jitter to priodically executed process in storage to avoid too concurrent executions - - a48420e3c 2025-07-18T16:57:41Z promote PodObservedGenerationTracking to beta - - 336b5aff4 2025-07-18T16:35:32Z Check for valid UID range when runasnonroot is true - - e9492239b 2025-07-18T16:29:31Z Promote windows graceful shutdown to Beta - - 00bf3b37a 2025-07-18T21:35:58+05:30 Graduate PodLifecycleSleepActionAllowZero to GA - - 99059895f 2025-07-18T17:53:23+02:00 Account for caching and maximum object size when estimating LIST request - - 2256f5747 2025-07-18T23:43:53+08:00 Add resize completed event after Inprogress conditionCleared is cleared - - d42a1d58d 2025-07-18T07:15:41-07:00 DRAAdminAccess: add metrics - - f5d12ed39 2025-07-18T14:10:45Z fix: Compare versions instead of pointer comparison - - 8dc20a0f6 2025-07-18T12:34:29+01:00 Fix IntOrString cost estimation when schema has a MaxLength constraint - - a2e9e9f66 2025-07-18T17:02:54+08:00 fix pass ctx into a revised HandleError function - - 729cd583a 2025-07-18T09:43:04+02:00 scheduler integration: fail test instead of existing - - bfa33b18a 2025-07-18T09:55:39+08:00 fix(kube-proxy) avoid add zero-masked loadBalancerSourceRanges to ipset - - d6e85b504 2025-07-17T20:30:06-05:00 Add kubelet_credential_provider_config_info metric - - 14a5ef56a 2025-07-17T23:21:26Z fix pipeline failure - - 21e2fcea9 2025-07-17T17:47:51-05:00 Add automatic_reload_last_config_info metric for auth configs - - 5f829195e 2025-07-17T14:46:47-07:00 Only warn when AppArmor annotation doesn't match pod field - - f2c48ffec 2025-07-17T16:32:47-05:00 Add generic config info custom collector - - 11921f758 2025-07-17T14:14:57-07:00 [KEP-5100] WinOverlay feature gate to GA - - e417232f9 2025-07-17T14:07:35-07:00 Warn when using AppArmor annotations with a pod field - - 4fdf09fdc 2025-07-17T14:07:35-07:00 Stop syncing AppArmor fields to annotations - - 3ecb3d230 2025-07-17T14:07:35-07:00 Remove unused appArmor*InUse functions - - 75ae2d727 2025-07-17T13:17:35-07:00 Add an E2E test for memory limit decrease usage check - - 2a9388c30 2025-07-17T13:17:35-07:00 Move memory limit decrease e2e test to success cases - - c7a78185c 2025-07-17T13:17:35-07:00 Remove the restriction on memory limit decrease - - d9c91127d 2025-07-17T13:17:35-07:00 Check memory usage before decreasing limits - - 465f72814 2025-07-17T20:09:05Z use gomega.BeComparableTo instead of Equal for resource quantity check in resize test - - cedcbfb94 2025-07-17T20:09:03Z Update cel-go to v0.26.0 - - 24065780e 2025-07-17T15:34:34-04:00 Add e2eendpointslice.WaitForEndpointPorts, use in some tests. - - f456a70bd 2025-07-17T19:19:05Z use CreateBatch and MakeResizePatch - - 5cea72d56 2025-07-17T21:18:28+02:00 DRA integration: add test case for FilterTimeout - - 241ac018e 2025-07-17T21:18:28+02:00 DRA integration: remove unnecessary anonymous import - - bc338e750 2025-07-17T21:18:28+02:00 DRA scheduler: implement filter timeout and cancellation - - 430c79b53 2025-07-17T19:03:35Z chore(validation-gen): hold uniqueness check of listmap - - 1745094c4 2025-07-17T18:40:01Z Update VolumeAttributesClass API Description - - 2cb30c779 2025-07-17T18:22:15Z Refactor target check - - 86bc1bf0a 2025-07-17T17:50:45Z more complex e2e test for deferred resizes - - 66de1960a 2025-07-17T18:13:10+02:00 Increase maxSeats for List requests - - 025c606e3 2025-07-17T16:47:47+02:00 DRA scheduler: add plugin configuration - - ee38a0013 2025-07-17T16:47:47+02:00 DRA scheduler: add DRASchedulerFilterTimeout feature gate - - 837ef29f5 2025-07-17T16:47:47+02:00 scheduler: enhance and document Filter cancellation - - 7910b43cd 2025-07-17T16:47:46+02:00 scheduler_perf: document benchstat usage - - b9ce92d50 2025-07-17T16:45:42+03:00 edit versioned_feature_list.yaml - - 070621bf7 2025-07-17T16:44:41+03:00 Remove unit tests that rely on feature gate enablement check - - 3f847d97c 2025-07-17T16:44:40+03:00 GA the NodeSwap feature gate - - 1a7630c09 2025-07-17T22:41:58+09:00 Remove deprecated LegacySidecarContainers feature gate - - 300c7b815 2025-07-17T22:33:32+09:00 set the timeout to Get method - - 2b13b87e6 2025-07-17T15:11:55+02:00 chore: replacing timer ptr with ptr.To - - 532d48fe6 2025-07-17T14:56:44+02:00 Convert `k8s.io/kubelet/pkg/apis/podresources` from gogo to protoc - - cf68f75fc 2025-07-17T14:30:16+02:00 Deprecate apiserver_storage_objects and replace it with apiserver_resource_objects metric using labels consistent with other metrics - - db342010f 2025-07-17T12:08:03+02:00 kube-controller-manager: enable WatchListClient - - cef9f9edb 2025-07-17T16:58:58+08:00 kubeadm: fix a bug where it should generate default etcd command based on etcd version when the etcd image tag supports semver - - ace2a2249 2025-07-17T10:17:30+02:00 drop rules for release-1.30 as it is EOL - - 6737c31d0 2025-07-17T10:12:19+02:00 update publishing bot go rules for release-1.31/1.32 - - a1a85ddb1 2025-07-17T09:56:28+02:00 SSA: test optional map keys - - 4d34975a4 2025-07-17T09:56:28+02:00 sigs.k8s.io/structured-merge-diff/v6 v6.3.0 - - 3357e8fc0 2025-07-17T09:56:28+02:00 SSA: add integration tests - - a2a3839a8 2025-07-17T09:43:44+02:00 DRA scheduler: add pohly as approver - - 4bc2ad6ee 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/preemption to contextual logging - - b96e3cac7 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/pod to contextual logging - - 0cb31bc40 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/nodeshutdown to contextual logging - - 75ccd69ba 2025-07-17T10:16:03+03:00 migrate pkg/kubelet/kubeletconfig to contextual logging - - 1d0fd5928 2025-07-17T00:16:01-07:00 kubectl: add port names to describe pod output - - 7dad9e2af 2025-07-17T10:15:58+03:00 migrate pkg/kubelet/apis to contextual logging - - f141907dd 2025-07-17T07:56:03+02:00 DRA kubelet: add v1 gRPC - - 1b5a08cbf 2025-07-17T09:51:42+08:00 cleanup: fetch individual PodResourceInfo from allocated resource state - - 6e7e6b37c 2025-07-17T01:37:22Z Fix the cost issue to match the bug fix for target being nil in CEL side. - - ad220eb6c 2025-07-17T09:08:12+08:00 chore: remove residual int64ptr usage with ptr.To - - a96446863 2025-07-16T15:59:55-07:00 Add PodCPUAndMemoryStats to stats.Provider interface - - 8f4a624a5 2025-07-16T22:56:59Z Fix pipeline errors - - e8536c019 2025-07-16T22:38:45Z add item + union and item + zeroroneof output tests - - be72d963b 2025-07-16T22:38:45Z add validate/zeroorone_test.go and add +k8s:zeroOrOneOfMember output tests - - 10b20852e 2025-07-16T22:38:45Z feat(validation-gen): add +k8s:zeroOrOneOfMember tag validator and associated validate method - - 81f18759e 2025-07-16T22:38:44Z add validate/union_test.go and add +k8s:unionMember and +k8s:unionDiscriminator output tests - - 5bc9b6911 2025-07-16T22:38:44Z feat(validation-gen): add +k8s:unionMember and +k8s:unionDiscriminator tag validators and associated validate methods - - bfb42fc31 2025-07-16T22:38:44Z refactor item.go with buildMatchConditions, make itemTagValidator a LateTagValidator - - 5d1c5ebd8 2025-07-16T22:38:32Z add ParentPath to context, remove Parent from context and plumb changes in validators - - c50da38aa 2025-07-16T22:33:58Z allow field validators to generate variables - - e7aeb4ff5 2025-07-16T21:23:13Z Promote MutableCSINodeAllocatableCount to Beta - - 9bcaa8c86 2025-07-16T15:11:21-04:00 Fix conversion-gen caching incorrect memory equality comparisons - - b35ad4e9b 2025-07-16T11:42:02-04:00 Add e2eendpointslice.WaitForEndpointPods, use in various test - - dbecdd187 2025-07-16T11:42:02-04:00 Use e2eendpointslice.WaitForEndpointCount in more network tests - - b7998a397 2025-07-16T11:42:00-04:00 Add e2eendpointslice.WaitForEndpointCount, use it in some network tests - - dd3691b16 2025-07-16T15:11:11Z refactor allocator, removed claimsToAllocate from NewAllocator(), instead, passed it through Allocate() - - 8e6651520 2025-07-16T16:46:39+02:00 Convert `k8s.io/kms/apis` from gogo to protoc - - 2f605f49f 2025-07-16T14:40:35Z CHANGELOG: Update directory for v1.34.0-beta.0 release - - 9cf00ec6d 2025-07-16T14:56:50+02:00 kube-apiserver: promote WatchList feature to beta - - e4320fe25 2025-07-16T15:49:41+03:00 e2e_node: DRA: test handling fatal serving failures - - ea05ad888 2025-07-16T15:49:41+03:00 e2e_node: DRA: add errorOnCloseListener - - fc21d3f37 2025-07-16T15:49:41+03:00 e2e: DRA: enable test plugin to cancel main context on error - - 1981c985b 2025-07-16T15:49:41+03:00 e2e: DRA: support test and public options - - d44b73744 2025-07-16T15:49:32+03:00 DRA: handle grpc.Server.Serve failures - - 169965350 2025-07-16T15:42:12+03:00 e2e_node: Refactor DRA tests to use variadic options - - 52fab5969 2025-07-16T21:33:33+09:00 Add NominatedNodeNameForExpectation feature flag - - fd23fa3d4 2025-07-16T12:52:01+02:00 Graduate ListFromCacheSnapshot to Beta - - 665599417 2025-07-16T06:17:34-04:00 Add e2eendpointslice.WaitForEndpointSlices, use it in a few places - - b5931f53d 2025-07-16T06:19:27Z Auto update openapi spec - - a100dfdfa 2025-07-16T05:11:52Z Using alpha as the stored version for one release. - - 6e9324453 2025-07-16T12:24:35+08:00 Add validation of volumeClaimTemplates in StatefulSet - - ae4a43de6 2025-07-16T11:01:37+08:00 Refactor: isolate flag registration to kube-apiserver to eliminate global state - - 5b4c1872a 2025-07-16T09:07:25+08:00 chore: residual intptr removal with ptr.To - - e9aab4648 2025-07-15T23:11:24Z CHANGELOG: Update directory for v1.31.11 release - - dc0ca0be3 2025-07-15T22:19:29Z CHANGELOG: Update directory for v1.33.3 release - - d6caa36dc 2025-07-15T22:18:25Z CHANGELOG: Update directory for v1.32.7 release - - d460611e7 2025-07-15T21:51:36Z Add more checks - - b69fd9d42 2025-07-15T16:03:07-04:00 Add egress selector support to JWT authenticator - - e9c1ca724 2025-07-15T15:38:13-04:00 Add conversion-gen memory equality test - - 62521d835 2025-07-15T18:23:30Z fix observedGeneration in pod resize conditions - - 386372602 2025-07-15T10:48:12-07:00 add unit-test for ensuring authn latency annotation - - 760eb7d5d 2025-07-15T10:39:08-07:00 fix: record authentication latency before audit filter wraps up - - 26c8ee7b8 2025-07-15T17:22:12Z DRA: Improve allocator with better backtracking - - d383c8e02 2025-07-15T17:46:28+02:00 Update history of checkpoint support in Kubelet - - 20914ef4e 2025-07-15T17:00:49+02:00 Prevent running two HPA cachers for different API versions - - bc5088cbf 2025-07-15T19:34:05+05:30 Revert "Kube proxy node manager" - - f8c7131b4 2025-07-15T15:32:13+02:00 Drop experimental- prefix from etcd flags - - d8747d716 2025-07-15T15:06:26+02:00 Use object size estimation for non-recursive list - - 05e1c4b48 2025-07-15T14:15:00+02:00 e2e: node: fix podresources API feature label - - 6e1875fac 2025-07-15T12:54:40+02:00 local-up-cluster.sh: don't require to be invoked in the root - - 356be5ae3 2025-07-15T12:54:40+02:00 DRA E2E: move upgrade/downgrade test into test/e2e_dra - - c8ca9249a 2025-07-15T12:54:40+02:00 DRA integration: add upgrade/downgrade testing with local-up-cluster.sh - - 60e9316c0 2025-07-15T12:54:40+02:00 DRA E2E: refactor helper code - - 2e3228e2c 2025-07-15T12:52:27+02:00 DRA E2E: support deploying driver on localhost - - e5f57d2cf 2025-07-15T12:52:27+02:00 ktesting: add WithoutCancel - - e01603b2e 2025-07-15T12:52:27+02:00 ktesting: document side effect of SetDefaultVerbosity during init - - 0b1bed1a1 2025-07-15T12:52:27+02:00 ktesting: WithCancel does not cancel on test completion anymore - - f381d7372 2025-07-15T12:52:27+02:00 DRA E2E: retry exec of hostpathplugin - - c2080e7e4 2025-07-15T12:52:27+02:00 DRA E2E: support using ktesting - - 906505281 2025-07-15T12:52:27+02:00 ktesting: add step Begin/End - - b7c2d6aba 2025-07-15T12:52:27+02:00 ktesting: skip logging error when capturing it - - 497716386 2025-07-15T12:52:26+02:00 DRA E2E: reduce port proxy verbosity - - 5721c927e 2025-07-15T12:52:26+02:00 DRA E2E: increase verbosity of resource claim controller - - 1a284472f 2025-07-15T12:52:26+02:00 E2E framework: retry also on EOF errors - - 6a7b9589f 2025-07-15T12:52:26+02:00 E2E framework: support setting REST config - - bd30b0ade 2025-07-15T16:55:12+08:00 remove general avaliable feature-gate DevicePluginCDIDevices - - 9c0e65b08 2025-07-15T10:11:23+02:00 test/apimachinery/watchlist: server supports sending resources in Table format - - 2dfc4e25a 2025-07-15T10:08:41+02:00 endpoints/handlers/respone: include metadata when IncludeNone and watchlist requested - - e1a0cf624 2025-07-15T14:56:43+08:00 handle stoppedCh and listenerStoppedCh returned by cc.SecureServing.Serve - - 6cd00cdcb 2025-07-15T04:48:13Z Auto gen - - a3ecea296 2025-07-15T01:44:13Z manual change - - 4f3334b7c 2025-07-15T01:44:13Z Promote feature gate - - 0d8fd61e6 2025-07-14T21:10:37Z address review comments - - 32afbd9ea 2025-07-14T23:02:18+02:00 Inconsistency resets cache snapshots and prevents collection of new ones until cache is marked consistent again - - 4f77a4618 2025-07-14T16:19:52-04:00 Generated files - - a04e7cf5e 2025-07-14T16:19:52-04:00 KEP-4601: Graduate selector authorization to stable - - 6f4be0d8c 2025-07-14T21:07:45+02:00 DRA allocator: skip unsupported test cases - - 740e56846 2025-07-14T18:13:00Z address review comments - - 61542e7a9 2025-07-14T18:13:00Z Cleanup: Remove field name from invalid field detail message - - 14f3c2684 2025-07-14T18:03:57Z Remove redundant metric field. - - ad03cb873 2025-07-15T00:31:20+08:00 chore: residual strPtr utility removal with ptr.To - - af249fb2e 2025-07-14T18:13:27+02:00 DRA E2E: test mixture of extended resources + ResourceClaim - - 9a7dddf5a 2025-07-15T01:07:43+09:00 fix test - - 09ec6f744 2025-07-15T01:07:25+09:00 chore - - 85adda5e6 2025-07-14T16:58:58+02:00 Use object size to estimate list cost assigning 1 sear per 100KB - - f20be4c09 2025-07-14T23:17:19+09:00 add test which checks release method calls Get - - 7d9eb2b3d 2025-07-14T16:09:29+02:00 test/apimachinery/watchlist: update tests that receive resources in Table format - - da7c55e0d 2025-07-14T15:42:57+02:00 reflector: detects unsupported meta.Table gvks for watchlist - - ebc1ccc49 2025-07-14T07:24:48-04:00 Bump k8s.io/kube-openapi to latest SHA (f3f2b991d03b) - - 8d1cbc83d 2025-07-14T13:02:14+02:00 endpoints/handlers/get: remove watchListEndpointRestrictions - - 14d1bbf36 2025-07-14T09:08:16+08:00 chore: maxPtr utility removal with ptr.To - - 6462ad918 2025-07-14T00:52:42+02:00 codegen tool: resolves GOBIN via `go env` - - 1073b3b90 2025-07-13T20:53:30Z Add unit tests for AddPod() - - fcb595a2d 2025-07-14T00:31:53+05:30 service-ip-alloc: delay ip processing on service recreate - - 8de14b526 2025-07-13T23:51:48+05:30 service-ip-alloc: make repair loop consumer clock interface - - e38361728 2025-07-13T12:42:45+02:00 Fix TestProgressNotify for etcd v3.6.2 - - e0f9914ef 2025-07-13T08:12:55+08:00 chore: replace int32Ptr usage with ptr.To - - cf4912eb4 2025-07-12T21:18:59Z chore(validation-gen): reorder imports - - 419e70b76 2025-07-12T21:18:59Z run update-codegen - - 4c8f489b8 2025-07-12T21:18:59Z add +k8s:neq tests - - fc1c832c4 2025-07-12T21:18:59Z feat: add +k8s:neq tag which enforces field is neq to a specified comparable value - - fb971325c 2025-07-12T21:18:59Z feat(validation-gen): add new test cases for item validation - - 5cc2721f6 2025-07-12T21:18:57Z feat(validation-gen): add k8s:item - - af05aa61d 2025-07-12T21:16:48Z feat: Add validation ratcheting for subfields tag - - daef13ecc 2025-07-12T21:16:48Z chore: improve error rendering and add unit tests for ErrorMatcher - - f40ee6f99 2025-07-12T21:16:48Z feat(validation-gen): add new test cases for validation of slices and maps - - b059bb551 2025-07-12T21:16:48Z feat(validation-gen): enhance validation functions for slices and maps - - 0b1fa64a9 2025-07-12T21:16:48Z refactor(validation-gen): streamline type validation logic - - 7ad89e199 2025-07-12T21:16:47Z feat(validation-gen): add FieldValidator - - ba45e37b2 2025-07-12T11:35:07+02:00 chore: removed boolPtrFn helpers with ptr package implementation - - 5971802fd 2025-07-12T16:44:39+08:00 chore: intPtr removal with ptr.To - - a091fa607 2025-07-11T22:58:00+02:00 Add apiserver_resource_size_estimate_bytes metric - - e6cf7dbf0 2025-07-11T22:19:55+02:00 Enable running cache inconsistency detection by default - - a06b3d356 2025-07-11T20:30:39+02:00 Bump dependencies, images and versions used to Go 1.24.5 and distroless iptables - - cba38b629 2025-07-11T20:20:48+02:00 DRA allocator: fix linter hint - - 5eab2b7a6 2025-07-11T10:59:20-07:00 Remove unuse runtimeCache parameter from stats.Provider - - 46e2c22fd 2025-07-11T23:06:44+05:30 kube-proxy: merge OnNodeAdd and OnNodeUpdate into OnNodeChange - - fa9e46694 2025-07-11T23:06:44+05:30 kube-proxy: merge NodeEligibleHandler with NodeManager - - c6735d9b3 2025-07-11T23:06:44+05:30 kube-proxy: merge NodePodCIDRHandler with NodeManager - - 45c355ca5 2025-07-11T19:48:11+03:00 Move unschedulablePods struct to a separate file - - bfeaae331 2025-07-11T18:25:46+02:00 Compact watch cache based on last observed etcd compaction - - c43104cbe 2025-07-11T21:48:52+05:30 kube-proxy: add NodeManager to manage life-cycle based on NodeIPs - - af7abde0e 2025-07-11T21:05:19+05:30 kube-proxy: add NodeTopologyConfig for tracking topology labels - - 98c4514ea 2025-07-11T10:32:01-05:00 add e2e_node tests for uncore alignment - - 70191dd21 2025-07-11T10:32:00-05:00 fix uncore cache alignment for odd integer cpus - - 65e0cff3c 2025-07-11T14:55:15+02:00 add Replicaset -> ReplicationController conversion test - - 9df4c35a6 2025-07-11T12:28:50Z Disable SchedulerAsyncPreemption feature correctly in integration tests - - 3636d5bd3 2025-07-11T08:23:44-04:00 Added NodeSelectors field to DriverDefinition - - 4f0d3eaa3 2025-07-11T18:59:14+08:00 enhance exec probe logging with pod and container context - - ffe908207 2025-07-11T08:34:39+02:00 DRA allocator: select tests based on supported features - - b1a35c640 2025-07-11T05:36:16Z Build etcd image v3.6.2 - - 7e37711d6 2025-07-10T23:20:27-05:00 kubelet: Add service account UID to token cache key for proper invalidation - - 45dfb4644 2025-07-10T23:20:23-05:00 Add TokenRequestServiceAccountUIDValidation feature gate with UID validation - - 237fbde8b 2025-07-10T22:30:21Z clean up e2e test and sorting code - - 4d2566eb5 2025-07-10T14:50:54-05:00 credentialprovider: wire in service account mode cache type - - 03db2278d 2025-07-10T14:50:51-05:00 kubelet: Add CacheType field to ServiceAccountTokenAttributes with validation - - ff4746af1 2025-07-10T19:19:13Z increase verbosity of kubelet preemption log - - f2de8897e 2025-07-10T12:13:40-07:00 Add metrics for mutation - - bfa7f38c6 2025-07-10T18:37:47Z fix TestPodResourceAllocationReset for windows - - e8b914c4b 2025-07-10T18:29:31Z address comments - - 6052c569d 2025-07-10T18:01:15Z prioritize resize requests by priorityClass and qos class - - c126870eb 2025-07-10T12:19:31-04:00 Bump RecoverVolumeExpansionFailure to GA - - 7b906f204 2025-07-10T17:34:21+02:00 DRA allocator: fork the code - - 5caf7bca1 2025-07-10T17:34:21+02:00 DRA allocator: refactor code - - 03e32bd26 2025-07-10T16:01:02+02:00 Expose compaction revision from compactor - - 5e3ea8e27 2025-07-10T16:00:12+02:00 Add test for compactor - - bbab59411 2025-07-10T15:30:56+02:00 local-up-cluster: stop running Docker - - f57662856 2025-07-10T15:30:56+02:00 local-up-cluster: store logs in artifacts directory - - 81b6e1d3a 2025-07-10T15:30:56+02:00 local-up-cluster: start containerd before Docker - - 27a77370d 2025-07-10T15:30:56+02:00 local-up-cluster: simplify installing packages - - ddda1dca3 2025-07-10T15:30:56+02:00 local-up-cluster.sh: add dry-run mode - - 0950b9ee5 2025-07-10T13:39:48+02:00 DRA allocator: export DeviceClassLister - - bc5aa94d8 2025-07-10T13:09:19+02:00 local-up-cluster.sh: allow configuring all ports - - a4b1d26b1 2025-07-10T13:09:18+02:00 local-up-cluster.sh: dump config on KUBE_VERBOSE >= 2 - - 5665bafaa 2025-07-09T23:12:11Z CHANGELOG: Update directory for v1.34.0-alpha.3 release - - 381b3f376 2025-07-09T21:44:08Z clear just the errors rather than the entire in-progress condition when a new resize is allocated - - b89ab301f 2025-07-09T20:50:07Z feedback round 2 - - 67aaa956d 2025-07-09T21:45:54+02:00 Update docs on shutdown and draining - - 7a6f6fdf7 2025-07-09T11:25:33-07:00 Delete unnecessary mutex - - 271233a62 2025-07-10T02:59:21+09:00 Prevent the failure of releasing the lock by updating the resource version in case of a resource conflict - - d9de590a2 2025-07-09T22:33:54+08:00 test: increase test coverage for pkg/kubelet/types - - 2dd07e924 2025-07-09T15:56:06+02:00 DRA E2E: ResourceSlice Controller test flake - - 26f54e5c0 2025-07-09T21:35:45+08:00 chore: replace int64ptr with ptr.To - - f2b24b984 2025-07-09T12:10:10Z Increase verbosity of frequently printed loglines in binder plugin - - 621482d68 2025-07-09T16:38:14+05:30 update pause version to 3.10.1 - - ce456c87f 2025-07-09T10:40:49+08:00 add SuccessCriteriaMet status for kubectl get job - - bb6bd5201 2025-07-08T23:49:34Z Add feature gate enable test for KubeletPodResourcesGet - - c92524377 2025-07-08T21:53:20Z address feedback - - c6fef9752 2025-07-08T13:25:26-07:00 fix: improve the pod level request validation (#132551) - - 89344dc23 2025-07-08T18:38:04Z feat(validation-gen): add k8s:enum validator - - 345641f10 2025-07-08T18:38:04Z feat(validation-gen): add Enum validator function - - adb71d041 2025-07-08T17:51:59Z Forcefully expire lease in integration test to fix flake - - 637bf55cb 2025-07-08T13:48:26-04:00 bump golang.org/x/vuln/cmd/govulncheck to v1.1.4 - - e0cc07af8 2025-07-08T17:43:52Z Promote PSI metrics feature to beta - - b46a124db 2025-07-08T17:14:49Z skip pending resize evaluation if sources aren't ready - - 35bf1522b 2025-07-08T17:14:48Z update allocation manager unit tests to cover push and retry of pending resizes - - e6d165b87 2025-07-08T17:14:47Z move resize allocation out of the sync loop - - 87fe2491a 2025-07-08T17:07:59Z add some additional helpers to kubelet status manager - - cb2baef91 2025-07-08T17:07:57Z move handlePodResourcesResize unit tests into allocation_manager_test - - 1a62ade74 2025-07-08T21:20:43+05:30 cleanup conntrack entries test for UDP service - - 8f92a8178 2025-07-08T17:18:34+02:00 node: e2e: podresources: add more e2e tests - - 380ed8d9b 2025-07-08T17:18:34+02:00 e2e: node: memory manager: build everywhere, run only on linux - - bc56d0e45 2025-07-08T17:18:34+02:00 podresources: list: use active pods in list - - 30a3bfdbc 2025-07-08T22:20:16+08:00 chore: remove residual uint64ptr usage with ptr package - - 006b2a3b5 2025-07-08T16:10:16+02:00 e2e: node: cpumanager: fix cpu quota non-regression tests - - 54f86a22e 2025-07-08T15:45:46+02:00 chore: removing redundant type conversion - - 25d9d8d9b 2025-07-08T15:48:35+03:00 refactor: use getLocalNode() to avoid code duplication - - bc9e8e1a9 2025-07-08T15:45:42+03:00 add a context argument to prePodCreationModificationFunc() - - 83584d13c 2025-07-08T20:27:34+08:00 fix: TestPatchResourceTimeout flaky test - - 994e106dc 2025-07-08T19:50:40+08:00 ci: update sample-apiserver version to v0.33.2 - - 3379d5ac4 2025-07-08T18:33:21+08:00 make sure all streams are created before starting demux websocket - - 1cec0aceb 2025-07-08T11:14:08+01:00 Short circuit CategorizeEndpoints when there are no endpoints - - c53b41e98 2025-07-08T11:41:36+02:00 Add testing compaction in storage List tests - - 1ac60e35e 2025-07-08T12:38:18+03:00 e2e test: Add a container_swap_limit_bytes metric - - bdd662f7c 2025-07-08T12:38:17+03:00 unit test: Add a container_swap_limit_bytes metric - - 341957a36 2025-07-08T12:36:59+03:00 Add a container_swap_limit_bytes metric - - c530b0225 2025-07-08T11:22:07+02:00 chore: depr. pointer pkg replacement for pkg/security and plugin/pkg - - dfe6a5c9c 2025-07-08T11:54:24+03:00 Clean up `unversioned_feature_list.yaml` file - - e909e0cf7 2025-07-08T09:48:56+02:00 chore: replacement of toPtr helper functions with ptr packge - - 841886df7 2025-07-08T08:08:30+02:00 Convert externaljwt from gogo to protoc - - 1b730abf8 2025-07-08T09:34:49+08:00 cleanup: use HandleErrorWithXXX instead of logger.Error where errors are intentionally ignored - - 075abb07a 2025-07-08T09:14:54+08:00 ci: redis removal for e2e test dependency simplicity - - 830a088d1 2025-07-08T09:03:38+08:00 chore: remove strPtr usage with ptr.To instead - - 838f3afc5 2025-07-07T17:37:36-07:00 storage/etcd3: add back missing errcheck - - 604cc2b51 2025-07-07T16:24:51-07:00 hack/update-openapi-spec.sh - - 5adc3bf08 2025-07-07T16:23:09-07:00 hack/update-codegen.sh - - ae7d637b8 2025-07-07T13:59:32-07:00 Delete unused ResizeContainerPatch function - - f1b35cae9 2025-07-07T13:58:40-07:00 Use MakeResizePatch instead of hand-written patch strings in resize E2Es - - 00c1c1a58 2025-07-07T13:57:48-07:00 Generate an E2E resize patch from original & desired ResizableContainerInfo - - cfd65c5f7 2025-07-07T21:28:54+02:00 chore: replacement of helper functions to ptr packge - - ff7c781e2 2025-07-07T18:34:01+02:00 Loop over all IP address from each node - - d9de37d93 2025-07-08T00:08:34+08:00 chore: typo invaILd occurrence replacement - - 1ae1964e8 2025-07-07T16:19:01+02:00 chore: depr. pointer pkg replacement for pkg/apis - - 311565141 2025-07-07T21:51:48+08:00 chore: remove uint64Ptr using ptr.To instead - - 38080c082 2025-07-07T13:30:48+02:00 kubeadm: use named ports in static pod manifests - - baf71997f 2025-07-07T13:22:36+02:00 chore: depr. pointer pkg replacement for pkg/controller - - 8abcdf088 2025-07-07T13:13:39+02:00 chore: depr. pointer pkg replacement for pkg/controller - - f966647b4 2025-07-07T12:54:05+02:00 chore: depr. pointer pkg replacement for pkg/apis - - 6cef8492e 2025-07-07T12:32:45+02:00 chore: depr. pointer pkg replacement for cli-runtime - - bc72fb81c 2025-07-07T12:25:55+02:00 chore: depr. pointer pkg replacement for test/e2e - - d193ffe57 2025-07-07T19:21:39+10:00 Use sets.Set instead of a local impl - - 277c665e8 2025-07-07T17:30:52+09:00 use early return - - 81be9065d 2025-07-07T17:17:11+09:00 improve the log message to clarify what users should do - - e74bbd5db 2025-07-06T22:32:21+02:00 chore: depr. pointer pkg replacement for test/e2e - - 2f7148782 2025-07-06T22:18:03+02:00 chore: depr. pointer pkg replacement for test/e2e and utils - - 1802c5565 2025-07-06T22:02:04+02:00 chore: depr. pointer pkg replacement for test integration - - b22ffdb48 2025-07-06T16:54:04+02:00 golangci-lint: exclude naming convention check for swagger docs - - 0e8424fcf 2025-07-06T11:27:16+02:00 chore: depr. pointer pkg replacement for the e2e_node - - bb24afe58 2025-07-06T11:20:53+02:00 chore: depr. pointer pkg replacement for component-base - - bd8d5f979 2025-07-06T11:14:15+02:00 chore: depr. pointer pkg replacement for controller-manager - - fe61e825e 2025-07-06T11:09:16+02:00 chore: second depr. pointer pkg replacement for apiserver - - 4a61b8170 2025-07-06T10:58:23+02:00 chore: first depr. pointer pkg replacement for apiserver - - 4625908a6 2025-07-06T15:58:06+08:00 remove unused file - - 995a7872c 2025-07-06T11:34:27+08:00 chore: remove utilpointer usage in pkg/api/pod - - ebae41933 2025-07-05T17:14:21-07:00 feat: add PreBindPreFlight and implement in in-tree plugins - - c5b0c9fdc 2025-07-05T12:23:02+02:00 chore: depr. pointer pkg replacement for psa policy - - 88d885e40 2025-07-05T12:13:28+02:00 chore: depr. pointer pkg replacement for psa admissiontest - - dc947510d 2025-07-05T12:09:17+02:00 chore: depr. pointer pkg replacement for psa tests - - 35e118a47 2025-07-05T09:51:57+02:00 chore: depr. pointer pkg replacement for apiext. apiservers validations - - 4a205cc7f 2025-07-05T09:50:03+02:00 chore: depr. pointer pkg replacement for apiext. pkg/cntroller - - 107c58eee 2025-07-05T09:47:37+02:00 chore: depr. pointer pkg replacement for apiextensions in general - - b8ec161d7 2025-07-05T09:39:02+02:00 chore: depr. pointer pkg replacement for apiext. integration - - ca1d7fff7 2025-07-05T11:45:52+08:00 chore: remove utilpointer usage in pkg/apis/autoscaling - - 0ad351281 2025-07-05T10:03:30+09:00 Cleanup duplicate function to get port number from named port - - 1ac5f661e 2025-07-04T11:10:55+01:00 Don't log irrelevant zone hints message on no endpoints - - 27812e44b 2025-07-04T10:47:12+02:00 chore: depr. pointer pkg replacement for apiext. pkg/registry - - b72ab8a4e 2025-07-04T09:51:22+02:00 chore: depr. pointer pkg replacement for the cloud-provider - - b464bbeb8 2025-07-04T08:55:57+02:00 Remove gogo-protobuf from CRI - - ce7b3694f 2025-07-04T12:54:52+08:00 chore: remove utilpointer usage in package test/integration/service/loadbancer_test.go - - 9016f9cb1 2025-07-04T09:29:47+08:00 chore: remove utilpointer usage in conversion package - - 90bbce56b 2025-07-03T21:14:44+03:00 PriorityMemoryEvictionOrdering: allocate more memory when swap is provisioned - - 25498cd34 2025-07-03T21:14:43+03:00 Eviction tests: small refactor - - 43b22a243 2025-07-03T05:07:24-07:00 Apply fix to namespace deletion test (#132691) - - 0766a3c6b 2025-07-03T11:58:42+02:00 chore: depr. pointer pkg replacement for the kube-aggregator apiregistration - - 6c3146e35 2025-07-03T11:34:13+02:00 chore: depr. pointer pkg replacement for the csr - - 934555227 2025-07-03T11:27:00+02:00 chore: depr. pointer pkg replacement for the reflactor - - ebea328f1 2025-07-03T10:46:45+02:00 Fix volume limit e2e test cleanup - - 38bf21327 2025-07-03T08:37:23+01:00 podtopologylabels: update topology.k8s.io->topology.kubernetes.io - - 2e966244e 2025-07-03T08:20:39+02:00 DRA resourceslice controller: fix recreation after quick delete - - fa3131700 2025-07-03T14:15:14+08:00 Remove unused PodIndexLabel feature reference - - 8c6c7df73 2025-07-03T09:57:15+08:00 remove apiserver_storage_objects metrics after crd deleted - - a7e8a505c 2025-07-02T18:53:24-07:00 Improve ignore-not-found behavior (#132542) - - 1c1f00a5f 2025-07-02T11:01:56-07:00 fix: add RV check on GC delete calls - - 84f6d742c 2025-07-02T09:50:33-07:00 Make dynamic and metadata clients plumb DeleteOptions - - ad0b2bf4f 2025-07-02T18:11:46+02:00 DRA E2E: serialize costly test - - 33cd2e1ba 2025-07-02T08:55:24-07:00 Fix AuthInfo godoc for Token / TokenFile precedence (#132659) - - c6f87f6e6 2025-07-02T10:17:26-04:00 Fix offline expansion tests for case where no node expansion tests is required - - b44b0fbf1 2025-07-02T08:00:43-04:00 Update github.com/emicklei/go-restful/v3 to v3.12.2 - - 58e620cc4 2025-07-02T07:37:06-04:00 Bump go.yaml.in/yaml/v3 to v3.0.4 - - 00f8cbae6 2025-07-02T07:32:24-04:00 Bump sigs.k8s.io/json to latest - no code changes - - 22138ef55 2025-07-02T12:57:33+02:00 Add DNS e2e test of NameIsDNSLabel validated Service names - - 97c1974e9 2025-07-02T12:57:32+02:00 Add integration test for RelaxedServiceNameValidation. - - 19e7e38af 2025-07-02T12:57:32+02:00 Add unit test for Ingress service ref relaxed validation - - 37a90b7c2 2025-07-02T12:57:32+02:00 Add unit test for Service relaxed validation - - b430159c8 2025-07-02T12:57:28+02:00 Allow Ingress service refs to be validated with apimachineryvalidation.NameIsDNSLabel - - 487eb8a9e 2025-07-02T12:55:53+02:00 Allow Service names to be validated with apimachineryvalidation.NameIsDNSLabel - - 9043afae6 2025-07-02T08:40:37+02:00 kubectl: Cache Verifier.HasSupport calls - - 179c4398f 2025-07-01T23:17:51-05:00 use defaultImage per OS - - 998776d80 2025-07-01T23:06:05-05:00 remove breaking test - - a17b0d7f6 2025-07-02T12:39:38+09:00 gofmt - - 1514568dd 2025-07-01T22:12:26-04:00 rename sortedfeatures -> sorted - - 9e1a21816 2025-07-01T22:03:22-04:00 update README - - 5cebe66b6 2025-07-01T21:57:50-04:00 update log line - - dcbed2fbd 2025-07-02T09:37:14+08:00 Graduate PodLifecycleSleepAction to GA - - 977c67073 2025-07-01T18:05:26-07:00 Add unit tests for minReady new behaviour - - 4b99dc5f1 2025-07-01T12:26:08-07:00 document hostnetwork <> port implications - - 952d2727a 2025-07-01T11:47:29-07:00 Add OrderedNamespaceDeletion to conformance. - - 12330a6c4 2025-07-01T12:49:16-04:00 Drop BoundedFrequencyRunner from pkg/util/async - - 5d4a85f9f 2025-07-01T16:13:56Z Enable versioned validation fuzz testing for certificates v1/v1alpha1/v1beta1 group - - 0fd4a0acc 2025-07-01T16:13:56Z CSR: Add declarative validation test suite - - 5db205668 2025-07-01T16:13:56Z CSR: Enable declarative validation - - eecba765d 2025-07-01T16:13:56Z Enable validation-gen on certificates/v1,v1alpha1&v1beta1 - - ec6471f63 2025-07-01T15:56:40Z Remove gnostic-models gopkg.in/yaml.v3 unwanted dependency - - d04ee27c9 2025-07-01T15:23:58Z Update vendor - - b41d375b8 2025-07-01T15:21:22Z pin kube-openapi to v0.0.0-20250628140032-d90c4fd18f59 - - 6d5e0bf2a 2025-07-01T16:59:19+02:00 review remarks - - 95b1151d2 2025-07-01T23:57:49+09:00 use format specifier - - 459188ce2 2025-07-01T08:54:14-04:00 Port BoundedFrequencyRunner from flowcontrol.RateLimiter to clock.Clock - - eae17c21b 2025-07-01T08:54:14-04:00 Change how BoundedFrequencyRunner retries work - - c16ee887e 2025-07-01T08:54:14-04:00 Remove burst syncs from BoundedFrequencyRunner - - 0298e04ea 2025-07-01T08:54:14-04:00 Updates to BoundedFrequencyRunner - - 6da9d363f 2025-07-01T08:53:54-04:00 Copy BoundedFrequencyRunner to kube-proxy - - 799aa8b2a 2025-07-01T13:04:40+02:00 Graduate streaming list encoding feature gates - - 5bae9fa89 2025-07-01T11:41:47+02:00 Graduate ConsistentListFromCache to GA - - d4e49b2ee 2025-07-01T02:25:37-07:00 Ensure Loadbalancer internal port is set to container port from endpointslice if the targetPort is not specified in service info creation. - - 6a25bdaac 2025-07-01T11:33:52+08:00 kubeadm: fix missing log of health check - - 764a8bc8b 2025-07-01T09:10:58+08:00 chore: remove utilpointer usage in package pkg/apis/admissionregistration - - a55318fe1 2025-06-30T23:11:49Z fix: versioned validation test avoid incorrect conversion - - 4c09aa907 2025-06-30T22:53:40Z review: feedback - - 776382daa 2025-06-30T21:19:21Z review: assert - - 43f6bd45f 2025-06-30T21:06:47Z review: assert - - fa87098ae 2025-06-30T17:00:27-04:00 fix: kubelet CRI portforward concurrent map write on error - - a0ea2569a 2025-06-30T20:50:51+08:00 chore: remove utilpointer usage in package staging/src/k8s.io/apiserver/pkg/registry/rest/delete - - 7236f3fc2 2025-06-30T12:35:58Z graduate APIServerTracing featuregate to GA - - 75fc2b1cf 2025-06-30T12:31:23Z promote TracingConfiguration to v1 - - a8068e27b 2025-06-30T21:31:21+09:00 scheduler_perf: Fix version emulation for empty featureGates map - - 5a20c38da 2025-06-30T12:30:47Z remove usage of KubeletTracing featuregate from kubelet - - 7faf797a9 2025-06-30T12:30:40Z promote KubeletTracing featuregate to GA - - d28791fa6 2025-06-30T20:59:13+09:00 Remove unused sysfsPath's methods - - 6e5c99dd0 2025-06-30T13:18:53+02:00 Review remarks - - ee8c265d3 2025-06-30T10:06:22Z Move Code and Status from pkg/scheduler/framework to k8s.io/kube-scheduler/framework - - 08dd9c47b 2025-06-30T18:27:55+09:00 improve the log message to clarify the cause of the failure - - a6e2cd4e8 2025-06-30T17:52:24+09:00 scheduler_perf: add logs to report the failure of measuring SchedulingThroughput - - 7e816ca9b 2025-06-30T16:14:50+09:00 Commented out for unused sysfspath methods - - 2bc45ca46 2025-06-30T16:14:44+09:00 Make test only helpers private (sysfspath methods, touchFile, createSymlink) - - 94973ba3f 2025-06-30T16:14:33+09:00 Fix typo: s/smock/mock/g - - ac86e67b7 2025-06-30T08:07:21+02:00 Commonize filtering of Pods by Owner with all orphans in namespace - - ca314b9f5 2025-06-30T07:58:04+02:00 Fix validation for Job with suspend=true,completions=0 to set Complete condition - - 1134220e0 2025-06-28T14:06:34+02:00 Add RelaxedServiceNameValidation feature gate - - f644e35d1 2025-06-28T11:21:54+02:00 kubeadm: cleanup after WaitForAllControlPlaneComponents GA - - cfe860450 2025-06-28T11:16:01+02:00 kubeadm: graduate WaitForAllControlPlaneComponents to GA - - f437aa4aa 2025-06-28T11:00:23+09:00 scheduler_perf: Set version emulation only when QueueingHints is disabled - - b2f27c064 2025-06-27T16:32:29-07:00 fix: Truncate too long Deployment name in RS name (#132560) - - d67e7937e 2025-06-27T17:57:16-04:00 Remove recovery related featuregates - - fa6f27c8f 2025-06-27T17:52:46-04:00 Add extra validations for newer resizing related fields - - 00dd610c9 2025-06-27T21:15:50+02:00 DRA E2E: run some tests without feature label - - f93b4408a 2025-06-27T15:02:34-04:00 Drop test that checks openAPI resource name since we currently don't guarantee name stability in the API - - 3eefb05a2 2025-06-27T11:49:41-07:00 Fix gRPC listener error message in kubeletplugin and some minor renaming - - e54e01e0a 2025-06-27T11:38:12-07:00 Enhance help text for the 'top' command - - 7d5ab7562 2025-06-27T14:30:58-04:00 Re-generate applyconfigurations - - 9af684ae0 2025-06-27T14:30:57-04:00 Applyconfig-gen: Only the root type is an applyconfiguration - - d50e1a684 2025-06-27T11:13:50-04:00 Ensure all the files have the updated sorting - - f2d8b7ec2 2025-06-27T11:05:13-04:00 Add linter to report on unsorted feature gates - - efcb03759 2025-06-27T16:10:38+02:00 E2E framework: sort tests in JUnit report - - dfd34a5b1 2025-06-27T16:30:51+08:00 fix pod template spec validation missing in sts - - a57f15e08 2025-06-27T10:06:50+02:00 DRA kubelet: remove v1alpha4 - - 005cef332 2025-06-27T09:30:28+02:00 DRA kubelet: API clarification - - f1845218e 2025-06-26T23:21:18-05:00 fixup! DRA: fix deleting orphaned ResourceClaim on startup - - 585ed0a5c 2025-06-26T22:00:41-04:00 [client-go #1415] Use transformer from provided store within internal stores in reflector to limit memory usage bursts - - 8632257c9 2025-06-26T21:24:43Z Cleanup: Remove redundant detail messages in field.Required - - e82d4f8e5 2025-06-26T18:25:42Z review: feedback - - 5cca03792 2025-06-27T00:49:02+09:00 resolve linter check - - ce86fca8c 2025-06-26T15:10:42Z Add warnings for use of Alpha features with Emulated Version Warn for both api and feature flag use of alpha features with emulated versions. This is an unsupported use case and users may run into issues. - - 00d375050 2025-06-26T08:06:29-07:00 Move ClusterEvent type to staging repo, leaving some functions (that contain logic internal to scheduler) in kubernetes/kubernetes (#132190) - - 74af3ac8a 2025-06-26T23:49:34+09:00 Revert "pop respects the context" - - 2dcce9333 2025-06-26T23:49:25+09:00 Revert "modify tests" - - 31667cc74 2025-06-26T09:15:02-04:00 Avoid killing kops etcd-manager - - 6d6a749c6 2025-06-26T14:31:03+02:00 DRA kubelet: add dra_resource_claims_in_use gauge vector - - 75432a141 2025-06-26T14:15:43+02:00 component-base metrics: allow usage of Prometheus types in tests - - 1639b0908 2025-06-26T11:09:24+02:00 Add benchmark for SizeBasedListCostEstimate feature - - c75d425ae 2025-06-26T07:44:13Z CHANGELOG: Update directory for v1.34.0-alpha.2 release - - 292679a28 2025-06-26T09:30:48+02:00 Handle consistent LIST in watch cache to avoid incorrect semantics while setting ResourceVersion on options - - c6c15bbe4 2025-06-26T00:11:20-04:00 bug: Remove duplicate DaemonSet update validations - - 39dda2b88 2025-06-26T00:59:34Z tests: runtime units - - 8bd8c1431 2025-06-25T22:00:40Z tests: add more units - - f9a5aec31 2025-06-25T23:59:44+05:30 Added unit tests - - 5390f7536 2025-06-25T23:59:26+05:30 Added podutil.HasAPIObjectReference to deny admission for static pods referencing API objects - - 8b2eb9090 2025-06-25T17:39:14Z chore: Remove vet target and associated script from Makefile and hack directory - - 7d85134ca 2025-06-25T17:18:07Z improve unit test coverage for pod observedGeneration - - 1a59c250e 2025-06-25T16:38:50Z feat: make CLE timers configurable - - ef117edf3 2025-06-25T11:11:43-05:00 DRA: fix deleting orphaned ResourceClaim on startup - - c5b4b133c 2025-06-25T11:42:12-04:00 switch to latest sigs.k8s.io/yaml v1.5.0 (run update-gofmt.sh as well) - - e2c6b7fdf 2025-06-25T17:25:58+02:00 Override getKeys when cacher is enabled - - 7cb241799 2025-06-25T17:25:58+02:00 Run background cleanup goroutine - - ec78b8305 2025-06-25T17:25:56+02:00 Estimate average size of objects in etcd and plug it into request cost estimator - - 190c8c7ab 2025-06-25T11:17:20-04:00 Use per-policy marker names for VAP integration tests. - - 6795d5366 2025-06-25T22:44:47+08:00 feature(kubectl): support mem-percent,cpu-value,cpu-average-value,mem-value,mem-average-value flag to kubectl autoscale - - 9de075def 2025-06-25T13:21:46+02:00 replacing deprecated pointer pkg with newer package version - - b8b398487 2025-06-25T04:04:29-07:00 client-go/reflector: stop exposing UseWatchList (#132453) - - 0028ea8e9 2025-06-25T08:51:29+02:00 Improve containers lifecycle test output parsing - - 7e0d71fc1 2025-06-25T08:51:20+02:00 apiserver/storage/cacher/listwatcher: error when the WatchList FG is disabled - - ec6ea2213 2025-06-25T13:39:12+08:00 test: code coverage increase for kubelet_client - - cb4014fb7 2025-06-24T22:25:41-04:00 cleanup: Migrate more usages of deprecated function ExtractCommentTags - - b50d50817 2025-06-25T08:23:53+08:00 bugfix(hpa): introduce buildQuantity helper for consistent resource quantity creation - - cbba973b6 2025-06-24T17:21:57-07:00 Fixing go-vet finding "call of reflect.DeepEqual copies lock value" by just asserting on the basic fields that should be reset when ClearState() is called - - 35ecb00f1 2025-06-24T22:19:35Z fix: Add wait for cache sync for customresourcediscovery tests - - d6d186ece 2025-06-24T20:56:44+02:00 Activly poll for namespace termination instead of sleeping - - e1daa69de 2025-06-24T14:52:37-04:00 Add printer column validation tests - - 369e6a25a 2025-06-24T14:52:27-04:00 Introduce k8s-short-name and k8s-long-name to the OpenAPI formats supported by CRDs - - 6f1295ae9 2025-06-24T11:04:25-07:00 fix: prevent SSA from creating CR while CRD terminating - - 3b0fd3281 2025-06-24T15:46:06+02:00 e2e: serial: cpumanager: continue on failure - - f76e1381d 2025-06-24T15:46:01+02:00 e2e: node: fix quota disablement testcases - - dc323756c 2025-06-24T09:24:27-04:00 Bump to latest kube-openapi - - d180fe28a 2025-06-24T09:23:39-04:00 Add json-patch v4 compatibility test - - 2ca4ffe65 2025-06-24T09:18:04-04:00 Add evanphx/json-patch/v5 to unwanted dependencies - - 5a7e04b6c 2025-06-24T21:12:56+08:00 feat: optimize ListAll and ListAllByNamespace to return directly when nothing to select - - ae13d1019 2025-06-24T12:41:42Z KEP-5229: Add SchedulerAsyncAPICalls feature gate - - dce69afad 2025-06-24T11:39:44+02:00 apiserver/cacher: properly wire listwatch options to the listwatcher - - 0276769c2 2025-06-24T11:07:47+02:00 kubectl: avoid logging during init - - 6040344a6 2025-06-24T10:42:46+02:00 kubelet: DRA: fix TestRegistrationHandler - - cc7893a42 2025-06-24T10:42:45+02:00 kubelet: DRA: fix unit test failure - - cf544da6f 2025-06-24T10:42:45+02:00 e2e_node: DRA: add tests for different socket setups - - 7f6389e77 2025-06-24T10:42:45+02:00 e2e_node: DRA: pass socket path as a parameter - - 3ae99f254 2025-06-24T10:42:45+02:00 kubelet: DRA: fix test failure on Windows - - c90c2e0d4 2025-06-24T10:42:45+02:00 kubelet: DRA: fix linter warnings - - 165bb1da5 2025-06-24T10:42:45+02:00 DRA kubelet: use TimedWorkersQueue - - 4ee7374b2 2025-06-24T10:42:41+02:00 DRA kubelet: add connection monitoring - - f927cd010 2025-06-24T09:05:43+02:00 DRA kubelet: simplify plugin creation and connection handling - - cfeab03ad 2025-06-24T11:50:18+08:00 remove kvh.exec - - 75862f3f4 2025-06-23T17:00:31-07:00 show namespace on delete (#126619) - - 56d97283a 2025-06-23T21:37:00Z fix: Improve error messaging on updating a deleted object - - fd8bf1c82 2025-06-23T14:58:57-04:00 e2e: retry getting status on restart policy tests - - c5f061e0d 2025-06-23T17:57:12Z Fix pod and container level swap metrics for CRI - - e1d74f1d3 2025-06-23T23:00:38+05:30 Update etcd image revision to 3.6.1-1 - - 7e3945808 2025-06-23T18:12:13+05:30 nftables: remove filter-output-post-dnat chain - - 91f2256b3 2025-06-23T18:12:13+05:30 update filter chains and priority - - 72305f82f 2025-06-23T13:06:19+02:00 Move UnsafeCorruptObjectDeletion outside of etcd3.New function - - 59dd2bd60 2025-06-23T17:57:59+08:00 ci: update test image base: nginx, nginx-new - - af89044a7 2025-06-23T00:37:28+05:30 conntrack: clean stale entries on endpoint port change - - 861e7b8fa 2025-06-20T12:30:51-07:00 fix unit test flake for authn config on windows - - 2fd93c089 2025-06-20T22:29:13+08:00 fix: data race for patchResource func - - ccdef28ac 2025-06-20T10:33:43+02:00 fixing large resourceversion and limit for storages - - fe8437745 2025-06-20T08:28:04+02:00 e2e/watchlist: new test for checking metadata informer - - d6ba9e1b9 2025-06-20T07:07:42+02:00 replacing depr. pointer pkg with new ptr pkg on src/apimachinery - - db32c4cf7 2025-06-20T09:11:35+10:00 fixing syntax issue for etcd builds - - 8454093f0 2025-06-19T15:19:00-05:00 DRA: add e2e test with initContainer using external claim - - 138e363e4 2025-06-19T11:48:15-04:00 cleanup shellcheck for temporary HOME directory - - 66c611125 2025-06-19T16:32:20+08:00 Add namespace-aware orphan pod indexing - - 5e54df3e7 2025-06-19T15:32:23+08:00 Fix [Failing test] [sig-node] [Feature:GPUDevicePlugin] [Serial]-related tests - - 280cecb8f 2025-06-19T17:07:32+10:00 fixing location to ensure the cp commands dont fail - - d2945a21f 2025-06-19T12:21:44+10:00 bumping revision - - fa1832484 2025-06-19T11:48:23+10:00 handling the etcd 3.6+ build directory location change - - e68d60134 2025-06-19T10:11:17+09:00 Don't panic in case of an unknown API error code - - 4ca91a030 2025-06-19T10:11:17+09:00 WIP: Fix tests - - 2b2c9adef 2025-06-19T10:11:16+09:00 Nicer value rendering in API errors - - cfff359b4 2025-06-18T18:01:28-04:00 fix for gimme when $HOME is not writable - - 6a654e5be 2025-06-18T21:15:30Z Deprecate StreamingConnectionIdleTimeout field, that is not being used for a long time - - b8cd05881 2025-06-18T14:13:47-07:00 Address PR comments - - 6f97f5bbf 2025-06-18T14:02:57-07:00 Use Mock CSI Driver for MutableCSINodeAllocatableCount storage e2e test (#132373) - - 176095ac3 2025-06-18T13:57:41-07:00 [KEP-5100] WinDSR feature gate to GA - - 64c44e1fa 2025-06-18T16:12:24-04:00 Test that generated applyconfigs are a runtime.ApplyConfig - - a5d42f569 2025-06-18T16:12:24-04:00 Re-Generate applyconfigs - - d5527b519 2025-06-18T16:12:24-04:00 Update applyconfiguration-gen so acs implement runtime.applyconfiguration - - 3fe4ea550 2025-06-18T16:12:24-04:00 Add an interface that all applyconfigs implement - - b0b52f4fb 2025-06-18T18:59:10Z CHANGELOG: Update directory for v1.30.14 release - - 2bc98f123 2025-06-18T18:36:13Z CHANGELOG: Update directory for v1.31.10 release - - 20e9f160c 2025-06-18T18:11:53Z CHANGELOG: Update directory for v1.32.6 release - - 9e126a377 2025-06-18T17:54:50Z CHANGELOG: Update directory for v1.33.2 release - - df32f10e0 2025-06-19T01:23:10+08:00 apimachinery/pkg/util/errors: deprecated MessageCountMap - - de2f22ee8 2025-06-18T17:43:58+02:00 e2e/watchlist: intro verifyStoreFor - - 017c9b94d 2025-06-18T17:34:05+02:00 e2e/watchlist: rename toSecretPointerSlice - - caa64afd0 2025-06-18T22:38:21+09:00 merge constants.go into attribute.go - - 73d65f830 2025-06-18T21:30:52+09:00 Put _linux suffix for linux specific go files - - 88b34ea1f 2025-06-18T21:28:41+09:00 Move bdfRegexp from global constant to local variable - - fc854a9a8 2025-06-18T21:26:15+09:00 Introduce DeviceAttribute{Name, Value} and change return type of 'GetPCIeRootAttributeByPCIBusID' with it - - 8ed8217e9 2025-06-18T21:26:13+09:00 Moved device attribute constants from api to deviceattribute package - - f7461a12d 2025-06-18T21:04:16+09:00 Revert "Add StandardDeviceAttributes and StandardPCIDeviceAttributes helper functions" - - 6b9ac7c51 2025-06-18T12:32:04+02:00 cluster/gce: rm KUBE_LIST_FROM_CACHE_INCONSISTENCY_DETECTOR - - 512563e7b 2025-06-18T14:22:26+05:30 pkg/proxy/conntrack: refactor - - 91b4816c2 2025-06-18T15:28:12+08:00 Optimize job controller performance: reduce work duration time & minimize cache locking - - 18dd1daae 2025-06-17T12:01:02-07:00 Add Windows Server 2025 (ltsc2025) to BASEIMAGEs (#132235) - - 44b4682a3 2025-06-17T22:38:10+05:30 Use jq docker image for pause windows build - - 3827d3bc4 2025-06-17T11:00:27-04:00 Drop usage of forked copies of goyaml.v2 and goyaml.v3 - - 2869b6f42 2025-06-17T23:04:43+09:00 Add StandardDeviceAttributes and StandardPCIDeviceAttributes helper functions - - a8ab9eb5f 2025-06-17T22:58:17+09:00 Simplify the implementation: just provide GetPCIeRootAttributeByPCIBusID - - d390902b9 2025-06-17T22:30:45+09:00 Verify scheduler resource metrics account for Pod Level Resources - - 32fcaf140 2025-06-17T15:05:46+02:00 client-go/util/consistencydetector: move IsDataConsistencyDetectionForWatchListEnabled - - 72654620a 2025-06-17T13:49:58+02:00 removing WaitIntervalString from iptables - - bad493904 2025-06-17T13:37:57+02:00 client-go/util/consistencydetector: remove CheckListFromCacheDataConsistencyIfRequested - - 15ca38b52 2025-06-17T12:01:02+02:00 apimachinery/meta/types.go: remove InitialEventsListBlueprintAnnotationKey const - - 690790257 2025-06-17T11:47:17+02:00 Add test verifying KUBECTL_KUBERC can be turned on and off - - 45449a78d 2025-06-17T11:14:47+02:00 Removing setting KUBECTL_KUBERC env var, now that it's on by default - - 3f32edeac 2025-06-17T15:45:44+08:00 chore: Remove the dependency of the volume manager on the container runtime. - - 3dc1810bb 2025-06-17T15:26:01+08:00 fix: failed unit test. - - b8a2127d2 2025-06-17T05:53:18Z Add random interval to nodeStatusReport interval every time after an actual node status change update or restart - - fbf4b47d1 2025-06-17T13:30:45+08:00 chore: clean up probemanager for shutdownnamager. - - 3fa23d06a 2025-06-17T06:39:33+02:00 Adjusting AdminAccess Type for API v1beta1 - - 2a5e4d558 2025-06-17T03:35:12Z add script for verifying dead code elimination - - 891e7fec6 2025-06-17T09:30:41+08:00 add seperate health check/probe for multi etcd override servers - grouping health checks for exclusion purposes & add exclude integration test - - 28573e373 2025-06-16T15:34:06-07:00 Add error prefixes for authn config load or validation failures - - 4cb6d3d77 2025-06-17T00:10:48+02:00 Validate requests sent to etcd in TestList "test List with limit" scenario - - 03afe6471 2025-06-16T17:10:42-04:00 Add a replacement for cmp.Diff using json+go-difflib - - 32ec4e68c 2025-06-16T21:51:24+02:00 adding omitempty tag and opt tag - - e654deba6 2025-06-16T18:44:59Z CHANGELOG: Update directory for v1.34.0-alpha.1 release - - f4a458625 2025-06-16T17:36:23Z fix APIServerTracing test data race - - 2004ee50f 2025-06-16T16:08:46Z Fix -Consistent paginated lists serve from cache - - bccc9fe47 2025-06-16T16:26:03+02:00 KEP-3939: Job Pod Replacement Policy; promote to GA - - fc198b92c 2025-06-16T07:02:59-07:00 apiserver/handlers/watch: stop encoding initialEventsListBlueprint (#132326) - - 854499f98 2025-06-16T20:51:17+08:00 clean: use correct pod template - - fae2fdd05 2025-06-15T23:49:43-05:00 DRA: wrap e2e finalizer update in retry - - 7a95f3e47 2025-06-16T00:11:48+09:00 Fix NetworkPolicy podSelector comments - - 233a0aeed 2025-06-15T13:04:25+02:00 DRA E2E: label tests which need a certain minimum kubelet, II - - 2cd5dbbda 2025-06-15T15:50:22+09:00 modify tests - - 59f0ab97c 2025-06-15T15:50:02+09:00 Add boilerplate header to go files - - 1c33d9876 2025-06-15T15:31:34+09:00 pop respects the context - - f67d30b35 2025-06-15T15:31:33+09:00 handle context in process loop - - 384240b4d 2025-06-14T17:50:38-07:00 Use "Invalid" errors rather than "TypeInvalid" - - bdfa8839b 2025-06-14T18:39:15+02:00 calculateStatus should use the same now time point for each pod - - ce44bcdf5 2025-06-14T16:10:04Z conformance servicecidr read status endpoint - - c2988884f 2025-06-15T00:01:29+08:00 fix kubeadm e2e tests - - cb26d065d 2025-06-14T15:57:48+09:00 Validate PCI Address (domain is 16 bits, bus is 8 bits, device is 5 bits, function is 3 bits) - - 752a04369 2025-06-14T15:57:46+09:00 fix lint: apply De Morgan's laws to simplify conditionals - - 76ef6a388 2025-06-14T14:45:29+08:00 fix kubeadm e2e tests - - 79601d135 2025-06-13T13:50:03-07:00 Fix CRI fake_runtime RemovePodSandbox - - 666f38f41 2025-06-14T04:19:00+09:00 DRA: Introduce a helper function producing standardized device attributes for DRA drivers - - 7a3af908c 2025-06-13T17:54:36Z add securitycontext OWNERS to be SIG Node as the package is mostly used and contributed by SIG Node - - 7f1dde2a0 2025-06-13T17:23:16+02:00 test/apimachinery/watchlist: properly wire modified config to informer for fallback case - - 40c718864 2025-06-13T15:28:55+02:00 chore(apiserver): avoid using html template which disables dce - - 6a3797684 2025-06-13T14:15:51+02:00 client-go/rest: rm watchlist - - 4372c59eb 2025-06-13T13:35:00+02:00 update go version for publishing bot rules - - e09b042d3 2025-06-13T16:28:35+05:30 Bump etcd to v3.6.1 - - 901441c66 2025-06-13T11:15:35+08:00 Promote SeparateTaintEvictionController to stable - - 85bc3cb09 2025-06-13T10:58:37+08:00 Remove GetExec method from VolumeHost - - 9251b2a7a 2025-06-12T16:02:19-04:00 Expand webhook test to check rejection metrics - - f8b4ea50e 2025-06-12T19:26:26+02:00 ./hack/update-internal-modules.sh - - 71b2f32d7 2025-06-12T18:16:04+02:00 DRA E2E: label tests which need a certain minimum kubelet - - 3908550c0 2025-06-12T11:20:39-04:00 Update to latest github.com/modern-go/reflect2 - - d8bfafe07 2025-06-12T16:02:10+02:00 test/apimachinery/watchlist: prove typed client's List method not streaming - - 601065a7c 2025-06-12T09:44:41-04:00 bug: Fix misleading response codes in admission control metrics - - 5882df8be 2025-06-12T21:43:03+08:00 promote env test to conformance - - 69a5bda83 2025-06-12T18:15:11+05:30 Bump base image used in nonewprivs to alpine:3.22 - - 04110fce1 2025-06-12T21:29:54+09:00 Correct error message to print `ResetConfigurationKind` - - 3443c1115 2025-06-12T13:54:57+02:00 make update - - 798c6ebab 2025-06-12T13:41:50+02:00 client-gen/code-generator: remove watchList - - db2555628 2025-06-12T07:35:07-04:00 Fix: HPA suppresses FailedRescale event on successful conflict retry - - 2f943293e 2025-06-12T13:13:02+02:00 client-go/gentype: remove watchlist - - f0dde3823 2025-06-12T17:29:17+08:00 Remove pluginName param from GetMounter and GetExec - - fb611f4c9 2025-06-12T11:27:51+03:00 kubectl delete: Update interactive delete to break on new line - - d46e13b9c 2025-06-12T16:06:50+08:00 change the command of the terminated container - - 226c0d109 2025-06-12T11:49:12+05:30 Bump ipc-utils base image to alpine:3.22 - - e75ccce83 2025-06-12T10:48:53+08:00 feat: optimize label selector match performance - - ac467d3ae 2025-06-11T23:44:52Z add ratcheting testcase for validateFalse tag - - 9384285c6 2025-06-11T23:44:52Z add ratcheting testcase for minimum tag - - 1574001a1 2025-06-11T23:44:52Z run update-codegen.sh - - f574115f1 2025-06-11T23:44:52Z feat: add default ratcheting support - - e9eabb200 2025-06-11T23:44:52Z feat(validation-gen): Refactor type handling and introduce utility functions - - 03c6e15f8 2025-06-11T16:35:44-07:00 bump to alpine 3.22 and bump apparmor-loader to 1.6 - - b86b4632b 2025-06-11T15:35:56-07:00 disable selinux relabeling when mounting sourcedir to shellcheck - - dc3836c49 2025-06-11T15:31:37-07:00 Remove deprecated encryption config controller metrics - - 5a2844a76 2025-06-11T16:46:03-04:00 Update to etcd v3.6.1 in vendor/ - - a9108e8f5 2025-06-11T15:52:40-04:00 Adding `grpcnotrace` tag for production (non-debug) builds - - 11abb0042 2025-06-11T17:14:39+02:00 Fix outdated links in VolumeSource godocs - - 4b2fe2a54 2025-06-11T22:35:08+08:00 pkg/kubeapiserver: use utils/ptr package instead of utils/pointer - - 69eddde89 2025-06-11T21:49:38+08:00 using finalizer - - 57d55fbb1 2025-06-11T21:29:24+09:00 test: Add test case for createNodeOp - - 1d69a2fbc 2025-06-11T12:04:53+02:00 ./hack/update-vendor.sh - - edadfee47 2025-06-11T12:04:48+02:00 test/apimachinery/watchlist: prove dynamic client's List method not streaming - - 348ff7497 2025-06-11T14:53:35+05:30 Build etcd image v3.6.1 - - 3038f3530 2025-06-11T09:58:05+02:00 client-go/dynamic: rm watchlist - - 86c709cd8 2025-06-11T12:34:18+05:30 skip nfacct test in IPv6 clusters - - e5f36796e 2025-06-11T08:24:35+02:00 Bump dependencies, images and versions used to Go 1.24.4 and distroless iptables - - 07151bb0f 2025-06-11T04:27:21Z chore: Add validation error for unsupported map of slices in validation-gen - - 89f5453e3 2025-06-10T23:16:41-04:00 Allow system:monitoring role to access kubelet metrics endpoints - - 2810f6e65 2025-06-10T20:10:02-07:00 add bentheelder to cmd/preferredimports *reviewers* - - 00a6d2c99 2025-06-10T20:09:57-07:00 add bentheelder to conformance related test *reviewers* - - 1dd055774 2025-06-10T20:05:40-07:00 backfill some sig-testing-reviewers (tech leads aojea and pohly) - - ad68a4b4c 2025-06-10T20:05:40-07:00 emeritus spiffxp - - 512f000d0 2025-06-10T14:11:30-07:00 Update tests for StructuredAuthenticationConfiguration feature gate GA - - efebfe9e3 2025-06-10T14:04:28-07:00 Set StructuredAuthenticationConfiguration feature gate to GA in v1.34 - - 769d71b30 2025-06-10T20:15:07Z Remove unused Expect methods in testscheme - - 105dd3b0a 2025-06-10T20:15:06Z Add ExpectMatches to ValidationTester - - 28e973c04 2025-06-10T18:08:45Z Better formatting of matcher errors - - b39741b50 2025-06-10T19:25:48+02:00 e2e: node: serial: fix cgroup path with crio - - 26b188aaa 2025-06-10T17:13:15Z KEP-4633: Graduate to Stable. - - fd5d7a18e 2025-06-10T19:58:36+03:00 reduce logspam when calculating sandbox resources - - 0baeccd32 2025-06-10T16:16:13Z KEP-740: promote ExternalJWTSigner feature to beta - - ef2c18a5a 2025-06-11T00:02:48+08:00 Add more test cases - - eb3c9a318 2025-06-10T15:41:50Z Promote feature OrderedNamespaceDeletion to GA. - - f8b701243 2025-06-10T16:56:58+02:00 Revert "improve display format" - - 449320a54 2025-06-10T10:50:54-04:00 update github.com/spf13/cobra v1.9.1 - - 260a720a8 2025-06-10T09:38:55-04:00 Rate-limit the LoadBalancer rolling update test - - 0a86ca406 2025-06-10T21:14:17+08:00 Add healthChecker to the kubeDeps - - dacafec88 2025-06-10T08:46:34-04:00 KEP-3015: PreferSameTrafficDistribution to Beta - - b2ab0ba19 2025-06-10T11:37:47+02:00 Drop unused testing manifest - - 96b39187c 2025-06-10T08:45:51+02:00 Add context to Count() - - 9d1bc51cb 2025-06-10T10:52:25+08:00 adjust durations for sleepAction - - c85ac59df 2025-06-09T17:41:41-04:00 Build k8s using latest commit of golang - - 4a7e68a35 2025-06-09T21:27:57+08:00 fix: Fix the issue where kubelet's slow startup causes it to be mistakenly killed by the watchdog. - - b02fba7e0 2025-06-09T14:30:05+08:00 Fix incorrect logging of insufficientResources in preemption - - fc7ba63ee 2025-06-08T16:48:09+05:30 support parsing of iperf 2.2.0 output - - 1755a9e54 2025-06-08T16:42:25+05:30 fix: iperf version in comments - - 0ca9c380a 2025-06-08T12:00:14+08:00 update all api files - - 32aa52adf 2025-06-07T19:52:48-04:00 tolerate newer golang/oauth2 version - - 3cfa73bc1 2025-06-07T17:42:29+03:00 add -q flag for git worktree - - 97ec8618d 2025-06-07T10:28:36-04:00 Fix kubelet iptables startup, clarify semantics of utiliptables calls. - - 6a4751da7 2025-06-07T20:32:03+08:00 Graduate RelaxedEnvironmentVariableValidation Feature gate to GA - - f4ab6c2be 2025-06-06T17:57:43-04:00 cleanup: Migrate deprecated function ExtractCommentTags - - 0d468f58c 2025-06-06T20:37:50Z kuberuntime_manager: don't log entire container spec. - - 858b88bce 2025-06-07T01:14:33+05:30 kube-proxy: log ipt errors during platformCheckSupported - - 1f46b3fdb 2025-06-06T18:31:38Z Clean backoff record earlier - - 7b1f49906 2025-06-06T18:24:33+02:00 DRA kubelet: rename Store + Plugin -> DRAPluginManager + DRAPlugin - - fad670c27 2025-06-06T18:24:33+02:00 DRA kubelet: move RegistrationHandler into Store - - 494a129d0 2025-06-06T18:24:33+02:00 DRA kubelet: clarify plugin vs, driver name - - 0d5578b83 2025-06-06T16:46:15+02:00 test/apimachinery/watchlist: prove metadata client's List method not streaming - - 5b0f0d2ef 2025-06-06T10:40:00-04:00 update pr template issue links section - - a38ad3a2c 2025-06-06T16:15:43+02:00 client-go/metadata: rm watchlist - - beb86a839 2025-06-06T16:15:30+02:00 KEP-3329: drop PodDisruptionConditions feature gate - - b5a8f5d0a 2025-06-06T16:08:21+02:00 KEP-3715: drop ElasticIndexedJob feature gate - - 10de6780c 2025-06-06T12:06:28+02:00 DRA API: remove obsolete types from v1alpha3 - - 089669369 2025-06-06T16:03:46+08:00 fix TestNodeAffinityPriority: calculate the priorities correctly even if PreScore is not called - - 087554448 2025-06-06T02:26:05Z Make nodeports scheduling plugin sidecar initContainer aware - - 1876c5445 2025-06-05T22:44:31Z Remove unsupported map of slice validation for non-byte elements in validation-gen - - 501393810 2025-06-05T18:24:06-04:00 Change option to a slice - - 990cb7547 2025-06-05T17:02:41-04:00 Use slice.Contains() - - 28e99ef2e 2025-06-05T16:51:11-04:00 Add type information to tag Docs() and use it to typecheck tags - - 31aa3c202 2025-06-05T15:29:12-04:00 Switch to using named args in output_tests - - 7892fd95f 2025-06-05T15:29:12-04:00 Use codetags in validation-gen - - 249801b7c 2025-06-06T00:42:58+05:30 Fix windows-pause-image-base:@ invalid reference format - - 2c4c3037b 2025-06-05T11:17:47-04:00 Fix field path for embedded fields in root types - - d1bddfd77 2025-06-05T18:03:56+03:00 Forbid github.com/pkg/errors in k/k - - efaaece0f 2025-06-05T17:58:09+03:00 go.mod: drop pkg/errors as a direct dep - - cbbfabe7f 2025-06-05T10:50:14-04:00 Support embedded fields properly - - d1a858ca9 2025-06-05T17:48:13+03:00 kubeadm: fix one missed pkg/errors location - - 036f4bfe2 2025-06-05T15:08:35+02:00 hack: fix KUBE_RACE in benchmark-dockerized.sh - - 5be254650 2025-06-05T16:05:02+03:00 kubeadm: start using util/errors - - f522d7cb8 2025-06-05T16:04:52+03:00 kubeadm: add a local implementation of wrapped errors - - 2bf3d8b73 2025-06-05T14:02:44+02:00 KEP-3335: drop StatefulSetStartOrdinal feature gate - - 1d1d0c154 2025-06-05T14:45:00+05:30 promote agnhost to v2.56 - - 258961cb3 2025-06-05T05:30:59Z pkg/appis/apps: use utils/ptr package instead of utils/pointer - - 7b664a113 2025-06-05T05:20:46Z pkg/volume: drop pointer wrapper functions. - - 253a08d7e 2025-06-05T04:48:25Z pkg/util: drop pointer wrapper functions. - - ac5cb2300 2025-06-04T22:39:08-04:00 Bump gengo/v2 to latest - - d6ec03a13 2025-06-04T13:28:20-07:00 Preempt based based on allocated resources rather than desired - - 7d47165e3 2025-06-04T13:48:11-05:00 Replace queue.FIFOs with k8s.io/utils/buffer.Ring - - 705e89b04 2025-06-04T11:45:12-07:00 Only set pod allocation if admission succeeds - - f8b893489 2025-06-04T20:36:15+02:00 Update pkg/kubelet/kubelet_test.go - - 147073102 2025-06-04T18:06:07Z fix: prevent data race in metric LabelValueAllowList initialization - - 8cdbbf5cd 2025-06-04T12:56:39-05:00 Update k8s.io/utils for new generic ring buffer - - daae472fe 2025-06-04T13:27:50-04:00 e2e_node: verify restart looping container correctly - - 109ae1bac 2025-06-04T10:08:00-07:00 feat: Allow leases to have custom labels set when a new holder has the lease - - 8d3fb9ee0 2025-06-04T07:10:38-07:00 [KEP-2400] kubectl top: add a --show-swap option (#129458) - - 4c7840ec5 2025-06-04T15:33:27+02:00 podResizeMutex cleanup - - c7fdf6abd 2025-06-04T11:47:03+05:30 Handler will return the server port number instead of address - - 6a495241e 2025-06-03T14:40:17-07:00 KEP-3331: Add test to simulate revocation via user validation rule using unique identifier (jti) - - 466fb8152 2025-06-03T15:58:41-03:00 test/e2e/apimachinery/namespace.go: make OrderedNamespaceDeletion test serial - - 7e7aa6d81 2025-06-03T18:22:48+02:00 e2e: node: cpumanager: require cgroup v2 - - 68efb079a 2025-06-03T16:17:25+02:00 kuberc: add tests for DefaultGetPreferences - - ad3a13e01 2025-06-03T19:28:20+08:00 Graduate NodeLocalCRISocket to beta - - b9d9dea03 2025-06-03T16:08:29+08:00 Update npd from v0.8.20 to v0.8.21 - - 47dead1c4 2025-06-02T22:46:55Z unexport allocationManager IsPodResizeInProgress - - de1d6fbf2 2025-06-03T01:12:31+03:00 fix: ResolverTypeProvider data race - - 9b8d7ce49 2025-06-02T17:51:03Z pr review feedback - - a512de6e0 2025-06-02T16:53:10Z Clarified the token scope and future plans for the next security scan to refer to it - - 032a9eaed 2025-06-02T18:30:04+02:00 DRA kubelet: code cleanup - - a6e226899 2025-06-02T14:29:38+02:00 Ensure github.com/pkg/errors is used only in kubeadm - - 7ccb9657f 2025-06-02T21:19:38+09:00 sched: Apply EnablePlugins to CoreResourceEnqueueTestCases - - 6cb14884b 2025-06-02T11:47:42+02:00 test-integration: allow enabling race detection - - 545fbc99c 2025-06-02T11:27:09+02:00 test: drop dependency on github.com/pkg/errors - - 899f76159 2025-06-01T00:48:16+08:00 add unit test for IsDNS1123SubdomainWithUnderscore function - - 0a7d9f9bf 2025-05-31T07:45:16+02:00 KEP-4427: Promote Relaxed DNS search string validation to GA - - 2aa7ef3d2 2025-05-30T22:20:30Z Address comments - - dbdd6a3b4 2025-05-30T15:33:42-04:00 FieldManagedObjectTracker: Fix to work with unstructured - - b7d16fea7 2025-05-30T21:08:12+02:00 disable terminatingReplicas reconciliation in ReplicationController - - ee33c1a9f 2025-05-30T13:32:52-04:00 e2e: fix userns test - - be049397d 2025-05-31T00:52:04+08:00 Fix IsDNS1123SubdomainWithUnderscore to return correct error message - - 4f91a69f2 2025-05-30T10:29:18+02:00 DRA integration: move and extend device status test - - 0a9661375 2025-05-30T16:13:06+08:00 proxy: remove iptables wait interval flag - - a5aabf9f7 2025-05-30T09:52:22+02:00 DRA kubelet: validation pass before changing claim info cache - - 5420dcec5 2025-05-29T20:22:34-04:00 Promote two more EndpointSlice tests to conformance - - b9496d1a9 2025-05-29T16:18:47-04:00 Update client-go template with backticks - - d70fcf731 2025-05-29T20:13:56Z Update client-go PR template - - d75af825f 2025-05-29T16:18:36Z Extract interface CycleState and move is to staging repo. CycleState implementation remains in k/k/pkg/scheduler/framework - - be6807e6a 2025-05-29T09:42:26-04:00 Allow specifying a directory for image credential providers json/yaml configuration - - aac00c1f0 2025-05-29T10:50:32+02:00 add orphanedPods parameter to getRSPods - - d13dcbbf9 2025-05-29T13:05:32+08:00 kube-dns bump to v1.26.4 - - 96b5ae792 2025-05-28T13:07:34-04:00 Add code for not expanding volume if it has NodeExpansionNotRequired annotation - - 2b0b34350 2025-05-28T15:44:09Z DRA: Improve implementation of counter management in allocator - - 1cd71cbb1 2025-05-28T11:27:01-04:00 ManagedFieldsObjectTracker: Reload scheme - - 4654496c3 2025-05-28T10:22:35-04:00 Add code to not expand certain types of volumes - - 741d0e2b8 2025-05-28T11:21:57+02:00 Gradute ResilientWatchCacheInitialization to GA - - c8f1a6530 2025-05-28T12:26:09+05:30 agnhost: added server address for conntrack cleanup entries - - 5058e385b 2025-05-27T21:19:25-07:00 DRAAdminAccess: update label key - - ee2d3b6a2 2025-05-28T01:08:24Z DRA: Exclude individual devices when PartitionableDevices feature is disabled - - ab6fdf46d 2025-05-27T13:36:16-07:00 Move the autoscaling e2e tests to be ran in parallel (#131091) - - 4e3634bbb 2025-05-27T16:51:51+02:00 Update security contacts for sig-cli owned repos - - b0847b476 2025-05-27T10:38:45-04:00 Add unit tests for fsGroupChangePolicy accessors - - 74167f904 2025-05-27T14:47:55+02:00 Fix typo in the `--anonymous-auth` flag name - - 6410329a0 2025-05-27T10:43:59+02:00 update go version for publishing bot rules - - 60b5338d4 2025-05-26T22:06:25-07:00 Promote automatic_reloads of authn config metrics to BETA - - f694c58c6 2025-05-26T21:23:46+02:00 feat: graduate QueueingHint to GA - - 1310fc027 2025-05-26T16:41:38+02:00 kubelet: drop dependency on github.com/pkg/errors - - 346fe182b 2025-05-26T15:30:39+02:00 DRA E2E: fail test when ResourceSlice publishing fails - - dc2f33f9d 2025-05-26T18:31:28+05:30 Update Perl to 5.40 - - 7c0f968ab 2025-05-26T08:32:09-04:00 Drop usages of deprecated otelgrpc methods - - 157903b09 2025-05-26T09:35:53Z Skip backoff when PodMaxBackoffDuration is set to zero - - 54b2fad03 2025-05-26T11:28:24+02:00 kubectl: drop dependency on github.com/pkg/errors - - b461d80f3 2025-05-26T15:06:50+08:00 etcd: update etcd image to v3.6.0 - - df2857e77 2025-05-26T12:16:48+09:00 Revert shorthand for kubectl explain --output - - 1d17ca9b7 2025-05-24T00:03:35-04:00 generate code - - 8ae717104 2025-05-24T00:03:28-04:00 Simplify subresource matching - - 9715c90b3 2025-05-23T21:47:09-04:00 Clarify errors and improve tests - - 4cac349f8 2025-05-23T21:47:08-04:00 Clarify group version lookup in validateDeclaratively - - c2eef42cf 2025-05-23T21:47:08-04:00 Add output_tests - - 6284a0f50 2025-05-23T21:47:08-04:00 Tag types with +k8s:isSubresource and +k8s:supportsSubresource for scale - - 7dc8660d0 2025-05-23T21:47:08-04:00 Update testing to fully track subresources - - 6ca6b7bb6 2025-05-23T21:47:08-04:00 Add +k8s:isSubresource and +k8s:supportsSubresource tags - - 105391403 2025-05-23T21:47:08-04:00 Enable scale subresource in generated validations - - a3eddf7d8 2025-05-23T21:47:07-04:00 Add declarative validation testing for replicationcontroller/scale - - 356f395f0 2025-05-23T21:47:07-04:00 Enable declarative validation for replicationcontroller/scale - - 030b4ab9c 2025-05-23T21:47:07-04:00 Add declarative validation testing to Scale.spec.replicas - - 48e1079cf 2025-05-23T21:47:07-04:00 Add subresource mapping support to ValidateDeclaratively and introduce configs - - 8c5c5fb76 2025-05-23T21:47:07-04:00 Add origin and use apivalidation.ValidateNonnegativeField for Scale.spec.replicas validation. - - d0f6fe30b 2025-05-23T21:47:07-04:00 Add k8s:minimum validation to Scale.spec.replicas - - ffb4e003f 2025-05-23T21:47:06-04:00 Enable validation-gen for scale group-versions - - e63019a87 2025-05-23T17:52:26+02:00 DRA integration: refactor code to support other tests - - 1ffda045c 2025-05-23T07:44:49-07:00 update to latest ishidawataru/sctp dependency - - 50f152440 2025-05-23T15:04:00+02:00 DRA integration: start scheduler on demand - - 488c94735 2025-05-23T08:58:13-04:00 Bump dependencies, images and versions used to Go 1.24.3 and distroless iptables - - 699dce0a5 2025-05-23T14:32:19+02:00 DRA kubelet: fix gRPC timeout flake - - 7215de79b 2025-05-23T13:05:42+02:00 DRA kubeletplugin: some doc updates - - 24c0e91d2 2025-05-23T12:54:26+02:00 DRA resource slice controller: disable resync - - 01820ff7c 2025-05-23T18:02:32+08:00 chore(scheduler): add filter integration tests for missing part plugins: NodeAffinity plugin - - 151d9d79f 2025-05-23T09:51:35Z Remove package protected field updatePodOther from ActionType. Make ActionType.None public - - 76f95271a 2025-05-23T11:02:58+02:00 kuberc: make update and update-vendor - - b8e6de08e 2025-05-23T10:56:59+02:00 kuberc: add API violation exceptions - - c29accaf5 2025-05-23T10:56:59+02:00 kuberc: introduce fuzzing for kuberc types - - b0370c483 2025-05-23T10:56:59+02:00 Promote kuberc to beta - - 1f355e5b4 2025-05-23T10:56:59+02:00 kuberc: pick the first known version when decoding + tests - - 0341b27c5 2025-05-23T10:56:59+02:00 kuberc: align internal and v1alpha1 go-types with v1beta1 - - 39195f9a4 2025-05-23T10:56:59+02:00 kuberc: add v1beta1 types - - 35870c480 2025-05-23T10:48:54+02:00 client-go remotecommand: avoid "unexpected error" log when there is no error - - 7287dcd2f 2025-05-23T09:18:33+03:00 vendor: update system-validators to v1.10.1 - - b35c5c0a3 2025-05-22T12:40:35-07:00 e2e: Fix shadowed error in reboot test and clean up containers after reboot test (#131699) - - f79012a0d 2025-05-21T20:45:01Z renamed SIG Node google groups - - 50fe29e52 2025-05-21T16:39:25-04:00 Add accessors for fsgroup change policy - - 17946fe79 2025-05-21T18:02:52Z Add Stress Tests for VolumeAttributesClass - - 32c45ecf1 2025-05-21T13:10:02+02:00 Bump github.com/vishvananda/netlink to v1.3.1 - - aea2743e4 2025-05-21T12:31:52+03:00 vendor: update system-validators to v1.10.0 - - 96e4cc65f 2025-05-21T09:09:46Z update baseimage - - c5f368522 2025-05-21T12:09:40+03:00 kubeadm: fix dryrun-latest e2e by updating cluster-info fixture - - d7b604909 2025-05-21T09:22:33+02:00 e2e: node: always declare testcase CPU requirements - - b571840d0 2025-05-20T23:05:17-04:00 bug: Remove duplicate ReplicaSet update validation - - 67345417c 2025-05-20T16:42:23-07:00 Update tests to use v1 for AuthenticationConfiguration - - aea874e5e 2025-05-20T16:28:49-07:00 Duplicate v1beta1 AuthenticationConfiguration to v1 - - c509e22d1 2025-05-20T18:05:57-04:00 Add a list of modules that should be pinned at current versions - - c4421fc13 2025-05-20T18:15:01Z address more feedback and some cleaning - - 637d234aa 2025-05-20T17:08:56Z feat: Add support for ECDSA-P384 encryption algorithm - - b98b86bd6 2025-05-20T09:57:16-07:00 DRA: Add scheduler perf test for partitionable devices (#131771) - - 4cc2bded9 2025-05-20T15:48:31Z DRA: Add an allocator test that uses an attribute selector - - 60c36432f 2025-05-20T17:43:30+02:00 DRA integration: set up nodes for scheduling - - 1c3beb47a 2025-05-20T22:41:19+08:00 Fix goroutine leak in unit tests - - f6fafba42 2025-05-20T21:57:44+08:00 fix flacky test: ResourceQuota should verify ResourceQuota with terminating scopes through scope selectors - - 8cf5e8db7 2025-05-20T13:31:57+02:00 Deprecate kubeconfig's preference field in favor of kuberc - - 1ce8503e9 2025-05-20T16:47:42+08:00 add UT for volumepathhandler - - a8ed33bc6 2025-05-20T08:41:01Z feat: add metrics for compatibility version - - c4a59afe9 2025-05-20T04:47:50Z Fix incorrect URL in build/dependencies.yaml file - - 5bb3f862a 2025-05-20T01:46:55Z DRA: Clean up allocator tests - - 583447668 2025-05-19T19:38:42Z fix lint and unit test failures - - 676978641 2025-05-19T19:38:42Z address feedback - - 88e1909e5 2025-05-19T19:38:42Z move pod admission and resize logic into the allocation manager - - 353073197 2025-05-19T10:19:14-07:00 Kubectl: check version skew (#127365) - - 3878f7e74 2025-05-19T18:23:49+02:00 E2E ResourceQuota: ensure consistent ResourceQuote during scope selector test - - 4a353d07e 2025-05-19T15:36:57+02:00 E2E ResourceQuota: fix pod creation flake - - 4b10ba9ee 2025-05-19T15:36:57+02:00 E2E ResourceQuota: dump last ResourceQuota - - f712b01dd 2025-05-19T13:07:42+02:00 Unify references to group resource in metrics - - d3afe8a87 2025-05-19T09:20:54+02:00 hack/local-up-cluster.sh: remove kubelet --cloud-config - - 772d01066 2025-05-19T08:02:43+02:00 client-go workqueue: clarify parallel reenqueuing - - d043beb22 2025-05-18T12:52:13-04:00 HealthChecker has a List method - - 9b3830fba 2025-05-18T12:52:05-04:00 Bump google.golang.org/grpc v1.72.1 - - be5d8c767 2025-05-18T18:38:16+10:00 Update cmd/kubeadm/app/cmd/upgrade/apply.go - - c0885e018 2025-05-18T18:36:45+10:00 Fix --config option from suggested kubeadm command - - 8f49fb5ce 2025-05-17T20:42:08-04:00 future-proof csi test mocks - - adc4916df 2025-05-17T12:39:58+02:00 feat: introduce pInfo.UnschedulableCount to make the backoff calculation more appropriate - - 968e19d1b 2025-05-17T09:30:09+02:00 docs: avoid broken link - - a271d3e53 2025-05-17T11:08:29+08:00 cleanup: remove error comment of AddIndexers func - - 5def7fadf 2025-05-16T20:46:55Z Drop dependency on x/exp package in mount_linux_test.go - - b9e2a1608 2025-05-16T21:53:35+03:00 e2e_node: dra: test plugin registration retry - - aef61622a 2025-05-16T21:53:35+03:00 e2e: dra: implement ResetGRPCCalls - - e8be3e575 2025-05-16T21:53:30+03:00 e2e: dra: simulate GetInfo failure - - 2f50d0a51 2025-05-16T16:04:15+01:00 Add kube-api-linter plugin to golangci-lint - - 0e5eab042 2025-05-16T08:04:07-07:00 test: Use sub-tests in watch tests - - 5da12b5ae 2025-05-16T08:16:24-04:00 Add tests that validate the return value of resize operation - - c369e3cd4 2025-05-16T19:06:09+08:00 etcd: build etcd image v3.6.0 - - 65a27eb97 2025-05-16T08:48:39Z restrict the use of scheme internally to client-go - - 671d1a07a 2025-05-16T13:28:37+05:30 Bump the busybox image - - 88b236054 2025-05-16T08:15:35+02:00 ResourceQuota E2E: more informative failure message - - ba77d2756 2025-05-16T07:52:55+02:00 DRA E2E: reduce risk of flake in ResourceSlice stress test - - 6b0ebedcc 2025-05-15T21:19:18-04:00 Set non-experimental WatchProgressNotifyInterval config field - - 079d4e52c 2025-05-15T21:19:18-04:00 Fix kubeadm etcd client interface - - cf0bbf117 2025-05-15T21:19:11-04:00 bump etcd client to 3.6 - - 7bccb1acb 2025-05-16T13:12:13+12:00 Update pkg/scheduler/framework/plugins/defaultpreemption/default_preemption.go - - 139fab0eb 2025-05-15T12:46:03-07:00 kubelet: don't import testing dependency in non-test code - - 90b256537 2025-05-15T11:21:54-07:00 Add suggestChangeEmulationVersion if setting locked feature. - - 5314fcece 2025-05-15T11:11:35-07:00 Promote automatic_reloads of authz config metrics to BETA - - 1b9bb3393 2025-05-15T14:01:18-04:00 test: Fix CURL download of Windows busybox test image - - b0ab168a7 2025-05-15T17:56:31Z CHANGELOG: Update directory for v1.30.13 release - - ec7e732cb 2025-05-15T20:55:17+03:00 e2e: dra: move gomega matchers to dedicated package - - fcfd87812 2025-05-15T17:52:37Z CHANGELOG: Update directory for v1.31.9 release - - 2b7f8e168 2025-05-15T17:51:41Z CHANGELOG: Update directory for v1.32.5 release - - 1ab54ffa6 2025-05-15T17:48:58Z CHANGELOG: Update directory for v1.33.1 release - - bba9c49e1 2025-05-15T19:31:16+03:00 e2e: DRA: test 2 claims with the same name - - 8d8fd9296 2025-05-15T19:31:16+03:00 DRA: test mismatched claim UIDs - - 96da66054 2025-05-15T19:31:16+03:00 DRA: genTestClaimInfo: add claimUID parameter - - 69e16d2f5 2025-05-15T19:31:11+03:00 DRA: kubelet: check for duplicate claim names - - b9fec8bf4 2025-05-15T13:46:48Z fix scheme import - - cf8acf5cb 2025-05-15T11:43:59Z package bootstrap matches dir - - e9fcdabcf 2025-05-15T18:23:30+07:00 feat: kubectl debug: add label for debugger pod - - b13cf0a65 2025-05-15T12:55:10+02:00 tests: userns: Add framework.WithFeatureGate() - - 9549c1115 2025-05-15T08:48:35Z fix e2e network test flake because of network programming latency - - ef0547741 2025-05-14T21:23:52-07:00 verify scripts: preserve exit code - - 0114d33c3 2025-05-14T17:44:00-07:00 datapol: compare types directly - - a1a4bc8fe 2025-05-15T02:23:51+02:00 fix: add BackoffExpiration to DeepCopy - - 2fe65bbf4 2025-05-14T19:10:10Z fix(kubelet): update lease duration when config changes - - 094466539 2025-05-14T18:44:04Z Add rotation and clean up for logging - - 125600e74 2025-05-14T11:05:46-07:00 Remove unused GetHostname method - - ee94ba913 2025-05-14T16:51:43+02:00 Run codegen - - 4eb9fb21b 2025-05-14T16:51:43+02:00 applyconfig-gen: handle non-pointer embedded members - - c374ab811 2025-05-14T16:51:43+02:00 Add a breaking example for applyconfig-gen - - 70e051326 2025-05-14T15:52:09+02:00 Separate getList and watch errors to prevent TestGetCacheBypass flakes - - 512111571 2025-05-14T11:39:04Z Add sig/scheduling label to scheduler integration tests and staging repo OWNERS - - 1ed6cf219 2025-05-14T13:06:03+03:00 Add e2e tests for kuberc - - 0ad8e65d9 2025-05-14T08:55:42Z e2e pod readiness gate network flake - - fe1b1fff7 2025-05-14T14:50:59+08:00 Remove unused GetHostIP method - - 504b681ae 2025-05-13T15:46:43-05:00 Adding Joel Speed - - 47f859606 2025-05-13T15:03:27-05:00 DRA: prevent admin access claims from getting duplicate devices - - c5e4cab9b 2025-05-13T13:14:47-04:00 e2e: add corresponding featuregate label to node features - - c4d6fcb19 2025-05-13T15:35:21Z Remove misleading comment from NodeTaint TimeAdded field - - d0b6ea36b 2025-05-13T15:35:18+02:00 update got to 1.23.8 for the active release branches - - 3043257b8 2025-05-13T15:34:38+02:00 remove release-1.29 as it is deprecated - - 9fd545bcc 2025-05-13T15:06:04+02:00 [sig-scheduling] SchedulerPreemption [Serial] validates various priority Pods preempt expectedly with the async preemption: replace finalizers with preStop hook and TerminationGracePeriodSeconds - - 74e9b27e5 2025-05-13T08:53:50-04:00 Port "Service endpoints latency should not be very high" to EndpointSlices - - e5f7fc25e 2025-05-13T16:18:19+09:00 TestNodeAffinityScoring: wait all nodes - - e42aba6c0 2025-05-12T19:56:46Z Optimize RS Controller Performance: Reduce Work Duration Time & Minimize Cache Locking - - 28602c66f 2025-05-13T06:56:27+12:00 Update pkg/scheduler/framework/plugins/defaultpreemption/default_preemption_test.go - - 52e7aa37d 2025-05-13T06:56:27+12:00 gofmt - - a507e64fe 2025-05-13T06:56:27+12:00 Have separate tests for custom selection vs ordering, add comments around system pod eligibility - - 283c5e6b6 2025-05-13T06:56:27+12:00 Have IsEligiblePod be supplemental to priority check, update tests - - 3ed73e058 2025-05-13T06:56:27+12:00 Clean up the affinity explanation, fix for new lint rule - - d4bc527a7 2025-05-13T06:56:27+12:00 Update comments: affinity info, default behavior, priority->importance - - 95ebc2c10 2025-05-13T06:56:27+12:00 Apply suggestions from code review - - 7f57c6e52 2025-05-13T06:56:27+12:00 Update factory to use generics, keep single New function - - 137da6a48 2025-05-13T06:56:27+12:00 Remove line about equal priority, fix typo - - b8ac17143 2025-05-13T06:56:27+12:00 Apply suggestions from code review - - 224e6a3a3 2025-05-13T06:56:27+12:00 Rename EligiblePod* to IsEligiblePod* - - 4bf684149 2025-05-13T06:56:27+12:00 Update the customizations to operate on individual pods, for more flexibility later - - c34f8db55 2025-05-13T06:56:27+12:00 Remove unnecessary context and typecheck, switch to cmp.Diff - - c6f2d3879 2025-05-13T06:56:26+12:00 Fix gofmt in default_preemption_test.go - - 78b059c06 2025-05-13T06:56:26+12:00 rename OrderedPods -> OrderPods - - 2616202ac 2025-05-13T06:56:26+12:00 Implement tests with example customizations, add direct constructor - - 760daaf11 2025-05-13T06:56:26+12:00 feature(scheduler): Custom pod selection/ordering in DefaultPreemption - - 721947a57 2025-05-12T14:11:19-04:00 Update staging/src/k8s.io/apiserver/pkg/audit/request_log_test.go - - 153233c67 2025-05-12T12:59:58-04:00 review from tallclair - - e418ee3a9 2025-05-12T12:11:38-04:00 Avoid encoding in LogResponseObject when we are not going to use it - - 26c198dc2 2025-05-12T16:08:15Z Some fixes - - 0b915a538 2025-05-12T16:02:11Z Cleanup after rebase - - a6586aa61 2025-05-12T16:01:01Z Addressed comments - - e262cccf2 2025-05-12T16:00:07Z Cleanup after rebase - - 861040435 2025-05-12T16:00:04Z Add e2e tests for Partitionable Devices - - ece35e588 2025-05-12T15:56:24Z Update DRA e2e test framework to allow publishing advanced ResourceSlices - - a437a269f 2025-05-12T11:22:18-04:00 Fix comments on ginkgo label functions - - 85734ac6b 2025-05-12T10:48:19+02:00 DRA E2E: don't run prioritized list tests twice - - 808a5cfd4 2025-05-12T11:57:27+08:00 e2e tests: remove all cloud provider calls in storage/volume_provisioning.go - - 514078682 2025-05-12T01:26:47+02:00 feat: improve the backoff calculation to o(1) - - cfe7d0424 2025-05-11T16:22:52-07:00 Account consumed newlines properly in YAML decoder - - d5a56739c 2025-05-11T13:12:29+08:00 use framework.ExpectNoError instead - - 699ec0a53 2025-05-10T13:15:12+02:00 Remove wrong comment - - f718096b7 2025-05-10T17:22:11+08:00 NoExecute taint should be added when a Node's ready condition becomes Unknown - - 3911b677b 2025-05-10T18:17:38+09:00 test: wait for nodes to be in scheduler's cache - - ea6b4ea7e 2025-05-10T16:16:04+08:00 kubeadm: bump supported etcd version - - 9d963298a 2025-05-09T14:29:06-07:00 test: Close response body in watch tests - - d1fb42a40 2025-05-09T22:26:33+01:00 fix: fixes a possible panic in `NewYAMLToJSONDecoder` - - 960a4939f 2025-05-09T14:26:13-04:00 Eliminate AuditContext`s SetEventLevel - - c39705281 2025-05-09T16:11:30+02:00 Self nominate adrianmoisey as sig-network reviewer - - b09d034a5 2025-05-09T11:33:04+02:00 DRA E2E: revise test labeling - - 13bd0b4ee 2025-05-09T11:07:05+02:00 e2e: node: rewrite the sidecar related tests - - f4265638b 2025-05-09T11:07:04+02:00 e2e: node: factor out reservedCPUs - - a8c8b0987 2025-05-09T11:07:04+02:00 e2e: node: dissolve skipIfNotEnoughAllocatableCPUs - - 32d4724ab 2025-05-09T11:07:04+02:00 e2e: node: add comment about reserved CPU - - daf2fc710 2025-05-09T11:07:04+02:00 e2e: node: rewrite multi-pod tests - - ccc662c22 2025-05-09T11:07:04+02:00 e2e: node: initial multi-container tests - - 2419d9ccc 2025-05-09T11:07:04+02:00 e2e: node: rewrite: multi-cpus single-container pods - - e4726719a 2025-05-09T11:07:04+02:00 e2e: node: rewrite more compatibility tests - - 74fda8c70 2025-05-09T11:07:04+02:00 e2e: node: rewrite compatibility tests - - dd3f9b607 2025-05-09T11:07:04+02:00 e2e: node: rewrite CFS quota tests - - b9ce058ab 2025-05-09T11:07:04+02:00 e2e: node: rewrite strict-cpu-reservation tests - - 3eb2e65fc 2025-05-09T11:07:04+02:00 e2e: node: rewrite cpumanager tests - - 94dd0b840 2025-05-09T14:15:17+08:00 Move test cases from mounted_volume_resize into testsuites/volume_expand.go - - 4aa3c968a 2025-05-09T10:25:25+08:00 Build etcd image v3.6.0-rc.5 - - 641834d03 2025-05-08T17:22:38-07:00 Fix broken recursion - - eb4641d65 2025-05-08T14:21:19-07:00 Add container Resources to the backoff key - - 080d6f9ea 2025-05-08T13:08:20-07:00 test: pass the test context to http requests - - 3f188e5d8 2025-05-08T12:54:06-07:00 refactor: Use http method constants in apimachinery - - 75afa1e0a 2025-05-08T15:31:16-04:00 Fix API server crash on concurrent map iteration and write - - f93e4645c 2025-05-08T11:28:52-07:00 refactor: Stop using ioutil in apiserver - - 9e3a1b0a9 2025-05-08T19:11:40+02:00 Add comment describing the feature gate with a link to KEP - - e3f3da5e7 2025-05-08T19:11:36+02:00 Swap KUBECTL_COMMAND_HEADERS to use the proper feature gate mechanism - - d1b5f268b 2025-05-08T19:04:58+02:00 Drop KUBECTL_ENABLE_CMD_SHADOW featgure gat entirely - - a6abd717e 2025-05-08T16:37:43Z DRA: Fix failure to allocate large number of devices - - 6cca37b36 2025-05-08T16:47:35+02:00 Add integration test for log verbosity - - 69682b75e 2025-05-08T16:47:29+02:00 Manually read verbosity before kubectl command construction - - ee4c6b90c 2025-05-08T21:15:24+08:00 add HirazawaUi to kubeadm approvers list - - 77b1236a5 2025-05-08T21:08:01+08:00 fix: Kubernetes versions in unit tests - - f40892f48 2025-05-08T14:33:11+02:00 client-go: call out WithContext inconsistency - - 871cabeed 2025-05-08T11:10:12+08:00 deflake e2e tests: StatefulSet Non-retain StatefulSetPersistentVolumeClaimPolicy should delete PVCs after adopting pod (WhenScaled) - - 8b81a3d88 2025-05-07T16:42:08-07:00 Rename GetStableKey to GetBackoffKey - - 861682235 2025-05-07T21:15:12Z DRA: Fix incorrect behavior for AllocationMode: All in ResourceClaim when used in subrequests - - a3097010f 2025-05-07T13:01:15-07:00 Change the implementation design of matchLabelKeys in PodTopologySpread to be aligned with PodAffinity (#129874) - - ce02da8da 2025-05-07T15:42:16-04:00 generate code - - 4821604f8 2025-05-07T15:42:09-04:00 Reorganize scheme type converter into apimachinery utils - - e81887276 2025-05-07T12:17:48-07:00 refactor: Add request method constants - - af1d60f30 2025-05-07T18:16:15Z Add hpa reviewers - - 0acc7bd4d 2025-05-07T16:26:27Z HPA: Fix int overflow in GetExternalPerPodMetricReplicas - - b9cb3cb33 2025-05-07T23:35:28+08:00 update klog flags - - 57218ac96 2025-05-07T19:53:45+05:30 Revert "kube-proxy: log errors during proxy boot" - - 9def40c9e 2025-05-07T15:41:27+02:00 DRA E2E: fix "must manage ResourceSlices" - - c71e29ff1 2025-05-07T15:41:27+02:00 DRA E2E: fix flaky "sequential update with pods replacing each other" - - d28c8cd48 2025-05-07T14:12:23+02:00 fix: not removing the plugin from the unsched plugins after PreEnqueue - - 47d296d62 2025-05-07T13:54:47+02:00 feat: introduce pInfo.GatingPlugin to filter out events more generally - - 441dd3051 2025-05-07T11:52:36+02:00 userns: Wrap more errors - - 43f61e80d 2025-05-07T11:52:36+02:00 userns: Improve error returned if userns is not supported - - c5efc843d 2025-05-06T15:56:29-04:00 Fix rudimentaryErrorBackoff to only be created once - - 97e64e80c 2025-05-06T12:43:17-07:00 Fix typo in comment - - 68f0204e3 2025-05-06T12:40:58-07:00 Better logs and debugging - - 8a571f7fb 2025-05-06T12:40:57-07:00 Rename discover() to discoverType() - - eb3c061ca 2025-05-06T12:40:57-07:00 Reorder and merge blocks handling named types - - 67bab26ea 2025-05-06T12:40:56-07:00 hasValidations should return cached values first - - bb10f55fd 2025-05-06T12:40:55-07:00 Fix lint warnings - - 22fa3c747 2025-05-06T18:33:25Z add retries to exec command in cgroup verification - - 8652b6ab2 2025-05-06T13:40:44-04:00 Update sig-network-approvers/reviewers - - b1bb9a588 2025-05-06T14:30:10-03:00 Kubelet: Randomize ClusterRole name in e2e - - 863168e47 2025-05-06T09:25:06-07:00 e2e: stabilize Windows memory pressure eviction test - - 4ed3768dc 2025-05-06T17:54:25+02:00 userns: Use len to handle empty non-nil slices - - 97a2cb39c 2025-05-06T15:37:57Z Make sig-scheduling-api-approvers actual approvers - - 6d927c3c2 2025-05-06T15:15:03Z Comment out sig-scheduling-api-reviewers, since it's currently empty. - - 038bb1a9a 2025-05-06T15:15:03Z Remove alculquicondor who is stepping down from sig-scheduling-api-reviewers - - 55b5827d8 2025-05-06T13:59:36Z integration: etcd data - - aa9f156d7 2025-05-06T13:59:09Z integration test for compatibility version - - 3be3051fb 2025-05-06T09:35:38-04:00 Adding test case for the webhook behavior change - - cf82fd7e9 2025-05-06T09:35:27-04:00 Treat error decoding a mutating webhook patch as error calling the webhook - - 9bcec340f 2025-05-06T13:29:55Z modify unit test for compatibility version - - 15ab88f88 2025-05-06T13:29:54Z remove networking v1alpha1 and make update - - 54b014be1 2025-05-06T13:29:54Z use networkingv1 as default storage for servicecidr and ipaddresses - - b2fe862ae 2025-05-06T13:29:45Z graduate disableAllocatorDualWrite and lock MultiCIDRServiceAllocator - - d2fa246b0 2025-05-06T09:00:38-04:00 Update codegen - - d78b295a8 2025-05-06T09:00:32-04:00 Reenable guard to only validat root and scale subresources until ratcheting merges. - - 94d043b14 2025-05-06T13:00:14+03:00 Drop KUBECTL_DEBUG_CUSTOM_PROFILE feature gate entirely - - d52f05dad 2025-05-06T15:26:20+08:00 remove hwdef from hack reviewer - - 2e6ec2414 2025-05-05T22:06:59-04:00 Remove unused function - - 2e8b409a5 2025-05-05T22:06:59-04:00 Rewrite Subresources godoc. - - 164fefa94 2025-05-05T22:06:59-04:00 Update codegen - - 2119555e0 2025-05-05T22:06:59-04:00 Add subresource to operation, do not special case subresources in validation-gen - - 2073ba237 2025-05-05T18:47:41-04:00 pkg/storage/cacher/cacher_whitebox_test: deflake TestWatchNotHangingOnStartupFailure when ResilientWatchCacheInitialization is on - - 2b3f2aa70 2025-05-05T19:31:48Z propogate error - - 10c5bdd6a 2025-05-05T15:03:11-04:00 Apply feedback - - 36685c6f1 2025-05-05T14:40:06-04:00 Add information about expected status - - 6c8904104 2025-05-05T22:08:05+08:00 fix(scheduler): node pre-check logic to consider NoExecute taint effect - - e36a168a6 2025-05-05T10:37:42-03:00 test/e2e/node/kubelet_authz.go: fix SAR to include service account groups - - aeb43eb22 2025-05-05T12:22:39Z Migrate ExtractCommentTags to ExtractFunctionStyleCommentTags - - 1ec7231f6 2025-05-05T14:21:25+02:00 DRA node: reject static pods which reference ResourceClaims - - 2ea4b1aba 2025-05-05T13:00:08+02:00 golangci-lint: don't warn about conversion and defaulting functions - - 15d9a93d7 2025-05-05T13:00:08+02:00 golangci-lint: redirecting stderr raced with termination of script - - 3b5cfeaf2 2025-05-05T08:49:09+02:00 DRA: use v1beta2 - - b262d5616 2025-05-05T08:41:21+02:00 DRA: client-go wrapper with latest API as types - - 8e9abfaf2 2025-05-05T08:41:21+02:00 DRA: v1beta1 <-> v1beta2 conversion - - d7a64d68b 2025-05-05T08:41:21+02:00 DRA resourceslices: clarify code - - a171795e3 2025-05-05T08:40:52+02:00 DRA resourceslices: better error reporting - - 6392b54e1 2025-05-05T08:30:26+02:00 DRA resourceslices: avoid update loop when partitionable devices feature is off - - 5af026120 2025-05-05T08:25:20+02:00 test: bump agnhost image to 2.54 - - e5ffec242 2025-05-04T20:27:09+02:00 Bump CNI to 1.7.1 - - 47fddb08f 2025-05-02T20:56:03-04:00 Expand has() tests for omitempty and omitzero - - c2c003a71 2025-05-02T23:11:30Z update k8s.io/utils to bring fakeClock.Waiters() - - b3bf5ed0e 2025-05-02T15:33:07-07:00 verify-shellcheck.sh: normalize KUBE_ROOT using pwd -P - - a1a620886 2025-05-02T15:33:07-07:00 use the minimal shellcheck image instead - - e0983dbee 2025-05-02T14:23:49-07:00 remove unused shell imports in verify-shellcheck - - 7b50c8a51 2025-05-02T17:18:24-04:00 jwt: support CEL expressions with escaped names - - 784c589a7 2025-05-02T16:29:04-04:00 Check for newer resizing related fields after expansion is successful - - 6bb6c9934 2025-05-02T15:38:40-04:00 Drop null creationTimestamp from test fixtures - - 41805aff9 2025-05-02T15:38:40-04:00 Update runtime convertor to honor IsZero() - - bc6051717 2025-05-02T15:38:38-04:00 bump cbor to add omitzero support - - 06b078406 2025-05-02T15:38:38-04:00 bump structured-merge-diff to add omitzero support - - fdf0bb41a 2025-05-02T15:38:37-04:00 Omit null metadata.creationTimestamp - - 79891eac8 2025-05-02T17:27:34+02:00 agnhost: bump version to 2.54 - - 09912f352 2025-05-02T10:03:51-04:00 Make ToUnstructured match stdlib omitempty and anonymous behavior - - 49f765e2b 2025-05-02T20:56:29+08:00 Remove redundant Required validation for IngressRules - - c78556fb4 2025-05-02T14:46:56+02:00 agnhost pause: report signal, support termination message - - a6549edd1 2025-05-02T15:41:01+03:00 kubeadm: use named ports for coredns probes - - 0faeb5a0d 2025-05-02T14:38:09+02:00 golangci-lint: move into hack/tools/golangci-lint - - 5d9a2f30f 2025-05-02T14:38:09+02:00 golangci-lint: finish migration to v2 - - 9bada79de 2025-05-02T12:51:02+02:00 DRA node test: fix useless gomega.Consistently - - 4adb58565 2025-05-02T12:51:02+02:00 chore: bump golangci-lint to v2 - - f6d049801 2025-05-02T13:23:22+03:00 Continue alias creation when __completion is used to enable completion - - dceae3b38 2025-05-02T10:52:56+02:00 DRA e2e: avoid terminationGracePeriodSeconds - - 56e533f4a 2025-05-02T08:26:17Z servicecidr: only patch status if necessary - - 7fedcc34e 2025-05-02T08:25:16Z refactor default service cidr sync status logic - - edda4b02d 2025-05-02T00:09:10-07:00 fixup! Introduce special handling for updates involving a single resource slice. - - 6d8b41fac 2025-05-01T22:24:23-07:00 Introduce special handling for updates involving a single resource slice. - - 2e98d87c5 2025-05-02T10:48:46+05:30 api: Fix typo in word "immediately" - - 5441f5fde 2025-05-01T12:32:20-04:00 jwt: add unit tests for using CEL with deeply nested claims - - 43ce37ed4 2025-05-01T14:56:28+02:00 Address feedback - - 7e1cec680 2025-05-01T14:53:26+02:00 e2e: Deduplicate cgroup verification - - cc4c14d4c 2025-04-30T15:11:05-04:00 Disable size check for xfs/ext3/ext4 filesystems before expansion - - 48054afd6 2025-04-30T13:41:22-04:00 Relax external signer path validation to allow relative paths - - 5712881ca 2025-04-30T11:43:36-04:00 Disable disk size checking when calling NeedsResize function - - e500f9451 2025-04-30T23:55:46+09:00 add missing space in string concatenation (kubeapiserver) - - c5a2c69b9 2025-04-30T23:51:11+09:00 add missing space in string concatenation (kubeadm) - - 43a0da588 2025-04-30T23:35:25+09:00 add missing space in string concatenation (kube-proxy) - - 66b8a8427 2025-04-30T09:24:39-04:00 Fix CEL equality bug for structs will nil field not marked as omitempty - - 1b9386aac 2025-04-30T12:17:33+02:00 Add comment explaining the metric sampling logic for plugin execution metrics - - 0a4ab9367 2025-04-30T17:07:43+08:00 fix incorrect comments - - 4d5d48da7 2025-04-30T13:41:27+08:00 Remove unused volume limit constants - - 3a5dda78a 2025-04-30T04:46:50Z e2e network: blue green deployments - - ea6441827 2025-04-29T15:37:26-04:00 Appease linters - - 43d6ea12e 2025-04-29T15:37:01-04:00 jwt: refactor CEL eval to drop unstructured and map[string]any - - 064074c07 2025-04-29T13:32:26-04:00 Add lazy reflective CEL object wrapper - - 903d6d4f0 2025-04-29T09:17:40-04:00 Don't reinitialize test framework during each test case - - a56378d9f 2025-04-29T16:15:41+08:00 Update UserNamespaceSupport feature gate name - - 3cadb6ff8 2025-04-29T09:55:05+02:00 DRA test: update examples - - c6f652d5f 2025-04-29T14:58:57+08:00 Refactor pod failure policy defaults - - 68b1a950f 2025-04-28T22:14:02-03:00 kube-proxy should check global IPv6 enablement - - 2080bafa1 2025-04-28T23:40:49Z Add sunnylovestiramisu as Reviewer - - d6b45bc98 2025-04-28T18:43:12+02:00 [FG:InPlacePodVerticalScaling] clean code resize test - - dddfeb4a0 2025-04-29T00:19:47+08:00 Handle unsupported node expansion for RWX volumes - - 62ddcfba5 2025-04-28T20:35:19+05:30 kube-proxy: conditionally skip e2e - - 8bb7b0563 2025-04-28T15:44:04+02:00 dependencies: github.com/client9/misspell -> github.com/golangci/misspell - - ad40bc885 2025-04-28T08:28:46+02:00 kubectl describe service: Add Traffic Distribution - - 28e7acf0f 2025-04-27T20:35:38+02:00 improve display format - - f30c23a78 2025-04-27T15:36:09+02:00 kubectl: sort configmaps alphabetically to avoid random order - - db960d100 2025-04-26T17:39:31-07:00 Fix openid discovery docs with external jwt signer. - - 1869f6f23 2025-04-26T14:36:33-07:00 Fix typo in service account config test. - - c7a870135 2025-04-27T01:05:45+05:30 nftables: cleanup service chain checks - - 494b2b563 2025-04-27T01:21:39+09:00 use testing.TempDir and delete helper function - - efcceee90 2025-04-27T00:33:07+09:00 reduce assignment - - f42ee7a2d 2025-04-26T23:08:02+09:00 use slices package to reduce the codes - - 9cb3dfb5d 2025-04-26T16:06:18+05:30 kube-proxy: log errors during proxy boot - - 2d337f515 2025-04-25T11:21:42-07:00 Retool validator utils realType and unaliasType - - 835bb2ecc 2025-04-25T11:13:03-07:00 Change v8n context.Type and Parent on typedefs - - 6ea1db51a 2025-04-25T11:13:03-07:00 Disallow pointers as listmap keys - - fc7f01735 2025-04-25T11:13:02-07:00 Handle typedef fields in optional validations - - 9d519c7c4 2025-04-25T11:13:02-07:00 Fix immutable validation for structs with pointers - - 0b190b817 2025-04-25T11:13:01-07:00 Add test cases for immutable to verify pointers - - 855918f75 2025-04-25T11:13:01-07:00 Add tests for optionalness of typedef fields - - 7a24c4ce5 2025-04-25T10:07:12+02:00 chore: update github.com/google/cel-go dependency to v0.25.0 - - addaf680a 2025-04-25T15:49:41+08:00 remove v1.31.0 api testdata - - 86a43f4b5 2025-04-25T15:49:16+08:00 Add v1.33.0 API testdata - - 89156452a 2025-04-25T15:38:14+08:00 fix nil pointer panic on windows node - - 00908ce2d 2025-04-25T01:09:08-05:00 Wait for resource quota status to be populated - - d5bf33e7d 2025-04-24T22:54:09-07:00 update-codegen.sh: automatically install protoc - - 8a2f367ec 2025-04-24T22:54:09-07:00 automatically install goimports when running update-codegen - - 1473aeaac 2025-04-24T22:54:09-07:00 add goimports to tools module - - 540ea5949 2025-04-24T22:40:05-07:00 skip kubectl proxy env tests when the host is localhost/loopback and would not be proxied - - 1214dc223 2025-04-25T03:15:42Z kubelet: Use node addresses from informer - - c0b2f341a 2025-04-25T10:19:05+08:00 clean up cloud provider code because cloud provider only supports empty or external and cloud is nil - - 187b43d5a 2025-04-24T17:17:27-07:00 enable dep-approvers for staging go.mod/go.sum - - f50ad91ed 2025-04-24T15:18:26-07:00 Create a single TypeDiscoverer for all inputs - - 08794974b 2025-04-24T15:02:29-07:00 track gopkg.in/yaml.v3 as an unwanted depdendency - - aee494525 2025-04-24T21:28:07Z alculquicondor stepping down from sig-scheduling approvers - - 58e5dfd45 2025-04-24T13:08:46-07:00 attempt to re-introduce dep-approvers for go.mod/go.sum - - 74e84dbf5 2025-04-24T12:00:50-07:00 Add more test cases to TestDescribeSecret test (#131422) - - 6eff9db0f 2025-04-24T11:01:03-07:00 chore: Add VeryShortWatchError typed error - - 92359cdc6 2025-04-24T16:05:01Z update godoc for and rename observedGeneration helpers - - 932cff5dd 2025-04-24T15:51:08Z add more error details to the failing cgroup check - - c3bb59d07 2025-04-24T17:06:27+02:00 Fix etcd3 watcher flake - - 0d3d2733f 2025-04-24T08:06:17-04:00 Update go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful to v0.44.0 - - a2281f97b 2025-04-24T17:01:00+08:00 bump fsnotify v1.9.0 - - 44d7132af 2025-04-24T00:45:27-07:00 Update hnslib version in Windows KubeProxy. - - 7c53a5aaa 2025-04-24T14:54:41+08:00 Remove feature label NodeOutOfServiceVolumeDetach - - f74424bd7 2025-04-24T08:54:13+02:00 etcd: better logging - - 24257f2d3 2025-04-24T11:45:38+08:00 Remove deprecated scheduler cache metrics - - 269d3ae51 2025-04-24T09:47:27+09:00 Fix comment for default gRPC log level in DRA plugin - - 2ea689207 2025-04-23T15:58:37-07:00 Always check for Immutable selector in Deployment Replicaset Daemonset (#131017) - - 947a9f26f 2025-04-23T14:02:36-07:00 Move pod resize e2e utilities out of e2e/framework - - 609e4a9ba 2025-04-23T13:31:14-07:00 Unhandled panic crash on rollout_history printer.PrintObj (#130503) - - fa8e37f78 2025-04-23T13:30:52-07:00 Allow disabling caching for webhook authorizers when using `apiserver.config.k8s.io/v1{alpha1,beta1}.AuthorizationConfiguration` (#129237) - - 1db2d6a01 2025-04-23T16:15:10-04:00 Mark NodeExpansion finsihed without featuregate check - - 70ebe90b1 2025-04-23T16:05:56-04:00 Also change final status by removing featuregate check - - 849924b6b 2025-04-23T11:56:12-07:00 Increase delay in kuberuntime termination order test to prevent time rounding flake. - - 0e40ed642 2025-04-23T11:37:22-04:00 Check for newer fields when deciding expansion recovery feature status - - 4fa090bd8 2025-04-23T14:03:19Z Remove alculquicondor from test framework OWNERS - - 6a17858ff 2025-04-23T13:24:19Z CHANGELOG: Update directory for v1.33.0 release - - 90de4b589 2025-04-22T10:30:51-04:00 Remove warning about resizing failed for unknown reason - - 418092840 2025-04-22T10:11:35+02:00 Update cri-tools to v1.33.0 - - f63702de0 2025-04-22T14:54:40+08:00 scheduler: return UnschedulableAndUnresolvable when node capacity is insufficient - - d10eb8692 2025-04-22T14:01:41+08:00 fix: Fix non-constant format string in framework.Logf call - - b9a6a257b 2025-04-21T13:34:37-07:00 add TODO for unifying .go-version - - 5c84ee07e 2025-04-21T13:34:35-07:00 test/images: read .go-version instead of duplicating - - 722581f5f 2025-04-21T17:34:42Z Expand etcd data test to n-3 - - c21f26895 2025-04-21T17:34:41Z Fix VAP test for v1.34 - - bfcee6645 2025-04-21T17:34:41Z Bump DefaultKubeBinaryVersion to 1.34 - - 27815acee 2025-04-21T13:58:58+08:00 remove outdate comment - - 64b4c96e2 2025-04-21T08:44:04+08:00 fix: use correct apiextensions v1 API instead of apiregistration v1 - - a53ea3357 2025-04-18T10:53:10+01:00 Updates prober_total_total to BETA and updates the list of stable metrics - - f844abfc6 2025-04-18T15:55:38+08:00 Fix typo in ResourceEncodingConfig comment - - ff108e72a 2025-04-17T17:16:23+02:00 DRA device taints: fix rare unit test flake - - 97dd6dc28 2025-04-17T15:02:29Z Add warning message for attach - - 8672956f7 2025-04-17T14:41:43+02:00 etcd: use Unix Domain socket for testserver - - 33f16a55b 2025-04-17T14:26:54+02:00 etcd: fix 5 second delay during shutdown - - ff2e6dddc 2025-04-17T10:57:27+02:00 DRA device taints: work around fake.ClientSet informer race - - 638abf033 2025-04-17T10:55:13+02:00 DRA device taints: more logging in test - - 40f2085d6 2025-04-17T10:55:13+02:00 DRA device taint: clean up test initialization - - 091d09b44 2025-04-17T16:40:27+08:00 deflake e2e tests: CustomResourcePublishOpenAPI works for multiple CRDs of same group and version but different kinds - - db1e10715 2025-04-17T00:42:26+09:00 Job: Fix API comments for SuccessCriteriaMet - - ac3274521 2025-04-16T17:24:08+08:00 scheduler: remove duplicate nominatedNodeName clearing in preemption - - 373866eee 2025-04-16T08:54:06Z Build etcd v3.6.0-rc.4 image - - 7fcc1bcf1 2025-04-15T17:23:32-07:00 chore: move watch handler tests to handlers pkg - - 3fcb26f01 2025-04-15T15:18:22-07:00 reduce etcd install log noise - - 3e609ecf6 2025-04-15T12:03:21-07:00 fix: Watcher deadlock from Stop not being called - - c704025a0 2025-04-15T11:27:26-04:00 Fix error handling and csi json file removal interaction - - 1654aa619 2025-04-15T15:33:40+08:00 deflake intergation test: TestEndpointHandlers - - 3d53bfec0 2025-04-14T17:19:50+02:00 Typo fix: watchActcion - - 4e3026fdb 2025-04-14T15:59:45+02:00 pr fix - - 7d6f86594 2025-04-14T15:55:57+02:00 kubectl: sort secrets alphabetically to avoid random order - - 8f1326251 2025-04-14T09:51:51+02:00 Improve Job API comment for the backoffLimit - - 9d5f78a99 2025-04-14T09:21:16+02:00 Update OWNERS_ALIASES add aojea to sig-network-api-reviews - - e8dbfc0b6 2025-04-14T09:07:51+08:00 add miss Shutdown call for selinux_warning controller - - 405b9e802 2025-04-13T13:56:37-05:00 Check expected emitted events with assert.Equal - - 5ebeb8def 2025-04-13T13:56:37-05:00 don't only run events in nested lists consecutively - - 614b1e901 2025-04-13T13:56:37-05:00 Run all permutations of events in ResourceSliceTracker tests - - 29b499e2b 2025-04-13T13:10:38-05:00 simplify applyEventPair - - 45b0ddff1 2025-04-13T13:07:14-05:00 make input events a slice - - 3883e050f 2025-04-12T22:02:06-05:00 Use shared test fixtures for ResourceSlice Tracker test cases - - 7f21df6ab 2025-04-13T00:53:57+09:00 resolved review comments - - 5928fc0e6 2025-04-11T13:36:37-07:00 Add ContainerIter utility for ranging over pod containers - - 3b2cd1234 2025-04-11T17:17:46Z fix(kubelet): acquire imageRecordsLock when removing image - - 6d6abaab7 2025-04-11T15:34:26+02:00 Simplify etcd3 watcher - - b82fd6c28 2025-04-11T16:42:44+08:00 add e2e test for healthz/ - - 8bc7e6c10 2025-04-11T16:42:44+08:00 add etcd server overrides to etcd probe factory for healthz and readyz - - b141ac6a2 2025-04-11T16:06:30+08:00 adjust container_spec_memory_limit_bytes e2e to range: ppc64le is 44*1024 less - - 2aa39a0c7 2025-04-10T22:38:18-07:00 Update the busybox test image to 1.37.0 - - f9c1876b4 2025-04-10T14:58:37-04:00 Make proxy CleanupLeftovers methods quieter - - b61ca041b 2025-04-10T14:58:35-04:00 Add some missing cleanup to "kube-proxy --cleanup" - - c1ff9cf4e 2025-04-10T21:16:47+08:00 chore: Upgrade the mockery version to v2.53.3. - - ffe235d2d 2025-04-10T15:07:18+02:00 replace context.TODO with context.Background in tests - - 4bd0c024e 2025-04-10T15:07:18+02:00 add goleak to kubelet vendor via hack/update-vendor.sh - - 161b44d04 2025-04-10T15:07:18+02:00 add missing header in httpstream_test.go; whitespace in imports - - 79150d1ec 2025-04-10T15:07:18+02:00 add unit tests to verify the fix - - 42d3716d7 2025-04-10T15:07:18+02:00 fixed the formatting - - 268033a51 2025-04-10T15:07:18+02:00 Fixed go routine leak in kubelet tests - - 30f1bcade 2025-04-10T09:05:23-04:00 Add a unit test for iptables.CleanupLeftovers, improve ipvs test - - 94530dad7 2025-04-10T09:03:25-04:00 Move iptables/ipvs/ipset interface creation into CleanupLeftovers - - 975e653af 2025-04-10T13:01:07+02:00 RWX tests should create RWX volumes - - 5ad90c3b6 2025-04-10T19:08:25+09:00 merge RunBenchmarkPerfScheduling and runBenchmarkPerfScheduling - - 780c0d672 2025-04-10T18:56:45+09:00 add license description in options.go - - 4f33b74a3 2025-04-10T09:25:08+02:00 Use Go 1.24 os.Root instead of filepath-securejoin - - 5677f7ab0 2025-04-09T16:16:48-04:00 Make Request#RequestURI honor configured context root - - b206264ff 2025-04-09T15:45:31+02:00 Shorten long directory names with e2e pod logs - - 2800c16c8 2025-04-09T15:00:16+02:00 Remove FlowSchemas handling non-leases-backed leader election - - 16f4a5c4e 2025-04-09T17:04:20+08:00 cleanup unneed code - - 88fbccd69 2025-04-09T16:21:38+08:00 Fix the allocatedResourceStatuses Field name mismatch in PVC status validation - - 302a85058 2025-04-09T13:08:21+05:30 Update coredns version to v1.12.1 - - d4fd41285 2025-04-08T10:21:02-07:00 update the log message to reflect success and failed jobs - - cc4284618 2025-04-08T07:10:13-07:00 Fix for HNS local endpoint was being deleted instead of the remote endpoint. - - 551f3c782 2025-04-07T17:37:19-07:00 merge the integration tests into a single one - - de98a71ff 2025-04-07T08:09:59-03:00 Update PodSecurityLevel used during Service CIDRs tests - - 58ff3129a 2025-04-03T15:57:08-05:00 update kubelet_authz.go to new test framework - - c7d0ed5c4 2025-04-01T12:38:15-07:00 add integration test for job failure event delay and remove the unit test - - 6747bf7a9 2025-04-01T13:59:32-04:00 Clean up leaked goroutines in cache unit tests - - 04d0715e6 2025-04-01T19:29:17+09:00 scheduler-perf: add option to enable api-server initialization - - 16af0d79d 2025-03-31T09:45:51-07:00 update sig-autoscaling maintainers - - 653f48d88 2025-03-30T10:46:59+08:00 Certificate store: ensure data is written to disk - - 5a14fdbf7 2025-03-28T11:18:33Z e2e: Keep original error when exec in container fails - - 9c228e81d 2025-03-28T12:39:01+03:00 Increase kubectl cp command timeout to 30 seconds - - 310b395a0 2025-03-27T17:56:06+01:00 [cloud-provider] respect the "exclude-from-external-load-balancers=false" label - - ae08504ca 2025-03-27T22:29:39+08:00 Remove unneeded return values - - 2c94112a0 2025-03-27T07:45:31Z Disable thresholds for PreemptionBasic and PreemptionPVs tests - - f7d885321 2025-03-27T10:07:25+09:00 Add dom4ha to SIG-Scheduling approvers - - 8e65a62b3 2025-03-26T16:50:26-07:00 Deduplicate MilliCPUToQuota function & constants - - 3067bbfe1 2025-03-26T12:10:23+01:00 hack/ginkgo-e2e.sh: fix misplaced brackets - - 5e4600e46 2025-03-26T07:55:40Z e2e service ip preservation test - - f7e82d805 2025-03-25T17:30:42-07:00 clarify mutual exclusivity of service account annotation keys in godoc - - 4fa963914 2025-03-25T15:08:34-07:00 kubectl http proxy e2e: do not append os.Environ() redundantly - - f7f4aa02b 2025-03-25T15:08:04-07:00 kubectl e2e: debug appended environment variables - - 5aa61f847 2025-03-24T18:27:50+01:00 Test tooling: fix agnhost pause command - - 65b8fba34 2025-03-24T12:53:50+01:00 Mask Linux thermal interrupt info in /proc and /sys. - - 0ff1e3778 2025-03-24T14:05:12+08:00 Remove general available feature-gate PodDisruptionConditions - - fe14689f2 2025-03-22T10:14:01+08:00 bump k8s.io/utils - - 1c3dc397a 2025-03-21T18:19:43-07:00 make update - - 8af1629f7 2025-03-21T18:19:29-07:00 remove inaccurate hostNetwork doc comment - - bad6c7e4c 2025-03-21T17:28:41Z Set LANGUAGE env variable in TestDiffProgram for consistent locale behavior - - c005b85d4 2025-03-21T15:23:08Z Reduce locking duration on cache to fetch data from Cache - - 252d584cb 2025-03-21T08:20:04-07:00 Implement validation-gen lint for CI - - 1a694bfd3 2025-03-21T08:19:49-07:00 Make validation-gen lint errors easier to read - - 8dc6806d2 2025-03-21T14:55:25+08:00 Expose NodeInfo to PreFilter plugins and Framework - - 5413d0edf 2025-03-21T12:37:19+09:00 chore: correct the comment on UnschedulablePlugins - - 8db5f0618 2025-03-20T22:46:38Z adding commits of the original PR - - 1b8bbcac4 2025-03-20T15:04:44-07:00 Add integration test - - 1402a5491 2025-03-20T14:51:54-07:00 Removed unused function UncompressLog. - - 88a3c000e 2025-03-20T14:33:38Z Implement CSI e2e test for MutableCSINodeAllocatableCount - - d868eeb08 2025-03-20T21:58:14+08:00 Migrate pkg/kubelet/status to contextual logging - - 7f263b057 2025-03-19T13:04:18-04:00 Tag api change instead of apimachinery on generated openapi. changes - - 4120ed1df 2025-03-19T16:06:30Z chore: `make update` for doc changes - - 356e14804 2025-03-19T15:46:30Z fix: comment on preferred PodAntiAffinity - - a2624f9c6 2025-03-19T15:09:26+08:00 make update - - 21f7026c2 2025-03-19T14:54:12+08:00 clean up CSIDriverRegistry - - a68501da7 2025-03-18T20:18:12Z Add check to see if promote worked within the retry loop - - 53499d97e 2025-03-13T16:15:24-07:00 prefer error over bool, prefer Should(gomega.Succeed()) - - d54ff7441 2025-03-13T13:57:55-07:00 test: don't panic during an Eventually retry loop - - cab6045a4 2025-03-13T17:36:25+01:00 hack: remove verify-e2e-suites.sh - - 73afab185 2025-03-10T14:01:29-07:00 handle review comments - - 51fdd55e8 2025-03-06T15:56:07-08:00 use sync map for the cache - - 3a5f8b4b9 2025-03-06T00:03:59-08:00 Update OWNERS_ALIASES for sig scalability - - 547c005cb 2025-03-04T14:42:13-08:00 handle job complete update delayed event - - 410ada002 2025-03-04T14:32:50+08:00 Made the unsupportedError msg more readable - - 780fac5a3 2025-02-28T09:45:42+08:00 chore(kubelet): migrate network to contextual logging - - 125b8d280 2025-02-25T14:43:53-08:00 Removed kubelet test duplicate line. - - c1efa2e16 2025-02-18T14:18:25+08:00 delete test/e2e/common/storage/volumes.go - - 429437962 2025-02-17T17:49:36+08:00 e2e storage test: intree driver adds the support for nfs v3 - - 6df869347 2025-02-17T14:13:48+08:00 remove outdate comment about pv controller - - 329990590 2025-02-14T20:23:30+01:00 Based on the issue #8304 add mfahlandt as ne Co Chair for Contributor Experience - - 9a60ea01f 2025-02-12T13:44:15+08:00 fix getPodMatches should call /runningpods endpoint - - 5da366e3e 2025-02-11T18:35:25+08:00 Update pkg/quota/v1/evaluator/core/resource_claims.go - - ce7d3ea00 2025-02-11T16:38:18+08:00 fix wrong api version in toExternalResourceClaimOrError - - 0f0f9d01c 2025-02-05T12:19:17+08:00 remove out-of-date comments about version - - c2b455f55 2025-01-25T23:02:41+08:00 remove unnecessary functions - - 44d31af29 2025-01-25T02:17:01Z Add example in etcd override flag help text - - 3dc611e66 2025-01-24T14:56:37+08:00 fix container lifecycle e2e tests - - 4a4fb0a11 2025-01-22T22:21:39+09:00 Fix LC_CTYPE for kubemark start scripts - - ea644981d 2025-01-14T14:19:16+08:00 Update pkg/controller/certificates/cleaner/cleaner.go - - 1e1e2dee9 2025-01-14T14:18:51+08:00 Update pkg/controller/certificates/cleaner/cleaner.go - - 006ebbc33 2025-01-07T21:18:25-06:00 Fix comment typos - - 4bf5f1a6b 2025-01-02T13:01:01-05:00 kubelet: add coverage for identical kubelet config and drop-in config content - - eae133919 2024-12-26T15:35:56+08:00 fix: killPodOptions support JSON serialization - - 55ba8f063 2024-12-10T16:18:57+02:00 kube-scheduler: Fix a misleading error message in the VolumeRestrictions plugin - - a52863827 2024-11-13T10:23:54+03:00 [kubectl] drain daemonSetFilter with other APIVersion - - 9f50740b7 2024-11-12T12:43:53-08:00 Simplify span handling - - c64b6f80e 2024-11-12T11:23:38-07:00 Trace across start handler invocations, nesting spans - - 6fd8954fe 2024-10-29T15:34:58+08:00 kube-controller-manager: also support context for record.NewBroadcaster - - bea35b1f5 2024-10-28T11:16:27+08:00 remove non-lease resource locks in tests. - - ff74405bd 2024-10-22T11:28:31+08:00 kubelet: remove --register-schedulable flag - - 05be83b38 2024-09-18T11:54:35+02:00 tracing: set audit-id on incoming requests - - eda71f9e9 2024-04-09T15:12:57+08:00 cleaner.go should use time.Until instead of t.Sub(time.Now()) - - 1354bb9e2 2023-11-20T17:54:16Z Update log verbosity for node health and taint checks +- kubernetes image-arm64 9f57f51e3485ccc1cfd01ec94e9a0f5bef38eacb to 9bbcda1bf017104f96c0f1bd27175d122f416f5a + - 9d621f97b 2025-12-10T10:10:48-03:00 UPSTREAM: 135476: Filter out the nodes created by other tests + - e2b978d53 2025-12-10T09:45:34+01:00 UPSTREAM: 135623: Fix the preemption test diff --git a/scripts/auto-rebase/commits.txt b/scripts/auto-rebase/commits.txt index 785e806c4d..a98a330ec4 100644 --- a/scripts/auto-rebase/commits.txt +++ b/scripts/auto-rebase/commits.txt @@ -1,35 +1,35 @@ -https://github.com/openshift/api embedded-component 5050707b5937d28133772a29825169e578310d2c -https://github.com/openshift/cluster-csi-snapshot-controller-operator embedded-component b022cf72ba3b4e982626d6d0b80bd53064bbe6ee -https://github.com/openshift/cluster-dns-operator embedded-component 2ec8a3de79d73760abbccdbcbbf9951fc93097cd -https://github.com/openshift/cluster-ingress-operator embedded-component 0cac97af560a68a5f5c0390a529726eb43556d51 -https://github.com/openshift/cluster-kube-apiserver-operator embedded-component adc82f6188f4037a515eeeaa686ce1c1a80894da -https://github.com/openshift/cluster-kube-controller-manager-operator embedded-component ffe5113eb88f384981fdeff599f22599e11a9d7c -https://github.com/openshift/cluster-kube-scheduler-operator embedded-component 10d89b53f7ddcf0ee45f838c1a43e408074343e6 -https://github.com/openshift/cluster-network-operator embedded-component a5879759fb042f6c4b26931fa7ef8540244c8660 -https://github.com/openshift/cluster-openshift-controller-manager-operator embedded-component da1e14c45093c19bc79e2055c9f4a55efc1cc1a8 -https://github.com/openshift/cluster-policy-controller embedded-component ef703966fe6e82f5f255b06bc5c758f105bf8b28 -https://github.com/openshift/csi-external-snapshotter embedded-component 15313fb28f5c42e4b896928478652768225692a6 -https://github.com/openshift/etcd embedded-component e2b3dfdf037938f7f0c489438eaa1138fd3fadba -https://github.com/openshift/kubernetes embedded-component 96593f323733d9ffc0fc70257ecad44a56df0ce3 +https://github.com/openshift/api embedded-component c2a41ea924bd8227622363c3d12f456cd2186924 +https://github.com/openshift/cluster-csi-snapshot-controller-operator embedded-component 0dd541084bee8885dbd14dcd6eb2f826ba779883 +https://github.com/openshift/cluster-dns-operator embedded-component 41a53fed36e6e99c7c9ceb3a699c3547ee5d9bb9 +https://github.com/openshift/cluster-ingress-operator embedded-component b62dd27c901d495e6e78b11968872c002cc2416f +https://github.com/openshift/cluster-kube-apiserver-operator embedded-component 2c58d2f2bad129f0017ca194ae8a38711917c21c +https://github.com/openshift/cluster-kube-controller-manager-operator embedded-component 395de96705749de9c6a5f25747b9d5c3d5f65a8f +https://github.com/openshift/cluster-kube-scheduler-operator embedded-component 4f59ea50a588e9afa714e30e7502eca8b570751b +https://github.com/openshift/cluster-network-operator embedded-component 8d09651e31c64340865f7ec7f349786528805ebd +https://github.com/openshift/cluster-openshift-controller-manager-operator embedded-component 2617a201bb3607192a9f82faa18384676f611e3c +https://github.com/openshift/cluster-policy-controller embedded-component 8b775487512fb543bff470ff1042bd3ac31b29be +https://github.com/openshift/csi-external-snapshotter embedded-component 9098db0e434e0d986eeadd2ebe69119540a550d1 +https://github.com/openshift/etcd embedded-component 806f690e1f140e0aea2eb05ef5f288b756b62895 +https://github.com/openshift/kubernetes embedded-component 9f57f51e3485ccc1cfd01ec94e9a0f5bef38eacb https://github.com/openshift/kubernetes-kube-storage-version-migrator embedded-component ce5ff17e9a81ce754567e6dd5053d13409c251e9 -https://github.com/openshift/machine-config-operator embedded-component 7007a56217125f6b5ea358a520c080c4ac002575 -https://github.com/openshift/openshift-controller-manager embedded-component 15fc552a73e47ae715f0cf59e3f535e26b43477a -https://github.com/openshift/operator-framework-olm embedded-component bdc0d750909a7cea17b087f53bcaa01d449638f1 -https://github.com/openshift/route-controller-manager embedded-component c337cf413bbbfc2154dc1d3c1bf8007ea1edfbc8 -https://github.com/openshift/service-ca-operator embedded-component e5d65c6f6b1446b77e0e915d64825d97be9c06de -https://github.com/openshift/oc image-amd64 672ff624b7d2523487d4f06565099949c625d43c -https://github.com/openshift/coredns image-amd64 91ae57f91e0bba5fc4fdb816e1f1cea633b3a8b5 -https://github.com/openshift/csi-external-snapshotter image-amd64 15313fb28f5c42e4b896928478652768225692a6 -https://github.com/openshift/router image-amd64 526b4d0ad4cd9d44b43e2585b3415e513fbaf3da -https://github.com/openshift/kube-rbac-proxy image-amd64 b9134351be37c43408334047d8eb85d0ac01fe4e -https://github.com/openshift/ovn-kubernetes image-amd64 3f971b1c061a775aedee0e9a06ab2a2a31bc64cc -https://github.com/openshift/kubernetes image-amd64 96593f323733d9ffc0fc70257ecad44a56df0ce3 -https://github.com/openshift/service-ca-operator image-amd64 e5d65c6f6b1446b77e0e915d64825d97be9c06de -https://github.com/openshift/oc image-arm64 672ff624b7d2523487d4f06565099949c625d43c -https://github.com/openshift/coredns image-arm64 91ae57f91e0bba5fc4fdb816e1f1cea633b3a8b5 -https://github.com/openshift/csi-external-snapshotter image-arm64 15313fb28f5c42e4b896928478652768225692a6 -https://github.com/openshift/router image-arm64 526b4d0ad4cd9d44b43e2585b3415e513fbaf3da -https://github.com/openshift/kube-rbac-proxy image-arm64 b9134351be37c43408334047d8eb85d0ac01fe4e -https://github.com/openshift/ovn-kubernetes image-arm64 3f971b1c061a775aedee0e9a06ab2a2a31bc64cc -https://github.com/openshift/kubernetes image-arm64 96593f323733d9ffc0fc70257ecad44a56df0ce3 -https://github.com/openshift/service-ca-operator image-arm64 e5d65c6f6b1446b77e0e915d64825d97be9c06de +https://github.com/openshift/machine-config-operator embedded-component e2f6042b4bd21ad64115fa5be529edc1cce8c451 +https://github.com/openshift/openshift-controller-manager embedded-component 438d52e79d691e016d66eabfe9a53c84229db40c +https://github.com/openshift/operator-framework-olm embedded-component 7d2dd62c2a73b66aa99e82c90f64ab53dd523ddf +https://github.com/openshift/route-controller-manager embedded-component 8a69194a461dc33d2ed67a220bca91d384d34df4 +https://github.com/openshift/service-ca-operator embedded-component e9622ba18c86bf24aceab0c19fdcb87339c14f44 +https://github.com/openshift/oc image-amd64 345800dc3c4164fbca313c1cbfb383f262547903 +https://github.com/openshift/coredns image-amd64 7486e9e4330c1e41d9a91e4673b7f2782efc112c +https://github.com/openshift/csi-external-snapshotter image-amd64 9098db0e434e0d986eeadd2ebe69119540a550d1 +https://github.com/openshift/router image-amd64 b231c65b5c06c1f74590ca8e77caecc6213beb6a +https://github.com/openshift/kube-rbac-proxy image-amd64 cd636680e06a55395c26570dff0cb37277014388 +https://github.com/openshift/ovn-kubernetes image-amd64 25a714b82c643bcfdf5543cb467afa32dac06787 +https://github.com/openshift/kubernetes image-amd64 9f57f51e3485ccc1cfd01ec94e9a0f5bef38eacb +https://github.com/openshift/service-ca-operator image-amd64 e9622ba18c86bf24aceab0c19fdcb87339c14f44 +https://github.com/openshift/oc image-arm64 345800dc3c4164fbca313c1cbfb383f262547903 +https://github.com/openshift/coredns image-arm64 7486e9e4330c1e41d9a91e4673b7f2782efc112c +https://github.com/openshift/csi-external-snapshotter image-arm64 9098db0e434e0d986eeadd2ebe69119540a550d1 +https://github.com/openshift/router image-arm64 b231c65b5c06c1f74590ca8e77caecc6213beb6a +https://github.com/openshift/kube-rbac-proxy image-arm64 cd636680e06a55395c26570dff0cb37277014388 +https://github.com/openshift/ovn-kubernetes image-arm64 25a714b82c643bcfdf5543cb467afa32dac06787 +https://github.com/openshift/kubernetes image-arm64 9bbcda1bf017104f96c0f1bd27175d122f416f5a +https://github.com/openshift/service-ca-operator image-arm64 e9622ba18c86bf24aceab0c19fdcb87339c14f44 diff --git a/scripts/auto-rebase/last_rebase.sh b/scripts/auto-rebase/last_rebase.sh index aff9dafe8d..773af90810 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.21.0-0.nightly-2025-10-19-181151" "registry.ci.openshift.org/ocp-arm64/release-arm64:4.21.0-0.nightly-arm64-2025-10-19-182251" +./scripts/auto-rebase/rebase.sh to "registry.ci.openshift.org/ocp/release:4.21.0-0.nightly-2025-12-10-193741" "registry.ci.openshift.org/ocp-arm64/release-arm64:4.21.0-0.nightly-arm64-2025-12-12-014247" diff --git a/scripts/auto-rebase/last_rebase_ai_model_serving.sh b/scripts/auto-rebase/last_rebase_ai_model_serving.sh index 6342e5d719..27303c971c 100755 --- a/scripts/auto-rebase/last_rebase_ai_model_serving.sh +++ b/scripts/auto-rebase/last_rebase_ai_model_serving.sh @@ -1,2 +1,2 @@ #!/bin/bash -x -./scripts/auto-rebase/rebase_ai_model_serving.sh to "registry.redhat.io/rhoai/odh-operator-bundle:v2.22" +./scripts/auto-rebase/rebase_ai_model_serving.sh to "registry.redhat.io/rhoai/odh-operator-bundle:v2.25" diff --git a/scripts/auto-rebase/last_rebase_sriov.sh b/scripts/auto-rebase/last_rebase_sriov.sh new file mode 100755 index 0000000000..7eabd6e8b2 --- /dev/null +++ b/scripts/auto-rebase/last_rebase_sriov.sh @@ -0,0 +1,2 @@ +#!/bin/bash -x +./scripts/auto-rebase/rebase_sriov.sh to "registry.redhat.io/openshift4/ose-sriov-network-operator-bundle:v4.20" diff --git a/scripts/auto-rebase/manifests_patches/020-dns-configmap.patch b/scripts/auto-rebase/manifests_patches/020-dns-configmap.patch new file mode 100644 index 0000000000..f78508a605 --- /dev/null +++ b/scripts/auto-rebase/manifests_patches/020-dns-configmap.patch @@ -0,0 +1,18 @@ +diff --git a/assets/components/openshift-dns/dns/configmap.yaml b/assets/components/openshift-dns/dns/configmap.yaml +index 9cd48dbe0..2b4194e99 100644 +--- a/assets/components/openshift-dns/dns/configmap.yaml ++++ b/assets/components/openshift-dns/dns/configmap.yaml +@@ -22,6 +22,13 @@ data: + cache 900 { + denial 9984 30 + } ++ ++ {{- if .HostsEnabled }} ++ hosts /tmp/hosts/hosts { ++ fallthrough ++ } ++ {{- end }} ++ + reload + } + hostname.bind:5353 { diff --git a/scripts/auto-rebase/manifests_patches/020-dns-daemonset.patch b/scripts/auto-rebase/manifests_patches/020-dns-daemonset.patch new file mode 100644 index 0000000000..569a170a22 --- /dev/null +++ b/scripts/auto-rebase/manifests_patches/020-dns-daemonset.patch @@ -0,0 +1,31 @@ +diff --git a/assets/components/openshift-dns/dns/daemonset.yaml b/assets/components/openshift-dns/dns/daemonset.yaml +index 630fa3f93..590fc3daa 100644 +--- a/assets/components/openshift-dns/dns/daemonset.yaml ++++ b/assets/components/openshift-dns/dns/daemonset.yaml +@@ -24,6 +24,11 @@ spec: + readOnly: true + - mountPath: /tmp + name: tmp-dir ++ {{- if .HostsEnabled }} ++ - mountPath: /tmp/hosts ++ name: hosts ++ readOnly: true ++ {{- end }} + ports: + - containerPort: 5353 + name: dns +@@ -95,6 +100,14 @@ spec: + secret: + defaultMode: 420 + secretName: dns-default-metrics-tls ++ {{- if .HostsEnabled }} ++ - name: hosts ++ configMap: ++ name: hosts-file ++ items: ++ - key: hosts ++ path: hosts ++ {{- end }} + - name: tmp-dir + emptyDir: {} + nodeSelector: diff --git a/scripts/auto-rebase/manifests_patches/020-dns-hosts-configmap-role.patch b/scripts/auto-rebase/manifests_patches/020-dns-hosts-configmap-role.patch new file mode 100644 index 0000000000..3e90016030 --- /dev/null +++ b/scripts/auto-rebase/manifests_patches/020-dns-hosts-configmap-role.patch @@ -0,0 +1,22 @@ +diff --git a/assets/components/openshift-dns/dns/hosts-configmap-role.yaml b/assets/components/openshift-dns/dns/hosts-configmap-role.yaml +new file mode 100644 +index 000000000..e23d64663 +--- /dev/null ++++ b/assets/components/openshift-dns/dns/hosts-configmap-role.yaml +@@ -0,0 +1,16 @@ ++kind: Role ++apiVersion: rbac.authorization.k8s.io/v1 ++metadata: ++ name: hosts-configmap-reader ++ namespace: openshift-dns ++rules: ++- apiGroups: ++ - "" ++ resources: ++ - configmaps ++ resourceNames: ++ - hosts-file ++ verbs: ++ - get ++ - list ++ - watch diff --git a/scripts/auto-rebase/manifests_patches/020-dns-hosts-configmap-rolebinding.patch b/scripts/auto-rebase/manifests_patches/020-dns-hosts-configmap-rolebinding.patch new file mode 100644 index 0000000000..3b94a0d4d0 --- /dev/null +++ b/scripts/auto-rebase/manifests_patches/020-dns-hosts-configmap-rolebinding.patch @@ -0,0 +1,19 @@ +diff --git a/assets/components/openshift-dns/dns/hosts-configmap-rolebinding.yaml b/assets/components/openshift-dns/dns/hosts-configmap-rolebinding.yaml +new file mode 100644 +index 000000000..e5acd3916 +--- /dev/null ++++ b/assets/components/openshift-dns/dns/hosts-configmap-rolebinding.yaml +@@ -0,0 +1,13 @@ ++kind: RoleBinding ++apiVersion: rbac.authorization.k8s.io/v1 ++metadata: ++ name: hosts-configmap-reader ++ namespace: openshift-dns ++subjects: ++- kind: ServiceAccount ++ name: dns ++ namespace: openshift-dns ++roleRef: ++ kind: Role ++ name: hosts-configmap-reader ++ apiGroup: rbac.authorization.k8s.io diff --git a/scripts/auto-rebase/presubmit.py b/scripts/auto-rebase/presubmit.py index d468afd6e4..5e90ed4639 100755 --- a/scripts/auto-rebase/presubmit.py +++ b/scripts/auto-rebase/presubmit.py @@ -28,6 +28,7 @@ "./scripts/auto-rebase/ossm_assets.yaml", "./scripts/auto-rebase/assets_ai_model_serving.yaml", "./scripts/auto-rebase/assets_cert_manager.yaml", + "./scripts/auto-rebase/assets_sriov.yaml", ] diff --git a/scripts/auto-rebase/rebase.py b/scripts/auto-rebase/rebase.py index 0924cb6261..4dfd566cb7 100755 --- a/scripts/auto-rebase/rebase.py +++ b/scripts/auto-rebase/rebase.py @@ -16,17 +16,16 @@ from pathlib import Path from timeit import default_timer as timer -from git import PushInfo, Repo # GitPython -from github import Github, GithubException, GithubIntegration # pygithub - -APP_ID_ENV = "APP_ID" # GitHub App's ID -KEY_ENV = "KEY" # Path to GitHub App's key -PAT_ENV = "TOKEN" # Personal Access Token -ORG_ENV = "ORG" -REPO_ENV = "REPO" +from github import GithubException # pygithub + +sys.path.append(str(Path(__file__).resolve().parent / '../pyutils')) +import gitutils # noqa: E402 +import ghutils # noqa: E402 + AMD64_RELEASE_ENV = "AMD64_RELEASE" ARM64_RELEASE_ENV = "ARM64_RELEASE" RHOAI_RELEASE_ENV = "RHOAI_RELEASE" +SRIOV_RELEASE_ENV = "SRIOV_RELEASE" OPM_VERSION_ENV = "OPM_RELEASE" JOB_NAME_ENV = "JOB_NAME" BUILD_ID_ENV = "BUILD_ID" @@ -36,9 +35,6 @@ BOT_REMOTE_NAME = "bot-creds" REMOTE_ORIGIN = "origin" -# List of reviewers to always request review from -REVIEWERS = [] - # If True, then just log action such as branch push and PR or comment creation REMOTE_DRY_RUN = False @@ -103,6 +99,26 @@ def run_rebase_ai_model_serving_sh(release): return RebaseScriptResult(success=result.returncode == 0, output=result.stdout) +def run_rebase_sriov_sh(release): + """Run the 'rebase_sriov.sh' script with the given release version and return the script's output.""" + script_dir = os.path.abspath(os.path.dirname(__file__)) + args = [f"{script_dir}/rebase_sriov.sh", "to", release] + env = os.environ.copy() + env["NO_BRANCH"] = "true" + logging.info(f"Running: '{' '.join(args)}'") + start = timer() + result = subprocess.run( + args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, check=False, + env=env) + logging.info(f"Return code: {result.returncode}. Output:\n" + + "==================================================\n" + + f"{result.stdout}" + + "==================================================\n") + end = timer() - start + logging.info(f"Script returned code: {result.returncode}. It ran for {end/60:.0f}m{end%60:.0f}s.") + return RebaseScriptResult(success=result.returncode == 0, output=result.stdout) + + def run_rebase_cert_manager_sh(release): """Run the 'rebase_cert_manager.sh' script with the given release version and return the script's output.""" script_dir = os.path.abspath(os.path.dirname(__file__)) @@ -123,28 +139,13 @@ def run_rebase_cert_manager_sh(release): return RebaseScriptResult(success=result.returncode == 0, output=result.stdout) -def commit_str(commit): - """Returns the first 8 characters of the commit's SHA hash and the commit summary.""" - return f"{commit.hexsha[:8]} - {commit.summary}" - - -def get_installation_access_token(app_id, key_path, org, repo): - """Get a installation access token for a GitHub App installation.""" - integration = GithubIntegration(app_id, Path(key_path).read_text(encoding='utf-8')) - app_installation = integration.get_installation(org, repo) - if app_installation is None: - sys.exit(f"Failed to get app_installation for {org}/{repo}. " + - f"Response: {app_installation.raw_data}") - return integration.get_access_token(app_installation.id).token - - def make_sure_rebase_script_created_new_commits_or_exit(git_repo, base_branch): """Exit the script if the 'rebase.sh' script did not create any new commits.""" if git_repo.active_branch.commit == git_repo.branches[base_branch].commit: logging.info(f"There's no new commit on branch {git_repo.active_branch} compared to '{base_branch}' " "meaning that the rebase.sh script didn't create any commits and " "MicroShift is already rebased on top of given release.\n" - f"Last commit: {commit_str(git_repo.active_branch.commit)}") + f"Last commit: {gitutils.commit_str(git_repo.active_branch.commit)}") sys.exit(0) @@ -178,106 +179,6 @@ def rebase_script_made_changes_considered_functional(git_repo, base_branch): return False -def get_remote_with_token(git_repo, token, org, repo): - """ - Returns the Git remote for the given repository using - the provided installation (or personal) access token. - """ - remote_url = f"https://x-access-token:{token}@github.com/{org}/{repo}" - try: - remote = git_repo.remote(BOT_REMOTE_NAME) - remote.set_url(remote_url) - except ValueError: - git_repo.create_remote(BOT_REMOTE_NAME, remote_url) - - return git_repo.remote(BOT_REMOTE_NAME) - - -def try_get_rebase_branch_ref_from_remote(remote, branch_name): - """ - Get the reference for the given branch on the specified Git remote, - otherwise return None if the branch does not exist. - """ - remote.fetch() - matching_remote_refs = [ref for ref in remote.refs if BOT_REMOTE_NAME + "/" + branch_name == ref.name] - - if len(matching_remote_refs) == 0: - logging.info(f"Branch '{branch_name}' does not exist on remote") - return None - - if len(matching_remote_refs) > 1: - matching_branches = ", ".join([r.name for r in matching_remote_refs]) - logging.warning(f"Found more than one branch matching '{branch_name}' " + - f"on remote: {matching_branches}. Taking first one") - _extra_msgs.append(f"Found more than one branch matching '{branch_name}' " + - f"on remote: {matching_branches}.") - return matching_remote_refs[0] - - if len(matching_remote_refs) == 1: - logging.info(f"Branch '{branch_name}' already exists on remote") - return matching_remote_refs[0] - - return None - - -def is_local_branch_based_on_newer_base_branch_commit(git_repo, base_branch_name, remote_branch_name, local_branch_name): - """ - Compares local and remote rebase branches by looking at their start on base branch. - Returns True if local branch starts on newer commit and needs to be pushed to remote, - otherwise False. - """ - remote_merge_base = git_repo.merge_base(base_branch_name, remote_branch_name) - local_merge_base = git_repo.merge_base(base_branch_name, local_branch_name) - - if remote_merge_base[0] == local_merge_base[0]: - logging.info("Remote branch is up to date. " + - f"Branch-off commit: {commit_str(remote_merge_base[0])}") - return False - - logging.info( - f"Remote branch is older - it needs updating. " - f"Remote branch is on top of {base_branch_name}'s commit: '{commit_str(remote_merge_base[0])}'. " - f"Local branch is on top of {base_branch_name}'s commit '{commit_str(local_merge_base[0])}'" - ) - return True - - -def try_get_pr(gh_repo, org, base_branch, branch_name): - """ - Try to get a pull request for a branch on a GitHub repository. - Returns - - The pull request if it exists and is open, otherwise None. - - If more than one pull request is found, then the first one will be used. - """ - prs = gh_repo.get_pulls(base=base_branch, head=f"{org}:{branch_name}", state="all") - - if prs.totalCount == 0: - logging.info(f"PR for branch {branch_name} does not exist yet on {gh_repo.full_name}") - return None - - pull_req = None - if prs.totalCount > 1: - pull_req = prs[0] - logging.warning( - f"Found more than one PR for branch {branch_name} on {gh_repo.full_name} -" + - f"this is unexpected, continuing with first one of: {[(x.state, x.html_url) for x in prs]}" - ) - - if prs.totalCount == 1: - pull_req = prs[0] - logging.info(f"Found PR #{pull_req.number} for branch {branch_name} on {gh_repo.full_name}: {pull_req.html_url}") - - if pull_req.state == 'closed': - logging.warning(f"PR #{pull_req.number} is not open - new PR will be created") - if pull_req.is_merged(): - logging.warning(f"PR #{pull_req.number} for '{branch_name}' branch is already merged but rebase.sh produced results") - _extra_msgs.append(f"PR #{pull_req.number} for '{branch_name}' was already merged but rebase.sh produced results") - else: - _extra_msgs.append(f"PR #{pull_req.number} for '{branch_name}' exists already but was closed") - return None - return pull_req - - def generate_pr_description(amd_tag, arm_tag, prow_job_url, rebase_script_succeded): # pylint: disable=unused-argument """ Returns a string that represents the body of a pull request (PR) description. @@ -316,79 +217,6 @@ def generate_pr_description(amd_tag, arm_tag, prow_job_url, rebase_script_succed else "# rebase.sh failed - check committed rebase_sh.log\n\n" + base) -def create_pr(gh_repo, base_branch, branch_name, title, desc): - """ - Creates a pull request (and requests reviews) for a given branch on a GitHub repository. - If the `REMOTE_DRY_RUN` variable is True, it logs the PR creation request without actually creating it. - """ - if REMOTE_DRY_RUN: - logging.info(f"[DRY RUN] Create PR: branch='{branch_name}', title='{title}', desc='{desc}'") - logging.info(f"[DRY RUN] Requesting review from {REVIEWERS}") - return None - - pull_req = gh_repo.create_pull( - title=title, body=desc, base=base_branch, head=branch_name, maintainer_can_modify=True) - logging.info(f"Created pull request: {pull_req.html_url}") - try: - pull_req.create_review_request(reviewers=REVIEWERS) - logging.info(f"Requested review from {REVIEWERS}") - except GithubException as err: - logging.info(f"Failed to request review from {REVIEWERS} because: {err}") - return pull_req - - -def update_pr(pull_req, title, desc): - """Updates the title and description of a pull request on a GitHub repository.""" - if REMOTE_DRY_RUN: - logging.info(f"[DRY RUN] Update PR #{pull_req.number}: {title}\n{desc}") - return - - pull_req.edit(title=title, body=desc) - pull_req.update() # arm64 release or prow job url might've changed - logging.info(f"Updated PR #{pull_req.number}: {title}\n{desc}") - - -def post_comment(pull_req, comment=""): - """ - Posts a comment on a GitHub pull request with - the contents of the global `_extra_msgs` list. - """ - if len(_extra_msgs) != 0: - if comment != "": - comment += "\n\n" - comment += "Extra messages:\n - " + "\n - ".join(_extra_msgs) - - if comment.strip() != "": - logging.info(f"Comment to post: {comment}") - if REMOTE_DRY_RUN: - logging.info("[DRY RUN] Posted a comment") - return - issue = pull_req.as_issue() - issue.create_comment(comment) - else: - logging.info("No content for comment") - - -def push_branch_or_die(remote, branch_name): - """ - Attempts to push a branch to a remote Git repository, - and terminates the program if the push fails. - """ - if REMOTE_DRY_RUN: - logging.info(f"[DRY RUN] git push --force {branch_name}") - return - - # TODO add retries - push_result = remote.push(branch_name, force=True) - - if len(push_result) != 1: - sys.exit(f"Unexpected amount ({len(push_result)}) of items in push_result: {push_result}") - if push_result[0].flags & PushInfo.ERROR: - sys.exit(f"Pushing branch failed: {push_result[0].summary}") - if push_result[0].flags & PushInfo.FORCED_UPDATE: - logging.info(f"Branch '{branch_name}' existed and was updated (force push)") - - def get_release_tag(release): """ Given a release string in the format "abc:xyz", returns the "xyz" portion of the string. @@ -441,26 +269,6 @@ def get_expected_branch_name(amd, arm): return f"rebase-{match_amd['version_stream']}_amd64-{match_amd['date']}_arm64-{match_arm['date']}" -def get_base_branch_name(gh_repo, base_branch): - """ - Given a branch name, determine if the rebase branch should be the same - or it should target main, depending on the current stage in the dev cycle. - """ - issues = gh_repo.get_issues(state="open") - for issue in issues: - title = issue.title - if title.startswith("Future Release Branches Frozen For Merging"): - try: - branches_part = title.split('|', 1)[1].strip() - branch_tokens = branches_part.split() - if f"branch:{base_branch}" in branch_tokens: - return "main" - except Exception as e: - logging.warning(f"Failed to parse freeze issue title: {title} ({e})") - continue - return base_branch - - def cleanup_branches(gh_repo): """ Deletes branches with names in the format "rebase-4*" that are @@ -491,32 +299,15 @@ def cleanup_branches(gh_repo): _extra_msgs.append("Deleted following branches: " + ", ".join(deleted_branches)) -def get_token(org, repo): - """ - Returns a token to be used with GitHub API. - It's either Personal Access Token if TOKEN env is set, - or Installation Access Token which is intended to be used with GitHub Apps. - """ - personal_access_token = try_get_env(PAT_ENV, die=False) - if personal_access_token != "": - logging.info("Using Personal Access Token to access GitHub API") - return personal_access_token - - app_id = try_get_env(APP_ID_ENV) - key_path = try_get_env(KEY_ENV) - return get_installation_access_token(app_id, key_path, org, repo) - - def main(): """ The main function of the script. Reads environment variables, retrieves the necessary information from GitHub, performs a rebase, creates a pull request, and cleans up old branches. """ - org = try_get_env(ORG_ENV) - repo = try_get_env(REPO_ENV) release_amd = try_get_env(AMD64_RELEASE_ENV) release_arm = try_get_env(ARM64_RELEASE_ENV) rhoai_release = try_get_env(RHOAI_RELEASE_ENV) + sriov_release = try_get_env(SRIOV_RELEASE_ENV) opm_version = try_get_env(OPM_VERSION_ENV) base_branch_override = try_get_env(BASE_BRANCH_ENV, die=False) @@ -525,25 +316,24 @@ def main(): if REMOTE_DRY_RUN: logging.info("Dry run mode") - token = get_token(org, repo) - gh_repo = Github(token).get_repo(f"{org}/{repo}") - git_repo = Repo('.') + g = gitutils.GitUtils(dry_run=REMOTE_DRY_RUN) base_branch = ( - git_repo.active_branch.name + g.git_repo.active_branch.name if base_branch_override == "" else base_branch_override ) rebase_result = run_rebase_sh(release_amd, release_arm) ai_rebase_result = run_rebase_ai_model_serving_sh(rhoai_release) + sriov_rebase_result = run_rebase_sriov_sh(sriov_release) cert_manager_rebase_result = run_rebase_cert_manager_sh(opm_version) - rebases_succeeded = all([rebase_result.success, ai_rebase_result.success, cert_manager_rebase_result.success]) + rebases_succeeded = all([rebase_result.success, ai_rebase_result.success, sriov_rebase_result.success, cert_manager_rebase_result.success]) if rebases_succeeded: # TODO How can we inform team that rebase job ran successfully just there was nothing new? - make_sure_rebase_script_created_new_commits_or_exit(git_repo, base_branch) - if rebase_script_made_changes_considered_functional(git_repo, base_branch): + make_sure_rebase_script_created_new_commits_or_exit(g.git_repo, base_branch) + if rebase_script_made_changes_considered_functional(g.git_repo, base_branch): logging.info("Detected functional changes made by rebase script - proceeding with creating PR") else: logging.info("Rebase did not produce any change considered to be functional - quitting") @@ -557,48 +347,49 @@ def main(): "rebase_ai_model_serving.sh:\n" + f"{ai_rebase_result.output}") writer.write(output) - if git_repo.active_branch.name == base_branch: + if g.git_repo.active_branch.name == base_branch: # rebase.sh didn't reach the step that would create a branch # so script needs to create it - branch = git_repo.create_head(get_expected_branch_name(release_amd, release_arm)) - branch.checkout() - git_repo.git.add(A=True) - git_repo.index.commit("rebase.sh failure artifacts") + g.checkout_branch(get_expected_branch_name(release_amd, release_arm)) + g.add_files_to_staging_area(all=True) + g.commit("rebase.sh failure artifacts") - rebase_branch_name = git_repo.active_branch.name - adjusted_base_branch = get_base_branch_name(gh_repo, base_branch) + gh = ghutils.GithubUtils(dry_run=REMOTE_DRY_RUN) + + rebase_branch_name = g.git_repo.active_branch.name + adjusted_base_branch = "main" if gh.is_branch_under_active_development(base_branch) else base_branch logging.info(f"Adjusted base branch: {adjusted_base_branch}") - git_remote = get_remote_with_token(git_repo, token, org, repo) - remote_branch = try_get_rebase_branch_ref_from_remote(git_remote, rebase_branch_name) # {BOT_REMOTE_NAME}/{rebase_branch_name} + + g.setup_remote_with_token(gh.token, gh.org, gh.repo) + remote_branch = g.get_remote_branch(rebase_branch_name) # {BOT_REMOTE_NAME}/{rebase_branch_name} rbranch_does_not_exists = remote_branch is None rbranch_exists_and_needs_update = ( remote_branch is not None and - is_local_branch_based_on_newer_base_branch_commit(git_repo, adjusted_base_branch, remote_branch.name, rebase_branch_name) + g.is_local_branch_based_on_newer_base_branch_commit(base_branch, remote_branch.name, rebase_branch_name) ) if rbranch_does_not_exists or rbranch_exists_and_needs_update: - push_branch_or_die(git_remote, rebase_branch_name) + g.push(rebase_branch_name) prow_job_url = try_create_prow_job_url() pr_title = create_pr_title(rebase_branch_name, rebase_result.success) desc = generate_pr_description(get_release_tag(release_amd), get_release_tag(release_arm), prow_job_url, rebase_result.success) comment = "" - pull_req = try_get_pr(gh_repo, org, adjusted_base_branch, rebase_branch_name) + pull_req = gh.get_existing_pr_for_a_branch(adjusted_base_branch, rebase_branch_name) if pull_req is None: - pull_req = create_pr(gh_repo, adjusted_base_branch, rebase_branch_name, pr_title, desc) + pull_req = gh.create_pr(adjusted_base_branch, rebase_branch_name, pr_title, desc) else: - update_pr(pull_req, pr_title, desc) + gh.update_pr(pull_req, pr_title, desc) comment = f"Rebase job updated the branch\n{desc}" if adjusted_base_branch == "main": - cleanup_branches(gh_repo) - post_comment(pull_req, comment) + cleanup_branches(gh.gh_repo) - post_comment(pull_req, '/verified by automatic-rebase') + gh.post_comment(pull_req, comment, _extra_msgs) - git_remote.remove(git_repo, BOT_REMOTE_NAME) - sys.exit(0 if rebase_result.success else 1) + g.remove_remote_with_token() + sys.exit(0 if rebases_succeeded else 1) if __name__ == "__main__": diff --git a/scripts/auto-rebase/rebase.sh b/scripts/auto-rebase/rebase.sh index 3ffd6c6c74..f92ea95cd1 100755 --- a/scripts/auto-rebase/rebase.sh +++ b/scripts/auto-rebase/rebase.sh @@ -232,8 +232,15 @@ replace_using_component_commit() { # edit and tidy commands, allow errors. A final tidy runs without -e to ensure all dependencies # are ok. go mod tidy -e - pseudoversion=$(grep_pseudoversion "$(get_replace_directive "$(pwd)/go.mod" "${modulepath}")") - pseudoversions["${component}"]="${pseudoversion}" + + if [[ "${modulepath}" =~ ^go.etcd.io/etcd/ ]]; then + # For some reason, pseudo-version created for one etcd package might not be working with another, despite being in the same repository. + # So for etcd, don't cache the pseudo-version. + : + else + pseudoversion=$(grep_pseudoversion "$(get_replace_directive "$(pwd)/go.mod" "${modulepath}")") + pseudoversions["${component}"]="${pseudoversion}" + fi fi } @@ -450,6 +457,7 @@ update_go_mod() { require_using_component_commit github.com/openshift/route-controller-manager route-controller-manager require_using_component_commit github.com/openshift/cluster-policy-controller cluster-policy-controller + make update-gofmt if grep -q "^patch-deps:" ./Makefile; then # etcd/ does not need to patch the dependencies make patch-deps @@ -519,6 +527,10 @@ handle_deps() { ;; esac + # Following file is always generating a diff because it has CRLF line endings, but `git add` updates it to LF and the diff is gone. + # Remove the problematic file once for all. + rm -f deps/github.com/openshift/kubernetes/vendor/github.com/MakeNowJust/heredoc/README.md || true + go mod tidy -e } @@ -551,20 +563,6 @@ update_go_mods() { go mod edit -toolchain=none "${REPOROOT}/etcd/go.mod" } - update_deps_fmt() { - # The verify-gofmt targets belong to build-machinery-go makefiles and we can not override - # the files that are checked. `vendor` is automatically excluded from checks, but deps is - # something that only exists in MicroShift and we can not override it. Running gofmt over - # this directory will ensure the verify target works while still not changing functionality. - title "Ensuring gofmt" - make update-gofmt - if [[ -n "$(git status -s deps)" ]]; then - title "## Commiting gofmt changes to deps directory" - git add deps - git commit -m "update deps gofmt" - fi - } - # Regenerates OpenAPIs after patching the vendor directory regenerate_openapi() { pushd "${STAGING_DIR}/kubernetes" >/dev/null @@ -1236,24 +1234,20 @@ rebase_to() { title "## Committing changes to ${dirname}/go.mod" git add "${dirpath}/go.mod" "${dirpath}/go.sum" git commit -m "update ${dirname}/go.mod" + fi - title "## Updating deps/ directory" - if [[ -n "$(git status -s "${dirpath}/deps")" ]]; then - title "## Commiting changes to ${dirname}/deps directory" - git add "${dirpath}/deps" - git commit -m "update ${dirname}/deps" - fi + if [[ -n "$(git status -s "${dirpath}/deps")" ]]; then + title "## Commiting changes to ${dirname}/deps directory" + git add "${dirpath}/deps" + git commit -m "update ${dirname}/deps" + fi - title "## Updating ${dirname}/vendor directory" - pushd "${dirpath}" && make vendor && popd || exit 1 - if [[ -n "$(git status -s "${dirpath}/vendor")" ]]; then - title "## Commiting changes to ${dirname}/vendor directory" - git add "${dirpath}/vendor" - git commit -m "update ${dirname}/vendor" - fi - update_deps_fmt - else - echo "No changes in ${dirname}/go.mod." + title "## Updating ${dirname}/vendor directory" + pushd "${dirpath}" && make vendor && popd || exit 1 + if [[ -n "$(git status -s "${dirpath}/vendor")" ]]; then + title "## Commiting changes to ${dirname}/vendor directory" + git add "${dirpath}/vendor" + git commit -m "update ${dirname}/vendor" fi done diff --git a/scripts/auto-rebase/rebase_ai_model_serving.sh b/scripts/auto-rebase/rebase_ai_model_serving.sh index 24f57b53a6..cd3e613ffa 100755 --- a/scripts/auto-rebase/rebase_ai_model_serving.sh +++ b/scripts/auto-rebase/rebase_ai_model_serving.sh @@ -115,14 +115,14 @@ update_kserve() { yq -i ".images.${image_name} = \"${image_ref}\"" "${RELEASE_JSON}" done - # Update kserve's config + ### Update kserve's config local -r microshift_config="${REPOROOT}/assets/optional/ai-model-serving/kserve/inferenceservice-config-microshift-patch.yaml" - local -r rhoai_config="${REPOROOT}/assets/optional/ai-model-serving/kserve/overlays/odh/inferenceservice-config-patch.yaml" + local -r rhoai_config="${REPOROOT}/assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-inferenceservice-config.yaml" # Clear the file and add a comment on top cat < "${microshift_config}" # This is a MicroShift specific kserve configuration. -# For RHOAI kserve configuration see: assets/optional/ai-model-serving/kserve/overlays/odh/inferenceservice-config-patch.yaml +# For RHOAI kserve configuration see: assets/optional/ai-model-serving/kserve/overlays/odh/patches/patch-inferenceservice-config.yaml # For upstream kserve configuration and description of the config see: assets/optional/ai-model-serving/kserve/configmap/inferenceservice.yaml # # The difference compared to RHOAI's kserve configuration is the 'deploy' section setting: @@ -136,6 +136,9 @@ EOF # Change Deployment Mode sed -i 's/"defaultDeploymentMode": "Serverless"/"defaultDeploymentMode": "RawDeployment"/g' "${microshift_config}" + + ### Remove Namespace from assets/optional/ai-model-serving/kserve/manager/service.yaml + yq -i 'del(select(.kind == "Namespace"))' "${REPOROOT}/assets/optional/ai-model-serving/kserve/manager/service.yaml" } update_runtimes() { diff --git a/scripts/auto-rebase/rebase_cert_manager.sh b/scripts/auto-rebase/rebase_cert_manager.sh index 95ef431515..54de006264 100755 --- a/scripts/auto-rebase/rebase_cert_manager.sh +++ b/scripts/auto-rebase/rebase_cert_manager.sh @@ -35,6 +35,8 @@ OPERATOR_INDEX="${STAGING_DIR}/redhat-operator-index.yaml" OPERATOR_CERT_MANAGER_INDEX="${STAGING_DIR}/redhat-operator-cert-manager-index.yaml" GO_MOD_DIRS=("$REPOROOT/" "$REPOROOT/etcd") +PULL_SECRET_FILE="${HOME}/.pull-secret.json" + OPERATOR_COMPONENTS="cert-manager-controller cert-manager-ca-injector cert-manager-webhook cert-manager-acmesolver cert-manager-istiocsr" declare -a ARCHS=("amd64" "arm64") @@ -55,6 +57,29 @@ check_preconditions() { DEST_DIR="${BIN_DIR}" "${REPOROOT}/scripts/fetch_tools.sh" opm fi + if [[ ! -f "${HOME}/.config/containers/policy.json" && ! -f /etc/containers/policy.json ]]; then + echo "Could not find ${HOME}/.config/containers/policy.json or /etc/containers/policy.json - creating" + # If these two files do not exist, we assume the script is running within the CI container. + # These are required for the `opm` command to work correctly. + # + mkdir -p "${HOME}/.config/containers/" + cat << EOF > "${HOME}/.config/containers/policy.json" +{ + "default": [ + { + "type": "insecureAcceptAnything" + } + ], + "transports": + { + "docker-daemon": + { + "": [{"type":"insecureAcceptAnything"}] + } + } +} +EOF + fi if ! hash python3; then echo "ERROR: python3 is not present on the system - please install" @@ -93,17 +118,27 @@ download_cert_manager(){ mkdir -p "${STAGING_DIR}" pushd "${STAGING_DIR}" >/dev/null - # export REGISTRY_AUTH_FILE=${PULL_SECRET_FILE} + operator_manifest="$1" - operator_manifest="$1" + # opm needs credentials to pull the image, but there's no flag like -a or --authfile to provide our ~/.pull-secret.json + clear_docker_config=false + if [[ -f "${PULL_SECRET_FILE}" && ! -f "${HOME}/.docker/config.json" ]]; then + mkdir -p "${HOME}/.docker/" + ln -s "${PULL_SECRET_FILE}" "${HOME}/.docker/config.json" + clear_docker_config=true + fi - # get the whole operator yaml for 4.19 + # get the whole operator yaml ${BIN_DIR}/opm render "${operator_manifest}" -o yaml >${OPERATOR_INDEX} + if "${clear_docker_config}"; then + rm "${HOME}/.docker/config.json" + fi + # find the latest published cert-manager-operator ie: cert-manager-operator.v1.16.0 export operator=$(yq 'select(.package == "openshift-cert-manager-operator" and .name == "stable-v1") | .entries[-1].name' ${OPERATOR_INDEX}) yq 'select (.name==env(operator))' ${OPERATOR_INDEX} >"${OPERATOR_CERT_MANAGER_INDEX}" - + echo "found operator version ${operator}" # convert from cert-manager-operator.v1.16.0 to cert-manager-x.y @@ -131,12 +166,12 @@ write_cert_manager_images_for_arch() { local operatorVersion=$(yq '.properties[] | select(.type == "olm.package").value.version' "${OPERATOR_CERT_MANAGER_INDEX}") jq -n "{\"release\": {\"base\": \"${operatorVersion}\"}, \"images\": {}}" > "${cert_manager_release_json}" - + #containerImage local operatorImageFull=$(yq '.properties[] | select(.type == "olm.csv.metadata").value.annotations.containerImage' "${OPERATOR_CERT_MANAGER_INDEX}") local operatorImage="${operatorImageFull%:*}" local operatorTag="${operatorImageFull#*:}" - + yq -i -o json ".images += {\"cert-manager-operator\": \"${operatorImageFull}\"}" "${cert_manager_release_json}" # update controller image in ConfigMap @@ -148,19 +183,19 @@ write_cert_manager_images_for_arch() { local component=$(yq ".relatedImages.${index}.name" "${OPERATOR_CERT_MANAGER_INDEX}") if [[ -n "${component}" && "${OPERATOR_COMPONENTS}" == *"${component}"* ]]; then yq -i -o json ".images += {\"${component}\": \"${image}\"}" "${cert_manager_release_json}" - + # update component image in ConfigMap update_configmap_image "${component}" "${image}" "${cert_manager_images_yaml}" - + # update environment variables in manager.yaml sed -i "s#value:.*${component}.*#value: ${image}#g" "${cert_manager_operator_yaml}" - # handle special case istiocsr v istio-csr mismatch + # handle special case istiocsr v istio-csr mismatch if [[ "${component}" == "cert-manager-istiocsr" ]]; then sed -i "s#value:.*cert-manager-istio-csr.*#value: ${image}#g" "${cert_manager_operator_yaml}" fi fi - + done diff --git a/scripts/auto-rebase/rebase_job_entrypoint.sh b/scripts/auto-rebase/rebase_job_entrypoint.sh index 3c500d7e91..74b1dce1ea 100755 --- a/scripts/auto-rebase/rebase_job_entrypoint.sh +++ b/scripts/auto-rebase/rebase_job_entrypoint.sh @@ -89,7 +89,9 @@ fi # # New references can be obtained from: # https://catalog.redhat.com/software/containers/rhoai/odh-operator-bundle/659803ca929f3c931af06f28 -rhoai_release="registry.redhat.io/rhoai/odh-operator-bundle:v2.22" +rhoai_release="registry.redhat.io/rhoai/odh-operator-bundle:v2.25" +# SR-IOV Operator is available through OLM and is not part of the OCP release. +sriov_release="registry.redhat.io/openshift4/ose-sriov-network-operator-bundle:v4.20" opm_release="registry.redhat.io/redhat/redhat-operator-index:v4.20" APP_ID=$(cat /secrets/pr-creds/app_id) \ KEY=/secrets/pr-creds/key.pem \ @@ -98,6 +100,7 @@ REPO=${REPO:-microshift} \ AMD64_RELEASE=${PULLSPEC_RELEASE_AMD64} \ ARM64_RELEASE=${PULLSPEC_RELEASE_ARM64} \ RHOAI_RELEASE=${rhoai_release} \ +SRIOV_RELEASE=${sriov_release} \ OPM_RELEASE=${opm_release} \ ./scripts/auto-rebase/rebase.py @@ -125,7 +128,6 @@ else ./scripts/auto-rebase/rebase-lvms.sh to "${pullspec_release_lvms_fallback}" fi - if [[ "${JOB_TYPE}" == "presubmit" ]]; then # Verify the assets after the rebase to make sure # nightly job will not fail on assets verification. diff --git a/scripts/auto-rebase/rebase_sriov.sh b/scripts/auto-rebase/rebase_sriov.sh new file mode 100755 index 0000000000..3e0cf471c2 --- /dev/null +++ b/scripts/auto-rebase/rebase_sriov.sh @@ -0,0 +1,453 @@ +#!/usr/bin/env bash + +set -o errexit +set -o errtrace +set -o nounset +set -o pipefail + +shopt -s expand_aliases +shopt -s extglob + +export PS4='+ $(date "+%T.%N") ${BASH_SOURCE#$HOME/}:$LINENO \011' + +REPOROOT="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/../..")" +STAGING_SRIOV="${REPOROOT}/_output/staging/sriov" + +CSV_FILENAME="sriov-network-operator.clusterserviceversion.yaml" +CONFIGMAP_FILENAME="supported-nic-ids_v1_configmap.yaml" +OPERATOR_FILENAME="operator.yaml" +PULL_SECRET_FILE="${HOME}/.pull-secret.json" + +RELEASE_JSON_X86="${REPOROOT}/assets/optional/sriov/release-sriov-x86_64.json" +RELEASE_JSON_ARM="${REPOROOT}/assets/optional/sriov/release-sriov-aarch64.json" +NAMESPACE="sriov-network-operator" +NO_BRANCH=${NO_BRANCH:-false} + +title() { + echo -e "\E[34m$1\E[00m"; +} + +check_preconditions() { + if [[ "${REPOROOT}" != "$(pwd)" ]]; then + echo "Script must be executed from root of the MicroShift repository" + exit 1 + fi + + if ! hash yq; then + title "Installing yq" + sudo DEST_DIR=/usr/bin/ "${REPOROOT}/scripts/fetch_tools.sh" yq + fi + + if ! hash python3; then + echo "ERROR: python3 is not present on the system - please install" + exit 1 + fi + + if ! python3 -c "import yaml"; then + echo "ERROR: missing python's yaml library - please install" + exit 1 + fi + + if ! hash oc; then + echo "ERROR: oc is not present on the system - please install" + exit 1 + fi +} + +get_auth() { + if [ -f "${PULL_SECRET_FILE}" ]; then + echo "--registry-config ${PULL_SECRET_FILE}" + else + >&2 echo "Warning: no pull secret found at ${PULL_SECRET_FILE}" + echo "" + fi +} + +# append_if_exists() checks if the target file is non-empty, and if so, appends +# "---" to it, so another manifest can be included in the same file +append_if_exists() { + local target="$1" + + if [[ -s "${target}" ]]; then + echo "---" >> "${target}" + fi +} + +download_sriov_bundle_manifests() { + local -r bundle_ref="${1}" + + title "downloading SRIOV bundle ${bundle_ref}" + rm -rf "${STAGING_SRIOV}" + mkdir -p "${STAGING_SRIOV}" + + local -r authentication="$(get_auth)" + # shellcheck disable=SC2086 + oc image extract \ + ${authentication} \ + --path "/manifests/:${STAGING_SRIOV}" \ + "${bundle_ref}" || return 1 + + extract_sriov_manifests + patch_sriov_manifests +} + +# extract_sriov_rbac_from_cluster_service_version() extract the RBAC from the +# CSV and saves the manifests in the STAGING_EXTRACTED directory. It is called +# by extract_sriov_manifests(). +# shellcheck disable=SC2207 +extract_sriov_rbac_from_cluster_service_version() { + local dest="$1" + local csv="$2" + local namespace="$3" + + title "extracting sriov clusterserviceversion.yaml into separate RBAC" + + local clusterPermissions=($(yq eval '.spec.install.spec.clusterPermissions[].serviceAccountName' < "${csv}")) + for service_account_name in "${clusterPermissions[@]}"; do + echo "extracting bundle .spec.install.spec.clusterPermissions by serviceAccountName ${service_account_name}" + + local clusterrole="${dest}/clusterrole.yaml" + echo "generating ${clusterrole}" + extract_sriov_clusterrole_from_csv_by_service_account_name "${service_account_name}" "${csv}" "${clusterrole}" + + local clusterrolebinding="${dest}/clusterrolebinding.yaml" + echo "generating ${clusterrolebinding}" + extract_sriov_clusterrolebinding_from_csv_by_service_account_name "${service_account_name}" "${namespace}" "${clusterrolebinding}" + + local service_account="${dest}/serviceaccount.yaml" + echo "generating ${service_account}" + extract_sriov_service_account_from_csv_by_service_account_name "${service_account_name}" "${namespace}" "${service_account}" + done + + local permissions=($(yq eval '.spec.install.spec.permissions[].serviceAccountName' < "${csv}")) + for service_account_name in "${permissions[@]}"; do + echo "extracting bundle .spec.install.spec.permissions by serviceAccountName ${service_account_name}" + + local role="${dest}/role.yaml" + echo "generating ${role}" + extract_sriov_role_from_csv_by_service_account_name "${service_account_name}" "${namespace}" "${csv}" "${role}" + + local rolebinding="${dest}/rolebinding.yaml" + echo "generating ${rolebinding}" + extract_sriov_rolebinding_from_csv_by_service_account_name "${service_account_name}" "${namespace}" "${rolebinding}" + done +} + +extract_sriov_clusterrole_from_csv_by_service_account_name() { + local service_account_name="$1" + local csv="$2" + local target="$3" + + append_if_exists "${target}" + + yq eval " + .spec.install.spec.clusterPermissions[] | + select(.serviceAccountName == \"${service_account_name}\") | + .apiVersion = \"rbac.authorization.k8s.io/v1\" | + .kind = \"ClusterRole\" | + .metadata.name = \"${service_account_name}\" | + del(.serviceAccountName) + " "${csv}" >> "${target}" +} + +extract_sriov_role_from_csv_by_service_account_name() { + local service_account_name="$1" + local namespace="$2" + local csv="$3" + local target="$4" + + append_if_exists "${target}" + + yq eval " + .spec.install.spec.permissions[] | + select(.serviceAccountName == \"${service_account_name}\") | + .apiVersion = \"rbac.authorization.k8s.io/v1\" | + .kind = \"Role\" | + .metadata.name = \"${service_account_name}\" | + .metadata.namespace = \"${namespace}\" | + del(.serviceAccountName) + " "${csv}" >> "${target}" +} +extract_sriov_clusterrolebinding_from_csv_by_service_account_name() { + local service_account_name="$1" + local namespace="$2" + local target="$3" + + append_if_exists "${target}" + + crb=$(cat <> "${target}" +} + +extract_sriov_rolebinding_from_csv_by_service_account_name() { + local service_account_name="$1" + local namespace="$2" + local target="$3" + + append_if_exists "${target}" + + rb=$(cat <> "${target}" +} + +extract_sriov_service_account_from_csv_by_service_account_name() { + local service_account_name="$1" + local namespace="$2" + local target="$3" + + append_if_exists "${target}" + + serviceAccount=$(cat <> "${target}" +} + +# extract_operator_from_csv() extracts the operator manifest from cluster +# service version. +extract_operator_from_csv() { + local csv="$1" + local namespace="$2" + local target="$3" + + yq eval " + .spec.install.spec.deployments[] + | select(.name == \"sriov-network-operator\") + | .apiVersion = \"apps/v1\" + | .kind = \"Deployment\" + | .metadata.name = .name + | .metadata.namespace = \"${namespace}\" + | del(.name) + | del(.label) + | .spec.template.spec.containers[0].env += [{\"name\": \"SRIOV_CNI_BIN_PATH\", \"value\": \"/run/cni/bin\"}] + " "${csv}" > "${target}" +} + +# create_namespace_yaml() creates a namespace manifest. +create_namespace_yaml() { + local namespace="$1" + local target="$2" + + namespace=$(cat < "${target}" +} + +# create_default_sriov_operator_config() creates the SriovOperatorConfig CR that +# the operator expects. This is not included in the csv, so I'm having to do it +# this way. +create_default_sriov_operator_config() { + local namespace="$1" + local target="$2" + + sriovoperatorconfig=$(cat < "${target}" +} + +extract_sriov_manifests() { + extract_sriov_rbac_from_cluster_service_version "${STAGING_SRIOV}" "${STAGING_SRIOV}/${CSV_FILENAME}" "${NAMESPACE}" + + local operator="${STAGING_SRIOV}/${OPERATOR_FILENAME}" + echo "generating ${operator}" + extract_operator_from_csv "${STAGING_SRIOV}/${CSV_FILENAME}" "${NAMESPACE}" "${operator}" + + local namespace="${STAGING_SRIOV}/namespace.yaml" + echo "generating ${namespace}" + create_namespace_yaml "${NAMESPACE}" "${namespace}" + + local sriovoperatorconfig="${STAGING_SRIOV}/sriovoperatorconfig.yaml" + echo "generating ${sriovoperatorconfig}" + create_default_sriov_operator_config "${NAMESPACE}" "${sriovoperatorconfig}" +} + +patch_sriov_manifests() { + yq eval -i " + .data.Intel_ixgbe_82576 = \"8086 10c9 10ca\" + | .metadata.namespace = \"${NAMESPACE}\" + " "${STAGING_SRIOV}/${CONFIGMAP_FILENAME}" + + yq eval -i " + ( + .spec.template.spec.containers[0].env[] | + select(.name == \"ADMISSION_CONTROLLERS_ENABLED\") + ).value = \"false\" + | + ( + .spec.template.spec.containers[0].env[] | + select(.name == \"METRICS_EXPORTER_PROMETHEUS_OPERATOR_ENABLED\") + ).value = \"false\" + | + .spec.template.spec.containers[0].env += [ + {\"name\": \"CLUSTER_TYPE\", \"value\": \"kubernetes\"} + ] + " "${STAGING_SRIOV}/${OPERATOR_FILENAME}" +} + +get_sriov_bundle_version() { + yq '.spec.version' "${STAGING_SRIOV}/${CSV_FILENAME}" +} + +update_last_rebase_sriov_sh() { + local -r operator_bundle="${1}" + + title "Updating last_rebase_sriov.sh" + local -r last_rebase_script="${REPOROOT}/scripts/auto-rebase/last_rebase_sriov.sh" + + rm -f "${last_rebase_script}" + cat - >"${last_rebase_script}" <&2 echo 'sriov staging dir not found, aborting image update' + return 1 + } + + yq " + ( + [.spec.template.spec.containers[].env[] | + select(.name | test(\"_IMAGE$\")) | + {\"key\": (.name | downcase), \"value\": .value}] | + from_entries + ) as \$env_images | + ( + .spec.template.spec.containers[] | + {(.name): .image} + ) as \$main_images | + {\"release\": {\"base\": \"$(get_sriov_bundle_version)\"}, \"images\": (\$env_images + \$main_images)} + " "${STAGING_SRIOV}/${OPERATOR_FILENAME}" -o json | sed 's/"sriov_\([^"]*\)_\([^"]*\)"/"sriov-\1-\2"/g; s/_/-/g' > "${RELEASE_JSON_X86}" + cp "${RELEASE_JSON_X86}" "${RELEASE_JSON_ARM}" +} + +rebase_sriov_to() { + local -r operator_bundle="${1}" + + title "Rebasing SR-IOV for MicroShift to ${operator_bundle}" + + download_sriov_bundle_manifests "${operator_bundle}" + + update_sriov_manifests + update_sriov_images + + update_last_rebase_sriov_sh "${operator_bundle}" + update_rebase_job_entrypoint_sh "${operator_bundle}" + + if [[ -n "$(git status -s ./assets ./scripts/auto-rebase/rebase_job_entrypoint.sh ./scripts/auto-rebase/last_rebase_sriov.sh)" ]]; then + title "Detected changes to assets/ or last_rebase_sriov.sh" + + if ! "${NO_BRANCH}"; then + branch="rebase-sriov-$(get_sriov_bundle_version)" + title "Creating branch ${branch}" + git branch -D "${branch}" 2>/dev/null || true && git checkout -b "${branch}" + fi + + title "Committing changes" + git add ./assets ./scripts/auto-rebase/rebase_job_entrypoint.sh ./scripts/auto-rebase/last_rebase_sriov.sh + git commit -m "Update SR-IOV for MicroShift" + else + title "No changes to assets/ or last_rebase_sriov.sh" + fi +} + +usage() { + echo "Usage:" + echo "$(basename "$0") to SRIOV_BUNDLE Performs all the steps to rebase SR-IOV for MicroShift" + echo "$(basename "$0") download SRIOV_BUNDLE Downloads the content of a SR-IOV bundle image to disk in preparation for rebasing." + echo "$(basename "$0") images Rebases the component images to the downloaded release" + echo "$(basename "$0") manifests Rebases the component manifests to the downloaded release" + exit 1 +} + +check_preconditions + +command=${1:-help} +case "${command}" in + to) + rebase_sriov_to "$2" + ;; + download) + download_sriov_bundle_manifests "$2" + ;; + images) + update_sriov_images + ;; + manifests) + update_sriov_manifests + ;; + *) usage;; +esac diff --git a/scripts/aws/cf-gen.yaml b/scripts/aws/cf-gen.yaml index 53008e5eb2..a7a58814ce 100644 --- a/scripts/aws/cf-gen.yaml +++ b/scripts/aws/cf-gen.yaml @@ -5,7 +5,7 @@ Conditions: Mappings: VolumeSize: MetalMachine: - PrimaryVolumeSize: "300" + PrimaryVolumeSize: "400" SecondaryVolumeSize: "0" Throughput: 750 Iops: 6000 @@ -290,6 +290,13 @@ Resources: #!/bin/bash -xe echo "====== Authorizing public key ======" | tee -a /tmp/init_output.txt echo "${PublicKeyString}" >> /home/ec2-user/.ssh/authorized_keys + # Redirect /tmp to /var/tmp to avoid tmpfs RAM usage + echo "====== Redirecting /tmp to /var/tmp ======" | tee -a /tmp/init_output.txt + # Move tmpfs /tmp out of the way and create symlink to disk-backed /var/tmp + mv /tmp /tmp.tmpfs + ln -sf /var/tmp /tmp + echo "====== /tmp successfully redirected to /var/tmp ======" | tee -a /tmp/init_output.txt + # Use the same defaults as OCP to avoid failing requests to apiserver, such as # requesting logs. echo "====== Updating inotify =====" | tee -a /tmp/init_output.txt diff --git a/scripts/ci-ai-model-serving/setup/01-microshift.sh b/scripts/ci-ai-model-serving/setup/01-microshift.sh index 50774df273..b3a9a9dac3 100755 --- a/scripts/ci-ai-model-serving/setup/01-microshift.sh +++ b/scripts/ci-ai-model-serving/setup/01-microshift.sh @@ -13,7 +13,7 @@ ROOTDIR="${SCRIPTDIR}/../../.." --force-firewall \ --optional-rpms \ --pull-images \ - --skip-optional-rpms low-latency \ + --skip-optional-rpms low-latency,cert-manager \ "${HOME}/.pull-secret.json" # Pull kserve and helper images for ai-model-serving, skip serving runtimes diff --git a/scripts/ci-nvidia-device-plugin/tests/02-wait-for-greenboot.sh b/scripts/ci-nvidia-device-plugin/tests/02-wait-for-greenboot.sh index b3b54555cc..d881226632 100755 --- a/scripts/ci-nvidia-device-plugin/tests/02-wait-for-greenboot.sh +++ b/scripts/ci-nvidia-device-plugin/tests/02-wait-for-greenboot.sh @@ -2,7 +2,7 @@ set -xeuo pipefail -retries=20 +retries=30 while [ ${retries} -gt 0 ] ; do ((retries-=1)) if sudo systemctl status greenboot-healthcheck | grep -q 'active (exited)'; then diff --git a/scripts/devenv-builder/configure-vm.sh b/scripts/devenv-builder/configure-vm.sh index 6b39065dc8..258304dff2 100755 --- a/scripts/devenv-builder/configure-vm.sh +++ b/scripts/devenv-builder/configure-vm.sh @@ -243,7 +243,7 @@ EOF function install_build_deps() { "${DNF_RETRY}" "clean" "all" if ${DNF_UPDATE}; then - "${DNF_RETRY}" "update" + "${DNF_RETRY}" "update" "--nobest" fi "${DNF_RETRY}" "install" "gcc git golang cockpit make jq selinux-policy-devel rpm-build jq bash-completion avahi-tools createrepo" diff --git a/scripts/release-notes/gen_ec_release_notes.sh b/scripts/pyutils/create-venv.sh similarity index 75% rename from scripts/release-notes/gen_ec_release_notes.sh rename to scripts/pyutils/create-venv.sh index 97e0ab4851..ed1b19f04d 100755 --- a/scripts/release-notes/gen_ec_release_notes.sh +++ b/scripts/pyutils/create-venv.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # shellcheck disable=all set -o nounset @@ -7,7 +7,7 @@ set -o pipefail SCRIPT_DIR="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")" ROOT_DIR=$(realpath "${SCRIPT_DIR}/../..") -DEFAULT_DEST_DIR="${ROOT_DIR}/_output/releasenotes" +DEFAULT_DEST_DIR="${ROOT_DIR}/_output/pyutils" DEST_DIR="${DEST_DIR:-${DEFAULT_DEST_DIR}}" if [ ! -d "${DEST_DIR}" ]; then @@ -16,6 +16,3 @@ if [ ! -d "${DEST_DIR}" ]; then "${DEST_DIR}/bin/python3" -m pip install --upgrade pip "${DEST_DIR}/bin/python3" -m pip install -r "${SCRIPT_DIR}/requirements.txt" fi -source "${DEST_DIR}/bin/activate" - -python3 "${SCRIPT_DIR}/gen_ec_release_notes.py" "$@" diff --git a/scripts/pyutils/ghutils.py b/scripts/pyutils/ghutils.py new file mode 100644 index 0000000000..ca6ee128a5 --- /dev/null +++ b/scripts/pyutils/ghutils.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 + +import os +import logging +import sys +from pathlib import Path +from github import GithubIntegration, Github + +APP_ID_ENV = "APP_ID" # GitHub App's ID +KEY_ENV = "KEY" # Path to GitHub App's key +PAT_ENV = "GH_TOKEN" # Personal Access Token + +ORG_ENV = "ORG" +_DEFAULT_ORG = "openshift" +REPO_ENV = "REPO" +_DEFAULT_REPO = "microshift" + + +class GithubUtils: + def __init__(self, dry_run=False): + self.dry_run = dry_run + self.org, self.repo = self._get_org_repo_from_env() + self.token = self._get_gh_token_from_env() + self.gh_repo = Github(self.token).get_repo(f"{self.org}/{self.repo}") + + def _get_org_repo_from_env(self) -> tuple[str, str]: + if self.dry_run: + logging.info(f"[DRY RUN] Using default org and repo: {_DEFAULT_ORG}/{_DEFAULT_REPO}") + return _DEFAULT_ORG, _DEFAULT_REPO + return try_get_env(ORG_ENV, default=_DEFAULT_ORG), try_get_env(REPO_ENV, default=_DEFAULT_REPO) + + def _get_gh_token_from_env(self) -> str: + """ + Returns a token to be used with GitHub API. + It's either Personal Access Token if TOKEN env is set, + or Installation Access Token which is intended to be used with GitHub Apps. + """ + personal_access_token = try_get_env(PAT_ENV) + if personal_access_token != "": + logging.info("Using Personal Access Token to access GitHub API") + return personal_access_token + + app_id = try_get_env(APP_ID_ENV, die=True) + key_path = try_get_env(KEY_ENV, die=True) + integration = GithubIntegration(app_id, Path(key_path).read_text(encoding='utf-8')) + app_installation = integration.get_repo_installation(self.org, self.repo) + if app_installation is None: + sys.exit(f"Failed to get app_installation for {self.org}/{self.repo}. " + + f"Response: {app_installation.raw_data}") + return integration.get_access_token(app_installation.id).token + + def is_branch_under_active_development(self, branch): + """ + Checks title of the issue #1239 in the openshift/microshift repository to check if + given branch is frozen and thus under active development is happening on main branch. + + It returns True if given branch is the first on the list of frozen branches. + In such case the target (base) branch of newly created PR should be switch to main. + """ + if self.dry_run: + logging.info(f"[DRY RUN] Assuming branch {branch} is under active development") + return True + + issue = self.gh_repo.get_issue(number=1239) + title = issue.title + try: + branches_part = title.split('|', 1)[1].strip() + frozen_branches = [x.replace('branch:', '') for x in branches_part.split()] + if len(frozen_branches) == 0: + raise Exception(f"Unexpected amount of branch in the Issue 1239 title: {title}") + # Assuming the first branch name is the release under development right now. + # No job creating PRs should run against the next release branch. + return branch == frozen_branches[0] + except Exception as e: + raise RuntimeError(f"Failed to parse freeze issue title: {title} ({e})") + + def create_pr(self, base_branch, branch_name, title, desc): + """Create a Pull Request""" + if self.dry_run: + logging.info(f"[DRY RUN] Create PR: {base_branch=} <- {branch_name=}: {title=} {desc=}") + return None + + if (self.org == _DEFAULT_ORG and self.repo == _DEFAULT_REPO and + self.is_branch_under_active_development(base_branch)): + base_branch = "main" + + pull_req = self.gh_repo.create_pull( + title=title, body=desc, base=base_branch, head=branch_name, maintainer_can_modify=True) + logging.info(f"Created pull request: {pull_req.html_url}") + return pull_req + + def update_pr(self, pull_req, title, desc): + """Updates the title and description of a pull request on a GitHub repository.""" + if self.dry_run: + logging.info(f"[DRY RUN] Update PR #{pull_req.number}: {title}\n{desc}") + return + + pull_req.edit(title=title, body=desc) + pull_req.update() # arm64 release or prow job url might've changed + logging.info(f"Updated PR #{pull_req.number}: {title}\n{desc}") + + def post_comment(self, pull_req, comment="", extra_msgs=[]): + """Post a comment on a Pull Request with the contents of the extra_msgs list.""" + if self.dry_run: + logging.info(f"[DRY RUN] Post comment: {comment}") + return + + if len(extra_msgs) != 0: + if comment != "": + comment += "\n\n" + comment += "Extra messages:\n - " + "\n - ".join(extra_msgs) + + if comment.strip() != "": + logging.info(f"Comment to post: {comment}") + if self.dry_run: + logging.info("[DRY RUN] Posted a comment") + return + issue = pull_req.as_issue() + issue.create_comment(comment) + else: + logging.info("No content for comment") + + def get_existing_pr_for_a_branch(self, base_branch, branch_name): + """ + Try to get a pull request for a branch on a GitHub repository. + Returns + - The pull request if it exists and is open, otherwise None. + - If more than one pull request is found, then the first one will be used. + """ + prs = self.gh_repo.get_pulls(base=base_branch, head=f"{self.org}:{branch_name}", state="all") + + if prs.totalCount == 0: + logging.info(f"PR for branch {branch_name} does not exist yet on {self.gh_repo.full_name}") + return None + + pull_req = None + if prs.totalCount > 1: + pull_req = prs[0] + logging.warning( + f"Found more than one PR for branch {branch_name} on {self.gh_repo.full_name} -" + + f"this is unexpected, continuing with first one of: {[(x.state, x.html_url) for x in prs]}" + ) + + if prs.totalCount == 1: + pull_req = prs[0] + logging.info(f"Found PR #{pull_req.number} for branch {branch_name} on {self.gh_repo.full_name}: {pull_req.html_url}") + + if pull_req.state == 'closed': + logging.warning(f"PR #{pull_req.number} is not open - new PR will be created") + if pull_req.is_merged(): + logging.warning(f"PR #{pull_req.number} for '{branch_name}' branch is already merged but rebase.sh produced results") + else: + logging.warning(f"PR #{pull_req.number} for '{branch_name}' exists already but was closed") + return None + return pull_req + + +def try_get_env(var_name, default=None, die=False) -> str: + val = os.getenv(var_name) + if val is None or val == "": + if default is not None: + logging.info(f"'{var_name}' env var is unset, using '{default}'") + return default + if die: + raise Exception(f"Could not get environment variable '{var_name}'") + else: + logging.info(f"Could not get environment variable '{var_name}' - ignoring") + return "" + return val diff --git a/scripts/pyutils/gitutils.py b/scripts/pyutils/gitutils.py new file mode 100644 index 0000000000..eaa1705b3d --- /dev/null +++ b/scripts/pyutils/gitutils.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 + +import logging + +from git import PushInfo, Repo # GitPython + +BOT_REMOTE_NAME = "bot-creds" +REMOTE_ORIGIN = "origin" + + +class GitUtils(): + def __init__(self, dry_run=False): + self.dry_run = dry_run + self.git_repo = Repo(".") + self.remote = None + + def file_changed(self, file_path) -> bool: + changedFiles = [item.a_path for item in self.git_repo.index.diff(None)] + return file_path in changedFiles + + def add_files_to_staging_area(self, file_paths=[], all=False): + if self.dry_run: + if all: + logging.info("[DRY RUN] git add -A") + else: + logging.info(f"[DRY RUN] git add {file_paths}") + return + + if all: + self.git_repo.index.add(A=True) + else: + self.git_repo.index.add(file_paths) + + def commit(self, message): + if self.dry_run: + logging.info(f"[DRY RUN] git commit -m {message}") + return + self.git_repo.index.commit(message) + + def checkout_branch(self, branch_name): + if self.dry_run: + logging.info(f"[DRY RUN] git checkout -b {branch_name}") + return + new_branch = self.git_repo.create_head(branch_name) + new_branch.checkout() + + def setup_remote_with_token(self, token, org, repo): + """ + Sets up the Git remote for the given repository using + the provided installation or personal access token. + """ + if self.dry_run: + logging.info(f"[DRY RUN] git remote add {BOT_REMOTE_NAME} https://x-access-token:TOKEN@github.com/{org}/{repo}") + return + + remote_url = f"https://x-access-token:{token}@github.com/{org}/{repo}" + try: + remote = self.git_repo.remote(BOT_REMOTE_NAME) + remote.set_url(remote_url) + except ValueError: + self.git_repo.create_remote(BOT_REMOTE_NAME, remote_url) + + self.remote = self.git_repo.remote(BOT_REMOTE_NAME) + return self.remote + + def remove_remote_with_token(self): + if self.dry_run: + logging.info(f"[DRY RUN] git remote remove {BOT_REMOTE_NAME}") + return + self.remote.remove(self.git_repo, BOT_REMOTE_NAME) + + def push(self, branch_name): + if self.dry_run: + logging.info(f"[DRY RUN] git push --force {branch_name}") + return + + push_result = self.remote.push(branch_name, force=True) + + if len(push_result) != 1: + raise Exception(f"Unexpected amount ({len(push_result)}) of items in push_result: {push_result}") + if push_result[0].flags & PushInfo.ERROR: + raise Exception(f"Pushing branch failed: {push_result[0].summary}") + if push_result[0].flags & PushInfo.FORCED_UPDATE: + logging.info(f"Branch '{branch_name}' existed and was updated (force push)") + + def get_remote_branch(self, branch_name): + """ + Get the reference for the given branch on the specified Git remote, + otherwise return None if the branch does not exist. + """ + if self.dry_run: + return None + + self.remote.fetch() + matching_remote_refs = [ref for ref in self.remote.refs if BOT_REMOTE_NAME + "/" + branch_name == ref.name] + + if len(matching_remote_refs) == 0: + logging.info(f"Branch '{branch_name}' does not exist on remote") + return None + + if len(matching_remote_refs) > 1: + matching_branches = ", ".join([r.name for r in matching_remote_refs]) + logging.warning(f"Found more than one branch matching '{branch_name}' " + + f"on remote: {matching_branches}. Taking first one") + return matching_remote_refs[0] + + if len(matching_remote_refs) == 1: + logging.info(f"Branch '{branch_name}' already exists on remote") + return matching_remote_refs[0] + + return None + + def is_local_branch_based_on_newer_base_branch_commit(self, base_branch_name, remote_branch_name, local_branch_name): + """ + Compares local and remote rebase branches by looking at their start on base branch. + Returns True if local branch starts on newer commit and should to be pushed to remote, + otherwise False. + """ + if self.dry_run: + return True + + remote_merge_base = self.git_repo.merge_base(base_branch_name, remote_branch_name) + local_merge_base = self.git_repo.merge_base(base_branch_name, local_branch_name) + + if remote_merge_base[0] == local_merge_base[0]: + logging.info("Remote branch is up to date. " + + f"Branch-off commit: {commit_str(remote_merge_base[0])}") + return False + + logging.info( + f"Remote branch is older - it needs updating. " + f"Remote branch is on top of {base_branch_name}'s commit: '{commit_str(remote_merge_base[0])}'. " + f"Local branch is on top of {base_branch_name}'s commit '{commit_str(local_merge_base[0])}'" + ) + return True + + +def commit_str(commit): + """Returns the first 8 characters of the commit's SHA hash and the commit summary.""" + return f"{commit.hexsha[:8]} - {commit.summary}" diff --git a/scripts/pyutils/requirements.txt b/scripts/pyutils/requirements.txt new file mode 100644 index 0000000000..9291dfa8a6 --- /dev/null +++ b/scripts/pyutils/requirements.txt @@ -0,0 +1,2 @@ +pygithub==2.8.1 +gitpython==3.1.45 diff --git a/scripts/release-notes/common.py b/scripts/release-notes/common.py new file mode 100644 index 0000000000..90e406d8b8 --- /dev/null +++ b/scripts/release-notes/common.py @@ -0,0 +1,250 @@ +import os +import logging +import github +import pathlib +import datetime +import subprocess +from urllib import request +import json +import urllib.error + +GITHUB_ORG = 'openshift' +GITHUB_REPO = 'microshift' +REMOTE = "token-remote" +MAX_RELEASE_NOTE_BODY_SIZE = 125000 +TRUNCATED_MESSAGE = '\n\n(release notes were truncated)\n\n' + +GITHUB_TOKEN = "" + + +def load_github_token(): + global GITHUB_TOKEN + GITHUB_TOKEN = os.environ.get('GITHUB_TOKEN') + + if not GITHUB_TOKEN: + logging.warning('GITHUB_TOKEN is not set, trying to authenticate using application credentials') + GITHUB_TOKEN = get_access_token_for_app() + + if not GITHUB_TOKEN: + raise RuntimeError('GITHUB_TOKEN does not appear to be set') + + +def get_access_token_for_app(): + """Return an access token for a GitHub App.""" + app_id = os.environ.get('APP_ID') + if not app_id: + raise RuntimeError('APP_ID is not set') + key_path = os.environ.get('CLIENT_KEY') + if not key_path: + raise RuntimeError('CLIENT_KEY is not set') + integration = github.GithubIntegration( + app_id, + pathlib.Path(key_path).read_text(encoding='utf-8'), + ) + app_installation = integration.get_installation(GITHUB_ORG, GITHUB_REPO) + if app_installation is None: + raise RuntimeError( + f"Failed to get app_installation for {GITHUB_ORG}/{GITHUB_REPO}. " + + f"Response: {app_installation.raw_data}" + ) + return integration.get_access_token(app_installation.id).token + + +def get_version_from_makefile(): + # The script runs as + # .../microshift/scripts/release-notes/common.py + # and we want the path to + # .../microshift + root_dir = pathlib.Path(__file__).parent.parent.parent + version_makefile = root_dir / 'Makefile.version.aarch64.var' + # Makefile contains something like + # OCP_VERSION := 4.16.0-0.nightly-arm64-2024-03-13-041907 + # and we want this ^^^^ + # + # We get it as ['4', '16'] to make the next part of the process of + # building the list of versions to scan easier. + _full_version = version_makefile.read_text('utf8').split('=')[-1].strip() + major, minor = _full_version.split('.')[:2] + return major, minor + + +def redact(input): + if GITHUB_TOKEN == "": + return input + return str.replace(input, GITHUB_TOKEN, '~~REDACTED~~') + + +def run_process(cmd: list[str], env={}): + """ + Helper function to run external commands and log (redacted) output. + Stdout is returned as a str. + If command fails, exception is raised. + """ + cmd_to_log = redact(' '.join(cmd)) + logging.debug(f"Running command: {cmd_to_log}") + + # Include our existing environment settings to ensure values like + # HOME and other git settings are propagated. + env.update(os.environ) + + completed = subprocess.run( + cmd, + env=env, + capture_output=True + ) + sout = completed.stdout.decode('utf-8') if completed.stdout else '' + serr = str.strip(redact(completed.stderr.decode('utf-8'))) if completed.stderr else '' + logging.debug(f"Command '{cmd_to_log}' finished: rc='{completed.returncode}' stdout='{str.strip(redact(sout))}' stderr='{serr}'") + + if completed.returncode != 0: + raise subprocess.CalledProcessError(completed.returncode, cmd_to_log, redact(sout), serr) + + return sout + + +def tag_exists(release_name): + "Checks if a given tag exists in the local repository." + try: + run_process(["git", "show", "--quiet", release_name]) + return True + except subprocess.CalledProcessError: + return False + + +def add_token_remote(): + """ + Adds the Git remote to the given repository using + the provided installation (or personal) access token. + """ + try: + run_process(["git", "remote", "remove", REMOTE]) + except subprocess.CalledProcessError: + pass + + remote_url = f"https://x-access-token:{GITHUB_TOKEN}@github.com/{GITHUB_ORG}/{GITHUB_REPO}" + run_process(["git", "remote", "add", REMOTE, remote_url]) + + +def get_previous_tag(release_name): + "Returns the name of the tag _before_ release_name on the branch." + output = run_process(["git", "describe", f'{release_name}~1', '--abbrev=0']) + return output.strip() + + +def tag_release(tag, sha, buildtime): + env = {} + timestamp = buildtime.strftime('%Y-%m-%d %H:%M') + env['GIT_COMMITTER_DATE'] = timestamp + + logging.info(f"Using 'GIT_COMMITTER_DATE={timestamp}' for 'git tag {tag} {sha}'") + run_process(['git', 'tag', '-m', tag, tag, sha], env) + + +def push_tag(tag): + run_process(['git', 'push', REMOTE, tag]) + + +def publish_release(new_release, preamble, take_action): + """Does the work to tag and publish a release. + """ + release_name = new_release.release_name + commit_sha = new_release.commit_sha + release_date = new_release.release_date + + if not tag_exists(release_name): + # release_date looks like 202402022103 + buildtime = datetime.datetime.strptime(release_date, '%Y%m%d%H%M') + tag_release(release_name, commit_sha, buildtime) + + # Get the previous tag on the branch as the starting point for the + # release notes. + previous_tag = get_previous_tag(release_name) + + # Auto-generate the release notes ourselves, add the preamble, + # then make sure the results fit within the size limits imposed by + # the API. + generated_notes = github_release_notes(previous_tag, release_name, commit_sha) + notes = f'{preamble}\n{generated_notes["body"]}' + if len(notes) > MAX_RELEASE_NOTE_BODY_SIZE: + lines = notes.splitlines() + last_line = lines[-1] + notes_content_we_can_truncate = notes[:-len(last_line)] + amount_we_can_keep = MAX_RELEASE_NOTE_BODY_SIZE - len(last_line) - len(TRUNCATED_MESSAGE) + truncated = notes_content_we_can_truncate[:amount_we_can_keep] + if truncated[-1] == '\n': + notes_to_keep = truncated + else: + # don't leave a partial line + notes_to_keep = truncated.rpartition('\n')[0].rstrip() + notes = f'{notes_to_keep}{TRUNCATED_MESSAGE}{last_line}' + + if not take_action: + logging.info(f'Dry run for new release {new_release} on commit {commit_sha} from {release_date}') + logging.info(notes) + return + + push_tag(release_name) + + # Create draft release with message that includes download URLs and history + github_release_create(release_name, notes) + + +def github_release_create(tag, notes): + prerelease = 'rc' in tag or 'ec' in tag + results = github_api( + f'/repos/{GITHUB_ORG}/{GITHUB_REPO}/releases', + tag_name=tag, + name=tag, + body=notes, + draft=False, + prerelease=prerelease, + ) + logging.info(f'Created new release {tag}:{ {"url":results["html_url"], "body": results["body"]} }') + + +def github_release_notes(previous_tag, tag_name, target_commitish): + results = github_api( + f'/repos/{GITHUB_ORG}/{GITHUB_REPO}/releases/generate-notes', + tag_name=tag_name, + target_commitish=target_commitish, + previous_tag_name=previous_tag, + ) + return results + + +def github_release_exists(tag): + try: + github_api(f'/repos/{GITHUB_ORG}/{GITHUB_REPO}/releases/tags/{tag}') + return True + except Exception: + return False + + +def github_api(path, **data): + url = f'https://api.github.com/{path.lstrip("/")}' + if data: + r = request.Request( + url=url, + data=json.dumps(data).encode('utf-8'), + ) + else: + r = request.Request(url=url) + + logging.info(f"GitHub API Request: { {'method':r.get_method(), 'url': url, 'data': data} }") + r.add_header('Accept', 'application/vnd.github+json') + r.add_header('User-agent', 'microshift-release-notes') + r.add_header('Authorization', f'Bearer {GITHUB_TOKEN}') + r.add_header('X-GitHub-Api-Version', '2022-11-28') + + try: + response = request.urlopen(r) + except urllib.error.URLError as e: + logging.error(f"GitHub API Request Failed: '{str(e.fp.readlines())}'") + # e.fp.readlines() sinks the response body but it's not read in any other place, + # so just re-raise for the exception type. + raise + except Exception as err: + logging.error(f"GitHub API Request Failed: '{err}'") + raise + + return json.loads(response.read().decode('utf-8')) diff --git a/scripts/release-notes/gen_gh_releases.sh b/scripts/release-notes/gen_gh_releases.sh new file mode 100755 index 0000000000..1331abf835 --- /dev/null +++ b/scripts/release-notes/gen_gh_releases.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# shellcheck disable=all +set -o nounset +set -o errexit +set -o pipefail + +SCRIPT_DIR="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")")" +ROOT_DIR=$(realpath "${SCRIPT_DIR}/../..") +DEFAULT_DEST_DIR="${ROOT_DIR}/_output/releasenotes" +DEST_DIR="${DEST_DIR:-${DEFAULT_DEST_DIR}}" + +function usage() { + echo "" + echo "Usage: $(basename "$0") {mirror, rhocp} [script_opts...]" + echo " mirror Execute gen_gh_releases_from_mirror.py: Generate GH releases of pre-release (ECs, RCs) MicroShift RPMs" + echo " rhocp Execute gen_gh_releases_from_rhocp.py: Generate GH release of released (on RHOCP repositories) MicroShift RPMs" + echo " script_opts Options passed through to executed python script" + echo "" + exit 1 +} + +if [ ! -d "${DEST_DIR}" ]; then + echo "Setting up virtualenv in ${DEST_DIR}" + python3 -m venv --system-site-packages "${DEST_DIR}" + "${DEST_DIR}/bin/python3" -m pip install --upgrade pip + "${DEST_DIR}/bin/python3" -m pip install -r "${SCRIPT_DIR}/requirements.txt" +fi +source "${DEST_DIR}/bin/activate" + +if [ "$#" -eq 0 ]; then + echo "Script requires at least 1 argument." + usage +fi + +cmd=$1 +shift + +if [[ "${cmd}" == "mirror" ]]; then + python3 "${SCRIPT_DIR}/gen_gh_releases_from_mirror.py" "$@" +elif [[ "${cmd}" == "rhocp" ]]; then + python3 "${SCRIPT_DIR}/gen_gh_releases_from_rhocp.py" "$@" +else + echo "Unrecognized argument: ${cmd}" + usage +fi diff --git a/scripts/release-notes/gen_ec_release_notes.py b/scripts/release-notes/gen_gh_releases_from_mirror.py old mode 100644 new mode 100755 similarity index 61% rename from scripts/release-notes/gen_ec_release_notes.py rename to scripts/release-notes/gen_gh_releases_from_mirror.py index 792526cba4..60a3a4666d --- a/scripts/release-notes/gen_ec_release_notes.py +++ b/scripts/release-notes/gen_gh_releases_from_mirror.py @@ -50,29 +50,18 @@ import argparse import collections -import datetime import html.parser import logging -import json -import os -import pathlib import re -import subprocess import textwrap -import urllib from urllib import request -import github +import common logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s') URL_BASE = "https://mirror.openshift.com/pub/openshift-v4/aarch64/microshift" URL_BASE_X86 = "https://mirror.openshift.com/pub/openshift-v4/x86_64/microshift" -GITHUB_ORG = 'openshift' -GITHUB_REPO = 'microshift' -REMOTE = "token-remote" -MAX_RELEASE_NOTE_BODY_SIZE = 125000 -TRUNCATED_MESSAGE = '\n\n(release notes were truncated)\n\n' # An EC RPM filename looks like # microshift-4.13.0~ec.4-202303070857.p0.gcf0bce2.assembly.ec.4.el9.aarch64.rpm @@ -94,10 +83,6 @@ re.VERBOSE, ) -# Save our token for use later -GITHUB_TOKEN = os.environ.get('GITHUB_TOKEN') - - # Representation of one release Release = collections.namedtuple( 'Release', @@ -110,22 +95,9 @@ def main(): The main function of the script. It runs the `check_one()` function for both 'ocp-dev-preview' and 'ocp' release types and for a specified version depending upon provided arguments. """ - global GITHUB_TOKEN - - # The script runs as - # .../microshift/scripts/release-notes/gen_ec_release_notes.py - # and we want the path to - # .../microshift - root_dir = pathlib.Path(__file__).parent.parent.parent - version_makefile = root_dir / 'Makefile.version.aarch64.var' - # Makefile contains something like - # OCP_VERSION := 4.16.0-0.nightly-arm64-2024-03-13-041907 - # and we want this ^^^^ - # - # We get it as ['4', '16'] to make the next part of the process of - # building the list of versions to scan easier. - _full_version = version_makefile.read_text('utf8').split('=')[-1].strip() - major, minor = _full_version.split('.')[:2] + common.load_github_token() + + major, minor = common.get_version_from_makefile() # We build a default list of versions to scan using the current # version and the previous version. This assumes the script is run @@ -190,12 +162,6 @@ def main(): ) args = parser.parse_args() - if not GITHUB_TOKEN: - logging.warning('GITHUB_TOKEN is not set, trying to authenticate using application credentials') - GITHUB_TOKEN = get_access_token_for_app() - if not GITHUB_TOKEN: - raise RuntimeError('GITHUB_TOKEN does not appear to be set') - # If the user has given us versions to scan, do not use the # computed defaults. if args.versions_to_scan: @@ -214,7 +180,7 @@ def main(): return print() - add_token_remote() + common.add_token_remote() unique_releases = { r.commit_sha: r @@ -222,60 +188,7 @@ def main(): } for new_release in unique_releases.values(): - publish_release(new_release, not args.dry_run) - - -def redact(input): - return str.replace(input, GITHUB_TOKEN, '~~REDACTED~~') - - -def run_process(cmd: list[str], env={}): - """ - Helper function to run external commands and log (redacted) output. - Stdout is returned as a str. - If command fails, exception is raised. - """ - cmd_to_log = redact(' '.join(cmd)) - logging.debug(f"Running command: {cmd_to_log}") - - # Include our existing environment settings to ensure values like - # HOME and other git settings are propagated. - env.update(os.environ) - - completed = subprocess.run( - cmd, - env=env, - capture_output=True - ) - sout = completed.stdout.decode('utf-8') if completed.stdout else '' - serr = str.strip(redact(completed.stderr.decode('utf-8'))) if completed.stderr else '' - logging.debug(f"Command '{cmd_to_log}' finished: rc='{completed.returncode}' stdout='{str.strip(redact(sout))}' stderr='{serr}'") - - if completed.returncode != 0: - raise subprocess.CalledProcessError(completed.returncode, cmd_to_log, redact(sout), serr) - - return sout - - -def get_access_token_for_app(): - """Return an access token for a GitHub App.""" - app_id = os.environ.get('APP_ID') - if not app_id: - raise RuntimeError('APP_ID is not set') - key_path = os.environ.get('CLIENT_KEY') - if not key_path: - raise RuntimeError('CLIENT_KEY is not set') - integration = github.GithubIntegration( - app_id, - pathlib.Path(key_path).read_text(encoding='utf-8'), - ) - app_installation = integration.get_installation(GITHUB_ORG, GITHUB_REPO) - if app_installation is None: - raise RuntimeError( - f"Failed to get app_installation for {GITHUB_ORG}/{GITHUB_REPO}. " + - f"Response: {app_installation.raw_data}" - ) - return integration.get_access_token(app_installation.id).token + publish_candidate_release(new_release, not args.dry_run) class VersionListParser(html.parser.HTMLParser): @@ -407,7 +320,7 @@ def check_for_new_releases(url_base, release_type, version): release_date = rpm_version_details["release_date"] patch_number = rpm_version_details["patch_num"] commit_sha = rpm_version_details["commit_sha"] - full_commit_sha = str.strip(run_process(["git", "rev-parse", "--verify", f"{commit_sha}^{{commit}}"])) + full_commit_sha = str.strip(common.run_process(["git", "rev-parse", "--verify", f"{commit_sha}^{{commit}}"])) # Older release names # look like "4.13.0-ec-2" but we had a few # sprints where we published multiple builds, so use more of the @@ -418,7 +331,7 @@ def check_for_new_releases(url_base, release_type, version): # Check if the release already exists logging.info(f"Checking for release {release_name}...") - if github_release_exists(release_name): + if common.github_release_exists(release_name): logging.info(f"Found an existing release {release_name}, no work to do") return None logging.info(f"Release tag {release_name} not found on remote repository") @@ -434,58 +347,13 @@ def check_for_new_releases(url_base, release_type, version): ) -def tag_exists(release_name): - "Checks if a given tag exists in the local repository." - try: - run_process(["git", "show", release_name]) - return True - except subprocess.CalledProcessError: - return False - - -def add_token_remote(): - """ - Adds the Git remote to the given repository using - the provided installation (or personal) access token. - """ - try: - run_process(["git", "remote", "remove", REMOTE]) - except subprocess.CalledProcessError: - pass - - remote_url = f"https://x-access-token:{GITHUB_TOKEN}@github.com/{GITHUB_ORG}/{GITHUB_REPO}" - run_process(["git", "remote", "add", REMOTE, remote_url]) - - -def get_previous_tag(release_name): - "Returns the name of the tag _before_ release_name on the branch." - output = run_process(["git", "describe", f'{release_name}~1', '--abbrev=0']) - return output.strip() - - -def tag_release(tag, sha, buildtime): - env = {} - timestamp = buildtime.strftime('%Y-%m-%d %H:%M') - env['GIT_COMMITTER_DATE'] = timestamp - - logging.info(f"Using 'GIT_COMMITTER_DATE={timestamp}' for 'git tag {tag} {sha}'") - run_process(['git', 'tag', '-m', tag, tag, sha], env) - - -def push_tag(tag): - run_process(['git', 'push', REMOTE, tag]) - - -def publish_release(new_release, take_action): - """Does the work to tag and publish a release. +def publish_candidate_release(new_release, take_action): + """Creates a release preamble, then tags and publishes the release. """ - release_name = new_release.release_name - commit_sha = new_release.commit_sha product_version = new_release.product_version candidate_type = new_release.candidate_type candidate_number = new_release.candidate_number release_type = new_release.release_type - release_date = new_release.release_date # Set up the release notes preamble with download links preamble = textwrap.dedent(f""" @@ -518,103 +386,7 @@ def publish_release(new_release, take_action): ``` """) - - if not tag_exists(release_name): - # release_date looks like 202402022103 - buildtime = datetime.datetime.strptime(release_date, '%Y%m%d%H%M') - tag_release(release_name, commit_sha, buildtime) - - # Get the previous tag on the branch as the starting point for the - # release notes. - previous_tag = get_previous_tag(release_name) - - # Auto-generate the release notes ourselves, add the preamble, - # then make sure the results fit within the size limits imposed by - # the API. - generated_notes = github_release_notes(previous_tag, release_name, commit_sha) - notes = f'{preamble}\n{generated_notes["body"]}' - if len(notes) > MAX_RELEASE_NOTE_BODY_SIZE: - lines = notes.splitlines() - last_line = lines[-1] - notes_content_we_can_truncate = notes[:-len(last_line)] - amount_we_can_keep = MAX_RELEASE_NOTE_BODY_SIZE - len(last_line) - len(TRUNCATED_MESSAGE) - truncated = notes_content_we_can_truncate[:amount_we_can_keep] - if truncated[-1] == '\n': - notes_to_keep = truncated - else: - # don't leave a partial line - notes_to_keep = truncated.rpartition('\n')[0].rstrip() - notes = f'{notes_to_keep}{TRUNCATED_MESSAGE}{last_line}' - - if not take_action: - logging.info(f'Dry run for new release {new_release} on commit {commit_sha} from {release_date}') - logging.info(notes) - return - - push_tag(release_name) - - # Create draft release with message that includes download URLs and history - github_release_create(release_name, notes) - - -def github_release_create(tag, notes): - results = github_api( - f'/repos/{GITHUB_ORG}/{GITHUB_REPO}/releases', - tag_name=tag, - name=tag, - body=notes, - draft=False, - prerelease=True, - ) - logging.info(f'Created new release {tag}:{ {"url":results["html_url"], "body": results["body"]} }') - - -def github_release_notes(previous_tag, tag_name, target_commitish): - results = github_api( - f'/repos/{GITHUB_ORG}/{GITHUB_REPO}/releases/generate-notes', - tag_name=tag_name, - target_commitish=target_commitish, - previous_tag_name=previous_tag, - ) - return results - - -def github_release_exists(tag): - try: - github_api(f'/repos/{GITHUB_ORG}/{GITHUB_REPO}/releases/tags/{tag}') - return True - except Exception: - return False - - -def github_api(path, **data): - url = f'https://api.github.com/{path.lstrip("/")}' - if data: - r = request.Request( - url=url, - data=json.dumps(data).encode('utf-8'), - ) - else: - r = request.Request(url=url) - - logging.info(f"GitHub API Request: { {'method':r.get_method(), 'url': url, 'data': data} }") - r.add_header('Accept', 'application/vnd.github+json') - r.add_header('User-agent', 'microshift-release-notes') - r.add_header('Authorization', f'Bearer {GITHUB_TOKEN}') - r.add_header('X-GitHub-Api-Version', '2022-11-28') - - try: - response = request.urlopen(r) - except urllib.error.URLError as e: - logging.error(f"GitHub API Request Failed: '{str(e.fp.readlines())}'") - # e.fp.readlines() sinks the response body but it's not read in any other place, - # so just re-raise for the exception type. - raise - except Exception as err: - logging.error(f"GitHub API Request Failed: '{err}'") - raise - - return json.loads(response.read().decode('utf-8')) + common.publish_release(new_release, preamble, take_action) if __name__ == "__main__": diff --git a/scripts/release-notes/gen_gh_releases_from_rhocp.py b/scripts/release-notes/gen_gh_releases_from_rhocp.py new file mode 100755 index 0000000000..f4ca1ca757 --- /dev/null +++ b/scripts/release-notes/gen_gh_releases_from_rhocp.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python3 + +"""Release Note Tool + +This script partially automates the process of publishing release +notes for released builds of MicroShift. +""" + +import argparse +import os +import dnf +import json +import textwrap +import logging +import platform + +from github import Github # pygithub + +from gen_gh_releases_from_mirror import Release +import common + +logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s') + + +def get_rpm_releases(): + """Gets the releases from the released MicroShift RPMs in the RHOCP repositories. + """ + arch = platform.machine() + _, current_minor = common.get_version_from_makefile() + + with dnf.Base() as base: + base.read_all_repos() + + # Disable all repos (in the memory, not on the host) to just query RHOCP repos and make operation faster. + base.repos.all().disable() + + # Enable RHOCP repos starting from 4.14 to the current-2 (inclusive; range() stops before the second argument). + # E.g., for 4.21 it's 4.14-4.19 because when 4.21 development started, the 4.20 wasn't released yet. + for minor in range(14, int(current_minor)-1): + repo_id = f"rhocp-4.{minor}-for-rhel-9-{arch}-rpms" + r = base.repos.get_matching(repo_id) + r.enable() + logging.info(f'Enabled repo: {r.id} - {r.name}') + + # It's faster to enable bunch of repos at once and fill the sack once rather than filling it after enabling each repo. + base.fill_sack() + + # Try to add current-1 (continuing example from above, it'd be 4.20). + # This is separate because DNF does not query remote repos in order, so enabling not active repo can derail whole cache update. + try: + r = base.repos.get(f"rhocp-4.{int(current_minor)-1}-for-rhel-9-{arch}-rpms") + r.enable() + logging.info(f'Enabled repo: {r.id} - {r.name}') + base.fill_sack() + except dnf.exceptions.RepoError as e: + if 'All mirrors were tried' in str(e): + logging.info('Repo is not up yet, skipping') + r.disable() + logging.info(f'Disabled repo: {r.id} - {r.name}') + else: + raise e + except Exception as e: + raise e + + releases = [] + + query = base.sack.query().available().filter(name='microshift') + for pkg in query: + # Example pkg.version value: 4.16.47 + # Example pkg.release value: 202509010322.p0.g54f411b.assembly.4.16.47.el9 + + pkg_release = pkg.release.split('.') + release_date = pkg_release[0] + commit_sha = pkg_release[2].lstrip('g') + full_commit_sha = str.strip(common.run_process(["git", "rev-parse", "--verify", f"{commit_sha}^{{commit}}"])) + if not full_commit_sha: + raise RuntimeError(f"No full commit SHA found for {pkg}") + + rel = Release( + f"{pkg.version}-{release_date}.{pkg_release[1]}", # 4.16.47-202509010322.p0 - name of the GH release / tag + full_commit_sha, # 54f411ba7c8853ab28b84f018391e81993e04c99 + pkg.version, # 4.16.47 + "", "", "", # Not applicable as these fields are intended for differentiating ECs and RCs. + release_date) # 202509010322 + releases.append(rel) + logging.info(f"Transformed RPM into Release struct: {pkg} => {rel}") + + return releases + + +def publish_release(new_release, take_action): + """ + Creates a release preamble, then tags and publishes the release. + """ + product_version = new_release.product_version + xy = '.'.join(product_version.split('.')[0:2]) + + # Set up the release notes preamble with download links + preamble = textwrap.dedent(f""" + To install MicroShift {product_version}, follow the documentation: https://docs.redhat.com/en/documentation/red_hat_build_of_microshift/{xy} + """) + + common.publish_release(new_release, preamble, take_action) + + +def is_branch_synced_with_main(ci_job_branch): + """ + Checks if the job is running against a branch that is synced with main. + This script should only run on a single branch as it handles all versions of released RPMs. + However, periodics against main are not allowed therefore we need to check if the current branch is synced with main. + """ + gh_repo = Github().get_repo(f"{common.GITHUB_ORG}/{common.GITHUB_REPO}") + issue = gh_repo.get_issue(number=1239) + title = issue.title + try: + branches_part = title.split('|', 1)[1].strip() + branch_tokens = [x.replace('branch:', '') for x in branches_part.split()] + if ci_job_branch in branch_tokens: + return True + except Exception as e: + raise RuntimeError(f"Failed to parse freeze issue title: {title} ({e})") + return False + + +def get_args_parser(): + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument( + '--ci-job-branch', + action='store', + default="", + dest='ci_job_branch', + help='The branch the CI job is running against - unnecessary if running the script locally', + ) + + subparsers = parser.add_subparsers(dest="command") + parser_query = subparsers.add_parser( + "query", help="Query the RHOCP repositories for all MicroShift RPMs. It's recommended to run this command as root to update the DNF cache.") + parser_query.add_argument( + '--keep-existing-tags', + action='store_true', + default=False, + dest='keep_existing_tags', + help='Keep releases that already exist based on the local repository tags. Default is to filter them out to avoid calling GitHub API unnecessarily.', + ) + parser_query.add_argument( + "--output", help="Path to save the results file", required=True) + + parser_publish = subparsers.add_parser( + "publish", help="Publish the draft releases to the GitHub repository. Avoid running as root to avoid potential local git repo issues.") + parser_publish.add_argument( + "--input", help="Path to the results file generated by the 'query' command", required=True) + parser_publish.add_argument( + "-n", "--dry-run", action="store_true", default=False, help="Report but take no action") + + return parser + + +def main(): + parser = get_args_parser() + args = parser.parse_args() + + if args.ci_job_branch and not is_branch_synced_with_main(args.ci_job_branch): + logging.warning(f"The CI job is running against a branch that is not synced with main: {args.ci_job_branch}") + exit(0) + + if args.command == "query": + if os.getuid() != 0: + logging.warning("Script is not running as root - dnf cache will not be updated.") + + rpm_releases = get_rpm_releases() + # Sort oldest first, so created GH releases have something to diff against (older patch versions within the same minor version). + rpm_releases.sort(key=lambda r: r.release_date) + if not args.keep_existing_tags: + rpm_releases = [r for r in rpm_releases if not common.tag_exists(r.release_name)] + with open(args.output, "w", encoding="utf-8") as f: + # Cannot serialize Release objects directly to JSON, so convert to dicts first. + release_dicts = [r._asdict() for r in rpm_releases] + f.write(json.dumps(release_dicts).replace("},", "},\n")) + logging.info(f"Saved {len(rpm_releases)} releases to {args.output}") + + elif args.command == "publish": + common.load_github_token() + + if os.getuid() == 0: + logging.warning("Running 'publish' as root is not recommended to avoid potential local git repo issues.") + exit(0) + + with open(args.input, "r", encoding="utf-8") as f: + j = json.load(f) + rpm_releases = [Release(**r) for r in j] + common.add_token_remote() + logging.info(f"Attempting to publish {len(rpm_releases)} draft releases") + i = 1 + for r in rpm_releases: + if not common.github_release_exists(r.release_name): + publish_release(r, not args.dry_run) + else: + logging.info(f"Release {r.release_name} already exists on remote GitHub repository, skipping") + logging.info(f"Progress: {i}/{len(rpm_releases)}") + i += 1 + + else: + parser.print_help() + + +if __name__ == "__main__": + main() diff --git a/scripts/release-notes/tag_stable_releases.py b/scripts/release-notes/tag_stable_releases.py deleted file mode 100644 index e8414ea327..0000000000 --- a/scripts/release-notes/tag_stable_releases.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import datetime -import logging -import os -import platform -import subprocess -import sys - -import dnf - -logger = logging.getLogger() - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--verbose', '-v', action='store_true', dest='verbose') - args = parser.parse_args() - - log_level = logging.WARN - if args.verbose: - log_level = logging.DEBUG - - logging.basicConfig( - stream=sys.stdout, - level=log_level, - ) - - machine_arch = platform.machine() - - logger.debug('reading dnf database') - base = dnf.Base() - base.read_all_repos() - base.fill_sack() - logger.debug('finding matching repositories') - repos = base.repos.get_matching(f'rhocp-4.*-{machine_arch}-rpms') - - for repo in sorted(repos, key=lambda r: r.name): - reponame = repo.id - logger.debug('starting %s', reponame) - - q = base.sack.query().available().filter( - name='microshift', - reponame=reponame, - ) - - for pkg in q: - # a release string looks like: - # 202305161335.p0.g17cae44.assembly.4.13.0.el9 - sha = pkg.release.split('.')[2].lstrip('g') - buildtime = datetime.datetime.fromtimestamp(pkg.buildtime) - tag = f'v{pkg.version}' - logger.debug('package %s sha %s tag %s buildtime %s', pkg, sha, tag, buildtime) - if tag_exists(tag): - logger.debug('found tag %s', tag) - else: - tag_release(tag, sha, buildtime) - - -def tag_exists(tag): - "Checks if a given tag exists in the local repository." - try: - subprocess.run(["git", "show", tag], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - check=True) - return True - except subprocess.CalledProcessError: - return False - - -def tag_release(tag, sha, buildtime): - env = {} - # Include our existing environment settings to ensure values like - # HOME and other git settings are propagated. - env.update(os.environ) - timestamp = buildtime.strftime('%Y-%m-%d %H:%M') - env['GIT_COMMITTER_DATE'] = timestamp - print(f'GIT_COMMITTER_DATE={timestamp} git tag -s {tag} {sha}') - subprocess.run( - ['git', 'tag', '-s', '-m', tag, tag, sha], - env=env, - check=True, - ) - - -# git-tag man page shows how to backdate tags using GIT_COMMITTER_DATE variable -if __name__ == '__main__': - main() diff --git a/test/assets/common_versions.sh.template b/test/assets/common_versions.sh.template index de2b736952..f2d8ddbd3f 100644 --- a/test/assets/common_versions.sh.template +++ b/test/assets/common_versions.sh.template @@ -45,6 +45,12 @@ get_vrel_from_rhsm() {{ get_vrel_from_rpm() {{ local -r rpm_dir="$1" + # exit if rpm_dir directory does not exist + if [ ! -d "${{rpm_dir}}" ]; then + echo "" + return + fi + local -r rpm_release_info_file=$(find "${{rpm_dir}}" -name "microshift-release-info-*.rpm" | sort | tail -n1) if [ -z "${{rpm_release_info_file}}" ]; then echo "" @@ -136,16 +142,29 @@ export CNCF_SYSTEMD_LOGS_VERSION={CNCF_SYSTEMD_LOGS_VERSION} export GITOPS_VERSION={GITOPS_VERSION} # The brew release versions needed for release regression testing -BREW_Y0_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/4.${{MINOR_VERSION}}-zstream/{ARCH}/")" -BREW_Y1_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/4.${{PREVIOUS_MINOR_VERSION}}-zstream/{ARCH}/")" -BREW_Y2_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/4.${{YMINUS2_MINOR_VERSION}}-zstream/{ARCH}/")" -BREW_RC_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/4.${{MINOR_VERSION}}-rc/{ARCH}/")" -BREW_EC_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/4.${{MINOR_VERSION}}-ec/{ARCH}/")" +Y0_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}$" | sort -V | tail -n1 || echo "")" +Y1_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{PREVIOUS_MINOR_VERSION}}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" +Y2_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{YMINUS2_MINOR_VERSION}}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" +Z1_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" +RC_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}-rc$" | sort -V | tail -n1 || echo "")" +EC_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}-ec$" | sort -V | tail -n1 || echo "")" +NIGHTLY_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}-nightly$" | sort -V | tail -n1 || echo "")" + +BREW_Y0_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Y0_VERSION}}/{ARCH}/")" +BREW_Y1_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Y1_VERSION}}/{ARCH}/")" +BREW_Y2_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Y2_VERSION}}/{ARCH}/")" +BREW_Z1_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Z1_VERSION}}/{ARCH}/")" +BREW_RC_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{RC_VERSION}}/{ARCH}/")" +BREW_EC_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{EC_VERSION}}/{ARCH}/")" +BREW_NIGHTLY_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{NIGHTLY_VERSION}}/{ARCH}/")" + export BREW_Y0_RELEASE_VERSION export BREW_Y1_RELEASE_VERSION export BREW_Y2_RELEASE_VERSION +export BREW_Z1_RELEASE_VERSION export BREW_RC_RELEASE_VERSION export BREW_EC_RELEASE_VERSION +export BREW_NIGHTLY_RELEASE_VERSION # Set the release type to ec, rc or zstream LATEST_RELEASE_TYPE="{LATEST_RELEASE_TYPE}" diff --git a/test/assets/kustomizations/greenboot/kustomization.yaml b/test/assets/kustomizations/greenboot/kustomization.yaml index 1a864f62a3..3540204607 100644 --- a/test/assets/kustomizations/greenboot/kustomization.yaml +++ b/test/assets/kustomizations/greenboot/kustomization.yaml @@ -6,4 +6,4 @@ resources: - busybox.yaml images: - name: BUSYBOX_IMAGE - newName: busybox:1.35 + newName: quay.io/microshift/busybox:1.36 diff --git a/test/assets/observability/otel_config.yaml b/test/assets/observability/otel_config.yaml index 847486dc7d..e11d2f72b5 100644 --- a/test/assets/observability/otel_config.yaml +++ b/test/assets/observability/otel_config.yaml @@ -55,8 +55,10 @@ exporters: metric_expiration: 30m prometheusremotewrite: endpoint: "http://[{{PROMETHEUS_HOST}}]:{{PROMETHEUS_PORT}}/api/v1/write" - loki: # only for logs, exports the logs in the loki server - endpoint: "http://[{{LOKI_HOST}}]:{{LOKI_PORT}}/loki/api/v1/push" + resource_to_telemetry_conversion: + enabled: true + otlphttp/loki: # only for logs, exports the logs in the loki server + endpoint: "http://[{{LOKI_HOST}}]:{{LOKI_PORT}}/otlp" extensions: file_storage: @@ -71,12 +73,13 @@ service: exporters: [ prometheus, prometheusremotewrite ] metrics/kubeletstats: receivers: [ kubeletstats ] + processors: [ resourcedetection/system ] exporters: [ prometheus, prometheusremotewrite ] logs/journald: receivers: [ journald ] - processors: [ batch, resource/journald ] - exporters: [ loki ] + processors: [ resourcedetection/system, batch, resource/journald ] + exporters: [ otlphttp/loki ] logs/kube_events: receivers: [ k8s_events ] - processors: [ batch, resource/kube_events ] - exporters: [ loki ] + processors: [ resourcedetection/system, batch, resource/kube_events ] + exporters: [ otlphttp/loki ] diff --git a/test/assets/sriov/sriov-network-policy-template.yaml b/test/assets/sriov/sriov-network-policy-template.yaml new file mode 100644 index 0000000000..735a81f118 --- /dev/null +++ b/test/assets/sriov/sriov-network-policy-template.yaml @@ -0,0 +1,17 @@ +apiVersion: sriovnetwork.openshift.io/v1 +kind: SriovNetworkNodePolicy +metadata: + name: policy-1 +spec: + nodeSelector: + node.kubernetes.io/instance-type: rhde + resourceName: intelnics + priority: 99 + mtu: 9000 + numVfs: 2 + nicSelector: + deviceID: "PLACEHOLDER_DEVICE_ID" + rootDevices: + - PLACEHOLDER_PCI_ADDRESS + vendor: "8086" + deviceType: netdevice diff --git a/test/bin/build_images.sh b/test/bin/build_images.sh index acf0d2a941..776f561083 100755 --- a/test/bin/build_images.sh +++ b/test/bin/build_images.sh @@ -721,6 +721,7 @@ if ${EXTRACT_CONTAINER_IMAGES}; then [ -n "${BREW_Y2_RELEASE_VERSION}" ] && extract_container_images "${BREW_Y2_RELEASE_VERSION}" "${BREW_REPO}" "${CONTAINER_LIST}" [ -n "${BREW_RC_RELEASE_VERSION}" ] && extract_container_images "${BREW_RC_RELEASE_VERSION}" "${BREW_REPO}" "${CONTAINER_LIST}" [ -n "${BREW_EC_RELEASE_VERSION}" ] && extract_container_images "${BREW_EC_RELEASE_VERSION}" "${BREW_REPO}" "${CONTAINER_LIST}" + [ -n "${BREW_NIGHTLY_RELEASE_VERSION}" ] && extract_container_images "${BREW_NIGHTLY_RELEASE_VERSION}" "${BREW_REPO}" "${CONTAINER_LIST}" fi trap 'osbuild_logs' EXIT diff --git a/test/bin/build_rpms.sh b/test/bin/build_rpms.sh index 785cbff52a..bb2b4dfffe 100755 --- a/test/bin/build_rpms.sh +++ b/test/bin/build_rpms.sh @@ -121,12 +121,10 @@ download_brew_rpms() { rm -rf "${BREW_RPM_SOURCE}" # Run the download procedure bash -x "${SCRIPTDIR}/../../scripts/fetch_tools.sh" brew - bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${MINOR_VERSION}" "${BREW_RPM_SOURCE}" - bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${MINOR_VERSION}" "${BREW_RPM_SOURCE}" "zstream" || true - bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${PREVIOUS_MINOR_VERSION}" "${BREW_RPM_SOURCE}" "zstream" || true - bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${YMINUS2_MINOR_VERSION}" "${BREW_RPM_SOURCE}" "zstream" || true - bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${MINOR_VERSION}" "${BREW_RPM_SOURCE}" "rc" || true - bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${MINOR_VERSION}" "${BREW_RPM_SOURCE}" "ec" || true + bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${MINOR_VERSION}" "${BREW_RPM_SOURCE}" "${LATEST_RELEASE_TYPE}" || echo "WARNING: Failed to download ${LATEST_RELEASE_TYPE} RPMs for 4.${MINOR_VERSION}" + bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${MINOR_VERSION}" "${BREW_RPM_SOURCE}" "nightly" || echo "WARNING: Failed to download nightly RPMs for 4.${MINOR_VERSION}" + bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${PREVIOUS_MINOR_VERSION}" "${BREW_RPM_SOURCE}" "zstream" || echo "WARNING: Failed to download zstream RPMs for 4.${PREVIOUS_MINOR_VERSION}" + bash -x "${SCRIPTDIR}/manage_brew_rpms.sh" download "4.${YMINUS2_MINOR_VERSION}" "${BREW_RPM_SOURCE}" "zstream" || ( echo "WARNING: Failed to download zstream RPMs for 4.${YMINUS2_MINOR_VERSION}" && return 1 ) else echo "WARNING: The Brew Hub site is not accessible, skipping the download" fi diff --git a/test/bin/ci_phase_boot_and_test.sh b/test/bin/ci_phase_boot_and_test.sh index 31e4522ade..fd87762fc4 100755 --- a/test/bin/ci_phase_boot_and_test.sh +++ b/test/bin/ci_phase_boot_and_test.sh @@ -48,7 +48,7 @@ bash -x ./scripts/devenv-builder/cleanup-composer.sh -full cd "${ROOTDIR}/test" -# Set up the hypervisor configuration for the tests and start webserver +# Set up the hypervisor configuration for the tests and start webserver, prometheus and loki bash -x ./bin/manage_hypervisor_config.sh create # Setup a container registry and mirror images. @@ -65,7 +65,7 @@ cd "${TESTDIR}" if [ ! -d "${RF_VENV}" ]; then "${ROOTDIR}/scripts/fetch_tools.sh" robotframework fi -if [[ "${SCENARIO_TYPE:-}" =~ .*releases.* ]]; then +if [[ "${SCENARIO_SOURCES:-}" =~ .*releases.* ]]; then "${ROOTDIR}/scripts/fetch_tools.sh" ginkgo fi diff --git a/test/bin/ci_phase_iso_build.sh b/test/bin/ci_phase_iso_build.sh index dc15ab7b3c..0abfee4f19 100755 --- a/test/bin/ci_phase_iso_build.sh +++ b/test/bin/ci_phase_iso_build.sh @@ -63,10 +63,12 @@ update_build_cache() { return fi - # Build the composer-cli base layer to be cached + # Build the composer-cli base layer and brew RPMs to be cached $(dry_run) bash -x ./bin/build_images.sh -l ./image-blueprints/layer1-base - # Build the bootc base layer to be cached + $(dry_run) bash -x ./bin/build_images.sh -l ./image-blueprints/layer4-release + # Build the bootc base layer and brew RPMs to be cached $(dry_run) bash -x ./bin/build_bootc_images.sh -l ./image-blueprints-bootc/layer1-base + $(dry_run) bash -x ./bin/build_bootc_images.sh -l ./image-blueprints-bootc/layer5-release # Prepare for the cache upload by stopping composer services and cleaning # temporary artifacts @@ -97,6 +99,9 @@ run_image_build() { if [[ "${CI_JOB_NAME}" =~ .*periodic.* ]]; then $(dry_run) bash -x ./bin/build_images.sh -l ./image-blueprints/layer3-periodic fi + if [[ "${CI_JOB_NAME}" =~ .*release.* ]]; then + $(dry_run) bash -x ./bin/build_images.sh -l ./image-blueprints/layer4-release + fi else # Fall back to full build when not running in CI $(dry_run) bash -x ./bin/build_images.sh @@ -117,11 +122,15 @@ run_bootc_image_build() { if [[ "${CI_JOB_NAME}" =~ .*upstream.* ]]; then $(dry_run) bash -x ./bin/build_bootc_images.sh -l ./image-blueprints-bootc/layer4-upstream fi + if [[ "${CI_JOB_NAME}" =~ .*release.* ]]; then + $(dry_run) bash -x ./bin/build_bootc_images.sh -l ./image-blueprints-bootc/layer5-release + fi else $(dry_run) bash -x ./bin/build_bootc_images.sh -l ./image-blueprints-bootc/layer1-base $(dry_run) bash -x ./bin/build_bootc_images.sh -l ./image-blueprints-bootc/layer2-presubmit $(dry_run) bash -x ./bin/build_bootc_images.sh -l ./image-blueprints-bootc/layer3-periodic $(dry_run) bash -x ./bin/build_bootc_images.sh -l ./image-blueprints-bootc/layer4-upstream + $(dry_run) bash -x ./bin/build_bootc_images.sh -l ./image-blueprints-bootc/layer5-release fi } @@ -135,7 +144,7 @@ cd "${ROOTDIR}" # Get firewalld and repos in place. Use scripts to get the right repos # for each branch. -$(dry_run) bash -x ./scripts/devenv-builder/configure-vm.sh --no-build --force-firewall "${PULL_SECRET}" +$(dry_run) bash -x ./scripts/devenv-builder/configure-vm.sh --skip-dnf-update --no-build --force-firewall "${PULL_SECRET}" $(dry_run) bash -x ./test/bin/manage_composer_config.sh create cd "${ROOTDIR}/test/" @@ -144,6 +153,9 @@ cd "${ROOTDIR}/test/" # shellcheck source=test/bin/common.sh source "${SCRIPTDIR}/common.sh" +# shellcheck source=test/bin/common_versions_verify.sh +source "${SCRIPTDIR}/common_versions_verify.sh" + if ${COMPOSER_CLI_BUILDS} ; then # Determine and create the ideal number of workers $(dry_run) bash -x ./bin/manage_composer_config.sh create-workers diff --git a/test/bin/common.sh b/test/bin/common.sh index 1886a86010..b8c2f63c31 100644 --- a/test/bin/common.sh +++ b/test/bin/common.sh @@ -370,7 +370,6 @@ MICROSHIFT_MANDATORY_RPMS_LIST=( microshift microshift-release-info ) - MICROSHIFT_Y2_OPTIONAL_RPMS_LIST=( microshift-olm microshift-olm-release-info @@ -379,19 +378,25 @@ MICROSHIFT_Y2_OPTIONAL_RPMS_LIST=( microshift-gateway-api microshift-gateway-api-release-info microshift-low-latency + microshift-observability ) MICROSHIFT_Y1_OPTIONAL_RPMS_LIST=( "${MICROSHIFT_Y2_OPTIONAL_RPMS_LIST[@]}" - microshift-observability + microshift-cert-manager + microshift-cert-manager-release-info ) MICROSHIFT_OPTIONAL_RPMS_LIST=( "${MICROSHIFT_Y1_OPTIONAL_RPMS_LIST[@]}" - microshift-cert-manager + microshift-sriov + microshift-sriov-release-info ) -MICROSHIFT_Y1_X86_64_RPMS_LIST=( +MICROSHIFT_Y2_X86_64_RPMS_LIST=( microshift-ai-model-serving microshift-ai-model-serving-release-info ) +MICROSHIFT_Y1_X86_64_RPMS_LIST=( + "${MICROSHIFT_Y2_X86_64_RPMS_LIST[@]}" +) MICROSHIFT_X86_64_RPMS_LIST=( "${MICROSHIFT_Y1_X86_64_RPMS_LIST[@]}" ) diff --git a/test/bin/common_versions.sh b/test/bin/common_versions.sh index d74f1bb8ac..3525542234 100644 --- a/test/bin/common_versions.sh +++ b/test/bin/common_versions.sh @@ -97,8 +97,8 @@ export CURRENT_RELEASE_VERSION # For a release branch, the previous release repository should come from the # official 'rhocp' stream.# The previous release repository value should either # point to the OpenShift mirror URL or the 'rhocp' repository name. -PREVIOUS_RELEASE_REPO="https://mirror.openshift.com/pub/openshift-v4/${UNAME_M}/microshift/ocp/latest-4.20/el9/os" -PREVIOUS_RELEASE_VERSION="$(get_vrel_from_beta "${PREVIOUS_RELEASE_REPO}")" +PREVIOUS_RELEASE_REPO="rhocp-4.20-for-rhel-9-${UNAME_M}-rpms" +PREVIOUS_RELEASE_VERSION="$(get_vrel_from_rhsm "${PREVIOUS_RELEASE_REPO}")" export PREVIOUS_RELEASE_REPO export PREVIOUS_RELEASE_VERSION @@ -122,7 +122,7 @@ export RHOCP_MINOR_Y_BETA # The 'rhocp_minor_y' variable should be the previous minor version number, if # the previous release is available through the 'rhocp' stream, otherwise empty. -RHOCP_MINOR_Y1="" +RHOCP_MINOR_Y1=20 # The beta repository, containing dependencies, should point to the # OpenShift mirror URL. The mirror for previous release should always # be available. @@ -142,16 +142,29 @@ export CNCF_SYSTEMD_LOGS_VERSION=v0.4 export GITOPS_VERSION=1.16 # The brew release versions needed for release regression testing -BREW_Y0_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/4.${MINOR_VERSION}-zstream/${UNAME_M}/")" -BREW_Y1_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/4.${PREVIOUS_MINOR_VERSION}-zstream/${UNAME_M}/")" -BREW_Y2_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/4.${YMINUS2_MINOR_VERSION}-zstream/${UNAME_M}/")" -BREW_RC_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/4.${MINOR_VERSION}-rc/${UNAME_M}/")" -BREW_EC_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/4.${MINOR_VERSION}-ec/${UNAME_M}/")" +Y0_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}$" | sort -V | tail -n1 || echo "")" +Y1_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${PREVIOUS_MINOR_VERSION}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" +Y2_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${YMINUS2_MINOR_VERSION}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" +Z1_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" +RC_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}-rc$" | sort -V | tail -n1 || echo "")" +EC_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}-ec$" | sort -V | tail -n1 || echo "")" +NIGHTLY_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}-nightly$" | sort -V | tail -n1 || echo "")" + +BREW_Y0_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Y0_VERSION}/${UNAME_M}/")" +BREW_Y1_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Y1_VERSION}/${UNAME_M}/")" +BREW_Y2_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Y2_VERSION}/${UNAME_M}/")" +BREW_Z1_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Z1_VERSION}/${UNAME_M}/")" +BREW_RC_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${RC_VERSION}/${UNAME_M}/")" +BREW_EC_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${EC_VERSION}/${UNAME_M}/")" +BREW_NIGHTLY_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${NIGHTLY_VERSION}/${UNAME_M}/")" + export BREW_Y0_RELEASE_VERSION export BREW_Y1_RELEASE_VERSION export BREW_Y2_RELEASE_VERSION +export BREW_Z1_RELEASE_VERSION export BREW_RC_RELEASE_VERSION export BREW_EC_RELEASE_VERSION +export BREW_NIGHTLY_RELEASE_VERSION # Set the release type to ec, rc or zstream LATEST_RELEASE_TYPE="ec" @@ -165,4 +178,3 @@ OPENSHIFT_TESTS_PRIVATE_REPO_BRANCH="release-4.${MINOR_VERSION}" OPENSHIFT_TESTS_PRIVATE_REPO_COMMIT="61613d96c91db7b2907c24dd257075d3f2201991" export OPENSHIFT_TESTS_PRIVATE_REPO_BRANCH export OPENSHIFT_TESTS_PRIVATE_REPO_COMMIT - diff --git a/test/bin/common_versions_verify.sh b/test/bin/common_versions_verify.sh new file mode 100644 index 0000000000..e8142f9054 --- /dev/null +++ b/test/bin/common_versions_verify.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +# Following script serves as a sort of presubmit to make sure that following files stay in sync: +# - test/bin/common_versions.sh +# - test/bin/pyutils/generate_common_versions.py +# - test/assets/common_versions.sh.template + +# Check if there was a change to common_versions.sh on current branch compared to base branch. +# --exit-code: 0 means no changes, 1 means changes hence the inverted condition with '!' +# Because the top commit is Merge Commit of PR branch into base branch (e.g. main), we need to check against the earlier commit (i.e. ^1). +if ! git diff --exit-code "${SCENARIO_BUILD_BRANCH}^1...HEAD" "${ROOTDIR}/test/bin/common_versions.sh"; then + # If the file was changed, regenerate it and compare - diff means that most likely the file was updated manually. + "${ROOTDIR}/scripts/pyutils/create-venv.sh" + + if [ "${SCENARIO_BUILD_BRANCH}" == "main" ]; then + y=$(awk -F'[ .]' '{print $4}' < "${ROOTDIR}/Makefile.version.x86_64.var") + else + y=$(echo "${SCENARIO_BUILD_BRANCH}" | awk -F'[-.]' '{ print $3 }') + fi + + "${ROOTDIR}/_output/pyutils/bin/python" \ + "${ROOTDIR}/test/bin/pyutils/generate_common_versions.py" \ + "${y}" \ + --update-file + if ! git diff --exit-code "${ROOTDIR}/test/bin/common_versions.sh"; then + echo "ERROR: Discovered that common_versions.sh was updated on the branch under test, but the regenerated version is different" + git diff + exit 1 + fi +fi diff --git a/test/bin/manage_brew_rpms.sh b/test/bin/manage_brew_rpms.sh index 263ca5e803..8e342827e8 100755 --- a/test/bin/manage_brew_rpms.sh +++ b/test/bin/manage_brew_rpms.sh @@ -5,12 +5,14 @@ SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # Note: Avoid sourcing common.sh or common_version.sh in this script to allow # its execution in a containerized environment with limited set of tools. +UNAME_M="${UNAME_M:-$(uname -m)}" + usage() { echo "Usage: $(basename "$0") [access | download [version_type]]" - echo " download: Download the RPM version to the path as specified" + echo " download: Download the latest RPM packages for the given version, Z-1, Y-2 and Y-1 to the path as specified" echo " - version: the X.Y version. Example: 4.19" echo " - path: the output directory. Example: /_output/test-images/brew-rpms" - echo " - version_type: Optional. Valid values: rc, ec and zstream. Default: ec" + echo " - version_type: Optional. Valid values: rc, ec, zstream and nightly. Default: nightly" echo " access: Exit with non-zero status if brew cannot be accessed" } @@ -18,7 +20,7 @@ action_access() { local -r outfile=$(mktemp /tmp/curl-brewhub.XXXXXXXX) local rc=0 - if ! curl --silent --show-error --head "https://brewhub.engineering.redhat.com" &> "${outfile}" ; then + if ! curl --retry 10 --retry-delay 5 --retry-max-time 120 --silent --show-error --head "https://brewhub.engineering.redhat.com" &> "${outfile}" ; then rc=1 # Display the error in case the site is not accessible. # This is useful to rule out certificate problems, etc. @@ -29,61 +31,204 @@ action_access() { return ${rc} } -action_download() { +find_package() { local -r ver=$1 - local -r dir=$2 - local -r ver_type=${3:-ec} + local -r ver_type=${2:-nightly} + local -r ver_prev_y=${3:-0} + local -r ver_prev_z=${4:-0} - if [ -z "${ver}" ] || [ -z "${dir}" ] ; then - echo "ERROR: At least two parameters (version and path) are required" - exit 1 + # Validate version format + if ! [[ "${ver}" =~ ^4\.[0-9]+(\.[0-9]+)?$ ]]; then + echo "ERROR: Version '${ver}' does not match required format 4.Y or 4.Y.Z (e.g., 4.20 or 4.20.1)" + return 1 fi - if ! action_access ; then - echo "ERROR: Brew Hub site is not accessible" - exit 1 + # Validate optional numeric parameters + if ! [[ "${ver_prev_y}" =~ ^[0-9]$ ]] || ! [[ "${ver_prev_z}" =~ ^[0-9]$ ]]; then + echo "ERROR: ver_prev_y '${ver_prev_y}' and ver_prev_z '${ver_prev_z}' must be a non-negative integer and less than 10" + return 1 fi - "${SCRIPTDIR}/../../scripts/fetch_tools.sh" brew - # Attempt downloading the specified build version - local package + # Extract version components + ver_x=$(echo "${ver}" | cut -d'.' -f1) + ver_y=$(echo "${ver}" | cut -d'.' -f2) + + # Calculate previous X.Y version + ver_y=$((ver_y - ver_prev_y)) + + local package="" + set +x case ${ver_type} in zstream) - package=$(brew list-builds --quiet --package=microshift --state=COMPLETE | grep "^microshift-${ver}" | grep -v "~" | uniq | tail -n1) || true + package_list=$(sudo dnf repoquery --quiet --repo "rhocp-${ver_x}.${ver_y}-for-rhel-9-${UNAME_M}-rpms" 2>/dev/null) || true + package_filtered=$(echo "${package_list}" | grep "microshift-0:" | sed 's/0://' | sed "s/.${UNAME_M}$//" | sort -V | uniq ) || true + if [ -z "${package}" ] ; then + package_list=$(brew list-builds --quiet --package=microshift --state=COMPLETE 2>/dev/null) || true + package_filtered=$(echo "${package_list}" | grep "^microshift-${ver_x}.${ver_y}" | grep -v "~" | sort -V | uniq ) || true + fi + package=$(echo "${package_filtered}" | tail -n$((1 + ver_prev_z)) | head -n1 | awk '{print $1}') || true + ;; + nightly) + package_list=$(brew list-builds --quiet --package=microshift --state=COMPLETE 2>/dev/null ) || true + package_filtered=$(echo "${package_list}" | grep "^microshift-${ver_x}.${ver_y}" | grep "nightly" | sort -V | uniq ) || true + package=$(echo "${package_filtered}" | tail -n1 | awk '{print $1}') || true ;; rc|ec) - package=$(brew list-builds --quiet --package=microshift --state=COMPLETE | grep "^microshift-${ver}.0~${ver_type}." | tail -n1) || true + package_list=$(brew list-builds --quiet --package=microshift --state=COMPLETE 2>/dev/null ) || true + package_filtered=$(echo "${package_list}" | grep "^microshift-${ver_x}.${ver_y}.0~${ver_type}." | sort -V | uniq ) || true + package=$(echo "${package_filtered}" | tail -n1 | awk '{print $1}') || true ;; *) - echo "ERROR: Invalid version_type '${ver_type}'. Valid values are: rc, ec and zstream" + echo "ERROR: Invalid version_type '${ver_type}'. Valid values are: rc, ec, zstream and nightly" exit 1 ;; esac + set -x + echo "${package}" +} + +action_download() { + local -r ver=$1 + local -r main_dir=$2 + local -r ver_type=${3:-nightly} + + local -a package_list=() + + # Find the packages to download + case ${ver_type} in + zstream) + package_y0="$(find_package "${ver}" "${ver_type}" "0" "0")" + package_z1="$(find_package "${ver}" "${ver_type}" "0" "1")" + package_y1="$(find_package "${ver}" "${ver_type}" "1" "0")" + package_y2="$(find_package "${ver}" "${ver_type}" "2" "0")" + package_list=("${package_y0}" "${package_y1}" "${package_y2}" "${package_z1}") + ;; + nightly|rc|ec) + package_latest="$(find_package "${ver}" "${ver_type}")" + package_list=("${package_latest}") + ;; + *) + echo "ERROR: Invalid version_type '${ver_type}'. Valid values are: rc, ec, zstream and nightly" + exit 1 + ;; + esac + + # Check at least one package is found + local all_empty=true + for package in "${package_list[@]}" ; do + if [ -n "${package}" ] ; then + all_empty=false + break + fi + done + if ${all_empty} ; then + echo "ERROR: No packages found for ${ver} ${ver_type}" + return 1 + fi + + # Download the packages + for package in "${package_list[@]}" ; do + if [ -z "${package}" ] ; then + continue + fi + sub_dir=$(echo "${package}" | cut -d'-' -f2) + if ! brew_cli_download "${package}" "${main_dir}" "${sub_dir}" "${ver_type}" ; then + echo "ERROR: Failed to download package: ${package}" + return 1 + fi + done +} +brew_cli_download() { + local -r package=$1 + local -r main_dir=$2 + local -r sub_dir=$3 + local -r ver_type=$4 + + # Validate parameters if [ -z "${package}" ] ; then - echo "ERROR: Cannot find MicroShift '${ver}' packages in brew" + echo "ERROR: Package is required" + exit 1 + fi + + if [ -z "${main_dir}" ] ; then + echo "ERROR: Main directory is required" exit 1 fi - package=$(awk '{print $1}' <<< "${package}") + if [ -z "${sub_dir}" ] ; then + echo "ERROR: Sub directory is required" + exit 1 + fi + # Check if brew is accessible + if ! action_access ; then + echo "ERROR: Brew Hub site is not accessible" + exit 1 + fi + "${SCRIPTDIR}/../../scripts/fetch_tools.sh" brew + echo "Downloading '${package}' packages from brew" + # Format sub_dir for EC, RC and nightly + if [ "${ver_type}" = "ec" ] || [ "${ver_type}" = "rc" ] || [ "${ver_type}" = "nightly" ] ; then + final_sub_dir=$(echo "${sub_dir}" | sed -E 's/(.*)(~)(.*)(rc|ec|nightly)(.*)/\1-\4/g') + elif [ "${ver_type}" = "zstream" ] ; then + final_sub_dir="${sub_dir}" + fi + # Download all the supported architectures as the required architecture # cannot be identified easily when running in a CI job for arch in x86_64 aarch64 ; do local adir - adir="${dir}/${ver}-${ver_type}/${arch}" + adir="${main_dir}/${final_sub_dir}/${arch}" - mkdir -p "${adir}" + if ! mkdir -p "${adir}" ; then + echo "ERROR: Failed to create directory '${adir}'" + exit 1 + fi pushd "${adir}" &>/dev/null if ! brew download-build --arch="${arch}" --arch="noarch" "${package}" ; then - echo "ERROR: Failed to download '${package}' packages from brew" - exit 1 + echo "WARNING: Failed to download '${package}' packages using brew download-build command, using curl as a fallback mechanism" + if ! brew_curl_download "${package}" "${arch}" ; then + echo "ERROR: Failed to download '${package}' packages using curl command" + popd &>/dev/null + exit 1 + fi fi popd &>/dev/null done } +brew_curl_download() { + local package=$1 + local arch=$2 + + # Parse package to extract version and build release + local version_and_release="${package#microshift-}" + local pkg_version="${version_and_release%%-*}" + local pkg_release="${version_and_release#*-}" + + for current_arch in ${arch} noarch; do + local base_url="http://download.devel.redhat.com/rhel-9/brew/packages/microshift/${pkg_version}/${pkg_release}/${current_arch}/" + + local rpm_files + rpm_files=$(curl -k -s "${base_url}" | sed -n 's/.*href="\([^"]*\.rpm\)".*/\1/p') || true + if [ -z "${rpm_files}" ]; then + echo "ERROR: No RPM files found at ${base_url}" + return 1 + fi + + echo "Downloading from: ${base_url}" + for rpm_file in ${rpm_files}; do + echo "Downloading: ${rpm_file}" + if ! curl -s -O "${base_url}${rpm_file}"; then + echo "ERROR: Failed to download ${rpm_file}" + return 1 + fi + done + done +} + # # Main # diff --git a/test/bin/manage_build_cache.sh b/test/bin/manage_build_cache.sh index eeb88378ac..dbc2dc5c51 100755 --- a/test/bin/manage_build_cache.sh +++ b/test/bin/manage_build_cache.sh @@ -8,8 +8,10 @@ SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "${SCRIPTDIR}/common.sh" AWS_BUCKET_NAME="${AWS_BUCKET_NAME:-microshift-build-cache}" +AWS_BUCKET_NAME="microshift-build-ushift-6073-cache-us-west-2" BCH_SUBDIR= TAG_SUBDIR= +ARCH_SUBDIR="${UNAME_M}" usage() { cat - <//'. -h Show this help. upload: Upload build artifacts from the local disk to the specified - '${AWS_BUCKET_NAME}//${UNAME_M}/' AWS S3 bucket. + '${AWS_BUCKET_NAME}///' AWS S3 bucket. The 'verify' operation is run before the upload attempt. If data already exists at the destination, the upload is skipped and the script exits with 0 status. download: Download build artifacts from the specified - '${AWS_BUCKET_NAME}//${UNAME_M}/' AWS S3 bucket + '${AWS_BUCKET_NAME}///' AWS S3 bucket to the local disk. verify: Exit with 0 status if the specified - '${AWS_BUCKET_NAME}//${UNAME_M}/' sub-directory + '${AWS_BUCKET_NAME}///' sub-directory exists and contains files, 1 otherwise. - setlast: Update the '${AWS_BUCKET_NAME}//${UNAME_M}/last' file + setlast: Update the '${AWS_BUCKET_NAME}///last' file contents in the AWS S3 bucket with the specified ''. - getlast: Retrieve the '${AWS_BUCKET_NAME}//${UNAME_M}/last' + getlast: Retrieve the '${AWS_BUCKET_NAME}///last' file contents from the AWS S3 bucket. The output format is "LAST: " for easy parsing. The script returns the specified '' as a fallback if the bucket file does not exist. - keep: Delete all data from the '${AWS_BUCKET_NAME}//${UNAME_M}' + dellast: Delete the data pointed by the '${AWS_BUCKET_NAME}///last' + file contents and update the 'last' file contents in the AWS S3 bucket + with the specified '' + + keep: Delete all data from the '${AWS_BUCKET_NAME}//' AWS S3 bucket, only keeping the 'last' and the specified '' sub-directories. @@ -56,6 +62,7 @@ Options: -t The tag sub-directory in the AWS S3 bucket. + -a The architecture sub-directory in the AWS S3 bucket (default: ${ARCH_SUBDIR}). EOF } @@ -68,7 +75,7 @@ run_aws_cli() { } check_contents(){ - local -r src_dir="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${UNAME_M}/${TAG_SUBDIR}" + local -r src_dir="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${ARCH_SUBDIR}/${TAG_SUBDIR}" local -r must_contain_array=("mirror-registry\.tar$" "brew-rpms\.tar$" "repo\.tar$" "${VM_POOL_BASENAME}/.*\.iso$") echo "Checking contents of '${src_dir}'" @@ -86,7 +93,7 @@ check_contents(){ action_upload() { local -r src_base="${IMAGEDIR}" - local -r dst_base="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${UNAME_M}/${TAG_SUBDIR}" + local -r dst_base="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${ARCH_SUBDIR}/${TAG_SUBDIR}" if check_contents ; then echo "The '${dst_base}' already exists with valid contents" @@ -120,7 +127,7 @@ action_upload() { } action_download() { - local -r src_base="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${UNAME_M}/${TAG_SUBDIR}" + local -r src_base="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${ARCH_SUBDIR}/${TAG_SUBDIR}" local -r dst_base="${IMAGEDIR}" # Download ISO images @@ -166,7 +173,7 @@ action_verify() { action_setlast() { local -r src_file="$(mktemp /tmp/setlast.XXXXXXXX)" - local -r dst_file="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${UNAME_M}/last" + local -r dst_file="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${ARCH_SUBDIR}/last" if [ "${TAG_SUBDIR}" = "last" ] ; then echo "ERROR: Cannot set 'last' tag to itself" @@ -180,7 +187,7 @@ action_setlast() { } action_getlast() { - local -r src_file="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${UNAME_M}/last" + local -r src_file="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${ARCH_SUBDIR}/last" local -r dst_file="$(mktemp /tmp/getlast.XXXXXXXX)" echo "Reading '${src_file}' tag contents" @@ -193,12 +200,45 @@ action_getlast() { rm -f "${dst_file}" } +action_dellast() { + local -r top_dir="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${ARCH_SUBDIR}" + # Get the last contents with the ${TAG_SUBDIR} default + local -r last_dir="$(action_getlast | awk '/LAST:/ {print $NF}')" + + if [ -z "${last_dir}" ] ; then + echo "ERROR: Cannot delete 'last' tag because it is not set or empty" + exit 1 + fi + if [ "${last_dir}" = "${TAG_SUBDIR}" ] ; then + echo "ERROR: Cannot delete 'last' tag because it is the same as the new '${TAG_SUBDIR}' tag" + exit 1 + fi + + # Verify that the new tag exists + if ! check_contents ; then + echo "ERROR: Cannot reset 'last' tag to a non-existent '${TAG_SUBDIR}' tag" + exit 1 + fi + + # Reset the last tag and delete the old contents + action_setlast + run_aws_cli s3 rm --recursive "${top_dir}/${last_dir}" +} + action_keep() { - local -r top_dir="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${UNAME_M}" + local -r top_dir="s3://${AWS_BUCKET_NAME}/${BCH_SUBDIR}/${ARCH_SUBDIR}" # Get the last contents with the ${TAG_SUBDIR} default local -r last_dir="$(action_getlast | awk '/LAST:/ {print $NF}')" - for sub_dir in $(run_aws_cli s3 ls "${top_dir}/" | awk '{print $NF}'); do + # Get all sub-directories in the top directory + local -r sub_dirs=$(run_aws_cli s3 ls "${top_dir}/" | grep '/$' | awk '{print $NF}') + # Skip if only one sub-directory exists + if [ "$(echo "${sub_dirs}" | wc -w)" -eq 1 ] ; then + echo "Only one sub-directory found in '${top_dir}', keeping it" + return 0 + fi + + for sub_dir in ${sub_dirs}; do if [ "${sub_dir}" = "last" ] ; then continue fi @@ -223,7 +263,7 @@ action="${1}" shift # Parse options -while getopts "b:t:h" opt; do +while getopts "b:t:a:h" opt; do case "${opt}" in h) usage @@ -235,6 +275,9 @@ while getopts "b:t:h" opt; do t) TAG_SUBDIR="${OPTARG}" ;; + a) + ARCH_SUBDIR="${OPTARG}" + ;; *) usage exit 1 @@ -262,7 +305,7 @@ fi # Run actions case "${action}" in - upload|download|verify|setlast|getlast|keep) + upload|download|verify|setlast|getlast|dellast|keep) "action_${action}" "$@" ;; -h|help) diff --git a/test/bin/manage_hypervisor_config.sh b/test/bin/manage_hypervisor_config.sh index 4bbab85213..10daee0a0e 100755 --- a/test/bin/manage_hypervisor_config.sh +++ b/test/bin/manage_hypervisor_config.sh @@ -139,6 +139,10 @@ action_create() { # Start nginx web server "${TESTDIR}/bin/manage_webserver.sh" "start" + + "${TESTDIR}/bin/manage_prometheus.sh" "start" + + "${TESTDIR}/bin/manage_loki.sh" "start" } action_cleanup() { @@ -176,6 +180,10 @@ action_cleanup() { # Stop nginx web server "${TESTDIR}/bin/manage_webserver.sh" "stop" + + "${TESTDIR}/bin/manage_prometheus.sh" "stop" + + "${TESTDIR}/bin/manage_loki.sh" "stop" } action_cleanup-all() { diff --git a/test/bin/manage_loki.sh b/test/bin/manage_loki.sh index 6bf65ab807..4632ce7a9b 100755 --- a/test/bin/manage_loki.sh +++ b/test/bin/manage_loki.sh @@ -19,18 +19,16 @@ ${BASH_SOURCE[0]} (start|stop) [port] start [port]: Start Loki. Uses port ${DEFAULT_HOST_PORT} on the host by default. - The container name will be loki-. + The container name will be loki. -stop [port]: Stop Loki. - Uses port ${DEFAULT_HOST_PORT} by default to identify the container. - The container name is assumed to be loki-. +stop: Stop Loki. + The container name is assumed to be loki. EOF } action_stop() { - local host_port="${1:-${DEFAULT_HOST_PORT}}" - local container_name="loki-${host_port}" + local container_name="loki" echo "Stopping Loki container ${container_name}" podman stop "${container_name}" > /dev/null || true podman rm --force "${container_name}" > /dev/null || true @@ -38,7 +36,7 @@ action_stop() { action_start() { local host_port="${1:-${DEFAULT_HOST_PORT}}" - local container_name="loki-${host_port}" + local container_name="loki" echo "Stopping previous instance of Loki container ${container_name} (if any)" action_stop "${host_port}" @@ -46,6 +44,7 @@ action_start() { echo "Starting Loki container ${container_name} on host port ${host_port}" podman run -d --rm --name "${container_name}" \ -p "${host_port}:3100" \ + --user root \ docker.io/grafana/loki > /dev/null } diff --git a/test/bin/manage_prometheus.sh b/test/bin/manage_prometheus.sh index e3564be7a3..369ddecdc6 100755 --- a/test/bin/manage_prometheus.sh +++ b/test/bin/manage_prometheus.sh @@ -10,7 +10,7 @@ SCRIPTDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "${SCRIPTDIR}/common.sh" PROMETHEUS_DIR="${IMAGEDIR}/prometheus" -DEFAULT_HOST_PORT="9092" +DEFAULT_HOST_PORT="9091" usage() { cat - <. + The container name will be prometheus. -stop [port]: Stop Prometheus. - Uses port ${DEFAULT_HOST_PORT} by default to identify the container. - The container name is assumed to be prometheus-. +stop: Stop Prometheus. + The container name is assumed to be prometheus. EOF } action_stop() { - local host_port="${1:-${DEFAULT_HOST_PORT}}" - local container_name="prometheus-${host_port}" + local container_name="prometheus" echo "Stopping Prometheus container ${container_name}" podman stop "${container_name}" > /dev/null || true @@ -40,7 +38,7 @@ action_stop() { action_start() { local host_port="${1:-${DEFAULT_HOST_PORT}}" - local container_name="prometheus-${host_port}" + local container_name="prometheus" mkdir -p "${PROMETHEUS_DIR}" PROM_CONFIG="${PROMETHEUS_DIR}/prometheus.yml" diff --git a/test/bin/mirror_registry.sh b/test/bin/mirror_registry.sh index 5232e22a26..07dd6f72ac 100755 --- a/test/bin/mirror_registry.sh +++ b/test/bin/mirror_registry.sh @@ -335,6 +335,11 @@ mirror_images() { echo "${src_img}" >> "${ffile}" done + # Add test assets images. + find "${SCRIPTDIR}/../assets/" -type f -exec grep -hPo "(?<=image: ).*\..*" {} \; | while read -r img; do + echo "${img}" >> "${ffile}" + done + sort -u "${ifile}" "${ffile}" > "${ofile}" "${ROOTDIR}/scripts/mirror-images.sh" --mirror "${QUAY_PULL_SECRET}" "${ofile}" "${MIRROR_REGISTRY_URL}" rm -f "${ofile}" "${ffile}" diff --git a/test/bin/pyutils/build_bootc_images.py b/test/bin/pyutils/build_bootc_images.py index 6887b1e590..6a1a75e2ea 100644 --- a/test/bin/pyutils/build_bootc_images.py +++ b/test/bin/pyutils/build_bootc_images.py @@ -4,6 +4,7 @@ import concurrent.futures import getpass import glob +import multiprocessing import os import platform import re @@ -113,6 +114,7 @@ def set_rpm_version_info_vars(): global BREW_Y2_RELEASE_VERSION global BREW_RC_RELEASE_VERSION global BREW_EC_RELEASE_VERSION + global BREW_NIGHTLY_RELEASE_VERSION FAKE_NEXT_MINOR_VERSION = common.get_env_var('FAKE_NEXT_MINOR_VERSION') PREVIOUS_RELEASE_REPO = common.get_env_var('PREVIOUS_RELEASE_REPO') @@ -124,6 +126,7 @@ def set_rpm_version_info_vars(): BREW_Y2_RELEASE_VERSION = common.get_env_var('BREW_Y2_RELEASE_VERSION') BREW_RC_RELEASE_VERSION = common.get_env_var('BREW_RC_RELEASE_VERSION') BREW_EC_RELEASE_VERSION = common.get_env_var('BREW_EC_RELEASE_VERSION') + BREW_NIGHTLY_RELEASE_VERSION = common.get_env_var('BREW_NIGHTLY_RELEASE_VERSION') # The source versions are deduced from the locally built RPMs global SOURCE_VERSION @@ -135,15 +138,6 @@ def set_rpm_version_info_vars(): SOURCE_VERSION = common.run_command_in_shell(f"rpm -q --queryformat '%{{version}}-%{{release}}' {release_info_rpm}") SOURCE_VERSION_BASE = common.run_command_in_shell(f"rpm -q --queryformat '%{{version}}-%{{release}}' {release_info_rpm_base}") - # The brew versions are deduced from the locally downloaded RPMs. - # If RPMs are missing, the version is empty and builds are skipped. - global BREW_VERSION - try: - release_info_rpm_brew = find_latest_rpm(BREW_REPO) - BREW_VERSION = common.run_command_in_shell(f"rpm -q --queryformat '%{{version}}-%{{release}}' {release_info_rpm_brew}") - except Exception: - BREW_VERSION = "" - global SSL_CLIENT_KEY_FILE global SSL_CLIENT_CERT_FILE # Find the first file matching "*-key.pem" in the entitlements directory @@ -157,8 +151,7 @@ def set_rpm_version_info_vars(): # Update selected environment variables based on the global variables. # These are used for templating container files and images. rpmver_globals_vars = [ - 'SOURCE_VERSION', 'SOURCE_VERSION_BASE', 'BREW_VERSION', - 'SSL_CLIENT_KEY_FILE', 'SSL_CLIENT_CERT_FILE' + 'SOURCE_VERSION', 'SOURCE_VERSION_BASE', 'SSL_CLIENT_KEY_FILE', 'SSL_CLIENT_CERT_FILE' ] for var in rpmver_globals_vars: value = globals().get(var) @@ -640,6 +633,8 @@ def main(): extract_container_images(BREW_RC_RELEASE_VERSION, BREW_REPO, CONTAINER_LIST, args.dry_run) if BREW_EC_RELEASE_VERSION: extract_container_images(BREW_EC_RELEASE_VERSION, BREW_REPO, CONTAINER_LIST, args.dry_run) + if BREW_NIGHTLY_RELEASE_VERSION: + extract_container_images(BREW_NIGHTLY_RELEASE_VERSION, BREW_REPO, CONTAINER_LIST, args.dry_run) # Sort the images list, only leaving unique entries common.sort_uniq_file(CONTAINER_LIST) @@ -680,5 +675,6 @@ def main(): if __name__ == "__main__": + multiprocessing.set_start_method("fork") _ = common.MeasureRunTimeInScope("[MAIN] Building Images") main() diff --git a/test/bin/pyutils/generate_common_versions.py b/test/bin/pyutils/generate_common_versions.py old mode 100644 new mode 100755 index e2f20a4805..a0accc1cea --- a/test/bin/pyutils/generate_common_versions.py +++ b/test/bin/pyutils/generate_common_versions.py @@ -11,6 +11,10 @@ import logging import pathlib +sys.path.append(str(pathlib.Path(__file__).resolve().parent / '../../../scripts/pyutils')) +import gitutils # noqa: E402 +import ghutils # noqa: E402 + ARCH = os.uname().machine # The version of Sonobuoy package used in CNCF tests. @@ -28,7 +32,7 @@ logging.basicConfig( level=logging.INFO, - format='%(levelname)s: %(message)s', + format='%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s', stream=sys.stderr ) @@ -96,7 +100,11 @@ def repo_provides_pkg(repo, pkg): try: logging.info(f"Running command: {' '.join(args)}") - subprocess.run(args, stdout=sys.stderr, check=True) + result = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, check=True) + output = result.stdout.strip() + logging.info(f"Command's output:\n{output}") + if "Usable URL not found" in output: + return False return True except subprocess.CalledProcessError: return False @@ -203,83 +211,128 @@ def get_release_version_string(repo, var_name): return None -parser = argparse.ArgumentParser(description="Generate common_versions.sh variables.") -parser.add_argument("minor", type=int, help="The minor version number.") - -args = parser.parse_args() - -minor_version = args.minor -previous_minor_version = minor_version - 1 -yminus2_minor_version = minor_version - 2 - -# The current release repository comes from the 'rhocp' stream for release -# branches, or the OpenShift mirror if only a RC or EC is available. It can -# be empty, if no candidate for the current minor has been built yet. -logging.info("Getting CURRENT_RELEASE_REPO") -current_release_repo = get_microshift_repo(minor_version) -current_release_version = get_release_version_string(current_release_repo, "CURRENT_RELEASE_REPO") - -# The previous release repository value should either point to the OpenShift -# mirror URL or the 'rhocp' repository name. -logging.info("Getting PREVIOUS_RELEASE_REPO") -previous_release_repo = get_microshift_repo(previous_minor_version) -previous_release_version = get_release_version_string(previous_release_repo, "PREVIOUS_RELEASE_REPO") - -# The y-2 release repository value should either point to the OpenShift -# mirror URL or the 'rhocp' repository name. It should always come from -# the 'rhocp' stream. -logging.info("Getting YMINUS2_RELEASE_REPO") -yminus2_release_repo = get_microshift_repo(yminus2_minor_version) -yminus2_release_version = get_release_version_string(yminus2_release_repo, "YMINUS2_RELEASE_REPO") - -# The 'rhocp_minor_y' variable should be the minor version number, if the -# current release is available through the 'rhocp' stream, otherwise empty. -rhocp_minor_y = minor_version if repo_provides_pkg(f"rhocp-4.{minor_version}-for-rhel-9-{ARCH}-rpms", "cri-o") else '""' - -# The beta repository, containing dependencies, should point to the -# OpenShift mirror URL. If the mirror for current minor is not -# available yet, it should point to an older release. -logging.info("Getting RHOCP_MINOR_Y_BETA") -rhocp_minor_y_beta = get_dependencies_repo_url(minor_version, 3) - -# The 'rhocp_minor_y' variable should be the previous minor version number, if -# the previous release is available through the 'rhocp' stream, otherwise empty. -rhocp_minor_y1 = previous_minor_version if repo_provides_pkg(f"rhocp-4.{previous_minor_version}-for-rhel-9-{ARCH}-rpms", "cri-o") else '""' - -# The beta repository, containing dependencies, should point to the -# OpenShift mirror URL. The mirror for previous release should always -# be available. -logging.info("Getting RHOCP_MINOR_Y1_BETA") -rhocp_minor_y1_beta = get_dependencies_repo_url(previous_minor_version) - -# The 'rhocp_minor_y2' should always be the y-2 minor version number. -rhocp_minor_y2 = yminus2_minor_version - -template_path = pathlib.Path(__file__).resolve().parent / '../../assets/common_versions.sh.template' - -with open(template_path, 'r') as f: - template_string = f.read() - -output = template_string.format( - minor_version=minor_version, - current_release_repo=current_release_repo, - current_release_version=current_release_version, - previous_release_repo=previous_release_repo, - previous_release_version=previous_release_version, - yminus2_release_repo=yminus2_release_repo, - yminus2_release_version=yminus2_release_version, - rhocp_minor_y=rhocp_minor_y, - rhocp_minor_y_beta=rhocp_minor_y_beta, - rhocp_minor_y1=rhocp_minor_y1, - rhocp_minor_y1_beta=rhocp_minor_y1_beta, - rhocp_minor_y2=rhocp_minor_y2, - CNCF_SONOBUOY_VERSION=CNCF_SONOBUOY_VERSION, - CNCF_SYSTEMD_LOGS_VERSION=CNCF_SYSTEMD_LOGS_VERSION, - GITOPS_VERSION=GITOPS_VERSION, - LATEST_RELEASE_TYPE=LATEST_RELEASE_TYPE, - ARCH=ARCH -) - -output_noarch = output.replace(ARCH, '${UNAME_M}') - -print(output_noarch) +def generate_common_versions(minor_version): + previous_minor_version = minor_version - 1 + yminus2_minor_version = minor_version - 2 + + # The current release repository comes from the 'rhocp' stream for release + # branches, or the OpenShift mirror if only a RC or EC is available. It can + # be empty, if no candidate for the current minor has been built yet. + logging.info("Getting CURRENT_RELEASE_REPO") + current_release_repo = get_microshift_repo(minor_version) + current_release_version = get_release_version_string(current_release_repo, "CURRENT_RELEASE_REPO") + + # The previous release repository value should either point to the OpenShift + # mirror URL or the 'rhocp' repository name. + logging.info("Getting PREVIOUS_RELEASE_REPO") + previous_release_repo = get_microshift_repo(previous_minor_version) + previous_release_version = get_release_version_string(previous_release_repo, "PREVIOUS_RELEASE_REPO") + + # The y-2 release repository value should either point to the OpenShift + # mirror URL or the 'rhocp' repository name. It should always come from + # the 'rhocp' stream. + logging.info("Getting YMINUS2_RELEASE_REPO") + yminus2_release_repo = get_microshift_repo(yminus2_minor_version) + yminus2_release_version = get_release_version_string(yminus2_release_repo, "YMINUS2_RELEASE_REPO") + + # The 'rhocp_minor_y' variable should be the minor version number, if the + # current release is available through the 'rhocp' stream, otherwise empty. + rhocp_minor_y = minor_version if repo_provides_pkg(f"rhocp-4.{minor_version}-for-rhel-9-{ARCH}-rpms", "cri-o") else '""' + + # The beta repository, containing dependencies, should point to the + # OpenShift mirror URL. If the mirror for current minor is not + # available yet, it should point to an older release. + logging.info("Getting RHOCP_MINOR_Y_BETA") + rhocp_minor_y_beta = get_dependencies_repo_url(minor_version, 3) + + # The 'rhocp_minor_y' variable should be the previous minor version number, if + # the previous release is available through the 'rhocp' stream, otherwise empty. + rhocp_minor_y1 = previous_minor_version if repo_provides_pkg(f"rhocp-4.{previous_minor_version}-for-rhel-9-{ARCH}-rpms", "cri-o") else '""' + + # The beta repository, containing dependencies, should point to the + # OpenShift mirror URL. The mirror for previous release should always + # be available. + logging.info("Getting RHOCP_MINOR_Y1_BETA") + rhocp_minor_y1_beta = get_dependencies_repo_url(previous_minor_version) + + # The 'rhocp_minor_y2' should always be the y-2 minor version number. + rhocp_minor_y2 = yminus2_minor_version + + template_path = pathlib.Path(__file__).resolve().parent / '../../assets/common_versions.sh.template' + + with open(template_path, 'r') as f: + template_string = f.read() + + output = template_string.format( + minor_version=minor_version, + current_release_repo=current_release_repo, + current_release_version=current_release_version, + previous_release_repo=previous_release_repo, + previous_release_version=previous_release_version, + yminus2_release_repo=yminus2_release_repo, + yminus2_release_version=yminus2_release_version, + rhocp_minor_y=rhocp_minor_y, + rhocp_minor_y_beta=rhocp_minor_y_beta, + rhocp_minor_y1=rhocp_minor_y1, + rhocp_minor_y1_beta=rhocp_minor_y1_beta, + rhocp_minor_y2=rhocp_minor_y2, + CNCF_SONOBUOY_VERSION=CNCF_SONOBUOY_VERSION, + CNCF_SYSTEMD_LOGS_VERSION=CNCF_SYSTEMD_LOGS_VERSION, + GITOPS_VERSION=GITOPS_VERSION, + LATEST_RELEASE_TYPE=LATEST_RELEASE_TYPE, + ARCH=ARCH + ) + + output_noarch = output.replace(ARCH, '${UNAME_M}') + + return output_noarch + + +def main(): + parser = argparse.ArgumentParser(description="Generate common_versions.sh variables.") + parser.add_argument("minor", type=int, help="The minor version number.") + parser.add_argument("--update-file", default=False, action="store_true", help="Update test/bin/common_versions.sh file.") + parser.add_argument("--create-pr", default=False, action="store_true", + help=("Commit the changes to a new branch, push it to the openshift/microshift, and create a pull request." + + "Implies --update-file. Expects following env vars to be set: ORG, REPO, GH_TOKEN or APP_ID and KEY")) + parser.add_argument("--dry-run", default=False, action="store_true", help="Dry run") + args = parser.parse_args() + + output = generate_common_versions(args.minor) + + if args.update_file or args.create_pr: + logging.info("Updating test/bin/common_versions.sh file") + dest_file = pathlib.Path(__file__).resolve().parent / '../common_versions.sh' + with open(dest_file, 'w') as f: + f.write(output) + else: + print(output) + + if args.create_pr: + g = gitutils.GitUtils(dry_run=args.dry_run) + if not g.file_changed("test/bin/common_versions.sh"): + logging.info("No changes to test/bin/common_versions.sh") + exit(0) + + base_branch = g.git_repo.active_branch.name + if not base_branch.startswith("release-4"): + logging.error(f"Script is expected to be executed on branch starting with 'release-4', but it's {base_branch}") + exit(1) + + gh = ghutils.GithubUtils(dry_run=args.dry_run) + g.setup_remote_with_token(gh.token, gh.org, gh.repo) + new_branch_name = f"common-versions-update-{base_branch}" + g.checkout_branch(new_branch_name) + g.add_files_to_staging_area(["test/bin/common_versions.sh"]) + g.commit("Update common_versions.sh") + g.push(new_branch_name) + + pull_req = gh.get_existing_pr_for_a_branch(base_branch, new_branch_name) + if pull_req is None: + # Assuming the script always runs against `release-4.y` branch for the value in brackets. + pr_title = f"[{base_branch}] NO-ISSUE: Update common_versions.sh" + gh.create_pr(base_branch, new_branch_name, pr_title, "") + + +if __name__ == "__main__": + main() diff --git a/test/bin/scenario.sh b/test/bin/scenario.sh index 39fc6085a5..5e5f3c81d9 100755 --- a/test/bin/scenario.sh +++ b/test/bin/scenario.sh @@ -32,7 +32,7 @@ IMAGE_SIGSTORE_ENABLED=false # may be overridden in scenario file VNC_CONSOLE=${VNC_CONSOLE:-false} # may be overridden in global settings file TEST_RANDOMIZATION="all" # may be overridden in scenario file TEST_EXCLUDES="none" # may be overridden in scenario file -TEST_EXECUTION_TIMEOUT="30m" # may be overriden in scenario file +TEST_EXECUTION_TIMEOUT="${TEST_EXECUTION_TIMEOUT:-30m}" # may be overriden in scenario file or CI config SUBSCRIPTION_MANAGER_PLUGIN="${SUBSCRIPTION_MANAGER_PLUGIN:-${SCRIPTDIR}/subscription_manager_register.sh}" # may be overridden in global settings file RUN_HOST_OVERRIDE="" # target any given VM for running scenarios @@ -395,6 +395,24 @@ does_image_exist() { fi } +# Exit the script if the commit is not found in the ostree repository. +exit_if_commit_not_found() { + local -r commit="${1}" + if ! does_commit_exist "${commit}"; then + echo "Commit '${commit}' not found in ostree repo - skipping test" + exit 0 + fi +} + +# Exit the script if the image is not found in the mirror registry. +exit_if_image_not_found() { + local -r image="${1}" + if ! does_image_exist "${image}"; then + echo "Image '${image}' not found in mirror registry - skipping test" + exit 0 + fi +} + # Show the IP address of the VM function get_vm_ip { local -r vmname="${1}" @@ -440,6 +458,26 @@ wait_for_ssh() { return 1 } +wait_for_microshift_to_be_ready() { + local vmname="${1}" + shift + + # Handle RUN_HOST_OVERRIDE + vmname=$(apply_host_override "${vmname}") + + # Set up kubeconfig for tests + local -r vm_ip=$(get_vm_property "${vmname}" "ip") + local -r full_vmname="$(full_vm_name "${vmname}")" + + # Wait for MicroShift to be ready + if ! wait_for_greenboot "${full_vmname}" "${vm_ip}"; then + record_junit "${vmname}" "pre_test_greenboot_check" "FAILED" + popd &>/dev/null + exit 1 + fi + record_junit "${vmname}" "pre_test_greenboot_check" "OK" +} + # Wait for greenboot health check to complete, without checking the results wait_for_greenboot() { local -r vmname="${1}" @@ -681,7 +719,12 @@ launch_vm() { for n in ${network}; do # For simplicity we assume that network filters are named the same as the networks # If there is a filter with the same name as the network, attach it to the NIC - vm_network_args+="--network network=${n},model=virtio" + if [ "${n}" = "sriov" ] ; then + vm_network_args+="--network network=default,model=igb" + else + vm_network_args+="--network network=${n},model=virtio" + fi + if sudo virsh nwfilter-list | awk '{print $2}' | grep -qx "${n}"; then vm_network_args+=",filterref=${n}" fi @@ -1041,11 +1084,7 @@ USHIFT_USER: "${USHIFT_USER:-redhat}" SSH_PRIV_KEY: "${SSH_PRIVATE_KEY:-}" SSH_PORT: ${ssh_port} EOF - if ! wait_for_greenboot "${full_vmname}" "${vm_ip}"; then - record_junit "${vmname}" "pre_test_greenboot_check" "FAILED" - return 1 - fi - record_junit "${vmname}" "pre_test_greenboot_check" "OK" + wait_for_microshift_to_be_ready "${vmname}" fi # Make sure the test execution times out after a predefined period. @@ -1082,8 +1121,8 @@ EOF fi } -# Implementation of Gingko tests -run_gingko_tests() { +# Setup oc client and kubeconfig for ginkgo tests +setup_oc_and_kubeconfig() { local vmname="${1}" shift @@ -1093,7 +1132,7 @@ run_gingko_tests() { # Save current directory pushd . &>/dev/null - # Check/install oc + # Install oc if ! command -v oc &> /dev/null ; then "${ROOTDIR}/scripts/fetch_tools.sh" "oc" || { record_junit "${vmname}" "oc_installed" "FAILED" @@ -1102,36 +1141,43 @@ run_gingko_tests() { fi record_junit "${vmname}" "oc_installed" "OK" - # Check/get openshift-tests-binary - if ! "${ROOTDIR}/scripts/fetch_tools.sh" "ginkgo"; then - record_junit "${vmname}" "build_test_binary" "FAILED" + # Get kubeconfig from VM + local -r vm_ip=$(get_vm_property "${vmname}" "ip") + local kubeconfig="${SCENARIO_INFO_DIR}/${SCENARIO}/kubeconfig" + if ! run_command_on_vm "${vmname}" "sudo cat /var/lib/microshift/resources/kubeadmin/${vm_ip}/kubeconfig" > "${kubeconfig}"; then + record_junit "${vmname}" "setup_kubeconfig" "FAILED" exit 1 fi - record_junit "${vmname}" "build_test_binary" "OK" + export KUBECONFIG="${kubeconfig}" + record_junit "${vmname}" "setup_kubeconfig" "OK" + + popd &>/dev/null +} - # Set up test environment variables - local kubeconfig="${SCENARIO_INFO_DIR}/${SCENARIO}/kubeconfig" - local -r test_results_dir="${SCENARIO_INFO_DIR}/${SCENARIO}/gingko-results" - mkdir -p "${test_results_dir}" +# Implementation of ginkgo tests +run_ginkgo_tests() { + local vmname="${1}" + shift - # Set up kubeconfig for tests - local -r vm_ip=$(get_vm_property "${vmname}" "ip") - local -r full_vmname="$(full_vm_name "${vmname}")" + # Handle RUN_HOST_OVERRIDE + vmname=$(apply_host_override "${vmname}") - # Wait for MicroShift to be ready - if ! wait_for_greenboot "${full_vmname}" "${vm_ip}"; then - record_junit "${vmname}" "pre_test_greenboot_check" "FAILED" - popd &>/dev/null + # Save current directory + pushd . &>/dev/null + + # Setup oc client and kubeconfig for ginkgo tests + setup_oc_and_kubeconfig "${vmname}" + + # Build ginkgo binary + if ! "${ROOTDIR}/scripts/fetch_tools.sh" "ginkgo"; then + record_junit "${vmname}" "build_ginkgo_binary" "FAILED" exit 1 fi - record_junit "${vmname}" "pre_test_greenboot_check" "OK" - - # Get kubeconfig from VM - run_command_on_vm "${vmname}" "sudo cat /var/lib/microshift/resources/kubeadmin/${vm_ip}/kubeconfig" > "${kubeconfig}" - export KUBECONFIG="${kubeconfig}" - record_junit "${vmname}" "setup_kubeconfig" "OK" + record_junit "${vmname}" "build_ginkgo_binary" "OK" # Create case selection file + local -r test_results_dir="${SCENARIO_INFO_DIR}/${SCENARIO}/ginkgo-results" + mkdir -p "${test_results_dir}" local case_selected="${test_results_dir}/case_selected" # Get all MicroShift tests using dry-run @@ -1151,6 +1197,9 @@ run_gingko_tests() { echo "Running Ginkgo tests with MicroShift filter..." fi + echo "----------------Remove 62738 test case---------------" + sed -i "/62738/d" "${case_selected}" + echo "-----------------------------------------------------" echo "------------------Selected test cases------------------" cat "${case_selected}" echo "-----------------------------------------------------" @@ -1167,7 +1216,7 @@ run_gingko_tests() { fi # Run the tests and capture output with 10m timeout for every test case - echo "Gingko test execution started..." + echo "ginkgo test execution started..." ginkgo_result_success=true if ! eval '${timeout_ginkgo} run --timeout 10m --junit-dir=${test_results_dir} -f ${case_selected}' 2>&1 | tee "${test_results_dir}/test-output.log"; then if [ $? -ge 124 ] ; then @@ -1175,7 +1224,7 @@ run_gingko_tests() { fi ginkgo_result_success=false fi - echo "Gingko test execution completed" + echo "ginkgo test execution completed" popd &>/dev/null # Clean the JUnit XML files @@ -1219,9 +1268,9 @@ run_gingko_tests() { # Record the junit result of the ginkgo tests if [[ "${ginkgo_result_success}" == "true" ]]; then - record_junit "${vmname}" "run_gingko_tests" "OK" + record_junit "${vmname}" "run_ginkgo_tests" "OK" else - record_junit "${vmname}" "run_gingko_tests" "FAILED" + record_junit "${vmname}" "run_ginkgo_tests" "FAILED" exit 1 fi } diff --git a/test/image-blueprints-bootc/layer1-base/group2/build-serialsim.sh.template b/test/image-blueprints-bootc/layer1-base/group2/build-serialsim.sh.template index ba33f2522e..d659cd769d 100644 --- a/test/image-blueprints-bootc/layer1-base/group2/build-serialsim.sh.template +++ b/test/image-blueprints-bootc/layer1-base/group2/build-serialsim.sh.template @@ -26,7 +26,8 @@ dnf install -y git make python3-pyserial dnf clean all # Clone the serialsim repository and build the serialsim module. -git clone https://github.com/pmtk/serialsim.git /tmp/serialsim +git clone https://github.com/microshift-io/serialsim.git /tmp/serialsim + cd /tmp/serialsim make KERNEL="${KERNEL_VER_ARCH}" all install rm -rf /tmp/serialsim diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel-isolated.containerfile b/test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel-isolated.containerfile new file mode 100644 index 0000000000..52d7011c25 --- /dev/null +++ b/test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel-isolated.containerfile @@ -0,0 +1,48 @@ +# {{- if env.Getenv "CURRENT_RELEASE_VERSION" "" -}} +# Note: This comment makes templating add a new line before the code +FROM localhost/rhel100-test-agent:latest + +# Copy repository configuration +COPY ./bootc-images/microshift-fast-datapath-rhel9.repo ./bootc-images/microshift-crel.repo ./bootc-images/microshift-rhocp-y.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift and cleanup. +RUN dnf repoinfo --enabled && \ + dnf install -y firewalld \ + {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "CURRENT_RELEASE_VERSION" }}" \ + {{ end -}} + && \ + systemctl enable microshift && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + dnf clean all + +# Embed images based on contents of release-info RPMs +COPY --chmod=755 ./bootc-images/microshift-copy-images.sh /usr/bin/microshift-copy-images +RUN --mount=type=secret,id=pullsecret,dst=/run/secrets/pull-secret.json \ + images="$(jq -r ".images[]" /usr/share/microshift/release/release-"$(uname -m)".json)" ; \ + images="${images} quay.io/microshift/busybox:1.36" ; \ + IMAGE_PULL_LIST="${images}" /usr/bin/microshift-copy-images pull + +# Install a systemd drop-in unit to address the problem with image upgrades +# overwriting the container images in additional store. The workaround is to +# copy the images from the pre-loaded to the main container storage. +# In this case, it is not necessary to update /etc/containers/storage.conf with +# the additional store path. +# See https://issues.redhat.com/browse/RHEL-75827 +RUN mkdir -p /usr/lib/systemd/system/microshift.service.d +COPY --chmod=644 ./bootc-images/microshift-copy-images.conf /usr/lib/systemd/system/microshift.service.d/microshift-copy-images.conf + +# Configure firewall +RUN firewall-offline-cmd --zone=public --add-port=22/tcp && \ + firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16 && \ + firewall-offline-cmd --zone=trusted --add-source=169.254.169.1 && \ + firewall-offline-cmd --zone=trusted --add-source=fd01::/48 && \ + firewall-offline-cmd --zone=public --add-port=80/tcp && \ + firewall-offline-cmd --zone=public --add-port=443/tcp && \ + firewall-offline-cmd --zone=public --add-port=5353/udp && \ + firewall-offline-cmd --zone=public --add-port=6443/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/udp +# {{- end -}} diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel-optionals.containerfile b/test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel-optionals.containerfile new file mode 100644 index 0000000000..4ec4a560c6 --- /dev/null +++ b/test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel-optionals.containerfile @@ -0,0 +1,40 @@ +# {{- if env.Getenv "CURRENT_RELEASE_VERSION" "" -}} +# Note: This comment makes templating add a new line before the code +FROM localhost/rhel100-test-agent:latest + +# Copy repository configuration +COPY ./bootc-images/microshift-fast-datapath-rhel9.repo ./bootc-images/microshift-crel.repo ./bootc-images/microshift-rhocp-y.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift with optional components and cleanup. +RUN dnf repoinfo --enabled && \ + dnf install -y firewalld \ + {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "CURRENT_RELEASE_VERSION" }}" \ + {{ end -}} + {{ range (env.Getenv "MICROSHIFT_OPTIONAL_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "CURRENT_RELEASE_VERSION" }}" \ + {{ end -}} + {{ if and (env.Getenv "UNAME_M" "") (eq "x86_64" .Env.UNAME_M) -}} + {{ range (env.Getenv "MICROSHIFT_X86_64_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "CURRENT_RELEASE_VERSION" }}" \ + {{ end -}} + {{ end -}} + && \ + systemctl enable microshift && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + dnf clean all + +# Configure firewall +RUN firewall-offline-cmd --zone=public --add-port=22/tcp && \ + firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16 && \ + firewall-offline-cmd --zone=trusted --add-source=169.254.169.1 && \ + firewall-offline-cmd --zone=trusted --add-source=fd01::/48 && \ + firewall-offline-cmd --zone=public --add-port=80/tcp && \ + firewall-offline-cmd --zone=public --add-port=443/tcp && \ + firewall-offline-cmd --zone=public --add-port=5353/udp && \ + firewall-offline-cmd --zone=public --add-port=6443/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/udp +# {{- end -}} diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel.containerfile b/test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel.containerfile new file mode 100644 index 0000000000..db6f4f9877 --- /dev/null +++ b/test/image-blueprints-bootc/layer1-base/group2/rhel100-bootc-crel.containerfile @@ -0,0 +1,32 @@ +# {{- if env.Getenv "CURRENT_RELEASE_VERSION" "" -}} +# Note: This comment makes templating add a new line before the code +FROM localhost/rhel100-test-agent:latest + +# Copy repository configuration +COPY ./bootc-images/microshift-fast-datapath-rhel9.repo ./bootc-images/microshift-crel.repo ./bootc-images/microshift-rhocp-y.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift and cleanup. +RUN dnf repoinfo --enabled && \ + dnf install -y firewalld \ + {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "CURRENT_RELEASE_VERSION" }}" \ + {{ end -}} + && \ + systemctl enable microshift && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + dnf clean all + +# Configure firewall +RUN firewall-offline-cmd --zone=public --add-port=22/tcp && \ + firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16 && \ + firewall-offline-cmd --zone=trusted --add-source=169.254.169.1 && \ + firewall-offline-cmd --zone=trusted --add-source=fd01::/48 && \ + firewall-offline-cmd --zone=public --add-port=80/tcp && \ + firewall-offline-cmd --zone=public --add-port=443/tcp && \ + firewall-offline-cmd --zone=public --add-port=5353/udp && \ + firewall-offline-cmd --zone=public --add-port=6443/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/udp +# {{- end -}} diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-z1-with-optional.containerfile b/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-z1-with-optional.containerfile new file mode 100644 index 0000000000..b4682b4e44 --- /dev/null +++ b/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-z1-with-optional.containerfile @@ -0,0 +1,49 @@ +# {{- if env.Getenv "BREW_Z1_RELEASE_VERSION" "" -}} +# Note: This comment makes templating add a new line before the code +FROM localhost/rhel96-test-agent:latest + +# Build arguments +ARG USHIFT_RPM_REPO_NAME=microshift-brew +ARG USHIFT_RPM_REPO_PATH=/tmp/$USHIFT_RPM_REPO_NAME + +# Copy the MicroShift repository contents +COPY ./rpm-repos/$USHIFT_RPM_REPO_NAME $USHIFT_RPM_REPO_PATH + +# Copy repository configuration +COPY ./bootc-images/$USHIFT_RPM_REPO_NAME.repo ./bootc-images/microshift-fast-datapath-rhel9.repo ./bootc-images/microshift-rhocp-y1.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift, test agent and cleanup. +RUN dnf repoinfo --enabled && \ + dnf install -y firewalld systemd-resolved \ + {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_Z1_RELEASE_VERSION" }}" \ + {{ end -}} + {{ range (env.Getenv "MICROSHIFT_Y1_OPTIONAL_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_Z1_RELEASE_VERSION" }}" \ + {{ end -}} + {{ if and (env.Getenv "UNAME_M" "") (eq "x86_64" .Env.UNAME_M) -}} + {{ range (env.Getenv "MICROSHIFT_Y1_X86_64_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_Z1_RELEASE_VERSION" }}" \ + {{ end -}} + {{ end -}} + && \ + systemctl enable microshift microshift-test-agent && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + rm -rvf $USHIFT_RPM_REPO_PATH && \ + dnf clean all + +# Configure firewall +RUN firewall-offline-cmd --zone=public --add-port=22/tcp && \ + firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16 && \ + firewall-offline-cmd --zone=trusted --add-source=169.254.169.1 && \ + firewall-offline-cmd --zone=trusted --add-source=fd01::/48 && \ + firewall-offline-cmd --zone=public --add-port=80/tcp && \ + firewall-offline-cmd --zone=public --add-port=443/tcp && \ + firewall-offline-cmd --zone=public --add-port=5353/udp && \ + firewall-offline-cmd --zone=public --add-port=6443/tcp && \ + firewall-offline-cmd --zone=public --add-port=8889/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/udp +# {{- end -}} diff --git a/test/image-blueprints-bootc/layer2-presubmit/group1/rhel100-bootc-source.containerfile b/test/image-blueprints-bootc/layer2-presubmit/group1/rhel100-bootc-source.containerfile index ff0c1b3e2d..0d582ee64a 100644 --- a/test/image-blueprints-bootc/layer2-presubmit/group1/rhel100-bootc-source.containerfile +++ b/test/image-blueprints-bootc/layer2-presubmit/group1/rhel100-bootc-source.containerfile @@ -13,8 +13,11 @@ COPY ./bootc-images/$USHIFT_RPM_REPO_NAME.repo ./bootc-images/microshift-fast-da # Print repository configuration contents. # Install MicroShift, test agent and cleanup. +# OpenSSL is added as a temporary workaround. Systemd-resolved will bump systemd to a newer +# version that requires openssl 3.4 or higher, but package is kept at 3.2.2. By installing +# it we force an upgrade so that everything works. RUN dnf repoinfo --enabled && \ - dnf install -y firewalld systemd-resolved \ + dnf install -y firewalld systemd-resolved openssl \ {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} "{{ . }}-{{ env.Getenv "SOURCE_VERSION" }}" \ {{ end -}} diff --git a/test/image-blueprints-bootc/layer2-presubmit/group2/rhel100-bootc-source-optionals.containerfile b/test/image-blueprints-bootc/layer2-presubmit/group2/rhel100-bootc-source-optionals.containerfile new file mode 100644 index 0000000000..289a385bb6 --- /dev/null +++ b/test/image-blueprints-bootc/layer2-presubmit/group2/rhel100-bootc-source-optionals.containerfile @@ -0,0 +1,33 @@ +FROM localhost/rhel100-bootc-source:latest + +# Build arguments +ARG USHIFT_RPM_REPO_NAME=microshift-local +ARG USHIFT_RPM_REPO_PATH=/tmp/$USHIFT_RPM_REPO_NAME + +# Copy the MicroShift repository contents +COPY ./rpm-repos/$USHIFT_RPM_REPO_NAME $USHIFT_RPM_REPO_PATH + +# Copy repository configuration +COPY ./bootc-images/$USHIFT_RPM_REPO_NAME.repo ./bootc-images/microshift-fast-datapath-rhel9.repo ./bootc-images/microshift-rhocp-y.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift optional packages and cleanup. +RUN dnf repoinfo --enabled && \ + dnf install -y \ + {{ range (env.Getenv "MICROSHIFT_OPTIONAL_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "SOURCE_VERSION" }}" \ + {{ end -}} + {{ if and (env.Getenv "UNAME_M" "") (eq "x86_64" .Env.UNAME_M) -}} + {{ range (env.Getenv "MICROSHIFT_X86_64_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "SOURCE_VERSION" }}" \ + {{ end -}} + {{ end -}} + && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + rm -rvf $USHIFT_RPM_REPO_PATH && \ + dnf clean all + +# Prepare system for testing Generic Device Plugin +COPY --chmod=755 ./bootc-images/build-serialsim.sh /tmp/build-serialsim.sh +RUN /tmp/build-serialsim.sh && rm -f /tmp/build-serialsim.sh diff --git a/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-fips.containerfile b/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-fips.containerfile index 2c2490bcf3..ff3ff731f6 100644 --- a/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-fips.containerfile +++ b/test/image-blueprints-bootc/layer2-presubmit/group2/rhel96-bootc-source-fips.containerfile @@ -8,6 +8,9 @@ match-architectures = ["x86_64"] EOF # Enable the FIPS crypto policy -RUN dnf install -y crypto-policies-scripts && \ +# +# Note: CNI plugins are required for podman to operate normally on RHEL 9.x. +# This package is no longer installed as cri-o dependency. +RUN dnf install -y crypto-policies-scripts containernetworking-plugins && \ update-crypto-policies --no-reload --set FIPS && \ dnf clean all diff --git a/test/image-blueprints-bootc/layer3-periodic/group1/rhel96-bootc-source-ai-model-serving.containerfile b/test/image-blueprints-bootc/layer3-periodic/group1/rhel96-bootc-source-ai-model-serving.containerfile index f56166d4a3..23246b51c0 100644 --- a/test/image-blueprints-bootc/layer3-periodic/group1/rhel96-bootc-source-ai-model-serving.containerfile +++ b/test/image-blueprints-bootc/layer3-periodic/group1/rhel96-bootc-source-ai-model-serving.containerfile @@ -52,7 +52,7 @@ RUN --mount=type=secret,id=pullsecret,dst=/run/secrets/pull-secret.json \ IMAGE_PULL_LIST="${images}" /usr/bin/microshift-copy-images pull # Images are filtered: -# - 'kserve*' are required for the kserve components +# - 'kserve*' are required for the kserve components (excluding kserve-llm-d due to its size) # - 'ovms-image' is needed for OpenVino Model Server # Images of remaining ServingRuntimes are omitted due to their size (they vary between 2 and 5 GiB). # Embedding them would unnecessarily increase size of the bootc image, size of the ISO installer, @@ -60,7 +60,7 @@ RUN --mount=type=secret,id=pullsecret,dst=/run/secrets/pull-secret.json \ # # Additionally, OCI image with resnet50 model is embedded. RUN --mount=type=secret,id=pullsecret,dst=/run/secrets/pull-secret.json \ - images="$(jq -r '.images | with_entries(select(.key | startswith("kserve") or startswith("ovms-image"))) | .[]' /usr/share/microshift/release/release-ai-model-serving-"$(uname -m)".json)" ; \ + images="$(jq -r '.images | with_entries(select((.key | startswith("kserve") or startswith("ovms-image")) and (.key | contains("kserve-llm-d") | not))) | .[]' /usr/share/microshift/release/release-ai-model-serving-"$(uname -m)".json)" ; \ images="${images} quay.io/microshift/ai-testing-model:ovms-resnet50" ; \ IMAGE_PULL_LIST="${images}" /usr/bin/microshift-copy-images pull diff --git a/test/image-blueprints-bootc/layer4-upstream/group2/cos10-bootc-source-optionals.containerfile b/test/image-blueprints-bootc/layer4-upstream/group2/cos10-bootc-source-optionals.containerfile new file mode 100644 index 0000000000..6a86a1342a --- /dev/null +++ b/test/image-blueprints-bootc/layer4-upstream/group2/cos10-bootc-source-optionals.containerfile @@ -0,0 +1,33 @@ +FROM localhost/cos10-bootc-source:latest + +# Build arguments +ARG USHIFT_RPM_REPO_NAME=microshift-local +ARG USHIFT_RPM_REPO_PATH=/tmp/$USHIFT_RPM_REPO_NAME + +# Copy the MicroShift repository contents +COPY ./rpm-repos/$USHIFT_RPM_REPO_NAME $USHIFT_RPM_REPO_PATH + +# Copy repository configuration +COPY ./bootc-images/$USHIFT_RPM_REPO_NAME.repo ./bootc-images/microshift-centos10-nfv.repo ./bootc-images/microshift-rhocp-y.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift optional packages and cleanup. +RUN dnf repoinfo --enabled && \ + dnf install -y \ + {{ range (env.Getenv "MICROSHIFT_OPTIONAL_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "SOURCE_VERSION" }}" \ + {{ end -}} + {{ if and (env.Getenv "UNAME_M" "") (eq "x86_64" .Env.UNAME_M) -}} + {{ range (env.Getenv "MICROSHIFT_X86_64_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "SOURCE_VERSION" }}" \ + {{ end -}} + {{ end -}} + && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + rm -rvf $USHIFT_RPM_REPO_PATH && \ + dnf clean all + +# Prepare system for testing Generic Device Plugin +COPY --chmod=755 ./bootc-images/build-serialsim.sh /tmp/build-serialsim.sh +RUN /tmp/build-serialsim.sh && rm -f /tmp/build-serialsim.sh diff --git a/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-ec-with-optional.containerfile b/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-ec-with-optional.containerfile new file mode 100644 index 0000000000..21aa5a07d3 --- /dev/null +++ b/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-ec-with-optional.containerfile @@ -0,0 +1,56 @@ +# {{- if env.Getenv "BREW_EC_RELEASE_VERSION" "" -}} +# Note: This comment makes templating add a new line before the code +FROM localhost/rhel100-test-agent:latest + +# Build arguments +ARG USHIFT_RPM_REPO_NAME=microshift-brew +ARG USHIFT_RPM_REPO_PATH=/tmp/$USHIFT_RPM_REPO_NAME + +# Copy the MicroShift repository contents +COPY ./rpm-repos/$USHIFT_RPM_REPO_NAME $USHIFT_RPM_REPO_PATH + +# Copy repository configuration +COPY ./bootc-images/$USHIFT_RPM_REPO_NAME.repo ./bootc-images/microshift-fast-datapath-rhel9.repo ./bootc-images/microshift-rhocp-y.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift, test agent and cleanup. +# OpenSSL is added as a temporary workaround. Systemd-resolved will bump systemd to a newer +# version that requires openssl 3.4 or higher, but package is kept at 3.2.2. By installing +# it we force an upgrade so that everything works. +RUN dnf repoinfo --enabled && \ + dnf install -y firewalld systemd-resolved openssl \ + {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_EC_RELEASE_VERSION" }}" \ + {{ end -}} + {{ range (env.Getenv "MICROSHIFT_OPTIONAL_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_EC_RELEASE_VERSION" }}" \ + {{ end -}} + {{ if and (env.Getenv "UNAME_M" "") (eq "x86_64" .Env.UNAME_M) -}} + {{ range (env.Getenv "MICROSHIFT_X86_64_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_EC_RELEASE_VERSION" }}" \ + {{ end -}} + {{ end -}} + && \ + systemctl enable microshift microshift-test-agent && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + rm -rvf $USHIFT_RPM_REPO_PATH && \ + dnf clean all + +# Configure firewall +RUN firewall-offline-cmd --zone=public --add-port=22/tcp && \ + firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16 && \ + firewall-offline-cmd --zone=trusted --add-source=169.254.169.1 && \ + firewall-offline-cmd --zone=trusted --add-source=fd01::/48 && \ + firewall-offline-cmd --zone=public --add-port=80/tcp && \ + firewall-offline-cmd --zone=public --add-port=443/tcp && \ + firewall-offline-cmd --zone=public --add-port=5353/udp && \ + firewall-offline-cmd --zone=public --add-port=6443/tcp && \ + firewall-offline-cmd --zone=public --add-port=8889/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/udp + +# Prepare system for testing Generic Device Plugin +COPY --chmod=755 ./bootc-images/build-serialsim.sh /tmp/build-serialsim.sh +RUN /tmp/build-serialsim.sh && rm -f /tmp/build-serialsim.sh +# {{- end -}} diff --git a/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-rc-with-optional.containerfile b/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-rc-with-optional.containerfile new file mode 100644 index 0000000000..0bc8ef253b --- /dev/null +++ b/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-rc-with-optional.containerfile @@ -0,0 +1,56 @@ +# {{- if env.Getenv "BREW_RC_RELEASE_VERSION" "" -}} +# Note: This comment makes templating add a new line before the code +FROM localhost/rhel100-test-agent:latest + +# Build arguments +ARG USHIFT_RPM_REPO_NAME=microshift-brew +ARG USHIFT_RPM_REPO_PATH=/tmp/$USHIFT_RPM_REPO_NAME + +# Copy the MicroShift repository contents +COPY ./rpm-repos/$USHIFT_RPM_REPO_NAME $USHIFT_RPM_REPO_PATH + +# Copy repository configuration +COPY ./bootc-images/$USHIFT_RPM_REPO_NAME.repo ./bootc-images/microshift-fast-datapath-rhel9.repo ./bootc-images/microshift-rhocp-y.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift, test agent and cleanup. +# OpenSSL is added as a temporary workaround. Systemd-resolved will bump systemd to a newer +# version that requires openssl 3.4 or higher, but package is kept at 3.2.2. By installing +# it we force an upgrade so that everything works. +RUN dnf repoinfo --enabled && \ + dnf install -y firewalld systemd-resolved openssl \ + {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_RC_RELEASE_VERSION" }}" \ + {{ end -}} + {{ range (env.Getenv "MICROSHIFT_OPTIONAL_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_RC_RELEASE_VERSION" }}" \ + {{ end -}} + {{ if and (env.Getenv "UNAME_M" "") (eq "x86_64" .Env.UNAME_M) -}} + {{ range (env.Getenv "MICROSHIFT_X86_64_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_RC_RELEASE_VERSION" }}" \ + {{ end -}} + {{ end -}} + && \ + systemctl enable microshift microshift-test-agent && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + rm -rvf $USHIFT_RPM_REPO_PATH && \ + dnf clean all + +# Configure firewall +RUN firewall-offline-cmd --zone=public --add-port=22/tcp && \ + firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16 && \ + firewall-offline-cmd --zone=trusted --add-source=169.254.169.1 && \ + firewall-offline-cmd --zone=trusted --add-source=fd01::/48 && \ + firewall-offline-cmd --zone=public --add-port=80/tcp && \ + firewall-offline-cmd --zone=public --add-port=443/tcp && \ + firewall-offline-cmd --zone=public --add-port=5353/udp && \ + firewall-offline-cmd --zone=public --add-port=6443/tcp && \ + firewall-offline-cmd --zone=public --add-port=8889/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/udp + +# Prepare system for testing Generic Device Plugin +COPY --chmod=755 ./bootc-images/build-serialsim.sh /tmp/build-serialsim.sh +RUN /tmp/build-serialsim.sh && rm -f /tmp/build-serialsim.sh +# {{- end -}} diff --git a/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-zstream-with-optional.containerfile b/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-zstream-with-optional.containerfile new file mode 100644 index 0000000000..cd191d6703 --- /dev/null +++ b/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew-zstream-with-optional.containerfile @@ -0,0 +1,56 @@ +# {{- if env.Getenv "BREW_Y0_RELEASE_VERSION" "" -}} +# Note: This comment makes templating add a new line before the code +FROM localhost/rhel100-test-agent:latest + +# Build arguments +ARG USHIFT_RPM_REPO_NAME=microshift-brew +ARG USHIFT_RPM_REPO_PATH=/tmp/$USHIFT_RPM_REPO_NAME + +# Copy the MicroShift repository contents +COPY ./rpm-repos/$USHIFT_RPM_REPO_NAME $USHIFT_RPM_REPO_PATH + +# Copy repository configuration +COPY ./bootc-images/$USHIFT_RPM_REPO_NAME.repo ./bootc-images/microshift-fast-datapath-rhel9.repo ./bootc-images/microshift-rhocp-y.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift, test agent and cleanup. +# OpenSSL is added as a temporary workaround. Systemd-resolved will bump systemd to a newer +# version that requires openssl 3.4 or higher, but package is kept at 3.2.2. By installing +# it we force an upgrade so that everything works. +RUN dnf repoinfo --enabled && \ + dnf install -y firewalld systemd-resolved openssl \ + {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_Y0_RELEASE_VERSION" }}" \ + {{ end -}} + {{ range (env.Getenv "MICROSHIFT_OPTIONAL_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_Y0_RELEASE_VERSION" }}" \ + {{ end -}} + {{ if and (env.Getenv "UNAME_M" "") (eq "x86_64" .Env.UNAME_M) -}} + {{ range (env.Getenv "MICROSHIFT_X86_64_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_Y0_RELEASE_VERSION" }}" \ + {{ end -}} + {{ end -}} + && \ + systemctl enable microshift microshift-test-agent && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + rm -rvf $USHIFT_RPM_REPO_PATH && \ + dnf clean all + +# Configure firewall +RUN firewall-offline-cmd --zone=public --add-port=22/tcp && \ + firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16 && \ + firewall-offline-cmd --zone=trusted --add-source=169.254.169.1 && \ + firewall-offline-cmd --zone=trusted --add-source=fd01::/48 && \ + firewall-offline-cmd --zone=public --add-port=80/tcp && \ + firewall-offline-cmd --zone=public --add-port=443/tcp && \ + firewall-offline-cmd --zone=public --add-port=5353/udp && \ + firewall-offline-cmd --zone=public --add-port=6443/tcp && \ + firewall-offline-cmd --zone=public --add-port=8889/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/udp + +# Prepare system for testing Generic Device Plugin +COPY --chmod=755 ./bootc-images/build-serialsim.sh /tmp/build-serialsim.sh +RUN /tmp/build-serialsim.sh && rm -f /tmp/build-serialsim.sh +# {{- end -}} diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew.containerfile b/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew.containerfile similarity index 83% rename from test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew.containerfile rename to test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew.containerfile index 3ed1a48b5f..b4b9a263a1 100644 --- a/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew.containerfile +++ b/test/image-blueprints-bootc/layer5-release/group1/rhel100-bootc-brew.containerfile @@ -1,6 +1,6 @@ # {{- if env.Getenv "BREW_VERSION" "" -}} # Note: This comment makes templating add a new line before the code -FROM localhost/rhel96-test-agent:latest +FROM localhost/rhel100-test-agent:latest # Build arguments ARG USHIFT_RPM_REPO_NAME=microshift-brew @@ -15,8 +15,11 @@ COPY ./bootc-images/$USHIFT_RPM_REPO_NAME.repo ./bootc-images/microshift-fast-da # Print repository configuration contents. # Install MicroShift, test agent and cleanup. +# OpenSSL is added as a temporary workaround. Systemd-resolved will bump systemd to a newer +# version that requires openssl 3.4 or higher, but package is kept at 3.2.2. By installing +# it we force an upgrade so that everything works. RUN dnf repoinfo --enabled && \ - dnf install -y firewalld systemd-resolved \ + dnf install -y firewalld systemd-resolved openssl \ {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} "{{ . }}-{{ env.Getenv "BREW_VERSION" }}" \ {{ end -}} diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-ec-with-optional.containerfile b/test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-ec-with-optional.containerfile similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-ec-with-optional.containerfile rename to test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-ec-with-optional.containerfile diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-rc-with-optional.containerfile b/test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-rc-with-optional.containerfile similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-rc-with-optional.containerfile rename to test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-rc-with-optional.containerfile diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-y1-with-optional.containerfile b/test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-y1-with-optional.containerfile similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-y1-with-optional.containerfile rename to test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-y1-with-optional.containerfile diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-y2-with-optional.containerfile b/test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-y2-with-optional.containerfile similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-y2-with-optional.containerfile rename to test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-y2-with-optional.containerfile diff --git a/test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-zstream-with-optional.containerfile b/test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-zstream-with-optional.containerfile similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group2/rhel96-bootc-brew-zstream-with-optional.containerfile rename to test/image-blueprints-bootc/layer5-release/group1/rhel96-bootc-brew-zstream-with-optional.containerfile diff --git a/test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-ec-with-optional-fips.containerfile b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-ec-with-optional-fips.containerfile similarity index 70% rename from test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-ec-with-optional-fips.containerfile rename to test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-ec-with-optional-fips.containerfile index ca75d6ce19..d3b9f662b1 100644 --- a/test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-ec-with-optional-fips.containerfile +++ b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-ec-with-optional-fips.containerfile @@ -10,7 +10,10 @@ match-architectures = ["x86_64"] EOF # Enable the FIPS crypto policy -RUN dnf install -y crypto-policies-scripts && \ +# +# Note: CNI plugins are required for podman to operate normally on RHEL 9.x. +# This package is no longer installed as cri-o dependency. +RUN dnf install -y crypto-policies-scripts containernetworking-plugins && \ update-crypto-policies --no-reload --set FIPS && \ dnf clean all # {{- end -}} diff --git a/test/image-blueprints-bootc/layer1-base/group4/rhel96-bootc-brew-ec-with-optional-tuned.containerfile b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-ec-with-optional-tuned.containerfile similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group4/rhel96-bootc-brew-ec-with-optional-tuned.containerfile rename to test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-ec-with-optional-tuned.containerfile diff --git a/test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-ec-with-optional.image-bootc b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-ec-with-optional.image-bootc similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-ec-with-optional.image-bootc rename to test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-ec-with-optional.image-bootc diff --git a/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-nightly-with-optional.containerfile b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-nightly-with-optional.containerfile new file mode 100644 index 0000000000..16105fe192 --- /dev/null +++ b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-nightly-with-optional.containerfile @@ -0,0 +1,53 @@ +# {{- if env.Getenv "BREW_NIGHTLY_RELEASE_VERSION" "" -}} +# Note: This comment makes templating add a new line before the code +FROM localhost/rhel96-test-agent:latest + +# Build arguments +ARG USHIFT_RPM_REPO_NAME=microshift-brew +ARG USHIFT_RPM_REPO_PATH=/tmp/$USHIFT_RPM_REPO_NAME + +# Copy the MicroShift repository contents +COPY ./rpm-repos/$USHIFT_RPM_REPO_NAME $USHIFT_RPM_REPO_PATH + +# Copy repository configuration +COPY ./bootc-images/$USHIFT_RPM_REPO_NAME.repo ./bootc-images/microshift-fast-datapath-rhel9.repo ./bootc-images/microshift-rhocp-y.repo \ + /etc/yum.repos.d/ + +# Print repository configuration contents. +# Install MicroShift, test agent and cleanup. +RUN dnf repoinfo --enabled && \ + dnf install -y firewalld systemd-resolved \ + {{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_NIGHTLY_RELEASE_VERSION" }}" \ + {{ end -}} + {{ range (env.Getenv "MICROSHIFT_OPTIONAL_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_NIGHTLY_RELEASE_VERSION" }}" \ + {{ end -}} + {{ if and (env.Getenv "UNAME_M" "") (eq "x86_64" .Env.UNAME_M) -}} + {{ range (env.Getenv "MICROSHIFT_X86_64_RPMS" | strings.Split " ") -}} + "{{ . }}-{{ env.Getenv "BREW_NIGHTLY_RELEASE_VERSION" }}" \ + {{ end -}} + {{ end -}} + && \ + systemctl enable microshift microshift-test-agent && \ + rm -vf /etc/yum.repos.d/microshift-*.repo && \ + rm -rvf $USHIFT_RPM_REPO_PATH && \ + dnf clean all + +# Configure firewall +RUN firewall-offline-cmd --zone=public --add-port=22/tcp && \ + firewall-offline-cmd --zone=trusted --add-source=10.42.0.0/16 && \ + firewall-offline-cmd --zone=trusted --add-source=169.254.169.1 && \ + firewall-offline-cmd --zone=trusted --add-source=fd01::/48 && \ + firewall-offline-cmd --zone=public --add-port=80/tcp && \ + firewall-offline-cmd --zone=public --add-port=443/tcp && \ + firewall-offline-cmd --zone=public --add-port=5353/udp && \ + firewall-offline-cmd --zone=public --add-port=6443/tcp && \ + firewall-offline-cmd --zone=public --add-port=8889/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/tcp && \ + firewall-offline-cmd --zone=public --add-port=30000-32767/udp + +# Prepare system for testing Generic Device Plugin +COPY --chmod=755 ./bootc-images/build-serialsim.sh /tmp/build-serialsim.sh +RUN /tmp/build-serialsim.sh && rm -f /tmp/build-serialsim.sh +# {{- end -}} diff --git a/test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-rc-with-optional-fips.containerfile b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-rc-with-optional-fips.containerfile similarity index 70% rename from test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-rc-with-optional-fips.containerfile rename to test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-rc-with-optional-fips.containerfile index f6e4f43e4d..36b341cf35 100644 --- a/test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-rc-with-optional-fips.containerfile +++ b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-rc-with-optional-fips.containerfile @@ -10,7 +10,10 @@ match-architectures = ["x86_64"] EOF # Enable the FIPS crypto policy -RUN dnf install -y crypto-policies-scripts && \ +# +# Note: CNI plugins are required for podman to operate normally on RHEL 9.x. +# This package is no longer installed as cri-o dependency. +RUN dnf install -y crypto-policies-scripts containernetworking-plugins && \ update-crypto-policies --no-reload --set FIPS && \ dnf clean all # {{- end -}} diff --git a/test/image-blueprints-bootc/layer1-base/group4/rhel96-bootc-brew-rc-with-optional-tuned.containerfile b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-rc-with-optional-tuned.containerfile similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group4/rhel96-bootc-brew-rc-with-optional-tuned.containerfile rename to test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-rc-with-optional-tuned.containerfile diff --git a/test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-rc-with-optional.image-bootc b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-rc-with-optional.image-bootc similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-rc-with-optional.image-bootc rename to test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-rc-with-optional.image-bootc diff --git a/test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-zstream-with-optional-fips.containerfile b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-zstream-with-optional-fips.containerfile similarity index 70% rename from test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-zstream-with-optional-fips.containerfile rename to test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-zstream-with-optional-fips.containerfile index 89607633a3..96dc287bcd 100644 --- a/test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-zstream-with-optional-fips.containerfile +++ b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-zstream-with-optional-fips.containerfile @@ -10,7 +10,10 @@ match-architectures = ["x86_64"] EOF # Enable the FIPS crypto policy -RUN dnf install -y crypto-policies-scripts && \ +# +# Note: CNI plugins are required for podman to operate normally on RHEL 9.x. +# This package is no longer installed as cri-o dependency. +RUN dnf install -y crypto-policies-scripts containernetworking-plugins && \ update-crypto-policies --no-reload --set FIPS && \ dnf clean all # {{- end -}} diff --git a/test/image-blueprints-bootc/layer1-base/group4/rhel96-bootc-brew-zstream-with-optional-tuned.containerfile b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-zstream-with-optional-tuned.containerfile similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group4/rhel96-bootc-brew-zstream-with-optional-tuned.containerfile rename to test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-zstream-with-optional-tuned.containerfile diff --git a/test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-zstream-with-optional.image-bootc b/test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-zstream-with-optional.image-bootc similarity index 100% rename from test/image-blueprints-bootc/layer1-base/group3/rhel96-bootc-brew-zstream-with-optional.image-bootc rename to test/image-blueprints-bootc/layer5-release/group2/rhel96-bootc-brew-zstream-with-optional.image-bootc diff --git a/test/image-blueprints/layer3-periodic/group1/rhel96-source-isolated.toml b/test/image-blueprints/layer3-periodic/group1/rhel96-source-isolated.toml index b9b508b14e..863f2bfc54 100644 --- a/test/image-blueprints/layer3-periodic/group1/rhel96-source-isolated.toml +++ b/test/image-blueprints/layer3-periodic/group1/rhel96-source-isolated.toml @@ -23,6 +23,12 @@ version = "*" name = "podman" version = "*" +# CNI plugins are required for podman to operate normally on RHEL 9.x. +# This package is no longer installed as cri-o dependency. +[[packages]] +name = "containernetworking-plugins" +version = "*" + [[packages]] name = "skopeo" version = "*" diff --git a/test/image-blueprints/layer1-base/group2/rhel96-brew-y2-with-optionals.toml b/test/image-blueprints/layer4-release/group1/rhel96-brew-y2-with-optionals.toml similarity index 100% rename from test/image-blueprints/layer1-base/group2/rhel96-brew-y2-with-optionals.toml rename to test/image-blueprints/layer4-release/group1/rhel96-brew-y2-with-optionals.toml diff --git a/test/image-blueprints/layer1-base/group3/rhel96-brew-y1-with-optionals.toml b/test/image-blueprints/layer4-release/group2/rhel96-brew-y1-with-optionals.toml similarity index 100% rename from test/image-blueprints/layer1-base/group3/rhel96-brew-y1-with-optionals.toml rename to test/image-blueprints/layer4-release/group2/rhel96-brew-y1-with-optionals.toml diff --git a/test/image-blueprints/layer1-base/group4/rhel96-brew-ec-with-optionals.toml b/test/image-blueprints/layer4-release/group3/rhel96-brew-ec-with-optionals.toml similarity index 100% rename from test/image-blueprints/layer1-base/group4/rhel96-brew-ec-with-optionals.toml rename to test/image-blueprints/layer4-release/group3/rhel96-brew-ec-with-optionals.toml diff --git a/test/image-blueprints/layer4-release/group3/rhel96-brew-nightly-with-optionals.toml b/test/image-blueprints/layer4-release/group3/rhel96-brew-nightly-with-optionals.toml new file mode 100644 index 0000000000..9fab7201f0 --- /dev/null +++ b/test/image-blueprints/layer4-release/group3/rhel96-brew-nightly-with-optionals.toml @@ -0,0 +1,71 @@ +{{- if and (env.Getenv "BREW_NIGHTLY_RELEASE_VERSION" "") (env.Getenv "BREW_Y1_RELEASE_VERSION" "") -}} +{{- /* + + We wrap this template in a test so that the body of the output is + empty when there is no "current" version release. The output file + must end up completely empty, so we need to remove whitespace from + around the first and last template instructions. + +*/ -}} + +name = "rhel-9.6-microshift-brew-optionals-4.{{ .Env.MINOR_VERSION}}-nightly" +description = "A RHEL 9.6 image with already built and released RPMs like EC, RC, or Z-stream release: {{ .Env.BREW_NIGHTLY_RELEASE_VERSION }}" +version = "0.0.1" +modules = [] +groups = [] +distro = "rhel-96" + +# Parent specification directive recognized by test/bin/build_images.sh to be +# used with the '--parent' argument of 'osbuild-composer' +# parent = "rhel-9.6-microshift-brew-optionals-4.{{ .Env.PREVIOUS_MINOR_VERSION }}-zstream" + +{{ range (env.Getenv "MICROSHIFT_MANDATORY_RPMS" | strings.Split " ") }} +[[packages]] +name = "{{ . }}" +version = "{{ env.Getenv "BREW_NIGHTLY_RELEASE_VERSION" }}" +{{ end }} + +{{ range (env.Getenv "MICROSHIFT_OPTIONAL_RPMS" | strings.Split " ") }} +[[packages]] +name = "{{ . }}" +version = "{{ env.Getenv "BREW_NIGHTLY_RELEASE_VERSION" }}" +{{ end }} + +{{- if and (env.Getenv "UNAME_M" "") (eq "x86_64" .Env.UNAME_M) }} +{{ range (env.Getenv "MICROSHIFT_X86_64_RPMS" | strings.Split " ") }} +[[packages]] +name = "{{ . }}" +version = "{{ env.Getenv "BREW_NIGHTLY_RELEASE_VERSION" }}" +{{ end }} +{{- end }} + +[[packages]] +name = "microshift-test-agent" +version = "*" + +[[packages]] +name = "systemd-resolved" +version = "*" + +[customizations.services] +enabled = ["microshift", "microshift-test-agent"] + +[customizations.firewall] +ports = [ + "22:tcp", + "80:tcp", + "443:tcp", + "5353:udp", + "6443:tcp", + "8889:tcp", + "30000-32767:tcp", + "30000-32767:udp", +] + +[customizations.firewall.services] +enabled = ["mdns", "ssh", "http", "https"] + +[[customizations.firewall.zones]] +name = "trusted" +sources = ["10.42.0.0/16", "169.254.169.1", "fd01::/48"] +{{- end -}} diff --git a/test/image-blueprints/layer1-base/group4/rhel96-brew-rc-with-optionals.toml b/test/image-blueprints/layer4-release/group3/rhel96-brew-rc-with-optionals.toml similarity index 100% rename from test/image-blueprints/layer1-base/group4/rhel96-brew-rc-with-optionals.toml rename to test/image-blueprints/layer4-release/group3/rhel96-brew-rc-with-optionals.toml diff --git a/test/image-blueprints/layer1-base/group4/rhel96-brew-zstream-with-optionals.toml b/test/image-blueprints/layer4-release/group3/rhel96-brew-zstream-with-optionals.toml similarity index 100% rename from test/image-blueprints/layer1-base/group4/rhel96-brew-zstream-with-optionals.toml rename to test/image-blueprints/layer4-release/group3/rhel96-brew-zstream-with-optionals.toml diff --git a/test/image-blueprints/layer2-presubmit/group1/rhel96-lrel-optionals-tuned.toml b/test/image-blueprints/layer4-release/group3/rhel96-lrel-optionals-tuned.toml similarity index 100% rename from test/image-blueprints/layer2-presubmit/group1/rhel96-lrel-optionals-tuned.toml rename to test/image-blueprints/layer4-release/group3/rhel96-lrel-optionals-tuned.toml diff --git a/test/kickstart-templates/includes/post-containers.cfg b/test/kickstart-templates/includes/post-containers.cfg index 26efff7437..433b021838 100644 --- a/test/kickstart-templates/includes/post-containers.cfg +++ b/test/kickstart-templates/includes/post-containers.cfg @@ -16,18 +16,19 @@ EOF # Setup mirror registries configuration here, as the hostname is dynamic and the file is verbose. # Use hostnames as IP addresses are not allowed. +# Mirroring happens for both digests(MicroShift itself) and tags (because of tests). There is +# no risk of stale images when mirroring by tags because the VMs are meant to be short lived +# and mirroring happens right before running the tests. mkdir -p /etc/containers/registries.conf.d cat > /etc/containers/registries.conf.d/999-microshift-mirror.conf <<'EOF' [[registry]] prefix = "" location = "REPLACE_MIRROR_HOSTNAME:REPLACE_MIRROR_PORT" - mirror-by-digest-only = true insecure = true [[registry]] prefix = "" location = "quay.io" - mirror-by-digest-only = true [[registry.mirror]] location = "REPLACE_MIRROR_HOSTNAME:REPLACE_MIRROR_PORT/microshift" insecure = true @@ -35,7 +36,6 @@ cat > /etc/containers/registries.conf.d/999-microshift-mirror.conf <<'EOF' [[registry]] prefix = "" location = "registry.redhat.io" - mirror-by-digest-only = true [[registry.mirror]] location = "REPLACE_MIRROR_HOSTNAME:REPLACE_MIRROR_PORT/microshift" insecure = true diff --git a/test/resources/common.resource b/test/resources/common.resource index 5abf5a8856..9f91c2ec78 100644 --- a/test/resources/common.resource +++ b/test/resources/common.resource @@ -138,3 +138,14 @@ Local Command Should Work Log ${stdout} Should Be Equal As Integers 0 ${rc} RETURN ${stdout} + +Remove Files + [Documentation] removes files from the microshift host + [Arguments] @{files} + Log ${files} + FOR ${file} IN @{files} + ${stdout} ${stderr} ${rc}= Execute Command + ... rm -f "${file}" + ... sudo=True return_stdout=True return_stderr=True return_rc=True + Should Be Equal As Integers ${rc} 0 + END diff --git a/test/resources/hosts.resource b/test/resources/hosts.resource new file mode 100644 index 0000000000..6077d3b4e1 --- /dev/null +++ b/test/resources/hosts.resource @@ -0,0 +1,44 @@ +*** Settings *** +Documentation Keywords for interacting with the hosts file + +Library Process +Library String +Resource common.resource + + +*** Keywords *** +Generate Random HostName + [Documentation] Generate Random Hostname + ${rand}= Generate Random String + ${rand}= Convert To Lower Case ${rand} + RETURN ${rand}.api.com + +Add Entry To Hosts + [Documentation] Add new entry to local /etc/hosts + [Arguments] ${ip} ${host} ${hostsfile}=/etc/hosts + VAR ${ttt}= ${ip}\t${host} # RF test marker\n + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command + ... echo "${ttt}" | sudo tee -a ${hostsfile} + ... sudo=True return_rc=True return_stderr=True return_stdout=True + Should Be Equal As Integers ${rc} 0 + +Remove Entry From Hosts + [Documentation] Removes entry from local /etc/hosts + [Arguments] ${host} ${hostsfile}=/etc/hosts + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command + ... sed -i "/${host} # RF test marker/d" ${hostsfile} + ... sudo=True return_rc=True return_stderr=True return_stdout=True + Should Be Equal As Integers ${rc} 0 + +Add Entry To Local Hosts + [Documentation] Add new entry to local /etc/hosts + [Arguments] ${ip} ${host} + VAR ${ttt}= ${ip}\t${host} # RF test marker\n + ${result}= Run Process sudo tee -a /etc/hosts shell=True stdin=${ttt} + Should Be Equal As Integers ${result.rc} 0 + +Remove Entry From Local Hosts + [Documentation] Removes entry from local /etc/hosts + [Arguments] ${host} + ${result}= Run Process sudo sed -i "/${host} # RF test marker/d" /etc/hosts shell=True + Should Be Equal As Integers ${result.rc} 0 diff --git a/test/resources/loki.py b/test/resources/loki.py index 9233d2e67e..7c21822f01 100644 --- a/test/resources/loki.py +++ b/test/resources/loki.py @@ -47,21 +47,37 @@ def _print_results(results: dict) -> None: sys.exit(1) streams = results["data"]["result"] + if len(streams) == 0: + raise Exception("ERROR: No results found") + for i, stream in enumerate(streams): _log(f"Labels: {stream['stream']}") + if stream["stream"]["service_name"] not in ["journald", "kube_events"]: + raise Exception(f"ERROR: Unknown service name: {stream['stream']['service_name']}") + + is_journald = stream["stream"]["service_name"] == "journald" for entry in stream["values"]: log_line = entry[1] - try: - log_line = json.loads(log_line) - if "MESSAGE" in log_line["body"]: - _log(f"{log_line['body']['MESSAGE']}") - else: - _log(f"{log_line['body']}") - except json.JSONDecodeError as e: - raise Exception(f"ERROR: Error decoding log line as JSON: {e}") + if is_journald: + try: + log_line = json.loads(log_line) + _log(f"{log_line['MESSAGE']}") + except json.JSONDecodeError as e: + raise Exception(f"ERROR: Error decoding log line as JSON: {e}") + else: + _log(f"{log_line}") def check_loki_query(host: str, port: int, query: str, limit: int = 10) -> None: + try: + from robot.libraries.BuiltIn import BuiltIn + # Running within RF + stdout, _, _ = BuiltIn().run_keyword("Command Execution", "hostname") + if stdout: + query = f"{query} | host_name=`{stdout}`" + _log(f"Added hostname to query: {query}") + except Exception: + None results = query_loki(f"http://{host}:{port}", query, limit) _print_results(results) diff --git a/test/resources/observability.resource b/test/resources/observability.resource index 108b4d1217..a2d0100217 100644 --- a/test/resources/observability.resource +++ b/test/resources/observability.resource @@ -1,24 +1,8 @@ *** Settings *** -Documentation Keywords common to observability test suites +Documentation Variables common to observability test suites -*** Keywords *** -Start Prometheus Server - [Documentation] Start a Prometheus Server on port 9092 - [Arguments] ${port}=9092 - Local Command Should Work bash -x ./bin/manage_prometheus.sh start ${port} - -Stop Prometheus Server - [Documentation] Stop the Prometheus Server - [Arguments] ${port}=9092 - Local Command Should Work bash -x ./bin/manage_prometheus.sh stop ${port} - -Start Loki Server - [Documentation] Start a Loki Server on port 3100 - [Arguments] ${port}=3100 - Local Command Should Work bash -x ./bin/manage_loki.sh start ${port} - -Stop Loki Server - [Documentation] Stop the Loki Server - [Arguments] ${port}=3100 - Local Command Should Work bash -x ./bin/manage_loki.sh stop ${port} +*** Variables *** +${PROMETHEUS_PORT} 9091 +${LOKI_PORT} 3100 +${PROM_EXPORTER_PORT} 8889 diff --git a/test/resources/oc.resource b/test/resources/oc.resource index 35630b091a..cba2eb13a8 100644 --- a/test/resources/oc.resource +++ b/test/resources/oc.resource @@ -56,8 +56,8 @@ Oc Delete Oc Exec [Documentation] Run 'oc exec' on a specific pod in the curret test namespace ... Returns the command's combined STDOUT/STDER - [Arguments] ${pod} ${cmd} ${ns}=${NAMESPACE} - ${output}= Run With Kubeconfig oc exec -n ${ns} pod/${pod} -- /bin/bash -c '${cmd}' + [Arguments] ${pod} ${cmd} ${ns}=${NAMESPACE} ${type}=pod + ${output}= Run With Kubeconfig oc exec -n ${ns} ${type}/${pod} -- /bin/bash -c '${cmd}' RETURN ${output} Oc Wait @@ -193,7 +193,7 @@ All Pods Should Be Running [Documentation] Check if all pods are running in the given namespace [Arguments] ${ns}=-A ${timeout}=${DEFAULT_WAIT_TIMEOUT} IF "${ns}"=="-A" - Oc Wait pods --all -A --for="condition=Ready" --timeout=${timeout} + Oc Wait pods -A --all --for="condition=Ready" --timeout=${timeout} ELSE - Oc Wait pods --all -n ${ns} --for="condition=Ready" --timeout=${timeout} + Oc Wait pods -n ${ns} --all --for="condition=Ready" --timeout=${timeout} END diff --git a/test/resources/prometheus.py b/test/resources/prometheus.py index ae61203049..01f94718d5 100644 --- a/test/resources/prometheus.py +++ b/test/resources/prometheus.py @@ -19,18 +19,28 @@ def _run_prometheus_query(host: str, port: int, query: str) -> requests.Response return response -def check_prometheus_query(host: str, port: int, query: str) -> None: - response = _run_prometheus_query(host, port, query) - data_result_list: list = response.json().get("data", {}).get("result") - if not data_result_list or len(data_result_list) == 0: - raise Exception("Prometheus query returned no results") +def _add_hostname_filter(query: str, add_hostname_filter: bool = True) -> str: + if not add_hostname_filter: + return query + try: + from robot.libraries.BuiltIn import BuiltIn + # Running within RF + stdout, _, _ = BuiltIn().run_keyword("Command Execution", "hostname") + if stdout: + query = f"{query}{{host_name=\"{stdout}\"}}" + _log(f"Added hostname to query: {query}") + except Exception: + None + return query -def check_prometheus_query_is_missing(host: str, port: int, query: str) -> None: + +def check_prometheus_query(host: str, port: int, query: str, add_hostname_filter: bool = True) -> None: + query = _add_hostname_filter(query, add_hostname_filter) response = _run_prometheus_query(host, port, query) data_result_list: list = response.json().get("data", {}).get("result") - if data_result_list and len(data_result_list) > 0: - raise Exception("Prometheus query returned results") + if not data_result_list or len(data_result_list) == 0: + raise Exception("Prometheus query returned no results") def check_prometheus_exporter(host: str, port: int, query: str) -> None: diff --git a/test/scenarios-bootc/periodics/el100-src@optional.sh b/test/scenarios-bootc/periodics/el100-src@optional.sh new file mode 100644 index 0000000000..c3978f59ef --- /dev/null +++ b/test/scenarios-bootc/periodics/el100-src@optional.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +# Redefine network-related settings to use the dedicated network bridge +VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_MULTUS_NETWORK}")" +# shellcheck disable=SC2034 # used elsewhere +WEB_SERVER_URL="http://${VM_BRIDGE_IP}:${WEB_SERVER_PORT}" + +# Skip the scenario if platform is ARM, as the igb driver is not supported. +check_platform() { + if [[ "${UNAME_M}" =~ aarch64 ]] ; then + record_junit "setup" "scenario_create_vms" "SKIPPED" + exit 0 + fi +} + +scenario_create_vms() { + check_platform + prepare_kickstart host1 kickstart-bootc.ks.template rhel100-bootc-source-optionals + # Three nics - one for sriov, one for macvlan, another for ipvlan (they cannot enslave the same interface) + launch_vm --boot_blueprint rhel100-bootc --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK},sriov" + + # Open the firewall ports. Other scenarios get this behavior by + # embedding settings in the blueprint, but there is no blueprint + # for this scenario. We need do this step before running the RF + # suite so that suite can assume it can reach all of the same + # ports as for any other test. + configure_vm_firewall host1 +} + +scenario_remove_vms() { + check_platform + remove_vm host1 +} + +scenario_run_tests() { + check_platform + run_tests host1 \ + --variable "PROMETHEUS_HOST:$(hostname)" \ + --variable "LOKI_HOST:$(hostname)" \ + --skip sriov \ + suites/optional/ +} diff --git a/test/scenarios-bootc/periodics/el96-crel@el96-src@optional-upgrade.sh b/test/scenarios-bootc/periodics/el96-crel@el96-src@optional-upgrade.sh deleted file mode 100644 index f297f544e7..0000000000 --- a/test/scenarios-bootc/periodics/el96-crel@el96-src@optional-upgrade.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -start_image=rhel96-bootc-crel-optionals - -scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - launch_vm --boot_blueprint rhel96-bootc -} - -scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - run_tests host1 \ - --variable "TARGET_REF:rhel96-bootc-source-optionals" \ - --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ - suites/upgrade/upgrade-multus.robot -} diff --git a/test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-fails-isolated.sh b/test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-fails-isolated.sh deleted file mode 100644 index 92496f5e2c..0000000000 --- a/test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-fails-isolated.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -start_image=rhel96-bootc-crel-isolated - -scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - launch_vm --boot_blueprint rhel96-bootc -} - -scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - run_tests host1 \ - --variable "FAILING_REF:rhel96-bootc-source-isolated" \ - --variable "REASON:fail_greenboot" \ - --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ - suites/upgrade/upgrade-fails-and-rolls-back.robot -} diff --git a/test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-fails.sh b/test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-fails.sh deleted file mode 100644 index 36786e30b2..0000000000 --- a/test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-fails.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -start_image=rhel96-bootc-crel - -scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - launch_vm --boot_blueprint rhel96-bootc -} - -scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - run_tests host1 \ - --variable "FAILING_REF:rhel96-bootc-source" \ - --variable "REASON:fail_greenboot" \ - --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ - suites/upgrade/upgrade-fails-and-rolls-back.robot -} diff --git a/test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-ok-isolated.sh b/test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-ok-isolated.sh deleted file mode 100644 index 091483f702..0000000000 --- a/test/scenarios-bootc/periodics/el96-crel@el96-src@upgrade-ok-isolated.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -start_image=rhel96-bootc-crel-isolated - -scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - launch_vm --boot_blueprint rhel96-bootc -} - -scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - run_tests host1 \ - --variable "TARGET_REF:rhel96-bootc-source-isolated" \ - --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ - suites/upgrade/upgrade-successful.robot -} diff --git a/test/scenarios-bootc/periodics/el96-crel@optional-sigstore.sh b/test/scenarios-bootc/periodics/el96-crel@optional-sigstore.sh deleted file mode 100644 index 8c74cdbcbf..0000000000 --- a/test/scenarios-bootc/periodics/el96-crel@optional-sigstore.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -# Enable container signature verification for current release images, -# including the optional components. -# These are ec / rc / z-stream, thus must all to be signed. -# shellcheck disable=SC2034 # used elsewhere -IMAGE_SIGSTORE_ENABLED=true - -start_image=rhel96-bootc-crel-optionals - -scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - launch_vm --boot_blueprint rhel96-bootc -} - -scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - # Run a minimal test for this scenario as its main functionality is - # to verify container image signature check is enabled - run_tests host1 \ - --variable "EXPECTED_OS_VERSION:9.6" \ - --variable "IMAGE_SIGSTORE_ENABLED:True" \ - suites/standard1/containers-policy.robot -} diff --git a/test/scenarios-bootc/periodics/el96-prel@el96-crel@upgrade-ok.sh b/test/scenarios-bootc/periodics/el96-prel@el96-crel@upgrade-ok.sh deleted file mode 100644 index b6104302c6..0000000000 --- a/test/scenarios-bootc/periodics/el96-prel@el96-crel@upgrade-ok.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -dest_image=rhel96-bootc-crel - -scenario_create_vms() { - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-prel - launch_vm --boot_blueprint rhel96-bootc -} - -scenario_remove_vms() { - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi - run_tests host1 \ - --variable "TARGET_REF:${dest_image}" \ - --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ - suites/upgrade/upgrade-successful.robot -} diff --git a/test/scenarios-bootc/periodics/el96-prel@el96-src@upgrade-ok.sh b/test/scenarios-bootc/periodics/el96-prel@el96-src@upgrade-ok.sh new file mode 100644 index 0000000000..0dd63d289a --- /dev/null +++ b/test/scenarios-bootc/periodics/el96-prel@el96-src@upgrade-ok.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +start_image=rhel96-bootc-prel + +scenario_create_vms() { + exit_if_image_not_found "${start_image}" + + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" + launch_vm --boot_blueprint rhel96-bootc +} + +scenario_remove_vms() { + exit_if_image_not_found "${start_image}" + + remove_vm host1 +} + +scenario_run_tests() { + exit_if_image_not_found "${start_image}" + + run_tests host1 \ + --variable "TARGET_REF:rhel96-bootc-source" \ + --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ + suites/upgrade/upgrade-successful.robot +} diff --git a/test/scenarios-bootc/periodics/el96-src@gitops.sh b/test/scenarios-bootc/periodics/el96-src@fault-tests-and-greenboot.sh similarity index 81% rename from test/scenarios-bootc/periodics/el96-src@gitops.sh rename to test/scenarios-bootc/periodics/el96-src@fault-tests-and-greenboot.sh index 0778c3c73d..3b0e2227dc 100644 --- a/test/scenarios-bootc/periodics/el96-src@gitops.sh +++ b/test/scenarios-bootc/periodics/el96-src@fault-tests-and-greenboot.sh @@ -3,7 +3,7 @@ # Sourced from scenario.sh and uses functions defined there. scenario_create_vms() { - prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-source-gitops + prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-source launch_vm --boot_blueprint rhel96-bootc } @@ -13,5 +13,6 @@ scenario_remove_vms() { scenario_run_tests() { run_tests host1 \ - suites/gitops/ + suites/fault-tests \ + suites/greenboot/ } diff --git a/test/scenarios-bootc/periodics/el96-src@fault-tests.sh b/test/scenarios-bootc/periodics/el96-src@fault-tests.sh deleted file mode 100644 index cb6afd5675..0000000000 --- a/test/scenarios-bootc/periodics/el96-src@fault-tests.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -scenario_create_vms() { - prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-source - launch_vm --boot_blueprint rhel96-bootc -} - -scenario_remove_vms() { - remove_vm host1 -} - -scenario_run_tests() { - run_tests host1 suites/fault-tests -} diff --git a/test/scenarios-bootc/periodics/el96-src@fips.sh.disabled b/test/scenarios-bootc/periodics/el96-src@fips.sh similarity index 100% rename from test/scenarios-bootc/periodics/el96-src@fips.sh.disabled rename to test/scenarios-bootc/periodics/el96-src@fips.sh diff --git a/test/scenarios-bootc/periodics/el96-src@telemetry.sh b/test/scenarios-bootc/periodics/el96-src@gitops-telemetry-clusterid-systemd.sh old mode 100644 new mode 100755 similarity index 71% rename from test/scenarios-bootc/periodics/el96-src@telemetry.sh rename to test/scenarios-bootc/periodics/el96-src@gitops-telemetry-clusterid-systemd.sh index 9ab4720dcd..306ad29510 --- a/test/scenarios-bootc/periodics/el96-src@telemetry.sh +++ b/test/scenarios-bootc/periodics/el96-src@gitops-telemetry-clusterid-systemd.sh @@ -3,7 +3,7 @@ # Sourced from scenario.sh and uses functions defined there. scenario_create_vms() { - prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-source + prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-source-gitops launch_vm --boot_blueprint rhel96-bootc } @@ -16,6 +16,8 @@ scenario_run_tests() { --variable "PROXY_HOST:${VM_BRIDGE_IP}" \ --variable "PROXY_PORT:9001" \ --variable "PROMETHEUS_HOST:$(hostname)" \ - --variable "PROMETHEUS_PORT:9092" \ - suites/telemetry/telemetry.robot + suites/gitops/ \ + suites/telemetry/telemetry.robot \ + suites/osconfig/clusterid.robot \ + suites/osconfig/systemd-resolved.robot } diff --git a/test/scenarios-bootc/periodics/el96-src@greenboot.sh b/test/scenarios-bootc/periodics/el96-src@greenboot.sh deleted file mode 100644 index 9453d13331..0000000000 --- a/test/scenarios-bootc/periodics/el96-src@greenboot.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -scenario_create_vms() { - prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-source - launch_vm --boot_blueprint rhel96-bootc -} - -scenario_remove_vms() { - remove_vm host1 -} - -scenario_run_tests() { - run_tests host1 suites/greenboot/ -} diff --git a/test/scenarios-bootc/periodics/el96-src@osconfig-misc.sh b/test/scenarios-bootc/periodics/el96-yminus2@el96-src@upgrade-ok.sh similarity index 63% rename from test/scenarios-bootc/periodics/el96-src@osconfig-misc.sh rename to test/scenarios-bootc/periodics/el96-yminus2@el96-src@upgrade-ok.sh index e18c6e84fb..f32d0cf994 100644 --- a/test/scenarios-bootc/periodics/el96-src@osconfig-misc.sh +++ b/test/scenarios-bootc/periodics/el96-yminus2@el96-src@upgrade-ok.sh @@ -3,7 +3,7 @@ # Sourced from scenario.sh and uses functions defined there. scenario_create_vms() { - prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-source + prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-yminus2 launch_vm --boot_blueprint rhel96-bootc } @@ -13,6 +13,7 @@ scenario_remove_vms() { scenario_run_tests() { run_tests host1 \ - suites/osconfig/clusterid.robot \ - suites/osconfig/systemd-resolved.robot + --variable "TARGET_REF:rhel96-bootc-source" \ + --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ + suites/upgrade/upgrade-successful.robot } diff --git a/test/scenarios-bootc/presubmits/el96-crel@el100-src@upgrade-ok.sh b/test/scenarios-bootc/presubmits/el96-crel@el100-src@upgrade-ok.sh deleted file mode 100644 index 5d7be44b96..0000000000 --- a/test/scenarios-bootc/presubmits/el96-crel@el100-src@upgrade-ok.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -start_image=rhel96-bootc-crel - -scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - launch_vm --boot_blueprint rhel96-bootc -} - -scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - run_tests host1 \ - --variable "TARGET_REF:rhel100-bootc-source" \ - --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ - suites/upgrade/upgrade-successful.robot -} diff --git a/test/scenarios-bootc/presubmits/el96-prel@el100-src@upgrade-ok.sh b/test/scenarios-bootc/presubmits/el96-prel@el100-src@upgrade-ok.sh index 0af7b72058..152f589b27 100644 --- a/test/scenarios-bootc/presubmits/el96-prel@el100-src@upgrade-ok.sh +++ b/test/scenarios-bootc/presubmits/el96-prel@el100-src@upgrade-ok.sh @@ -5,27 +5,21 @@ start_image=rhel96-bootc-prel scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + run_tests host1 \ --variable "TARGET_REF:rhel100-bootc-source" \ --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ diff --git a/test/scenarios-bootc/presubmits/el96-prel@el96-src@upgrade-ok.sh b/test/scenarios-bootc/presubmits/el96-prel@el96-src@upgrade-ok.sh index 4991fc39e1..0dd63d289a 100644 --- a/test/scenarios-bootc/presubmits/el96-prel@el96-src@upgrade-ok.sh +++ b/test/scenarios-bootc/presubmits/el96-prel@el96-src@upgrade-ok.sh @@ -5,27 +5,21 @@ start_image=rhel96-bootc-prel scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + run_tests host1 \ --variable "TARGET_REF:rhel96-bootc-source" \ --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ diff --git a/test/scenarios-bootc/presubmits/el96-src@optional.sh b/test/scenarios-bootc/presubmits/el96-src@optional.sh index 4e844a6aa8..1d4a3b6b7d 100644 --- a/test/scenarios-bootc/presubmits/el96-src@optional.sh +++ b/test/scenarios-bootc/presubmits/el96-src@optional.sh @@ -7,10 +7,19 @@ VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_MULTUS_NETWORK}")" # shellcheck disable=SC2034 # used elsewhere WEB_SERVER_URL="http://${VM_BRIDGE_IP}:${WEB_SERVER_PORT}" +# Skip the scenario if platform is ARM, as the igb driver is not supported. +check_platform() { + if [[ "${UNAME_M}" =~ aarch64 ]] ; then + record_junit "setup" "scenario_create_vms" "SKIPPED" + exit 0 + fi +} + scenario_create_vms() { + check_platform prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-source-optionals - # Two nics - one for macvlan, another for ipvlan (they cannot enslave the same interface) - launch_vm --boot_blueprint rhel96-bootc --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK}" + # Three nics - one for sriov, one for macvlan, another for ipvlan (they cannot enslave the same interface) + launch_vm --boot_blueprint rhel96-bootc --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK},sriov" # Open the firewall ports. Other scenarios get this behavior by # embedding settings in the blueprint, but there is no blueprint @@ -21,15 +30,14 @@ scenario_create_vms() { } scenario_remove_vms() { + check_platform remove_vm host1 } scenario_run_tests() { - run_tests host1 \ + check_platform + run_tests host1 \ --variable "PROMETHEUS_HOST:$(hostname)" \ - --variable "PROMETHEUS_PORT:9092" \ --variable "LOKI_HOST:$(hostname)" \ - --variable "LOKI_PORT:3200" \ - --variable "PROM_EXPORTER_PORT:8889" \ suites/optional/ } diff --git a/test/scenarios-bootc/presubmits/el96-src@standard-suite1.sh b/test/scenarios-bootc/presubmits/el96-src@standard-suite1.sh index d30951a6ce..273b443229 100644 --- a/test/scenarios-bootc/presubmits/el96-src@standard-suite1.sh +++ b/test/scenarios-bootc/presubmits/el96-src@standard-suite1.sh @@ -12,7 +12,10 @@ scenario_remove_vms() { } scenario_run_tests() { + # The SYNC_FREQUENCY is set to a shorter-than-default value to speed up + # pre-submit scenario completion time in DNS tests. run_tests host1 \ --variable "EXPECTED_OS_VERSION:9.6" \ + --variable "SYNC_FREQUENCY:5s" \ suites/standard1/ suites/selinux/validate-selinux-policy.robot } diff --git a/test/scenarios-bootc/presubmits/el96-crel@el96-src@upgrade-ok.sh b/test/scenarios-bootc/releases/el100-lrel@ginkgo-tests.sh similarity index 71% rename from test/scenarios-bootc/presubmits/el96-crel@el96-src@upgrade-ok.sh rename to test/scenarios-bootc/releases/el100-lrel@ginkgo-tests.sh index 8a10df649f..472d3e036a 100644 --- a/test/scenarios-bootc/presubmits/el96-crel@el96-src@upgrade-ok.sh +++ b/test/scenarios-bootc/releases/el100-lrel@ginkgo-tests.sh @@ -2,15 +2,16 @@ # Sourced from scenario.sh and uses functions defined there. -start_image=rhel96-bootc-crel +start_image="rhel100-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { if ! does_image_exist "${start_image}"; then echo "Image '${start_image}' not found - skipping test" return 0 fi + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - launch_vm --boot_blueprint rhel96-bootc + launch_vm --boot_blueprint rhel100-bootc --vm_disksize 30 } scenario_remove_vms() { @@ -18,6 +19,7 @@ scenario_remove_vms() { echo "Image '${start_image}' not found - skipping test" return 0 fi + remove_vm host1 } @@ -26,8 +28,9 @@ scenario_run_tests() { echo "Image '${start_image}' not found - skipping test" return 0 fi - run_tests host1 \ - --variable "TARGET_REF:rhel96-bootc-source" \ - --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ - suites/upgrade/upgrade-successful.robot + + # Wait for MicroShift to be ready + wait_for_microshift_to_be_ready host1 + + run_ginkgo_tests host1 "~Disruptive" } diff --git a/test/scenarios-bootc/releases/el100-lrel@optional.sh b/test/scenarios-bootc/releases/el100-lrel@optional.sh new file mode 100644 index 0000000000..4844499fd9 --- /dev/null +++ b/test/scenarios-bootc/releases/el100-lrel@optional.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +# Redefine network-related settings to use the dedicated network bridge +VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_MULTUS_NETWORK}")" +# shellcheck disable=SC2034 # used elsewhere +WEB_SERVER_URL="http://${VM_BRIDGE_IP}:${WEB_SERVER_PORT}" + +start_image="rhel100-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" + +scenario_create_vms() { + exit_if_image_not_found "${start_image}" + + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" + # Two nics - one for macvlan, another for ipvlan (they cannot enslave the same interface) + launch_vm --boot_blueprint rhel100-bootc --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK}" +} + +scenario_remove_vms() { + exit_if_image_not_found "${start_image}" + + remove_vm host1 +} + +scenario_run_tests() { + exit_if_image_not_found "${start_image}" + + run_tests host1 \ + --variable "PROMETHEUS_HOST:$(hostname)" \ + --variable "LOKI_HOST:$(hostname)" \ + suites/optional/ +} diff --git a/test/scenarios-bootc/periodics/el96-crel@brew-standard1.sh b/test/scenarios-bootc/releases/el100-lrel@standard1.sh similarity index 81% rename from test/scenarios-bootc/periodics/el96-crel@brew-standard1.sh rename to test/scenarios-bootc/releases/el100-lrel@standard1.sh index 478c0375fd..1b2acfa3cd 100644 --- a/test/scenarios-bootc/periodics/el96-crel@brew-standard1.sh +++ b/test/scenarios-bootc/releases/el100-lrel@standard1.sh @@ -2,15 +2,16 @@ # Sourced from scenario.sh and uses functions defined there. -start_image=rhel96-bootc-brew +start_image="rhel100-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { if ! does_image_exist "${start_image}"; then echo "Image '${start_image}' not found - skipping test" return 0 fi + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - launch_vm --boot_blueprint rhel96-bootc + launch_vm --boot_blueprint rhel100-bootc } scenario_remove_vms() { @@ -18,6 +19,7 @@ scenario_remove_vms() { echo "Image '${start_image}' not found - skipping test" return 0 fi + remove_vm host1 } @@ -26,7 +28,8 @@ scenario_run_tests() { echo "Image '${start_image}' not found - skipping test" return 0 fi + run_tests host1 \ - --variable "EXPECTED_OS_VERSION:9.6" \ + --variable "EXPECTED_OS_VERSION:10.0" \ suites/standard1/ suites/selinux/validate-selinux-policy.robot } diff --git a/test/scenarios-bootc/periodics/el96-crel@brew-standard2.sh b/test/scenarios-bootc/releases/el100-lrel@standard2.sh similarity index 85% rename from test/scenarios-bootc/periodics/el96-crel@brew-standard2.sh rename to test/scenarios-bootc/releases/el100-lrel@standard2.sh index 4d199a5d13..f0aad0c1c5 100644 --- a/test/scenarios-bootc/periodics/el96-crel@brew-standard2.sh +++ b/test/scenarios-bootc/releases/el100-lrel@standard2.sh @@ -2,15 +2,16 @@ # Sourced from scenario.sh and uses functions defined there. -start_image=rhel96-bootc-brew +start_image="rhel100-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { if ! does_image_exist "${start_image}"; then echo "Image '${start_image}' not found - skipping test" return 0 fi + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - launch_vm --boot_blueprint rhel96-bootc + launch_vm --boot_blueprint rhel100-bootc } scenario_remove_vms() { @@ -18,6 +19,7 @@ scenario_remove_vms() { echo "Image '${start_image}' not found - skipping test" return 0 fi + remove_vm host1 } @@ -26,5 +28,6 @@ scenario_run_tests() { echo "Image '${start_image}' not found - skipping test" return 0 fi + run_tests host1 suites/standard2 } diff --git a/test/scenarios-bootc/periodics/el96-crel@published-images-standard1.sh b/test/scenarios-bootc/releases/el96-crel@published-images-standard1.sh similarity index 100% rename from test/scenarios-bootc/periodics/el96-crel@published-images-standard1.sh rename to test/scenarios-bootc/releases/el96-crel@published-images-standard1.sh diff --git a/test/scenarios-bootc/periodics/el96-crel@published-images-standard2.sh b/test/scenarios-bootc/releases/el96-crel@published-images-standard2.sh similarity index 100% rename from test/scenarios-bootc/periodics/el96-crel@published-images-standard2.sh rename to test/scenarios-bootc/releases/el96-crel@published-images-standard2.sh diff --git a/test/scenarios-bootc/releases/el96-lrel@ai-model-serving-online.sh b/test/scenarios-bootc/releases/el96-lrel@ai-model-serving-online.sh index 2306fa9079..4c5d75d1db 100644 --- a/test/scenarios-bootc/releases/el96-lrel@ai-model-serving-online.sh +++ b/test/scenarios-bootc/releases/el96-lrel@ai-model-serving-online.sh @@ -17,12 +17,8 @@ check_platform() { } scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - check_platform true + exit_if_image_not_found "${start_image}" # Increased disk size because of the additional embedded images (especially OVMS which is ~3.5GiB) LVM_SYSROOT_SIZE=20480 prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" @@ -30,23 +26,15 @@ scenario_create_vms() { } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - check_platform + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - check_platform + exit_if_image_not_found "${start_image}" run_tests host1 \ suites/ai-model-serving/ai-model-serving-online.robot diff --git a/test/scenarios-bootc/releases/el96-lrel@dual-stack.sh b/test/scenarios-bootc/releases/el96-lrel@dual-stack.sh index 62db73086f..115a8124bc 100644 --- a/test/scenarios-bootc/releases/el96-lrel@dual-stack.sh +++ b/test/scenarios-bootc/releases/el96-lrel@dual-stack.sh @@ -5,29 +5,20 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc --network "${VM_DUAL_STACK_NETWORK}" } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" local -r vmname=$(full_vm_name host1) # Valid IP addresses are the first two entries returned by manage-vm script. diff --git a/test/scenarios-bootc/releases/el96-lrel@fips.sh.disabled b/test/scenarios-bootc/releases/el96-lrel@fips.sh similarity index 81% rename from test/scenarios-bootc/releases/el96-lrel@fips.sh.disabled rename to test/scenarios-bootc/releases/el96-lrel@fips.sh index a73d5b3756..8f6791a61f 100644 --- a/test/scenarios-bootc/releases/el96-lrel@fips.sh.disabled +++ b/test/scenarios-bootc/releases/el96-lrel@fips.sh @@ -12,12 +12,8 @@ check_platform() { } scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - check_platform + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc --fips @@ -25,13 +21,14 @@ scenario_create_vms() { scenario_remove_vms() { check_platform + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { check_platform + exit_if_image_not_found "${start_image}" run_tests host1 suites/fips/ } - diff --git a/test/scenarios-bootc/releases/el96-lrel@ginkgo-tests.sh b/test/scenarios-bootc/releases/el96-lrel@ginkgo-tests.sh index 1e9948e27f..62b456e413 100644 --- a/test/scenarios-bootc/releases/el96-lrel@ginkgo-tests.sh +++ b/test/scenarios-bootc/releases/el96-lrel@ginkgo-tests.sh @@ -5,29 +5,23 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc --vm_disksize 30 } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" - run_gingko_tests host1 "~Disruptive" + # Wait for MicroShift to be ready + wait_for_microshift_to_be_ready host1 + + run_ginkgo_tests host1 "~Disruptive" } diff --git a/test/scenarios-bootc/releases/el96-lrel@ipv6.sh b/test/scenarios-bootc/releases/el96-lrel@ipv6.sh index 2369c50f85..0e2fd9601c 100644 --- a/test/scenarios-bootc/releases/el96-lrel@ipv6.sh +++ b/test/scenarios-bootc/releases/el96-lrel@ipv6.sh @@ -7,40 +7,33 @@ VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_IPV6_NETWORK}")" # shellcheck disable=SC2034 # used elsewhere WEB_SERVER_URL="http://[${VM_BRIDGE_IP}]:${WEB_SERVER_PORT}" -# Using `hostname` here instead of a raw ip because skopeo only allows either -# ipv4 or fqdn's, but not ipv6. Since the registry is hosted on the ipv6 -# network gateway in the host, we need to use a combination of the hostname -# plus /etc/hosts resolution (which is taken care of by kickstart). -# shellcheck disable=SC2034 # used elsewhere -MIRROR_REGISTRY_URL="$(hostname):${MIRROR_REGISTRY_PORT}/microshift" start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { + exit_if_image_not_found "${start_image}" + + # Using `hostname` here instead of a raw ip because skopeo only allows either + # ipv4 or fqdn's, but not ipv6. Since the registry is hosted on the ipv6 + # network gateway in the host, we need to use a combination of the hostname + # plus /etc/hosts resolution (which is taken care of by kickstart). + # Save the original value and temporarily override for prepare_kickstart + local original_mirror_registry_url="${MIRROR_REGISTRY_URL}" + MIRROR_REGISTRY_URL="$(hostname):${MIRROR_REGISTRY_PORT}/microshift" # Enable IPv6 single stack in kickstart - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" false true + MIRROR_REGISTRY_URL="${original_mirror_registry_url}" launch_vm --boot_blueprint rhel96-bootc --network "${VM_IPV6_NETWORK}" } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" run_tests host1 suites/ipv6/singlestack.robot } diff --git a/test/scenarios-bootc/releases/el96-lrel@low-latency.sh b/test/scenarios-bootc/releases/el96-lrel@low-latency.sh index 2330e5070e..575e81e30b 100644 --- a/test/scenarios-bootc/releases/el96-lrel@low-latency.sh +++ b/test/scenarios-bootc/releases/el96-lrel@low-latency.sh @@ -8,29 +8,21 @@ export TEST_RANDOMIZATION=none start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional-tuned" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" true launch_vm --boot_blueprint rhel96-bootc --vm_vcpus 6 } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + # Should not be run immediately after creating VM because of # microshift-tuned rebooting the node to activate the profile. local -r start_time=$(date +%s) diff --git a/test/scenarios-bootc/releases/el96-lrel@multi-config-standard1.sh b/test/scenarios-bootc/releases/el96-lrel@multi-config-standard1.sh new file mode 100644 index 0000000000..128cb9d704 --- /dev/null +++ b/test/scenarios-bootc/releases/el96-lrel@multi-config-standard1.sh @@ -0,0 +1,118 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +# Multi-config scenario: Combines multiple configurations to validate no conflicts +# - Low-latency (tuned) +# - TLSv1.3 +# - LVMS (default) +# - IPv6 (network configuration) + +export TEST_RANDOMIZATION=none + +# Redefine network-related settings to use the dedicated IPv6 network bridge +# shellcheck disable=SC2034 # used elsewhere +VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_IPV6_NETWORK}")" +# shellcheck disable=SC2034 # used elsewhere +WEB_SERVER_URL="http://[${VM_BRIDGE_IP}]:${WEB_SERVER_PORT}" + +start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional-tuned" + +scenario_create_vms() { + if ! does_image_exist "${start_image}"; then + echo "Image '${start_image}' not found - skipping test" + return 0 + fi + + # Temporarily override MIRROR_REGISTRY_URL for kickstart preparation + # The kickstart template needs a hostname-based URL, not an IPv6 address + local original_mirror_url="${MIRROR_REGISTRY_URL}" + # shellcheck disable=SC2034 # used elsewhere + MIRROR_REGISTRY_URL="$(hostname):${MIRROR_REGISTRY_PORT}/microshift" + + # Enable IPv6 single stack in kickstart, with tuned configuration enabled + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" false true + + # Restore original MIRROR_REGISTRY_URL for runtime use + # shellcheck disable=SC2034 # used elsewhere + MIRROR_REGISTRY_URL="${original_mirror_url}" + + launch_vm --boot_blueprint rhel96-bootc --network "${VM_IPV6_NETWORK}" --vm_vcpus 6 +} + +scenario_remove_vms() { + if ! does_image_exist "${start_image}"; then + echo "Image '${start_image}' not found - skipping test" + return 0 + fi + + remove_vm host1 +} + +scenario_run_tests() { + if ! does_image_exist "${start_image}"; then + echo "Image '${start_image}' not found - skipping test" + return 0 + fi + + # Wait for microshift-tuned to reboot the node + local -r start_time=$(date +%s) + while true; do + boot_num=$(run_command_on_vm host1 "sudo journalctl --list-boots --quiet | wc -l" || true) + boot_num="${boot_num%$'\r'*}" + if [[ "${boot_num}" -ge 2 ]]; then + break + fi + if [ $(( $(date +%s) - start_time )) -gt 60 ]; then + echo "Timed out waiting for VM having 2 boots" + exit 1 + fi + sleep 5 + done + + # Apply TLSv1.3 configuration via drop-in config + echo "INFO: Configuring TLSv1.3..." + run_command_on_vm host1 "sudo mkdir -p /etc/microshift/config.d" + run_command_on_vm host1 "sudo tee /etc/microshift/config.d/10-tls.yaml > /dev/null << 'EOF' +apiServer: + tls: + minVersion: VersionTLS13 +EOF" + + # Restart MicroShift to apply TLS configuration + echo "INFO: Restarting MicroShift to apply TLS configuration..." + run_command_on_vm host1 "sudo systemctl restart microshift" + + # Wait for MicroShift to be ready + wait_for_microshift_to_be_ready host1 + + # Setup oc client and kubeconfig for scripts that need it + setup_oc_and_kubeconfig host1 + + # Create LVMS workloads + echo "INFO: Creating LVMS workloads to validate storage..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/createWorkloads.sh" + + echo "INFO: Checking LVMS resources..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/checkLvmsResources.sh" + + # Validate LVMS workloads before running tests + echo "INFO: Validating LVMS workloads..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/checkWorkloadExists.sh" + + # Cleanup LVMS workloads before running tests that may restart MicroShift + echo "INFO: Cleaning up LVMS workloads..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/cleanupWorkload.sh" + + # Run all standard1 tests except version (which requires RPM install verification) + # and tls-configuration (which is already configured) + echo "INFO: Running validation tests for multi-config scenario..." + run_tests host1 \ + --variable "EXPECTED_OS_VERSION:9.6" \ + --exclude tls-configuration \ + --exclude version \ + suites/standard1/ \ + suites/selinux/validate-selinux-policy.robot + + echo "SUCCESS: Multi-config scenario validation completed - no conflicts detected" +} diff --git a/test/scenarios-bootc/releases/el96-lrel@multi-config-standard2.sh b/test/scenarios-bootc/releases/el96-lrel@multi-config-standard2.sh new file mode 100644 index 0000000000..fe633112f2 --- /dev/null +++ b/test/scenarios-bootc/releases/el96-lrel@multi-config-standard2.sh @@ -0,0 +1,114 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +# Multi-config scenario: Combines multiple configurations to validate no conflicts +# - Low-latency (tuned) +# - TLSv1.3 +# - LVMS (default) +# - IPv6 (network configuration) + +export TEST_RANDOMIZATION=none + +# Redefine network-related settings to use the dedicated IPv6 network bridge +# shellcheck disable=SC2034 # used elsewhere +VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_IPV6_NETWORK}")" +# shellcheck disable=SC2034 # used elsewhere +WEB_SERVER_URL="http://[${VM_BRIDGE_IP}]:${WEB_SERVER_PORT}" + +start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional-tuned" + +scenario_create_vms() { + if ! does_image_exist "${start_image}"; then + echo "Image '${start_image}' not found - skipping test" + return 0 + fi + + # Temporarily override MIRROR_REGISTRY_URL for kickstart preparation + # The kickstart template needs a hostname-based URL, not an IPv6 address + local original_mirror_url="${MIRROR_REGISTRY_URL}" + # shellcheck disable=SC2034 # used elsewhere + MIRROR_REGISTRY_URL="$(hostname):${MIRROR_REGISTRY_PORT}/microshift" + + # Enable IPv6 single stack in kickstart + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" false true + + # Restore original MIRROR_REGISTRY_URL for runtime use + # shellcheck disable=SC2034 # used elsewhere + MIRROR_REGISTRY_URL="${original_mirror_url}" + + launch_vm --boot_blueprint rhel96-bootc --network "${VM_IPV6_NETWORK}" --vm_vcpus 6 +} + +scenario_remove_vms() { + if ! does_image_exist "${start_image}"; then + echo "Image '${start_image}' not found - skipping test" + return 0 + fi + + remove_vm host1 +} + +scenario_run_tests() { + if ! does_image_exist "${start_image}"; then + echo "Image '${start_image}' not found - skipping test" + return 0 + fi + + # Wait for microshift-tuned to reboot the node + local -r start_time=$(date +%s) + while true; do + boot_num=$(run_command_on_vm host1 "sudo journalctl --list-boots --quiet | wc -l" || true) + boot_num="${boot_num%$'\r'*}" + if [[ "${boot_num}" -ge 2 ]]; then + break + fi + if [ $(( $(date +%s) - start_time )) -gt 60 ]; then + echo "Timed out waiting for VM having 2 boots" + exit 1 + fi + sleep 5 + done + + # Apply TLSv1.3 configuration via drop-in config + echo "INFO: Configuring TLSv1.3..." + run_command_on_vm host1 "sudo mkdir -p /etc/microshift/config.d" + run_command_on_vm host1 "sudo tee /etc/microshift/config.d/10-tls.yaml > /dev/null << 'EOF' +apiServer: + tls: + minVersion: VersionTLS13 +EOF" + + # Restart MicroShift to apply TLS configuration + run_command_on_vm host1 "sudo systemctl restart microshift" + + # Wait for MicroShift to be ready + wait_for_microshift_to_be_ready host1 + + # Setup oc client and kubeconfig for gingko tests + setup_oc_and_kubeconfig host1 + + # Create LVMS workloads + echo "INFO: Creating LVMS workloads to validate storage..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/createWorkloads.sh" + + echo "INFO: Checking LVMS resources..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/checkLvmsResources.sh" + + # Validate LVMS still works after all tests + echo "INFO: Validating LVMS workloads after tests..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/checkWorkloadExists.sh" + + # Cleanup LVMS workloads + echo "INFO: Cleaning up LVMS workloads..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/cleanupWorkload.sh" + + # Run all standard2 tests except default-config (which conflicts with TLS drop-in config) + echo "INFO: Running validation tests for multi-config scenario..." + run_tests host1 \ + --variable "EXPECTED_OS_VERSION:9.6" \ + --exclude default-config \ + suites/standard2/ + + echo "SUCCESS: Multi-config scenario validation completed - no conflicts detected" +} diff --git a/test/scenarios-bootc/releases/el96-lrel@multi-nic.sh b/test/scenarios-bootc/releases/el96-lrel@multi-nic.sh index 1f1b7dee52..a64f58808b 100644 --- a/test/scenarios-bootc/releases/el96-lrel@multi-nic.sh +++ b/test/scenarios-bootc/releases/el96-lrel@multi-nic.sh @@ -5,10 +5,7 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" # Using multus as secondary network to have 2 nics in different networks. @@ -16,19 +13,13 @@ scenario_create_vms() { } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" local -r vmname=$(full_vm_name host1) local -r vm_ip1=$("${ROOTDIR}/scripts/devenv-builder/manage-vm.sh" ip -n "${vmname}" | head -1) diff --git a/test/scenarios-bootc/releases/el96-lrel@nightly-brew-standard1.sh b/test/scenarios-bootc/releases/el96-lrel@nightly-brew-standard1.sh new file mode 100644 index 0000000000..0fdebdd3be --- /dev/null +++ b/test/scenarios-bootc/releases/el96-lrel@nightly-brew-standard1.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +start_image=rhel96-bootc-brew-nightly-with-optional + +scenario_create_vms() { + exit_if_image_not_found "${start_image}" + + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" + launch_vm --boot_blueprint rhel96-bootc +} + +scenario_remove_vms() { + exit_if_image_not_found "${start_image}" + + remove_vm host1 +} + +scenario_run_tests() { + exit_if_image_not_found "${start_image}" + + run_tests host1 \ + --variable "EXPECTED_OS_VERSION:9.6" \ + suites/standard1/ suites/selinux/validate-selinux-policy.robot +} + diff --git a/test/scenarios-bootc/releases/el96-lrel@nightly-brew-standard2.sh b/test/scenarios-bootc/releases/el96-lrel@nightly-brew-standard2.sh new file mode 100644 index 0000000000..f01042bd32 --- /dev/null +++ b/test/scenarios-bootc/releases/el96-lrel@nightly-brew-standard2.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +start_image=rhel96-bootc-brew-nightly-with-optional + +scenario_create_vms() { + exit_if_image_not_found "${start_image}" + + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" + launch_vm --boot_blueprint rhel96-bootc +} + +scenario_remove_vms() { + exit_if_image_not_found "${start_image}" + + remove_vm host1 +} + +scenario_run_tests() { + exit_if_image_not_found "${start_image}" + + run_tests host1 suites/standard2 +} + diff --git a/test/scenarios-bootc/releases/el96-lrel@optional.sh b/test/scenarios-bootc/releases/el96-lrel@optional.sh index fd9c89b5a2..57835d7c0b 100644 --- a/test/scenarios-bootc/releases/el96-lrel@optional.sh +++ b/test/scenarios-bootc/releases/el96-lrel@optional.sh @@ -9,37 +9,36 @@ WEB_SERVER_URL="http://${VM_BRIDGE_IP}:${WEB_SERVER_PORT}" start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" -scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 +# Skip the scenario if platform is ARM, as the igb driver is not supported. +check_platform() { + if [[ "${UNAME_M}" =~ aarch64 ]] ; then + record_junit "setup" "scenario_create_vms" "SKIPPED" + exit 0 fi +} + +scenario_create_vms() { + check_platform + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" - # Two nics - one for macvlan, another for ipvlan (they cannot enslave the same interface) - launch_vm --boot_blueprint rhel96-bootc --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK}" + # Three nics - one for sriov, one for macvlan, another for ipvlan (they cannot enslave the same interface) + launch_vm --boot_blueprint rhel96-bootc --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK},sriov" } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + check_platform + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + check_platform + exit_if_image_not_found "${start_image}" - run_tests host1 \ + run_tests host1 \ --variable "PROMETHEUS_HOST:$(hostname)" \ - --variable "PROMETHEUS_PORT:9092" \ --variable "LOKI_HOST:$(hostname)" \ - --variable "LOKI_PORT:3200" \ - --variable "PROM_EXPORTER_PORT:8889" \ suites/optional/ } diff --git a/test/scenarios-bootc/releases/el96-lrel@osconfig.sh b/test/scenarios-bootc/releases/el96-lrel@osconfig.sh index e12f896c52..ddaac99fc5 100644 --- a/test/scenarios-bootc/releases/el96-lrel@osconfig.sh +++ b/test/scenarios-bootc/releases/el96-lrel@osconfig.sh @@ -5,29 +5,20 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" run_tests host1 \ suites/osconfig/clusterid.robot \ diff --git a/test/scenarios-bootc/releases/el96-lrel@router.sh b/test/scenarios-bootc/releases/el96-lrel@router.sh index e98e710d92..a7d2b44d29 100644 --- a/test/scenarios-bootc/releases/el96-lrel@router.sh +++ b/test/scenarios-bootc/releases/el96-lrel@router.sh @@ -5,29 +5,20 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" run_tests host1 \ suites/router diff --git a/test/scenarios-bootc/releases/el96-lrel@standard1.sh b/test/scenarios-bootc/releases/el96-lrel@standard1.sh index d0b8ffd9a0..89648881cd 100644 --- a/test/scenarios-bootc/releases/el96-lrel@standard1.sh +++ b/test/scenarios-bootc/releases/el96-lrel@standard1.sh @@ -5,29 +5,20 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint "${start_image}" } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" run_tests host1 \ --variable "EXPECTED_OS_VERSION:9.6" \ diff --git a/test/scenarios-bootc/releases/el96-lrel@standard2.sh b/test/scenarios-bootc/releases/el96-lrel@standard2.sh index ceac34c093..9381733d4c 100644 --- a/test/scenarios-bootc/releases/el96-lrel@standard2.sh +++ b/test/scenarios-bootc/releases/el96-lrel@standard2.sh @@ -5,29 +5,20 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint "${start_image}" } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" run_tests host1 suites/standard2 } diff --git a/test/scenarios-bootc/releases/el96-lrel@storage.sh b/test/scenarios-bootc/releases/el96-lrel@storage.sh index aa21366d0a..c8b2be28b3 100644 --- a/test/scenarios-bootc/releases/el96-lrel@storage.sh +++ b/test/scenarios-bootc/releases/el96-lrel@storage.sh @@ -5,29 +5,20 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" run_tests host1 suites/storage/ } diff --git a/test/scenarios-bootc/releases/el96-lrel@telemetry.sh b/test/scenarios-bootc/releases/el96-lrel@telemetry.sh index 9ed75dc229..14f874dc43 100644 --- a/test/scenarios-bootc/releases/el96-lrel@telemetry.sh +++ b/test/scenarios-bootc/releases/el96-lrel@telemetry.sh @@ -5,34 +5,24 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" run_tests host1 \ --variable "PROXY_HOST:${VM_BRIDGE_IP}" \ --variable "PROXY_PORT:9001" \ --variable "PROMETHEUS_HOST:$(hostname)" \ - --variable "PROMETHEUS_PORT:9092" \ suites/telemetry/telemetry.robot } diff --git a/test/scenarios-bootc/releases/el96-lrel@tlsv13-standard1.sh b/test/scenarios-bootc/releases/el96-lrel@tlsv13-standard1.sh index a761a90a0d..56edc90a00 100644 --- a/test/scenarios-bootc/releases/el96-lrel@tlsv13-standard1.sh +++ b/test/scenarios-bootc/releases/el96-lrel@tlsv13-standard1.sh @@ -5,29 +5,20 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" # Apply TLS v1.3 configuration via drop-in config run_command_on_vm host1 "sudo mkdir -p /etc/microshift/config.d" diff --git a/test/scenarios-bootc/releases/el96-lrel@tlsv13-standard2.sh b/test/scenarios-bootc/releases/el96-lrel@tlsv13-standard2.sh index 6a0fc601d6..87866ee825 100644 --- a/test/scenarios-bootc/releases/el96-lrel@tlsv13-standard2.sh +++ b/test/scenarios-bootc/releases/el96-lrel@tlsv13-standard2.sh @@ -5,29 +5,20 @@ start_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" # Apply TLS v1.3 configuration via drop-in config run_command_on_vm host1 "sudo mkdir -p /etc/microshift/config.d" diff --git a/test/scenarios-bootc/releases/el96-y1@el96-lrel@lvms.sh b/test/scenarios-bootc/releases/el96-y1@el96-lrel@lvms.sh index 1ee30e736d..b5da5d27aa 100644 --- a/test/scenarios-bootc/releases/el96-y1@el96-lrel@lvms.sh +++ b/test/scenarios-bootc/releases/el96-y1@el96-lrel@lvms.sh @@ -10,49 +10,29 @@ start_image="rhel96-bootc-brew-y1-with-optional" dest_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi - - # Verify if microshift has started up fully - local vmname="host1" - local -r full_vmname="$(full_vm_name "${vmname}")" - local -r vm_ip="$(get_vm_property "${vmname}" ip)" - if ! wait_for_greenboot "${full_vmname}" "${vm_ip}"; then - record_junit "${vmname}" "pre_test_greenboot_check" "FAILED" - return 1 - fi - record_junit "${vmname}" "pre_test_greenboot_check" "OK" + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + + # Wait for MicroShift to be ready + wait_for_microshift_to_be_ready host1 + + # Setup oc client and kubeconfig for ginkgo tests + setup_oc_and_kubeconfig host1 # Pre-upgrade: Create LVMS workloads and validate LVMS is working echo "INFO: Creating LVMS workloads before upgrade..." diff --git a/test/scenarios-bootc/releases/el96-y1@el96-lrel@standard1.sh b/test/scenarios-bootc/releases/el96-y1@el96-lrel@standard1.sh index 84de2f6dc7..7b6400c3f2 100644 --- a/test/scenarios-bootc/releases/el96-y1@el96-lrel@standard1.sh +++ b/test/scenarios-bootc/releases/el96-y1@el96-lrel@standard1.sh @@ -10,39 +10,24 @@ start_image="rhel96-bootc-brew-y1-with-optional" dest_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + run_tests host1 \ --variable "TARGET_REF:${dest_image}" \ --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ diff --git a/test/scenarios-bootc/releases/el96-y1@el96-lrel@standard2.sh b/test/scenarios-bootc/releases/el96-y1@el96-lrel@standard2.sh index 5852724f07..a215f269aa 100644 --- a/test/scenarios-bootc/releases/el96-y1@el96-lrel@standard2.sh +++ b/test/scenarios-bootc/releases/el96-y1@el96-lrel@standard2.sh @@ -10,39 +10,24 @@ start_image="rhel96-bootc-brew-y1-with-optional" dest_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + run_tests host1 \ --variable "TARGET_REF:${dest_image}" \ --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ diff --git a/test/scenarios-bootc/releases/el96-y2@el96-lrel@lvms.sh b/test/scenarios-bootc/releases/el96-y2@el96-lrel@lvms.sh index f4a8b94a68..cfbff31646 100644 --- a/test/scenarios-bootc/releases/el96-y2@el96-lrel@lvms.sh +++ b/test/scenarios-bootc/releases/el96-y2@el96-lrel@lvms.sh @@ -10,50 +10,29 @@ start_image="rhel96-bootc-brew-y2-with-optional" dest_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" launch_vm --boot_blueprint rhel96-bootc --vm_disksize 30 } scenario_remove_vms() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi - - # Verify if microshift has started up fully - local vmname="host1" - local -r full_vmname="$(full_vm_name "${vmname}")" - local -r vm_ip="$(get_vm_property "${vmname}" ip)" - if ! wait_for_greenboot "${full_vmname}" "${vm_ip}"; then - record_junit "${vmname}" "pre_test_greenboot_check" "FAILED" - return 1 - fi - record_junit "${vmname}" "pre_test_greenboot_check" "OK" + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + + # Wait for MicroShift to be ready + wait_for_microshift_to_be_ready host1 + + # Setup oc client and kubeconfig for ginkgo tests + setup_oc_and_kubeconfig host1 # Pre-upgrade: Create LVMS workloads and validate LVMS is working echo "INFO: Creating LVMS workloads before upgrade..." @@ -77,7 +56,7 @@ scenario_run_tests() { run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/checkLvmsResources.sh" # Run ginkgo tests to validate functionality - run_gingko_tests host1 "~Disruptive" + run_ginkgo_tests host1 "~Disruptive" # Cleanup LVMS workloads echo "INFO: Cleaning up LVMS workloads..." diff --git a/test/scenarios-bootc/releases/el96-y2@el96-lrel@standard1.sh b/test/scenarios-bootc/releases/el96-y2@el96-lrel@standard1.sh index 961ad60a96..4fffd591b5 100644 --- a/test/scenarios-bootc/releases/el96-y2@el96-lrel@standard1.sh +++ b/test/scenarios-bootc/releases/el96-y2@el96-lrel@standard1.sh @@ -9,27 +9,21 @@ export TEST_RANDOMIZATION=none dest_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${dest_image}" + prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-brew-y2-with-optional launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${dest_image}" + remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${dest_image}" + run_tests host1 \ --variable "TARGET_REF:${dest_image}" \ --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ diff --git a/test/scenarios-bootc/releases/el96-y2@el96-lrel@standard2.sh b/test/scenarios-bootc/releases/el96-y2@el96-lrel@standard2.sh index 4b05c86799..34740ae3ae 100644 --- a/test/scenarios-bootc/releases/el96-y2@el96-lrel@standard2.sh +++ b/test/scenarios-bootc/releases/el96-y2@el96-lrel@standard2.sh @@ -9,27 +9,21 @@ export TEST_RANDOMIZATION=none dest_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" scenario_create_vms() { - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${dest_image}" + prepare_kickstart host1 kickstart-bootc.ks.template rhel96-bootc-brew-y2-with-optional launch_vm --boot_blueprint rhel96-bootc } scenario_remove_vms() { - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${dest_image}" + remove_vm host1 } scenario_run_tests() { - if ! does_image_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_image_not_found "${dest_image}" + run_tests host1 \ --variable "TARGET_REF:${dest_image}" \ --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ diff --git a/test/scenarios-bootc/releases/el96-z1@el96-lrel@standard1.sh b/test/scenarios-bootc/releases/el96-z1@el96-lrel@standard1.sh new file mode 100644 index 0000000000..3ed9738f95 --- /dev/null +++ b/test/scenarios-bootc/releases/el96-z1@el96-lrel@standard1.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +# NOTE: Unlike most suites, these tests rely on being run IN ORDER to +# ensure MicroShift is upgraded before running standard suite tests +export TEST_RANDOMIZATION=none + +start_image="rhel96-bootc-brew-z1-with-optional" +dest_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" + +scenario_create_vms() { + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" + launch_vm --boot_blueprint rhel96-bootc +} + +scenario_remove_vms() { + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + + remove_vm host1 +} + +scenario_run_tests() { + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + + run_tests host1 \ + --variable "TARGET_REF:${dest_image}" \ + --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ + --variable "EXPECTED_OS_VERSION:9.6" \ + suites/upgrade/upgrade-successful.robot \ + suites/standard1/ suites/selinux/validate-selinux-policy.robot +} diff --git a/test/scenarios-bootc/releases/el96-z1@el96-lrel@standard2.sh b/test/scenarios-bootc/releases/el96-z1@el96-lrel@standard2.sh new file mode 100644 index 0000000000..7fac3bcd52 --- /dev/null +++ b/test/scenarios-bootc/releases/el96-z1@el96-lrel@standard2.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +# NOTE: Unlike most suites, these tests rely on being run IN ORDER to +# ensure MicroShift is upgraded before running standard suite tests +export TEST_RANDOMIZATION=none + +start_image="rhel96-bootc-brew-z1-with-optional" +dest_image="rhel96-bootc-brew-${LATEST_RELEASE_TYPE}-with-optional" + +scenario_create_vms() { + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + + prepare_kickstart host1 kickstart-bootc.ks.template "${start_image}" + launch_vm --boot_blueprint rhel96-bootc +} + +scenario_remove_vms() { + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + + remove_vm host1 +} + +scenario_run_tests() { + exit_if_image_not_found "${start_image}" + exit_if_image_not_found "${dest_image}" + + run_tests host1 \ + --variable "TARGET_REF:${dest_image}" \ + --variable "BOOTC_REGISTRY:${MIRROR_REGISTRY_URL}" \ + suites/upgrade/upgrade-successful.robot \ + suites/standard2 +} diff --git a/test/scenarios-bootc/upstream/cos10-src@optional.sh b/test/scenarios-bootc/upstream/cos10-src@optional.sh new file mode 100644 index 0000000000..0cdde57214 --- /dev/null +++ b/test/scenarios-bootc/upstream/cos10-src@optional.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +# Redefine network-related settings to use the dedicated network bridge +VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_MULTUS_NETWORK}")" +# shellcheck disable=SC2034 # used elsewhere +WEB_SERVER_URL="http://${VM_BRIDGE_IP}:${WEB_SERVER_PORT}" + +# Skip the scenario if platform is ARM, as the igb driver is not supported. +check_platform() { + if [[ "${UNAME_M}" =~ aarch64 ]] ; then + record_junit "setup" "scenario_create_vms" "SKIPPED" + exit 0 + fi +} + +scenario_create_vms() { + check_platform + prepare_kickstart host1 kickstart-bootc.ks.template cos10-bootc-source-optionals + # Three nics - one for sriov, one for macvlan, another for ipvlan (they cannot enslave the same interface) + launch_vm --boot_blueprint centos10-bootc --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK},sriov" + + # Open the firewall ports. Other scenarios get this behavior by + # embedding settings in the blueprint, but there is no blueprint + # for this scenario. We need do this step before running the RF + # suite so that suite can assume it can reach all of the same + # ports as for any other test. + configure_vm_firewall host1 +} + +scenario_remove_vms() { + check_platform + remove_vm host1 +} + +scenario_run_tests() { + check_platform + run_tests host1 \ + --variable "PROMETHEUS_HOST:$(hostname)" \ + --variable "LOKI_HOST:$(hostname)" \ + --skip sriov \ + suites/optional/ +} diff --git a/test/scenarios-bootc/upstream/cos9-src@optional.sh b/test/scenarios-bootc/upstream/cos9-src@optional.sh index 7e6d9791cd..f5be6ab6db 100644 --- a/test/scenarios-bootc/upstream/cos9-src@optional.sh +++ b/test/scenarios-bootc/upstream/cos9-src@optional.sh @@ -7,10 +7,19 @@ VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_MULTUS_NETWORK}")" # shellcheck disable=SC2034 # used elsewhere WEB_SERVER_URL="http://${VM_BRIDGE_IP}:${WEB_SERVER_PORT}" +# Skip the scenario if platform is ARM, as the igb driver is not supported. +check_platform() { + if [[ "${UNAME_M}" =~ aarch64 ]] ; then + record_junit "setup" "scenario_create_vms" "SKIPPED" + exit 0 + fi +} + scenario_create_vms() { + check_platform prepare_kickstart host1 kickstart-bootc.ks.template cos9-bootc-source-optionals - # Two nics - one for macvlan, another for ipvlan (they cannot enslave the same interface) - launch_vm --boot_blueprint centos9-bootc --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK}" + # Three nics - one for sriov, one for macvlan, another for ipvlan (they cannot enslave the same interface) + launch_vm --boot_blueprint centos9-bootc --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK},sriov" # Open the firewall ports. Other scenarios get this behavior by # embedding settings in the blueprint, but there is no blueprint @@ -21,15 +30,15 @@ scenario_create_vms() { } scenario_remove_vms() { + check_platform remove_vm host1 } scenario_run_tests() { - run_tests host1 \ + check_platform + run_tests host1 \ --variable "PROMETHEUS_HOST:$(hostname)" \ - --variable "PROMETHEUS_PORT:9093" \ --variable "LOKI_HOST:$(hostname)" \ - --variable "LOKI_PORT:3200" \ - --variable "PROM_EXPORTER_PORT:8889" \ + --skip sriov \ suites/optional/ } diff --git a/test/scenarios/periodics/el96-crel@el96-src@optional-upgrade.sh b/test/scenarios/periodics/el96-crel@el96-src@optional-upgrade.sh deleted file mode 100644 index 6b2493ef77..0000000000 --- a/test/scenarios/periodics/el96-crel@el96-src@optional-upgrade.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -start_commit=rhel-9.6-microshift-crel-optionals - -scenario_create_vms() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart.ks.template "${start_commit}" - launch_vm -} - -scenario_remove_vms() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - run_tests host1 \ - --variable "TARGET_REF:rhel-9.6-microshift-source-optionals" \ - suites/upgrade/upgrade-multus.robot -} diff --git a/test/scenarios/periodics/el96-crel@el96-src@upgrade-fails.sh b/test/scenarios/periodics/el96-crel@el96-src@upgrade-fails.sh deleted file mode 100644 index 3c2f5698a7..0000000000 --- a/test/scenarios/periodics/el96-crel@el96-src@upgrade-fails.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -start_commit=rhel-9.6-microshift-crel - -scenario_create_vms() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart.ks.template "${start_commit}" - launch_vm -} - -scenario_remove_vms() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - run_tests host1 \ - --variable "FAILING_REF:rhel-9.6-microshift-source" \ - --variable "REASON:fail_greenboot" \ - suites/upgrade/upgrade-fails-and-rolls-back.robot -} diff --git a/test/scenarios/periodics/el96-crel@optional-sigstore.sh b/test/scenarios/periodics/el96-crel@optional-sigstore.sh deleted file mode 100644 index d7d4bb5a83..0000000000 --- a/test/scenarios/periodics/el96-crel@optional-sigstore.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -# Enable container signature verification for current release images, -# including the optional components. -# These are ec / rc / z-stream, thus must all to be signed. -# shellcheck disable=SC2034 # used elsewhere -IMAGE_SIGSTORE_ENABLED=true - -start_commit=rhel-9.6-microshift-crel-optionals - -scenario_create_vms() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart.ks.template "${start_commit}" - launch_vm -} - -scenario_remove_vms() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - # Run a minimal test for this scenario as its main functionality is - # to verify container image signature check is enabled - run_tests host1 \ - --variable "EXPECTED_OS_VERSION:9.6" \ - --variable "IMAGE_SIGSTORE_ENABLED:True" \ - suites/standard1/containers-policy.robot -} diff --git a/test/scenarios/periodics/el96-prel@el96-crel@upgrade-ok.sh b/test/scenarios/periodics/el96-prel@el96-crel@upgrade-ok.sh deleted file mode 100644 index e6298bb095..0000000000 --- a/test/scenarios/periodics/el96-prel@el96-crel@upgrade-ok.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -target_commit=rhel-9.6-microshift-crel - -scenario_create_vms() { - if ! does_commit_exist "${target_commit}"; then - echo "Commit '${target_commit}' not found in ostree repo - skipping test" - return 0 - fi - - prepare_kickstart host1 kickstart.ks.template "rhel-9.6-microshift-4.${PREVIOUS_MINOR_VERSION}" - launch_vm -} - -scenario_remove_vms() { - if ! does_commit_exist "${target_commit}"; then - echo "Commit '${target_commit}' not found in ostree repo - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_commit_exist "${target_commit}"; then - echo "Commit '${target_commit}' not found in ostree repo - skipping test" - return 0 - fi - run_tests host1 \ - --variable "TARGET_REF:${target_commit}" \ - suites/upgrade/upgrade-successful.robot -} diff --git a/test/scenarios/periodics/el96-prel@el96-src@upgrade-ok.sh b/test/scenarios/periodics/el96-prel@el96-src@upgrade-ok.sh new file mode 100644 index 0000000000..2c6d730b22 --- /dev/null +++ b/test/scenarios/periodics/el96-prel@el96-src@upgrade-ok.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +scenario_create_vms() { + prepare_kickstart host1 kickstart.ks.template "rhel-9.6-microshift-4.${PREVIOUS_MINOR_VERSION}" + launch_vm +} + +scenario_remove_vms() { + remove_vm host1 +} + +scenario_run_tests() { + run_tests host1 \ + --variable "TARGET_REF:rhel-9.6-microshift-source" \ + suites/upgrade/upgrade-successful.robot +} diff --git a/test/scenarios/periodics/el96-src@fips-rpm.sh b/test/scenarios/periodics/el96-src@fips-rpm.sh new file mode 100644 index 0000000000..e92aee948d --- /dev/null +++ b/test/scenarios/periodics/el96-src@fips-rpm.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +check_platform() { + if [[ "${UNAME_M}" =~ aarch64 ]] ; then + record_junit "setup" "scenario_create_vms" "SKIPPED" + exit 0 + fi +} + +scenario_create_vms() { + check_platform + prepare_kickstart host1 kickstart-liveimg.ks.template "" true + launch_vm --boot_blueprint rhel-9.6-microshift-source-isolated --fips +} + +scenario_remove_vms() { + check_platform + remove_vm host1 +} + +scenario_run_tests() { + check_platform + run_tests host1 suites/fips/ +} diff --git a/test/scenarios/periodics/el96-src@fips-rpm.sh.disabled b/test/scenarios/periodics/el96-src@fips-rpm.sh.disabled deleted file mode 100644 index 9d0dcea861..0000000000 --- a/test/scenarios/periodics/el96-src@fips-rpm.sh.disabled +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -scenario_create_vms() { - [[ "${UNAME_M}" =~ aarch64 ]] && { record_junit "setup" "scenario_create_vms" "SKIPPED"; exit 0; } - - prepare_kickstart host1 kickstart-liveimg.ks.template "" true - launch_vm --boot_blueprint rhel-9.6-microshift-source-isolated --fips -} - -scenario_remove_vms() { - [[ "${UNAME_M}" =~ aarch64 ]] && { echo "Only x86_64 architecture is supported with FIPS"; exit 0; } - - remove_vm host1 -} - -scenario_run_tests() { - [[ "${UNAME_M}" =~ aarch64 ]] && { echo "Only x86_64 architecture is supported with FIPS"; exit 0; } - - run_tests host1 suites/fips/ -} diff --git a/test/scenarios/periodics/el96-src@fips.sh.disabled b/test/scenarios/periodics/el96-src@fips.sh similarity index 54% rename from test/scenarios/periodics/el96-src@fips.sh.disabled rename to test/scenarios/periodics/el96-src@fips.sh index 4aed29680c..6546a43332 100644 --- a/test/scenarios/periodics/el96-src@fips.sh.disabled +++ b/test/scenarios/periodics/el96-src@fips.sh @@ -2,21 +2,25 @@ # Sourced from scenario.sh and uses functions defined there. -scenario_create_vms() { - [[ "${UNAME_M}" =~ aarch64 ]] && { record_junit "setup" "scenario_create_vms" "SKIPPED"; exit 0; } +check_platform() { + if [[ "${UNAME_M}" =~ aarch64 ]] ; then + record_junit "setup" "scenario_create_vms" "SKIPPED" + exit 0 + fi +} +scenario_create_vms() { + check_platform prepare_kickstart host1 kickstart.ks.template rhel-9.6-microshift-source-isolated true launch_vm --boot_blueprint rhel-9.6-microshift-source-isolated --fips } scenario_remove_vms() { - [[ "${UNAME_M}" =~ aarch64 ]] && { echo "Only x86_64 architecture is supported with FIPS"; exit 0; } - + check_platform remove_vm host1 } scenario_run_tests() { - [[ "${UNAME_M}" =~ aarch64 ]] && { echo "Only x86_64 architecture is supported with FIPS"; exit 0; } - + check_platform run_tests host1 suites/fips/ } diff --git a/test/scenarios/periodics/el96-src@optional.sh b/test/scenarios/periodics/el96-src@optional.sh index 80f3605a7d..61ef66ff98 100644 --- a/test/scenarios/periodics/el96-src@optional.sh +++ b/test/scenarios/periodics/el96-src@optional.sh @@ -7,10 +7,19 @@ VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_MULTUS_NETWORK}")" # shellcheck disable=SC2034 # used elsewhere WEB_SERVER_URL="http://${VM_BRIDGE_IP}:${WEB_SERVER_PORT}" +# Skip the scenario if platform is ARM, as the igb driver is not supported. +check_platform() { + if [[ "${UNAME_M}" =~ aarch64 ]] ; then + record_junit "setup" "scenario_create_vms" "SKIPPED" + exit 0 + fi +} + scenario_create_vms() { + check_platform prepare_kickstart host1 kickstart.ks.template rhel-9.6-microshift-source-optionals - # Two nics - one for macvlan, another for ipvlan (they cannot enslave the same interface) - launch_vm --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK}" + # Three nics - one for sriov, one for macvlan, another for ipvlan (they cannot enslave the same interface) + launch_vm --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK},sriov" # Open the firewall ports. Other scenarios get this behavior by # embedding settings in the blueprint, but there is no blueprint @@ -21,10 +30,12 @@ scenario_create_vms() { } scenario_remove_vms() { + check_platform remove_vm host1 } scenario_run_tests() { + check_platform # Generic Device Plugin suite is excluded because getting serialsim for ostree would require: # - getting the version of the kernel of ostree image, # - installing kernel-devel of that version on the hypervisor, @@ -34,10 +45,7 @@ scenario_run_tests() { # GDP suite is tested with bootc images instead. run_tests host1 \ --variable "PROMETHEUS_HOST:$(hostname)" \ - --variable "PROMETHEUS_PORT:9092" \ --variable "LOKI_HOST:$(hostname)" \ - --variable "LOKI_PORT:3200" \ - --variable "PROM_EXPORTER_PORT:8889" \ --exclude generic-device-plugin \ suites/optional/ } diff --git a/test/scenarios/periodics/el96-yminus2@el96-src@upgrade-ok.sh b/test/scenarios/periodics/el96-yminus2@el96-src@upgrade-ok.sh new file mode 100644 index 0000000000..588221d818 --- /dev/null +++ b/test/scenarios/periodics/el96-yminus2@el96-src@upgrade-ok.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +scenario_create_vms() { + prepare_kickstart host1 kickstart.ks.template "rhel-9.6-microshift-4.${YMINUS2_MINOR_VERSION}" + launch_vm +} + +scenario_remove_vms() { + remove_vm host1 +} + +scenario_run_tests() { + run_tests host1 \ + --variable "TARGET_REF:rhel-9.6-microshift-source" \ + suites/upgrade/upgrade-successful.robot +} diff --git a/test/scenarios/presubmits/el96-crel@el96-src@upgrade-ok.sh b/test/scenarios/presubmits/el96-crel@el96-src@upgrade-ok.sh deleted file mode 100644 index 6a27ccd2b0..0000000000 --- a/test/scenarios/presubmits/el96-crel@el96-src@upgrade-ok.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash - -# Sourced from scenario.sh and uses functions defined there. - -start_commit=rhel-9.6-microshift-crel - -scenario_create_vms() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - prepare_kickstart host1 kickstart.ks.template "${start_commit}" - launch_vm -} - -scenario_remove_vms() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - remove_vm host1 -} - -scenario_run_tests() { - if ! does_commit_exist "${start_commit}"; then - echo "Commit '${start_commit}' not found in ostree repo - skipping test" - return 0 - fi - run_tests host1 \ - --variable "TARGET_REF:rhel-9.6-microshift-source" \ - suites/upgrade/upgrade-successful.robot -} diff --git a/test/scenarios/presubmits/el96-src@low-latency.sh b/test/scenarios/presubmits/el96-src@low-latency.sh index 0e23cf79ab..ac9e2efbeb 100644 --- a/test/scenarios/presubmits/el96-src@low-latency.sh +++ b/test/scenarios/presubmits/el96-src@low-latency.sh @@ -38,5 +38,6 @@ scenario_run_tests() { --exitonfailure \ suites/tuned/profile.robot \ suites/tuned/microshift-tuned.robot \ - suites/tuned/workload-partitioning.robot + suites/tuned/workload-partitioning.robot \ + suites/tuned/uncore-cache.robot } diff --git a/test/scenarios/presubmits/el96-src@standard-suite1.sh b/test/scenarios/presubmits/el96-src@standard-suite1.sh index c460d45899..60724e71d2 100644 --- a/test/scenarios/presubmits/el96-src@standard-suite1.sh +++ b/test/scenarios/presubmits/el96-src@standard-suite1.sh @@ -12,7 +12,10 @@ scenario_remove_vms() { } scenario_run_tests() { + # The SYNC_FREQUENCY is set to a shorter-than-default value to speed up + # pre-submit scenario completion time in DNS tests. run_tests host1 \ --variable "EXPECTED_OS_VERSION:9.6" \ + --variable "SYNC_FREQUENCY:5s" \ suites/standard1/ suites/selinux/validate-selinux-policy.robot } diff --git a/test/scenarios/releases/el96-lrel@backups.sh b/test/scenarios/releases/el96-lrel@backups.sh index 469a8ecab2..4b77ea8566 100644 --- a/test/scenarios/releases/el96-lrel@backups.sh +++ b/test/scenarios/releases/el96-lrel@backups.sh @@ -5,29 +5,20 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" run_tests host1 suites/backup/backups.robot } diff --git a/test/scenarios/releases/el96-lrel@dual-stack.sh b/test/scenarios/releases/el96-lrel@dual-stack.sh index d211869c03..3aa81ed0dc 100644 --- a/test/scenarios/releases/el96-lrel@dual-stack.sh +++ b/test/scenarios/releases/el96-lrel@dual-stack.sh @@ -5,29 +5,20 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm --network "${VM_DUAL_STACK_NETWORK}" } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" local -r vmname=$(full_vm_name host1) local -r vm_ip1=$("${ROOTDIR}/scripts/devenv-builder/manage-vm.sh" ip -n "${vmname}" | head -1) diff --git a/test/scenarios/releases/el96-lrel@ginkgo-multi-config.sh b/test/scenarios/releases/el96-lrel@ginkgo-multi-config.sh new file mode 100644 index 0000000000..a61e861804 --- /dev/null +++ b/test/scenarios/releases/el96-lrel@ginkgo-multi-config.sh @@ -0,0 +1,112 @@ +#!/bin/bash + +# Sourced from scenario.sh and uses functions defined there. + +# Multi-config scenario: Combines multiple configurations to validate no conflicts +# - Low-latency (tuned) +# - TLSv1.3 +# - LVMS (default) +# - IPv6 (network configuration) + +export TEST_RANDOMIZATION=none +export TEST_EXECUTION_TIMEOUT="40m" + +# Redefine network-related settings to use the dedicated IPv6 network bridge +# shellcheck disable=SC2034 # used elsewhere +VM_BRIDGE_IP="$(get_vm_bridge_ip "${VM_IPV6_NETWORK}")" +# shellcheck disable=SC2034 # used elsewhere +WEB_SERVER_URL="http://[${VM_BRIDGE_IP}]:${WEB_SERVER_PORT}" + +start_image="rhel-9.6-microshift-brew-tuned-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" + +scenario_create_vms() { + if ! does_commit_exist "${start_image}"; then + echo "Image '${start_image}' not found - skipping test" + return 0 + fi + + # Temporarily override MIRROR_REGISTRY_URL for kickstart preparation + # The kickstart template needs a hostname-based URL, not an IPv6 address + local original_mirror_url="${MIRROR_REGISTRY_URL}" + # shellcheck disable=SC2034 # used elsewhere + MIRROR_REGISTRY_URL="$(hostname):${MIRROR_REGISTRY_PORT}" + + # Enable IPv6 single stack in kickstart + prepare_kickstart host1 kickstart.ks.template "${start_image}" false true + + # Restore original MIRROR_REGISTRY_URL for runtime use + # shellcheck disable=SC2034 # used elsewhere + MIRROR_REGISTRY_URL="${original_mirror_url}" + + launch_vm --network "${VM_IPV6_NETWORK}" --vm_vcpus 6 --vm_disksize 30 +} + +scenario_remove_vms() { + if ! does_commit_exist "${start_image}"; then + echo "Image '${start_image}' not found - skipping test" + return 0 + fi + + remove_vm host1 +} + +scenario_run_tests() { + if ! does_commit_exist "${start_image}"; then + echo "Image '${start_image}' not found - skipping test" + return 0 + fi + + # Wait for microshift-tuned to reboot the node + local -r start_time=$(date +%s) + while true; do + boot_num=$(run_command_on_vm host1 "sudo journalctl --list-boots --quiet | wc -l" || true) + boot_num="${boot_num%$'\r'*}" + if [[ "${boot_num}" -ge 2 ]]; then + break + fi + if [ $(( $(date +%s) - start_time )) -gt 60 ]; then + echo "Timed out waiting for VM having 2 boots" + exit 1 + fi + sleep 5 + done + + # Apply TLSv1.3 configuration via drop-in config + echo "INFO: Configuring TLSv1.3..." + run_command_on_vm host1 "sudo mkdir -p /etc/microshift/config.d" + run_command_on_vm host1 "sudo tee /etc/microshift/config.d/10-tls.yaml > /dev/null << 'EOF' +apiServer: + tls: + minVersion: VersionTLS13 +EOF" + + # Restart MicroShift to apply TLS configuration + run_command_on_vm host1 "sudo systemctl restart microshift" + + # Wait for MicroShift to be ready + wait_for_microshift_to_be_ready host1 + + # Setup oc client and kubeconfig for gingko tests + setup_oc_and_kubeconfig host1 + + # Create LVMS workloads + echo "INFO: Creating LVMS workloads to validate storage..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/createWorkloads.sh" + + echo "INFO: Checking LVMS resources..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/checkLvmsResources.sh" + + # Run ginkgo tests to validate all configurations work together + echo "INFO: Running ginkgo validation tests for multi-config scenario..." + run_ginkgo_tests host1 "~Disruptive" + + # Validate LVMS still works after all tests + echo "INFO: Validating LVMS workloads after tests..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/checkWorkloadExists.sh" + + # Cleanup LVMS workloads + echo "INFO: Cleaning up LVMS workloads..." + run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/cleanupWorkload.sh" + + echo "SUCCESS: Multi-config scenario validation completed - no conflicts detected" +} diff --git a/test/scenarios/releases/el96-lrel@ginkgo-tests.sh b/test/scenarios/releases/el96-lrel@ginkgo-tests.sh index cb81117ea0..2b16e36643 100644 --- a/test/scenarios/releases/el96-lrel@ginkgo-tests.sh +++ b/test/scenarios/releases/el96-lrel@ginkgo-tests.sh @@ -5,29 +5,21 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm --vm_disksize 30 } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" - run_gingko_tests host1 "~Disruptive" + wait_for_microshift_to_be_ready host1 + run_ginkgo_tests host1 "~Disruptive" } diff --git a/test/scenarios/releases/el96-lrel@ipv6.sh b/test/scenarios/releases/el96-lrel@ipv6.sh index ba2a5abdac..ce4bb93c0a 100644 --- a/test/scenarios/releases/el96-lrel@ipv6.sh +++ b/test/scenarios/releases/el96-lrel@ipv6.sh @@ -13,30 +13,21 @@ MIRROR_REGISTRY_URL="${VM_BRIDGE_IP}:${MIRROR_REGISTRY_PORT}" start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - # Enable IPv6 single stack in kickstart - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" + # Enable IPv6 single stack in kickstart prepare_kickstart host1 kickstart.ks.template "${start_image}" false true launch_vm --network "${VM_IPV6_NETWORK}" } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" run_tests host1 suites/ipv6/singlestack.robot } diff --git a/test/scenarios/releases/el96-lrel@low-latency.sh b/test/scenarios/releases/el96-lrel@low-latency.sh index e44c2319cc..9e111f2c22 100644 --- a/test/scenarios/releases/el96-lrel@low-latency.sh +++ b/test/scenarios/releases/el96-lrel@low-latency.sh @@ -8,29 +8,21 @@ export TEST_RANDOMIZATION=none start_image="rhel-9.6-microshift-brew-tuned-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm --vm_vcpus 6 } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" + # Should not be run immediately after creating VM because of # microshift-tuned rebooting the node to activate the profile. local -r start_time=$(date +%s) @@ -54,5 +46,6 @@ scenario_run_tests() { --exitonfailure \ suites/tuned/profile.robot \ suites/tuned/microshift-tuned.robot \ - suites/tuned/workload-partitioning.robot + suites/tuned/workload-partitioning.robot \ + suites/tuned/uncore-cache.robot } diff --git a/test/scenarios/releases/el96-lrel@multi-nic.sh b/test/scenarios/releases/el96-lrel@multi-nic.sh index eab6f04326..d60bf01e2d 100644 --- a/test/scenarios/releases/el96-lrel@multi-nic.sh +++ b/test/scenarios/releases/el96-lrel@multi-nic.sh @@ -5,10 +5,7 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" # Using multus as secondary network to have 2 nics in different networks. @@ -16,19 +13,13 @@ scenario_create_vms() { } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" local -r vmname=$(full_vm_name host1) local -r vm_ip1=$("${ROOTDIR}/scripts/devenv-builder/manage-vm.sh" ip -n "${vmname}" | head -1) diff --git a/test/scenarios/releases/el96-lrel@optional.sh b/test/scenarios/releases/el96-lrel@optional.sh index 8445f674b3..96d0ed3266 100644 --- a/test/scenarios/releases/el96-lrel@optional.sh +++ b/test/scenarios/releases/el96-lrel@optional.sh @@ -9,31 +9,33 @@ WEB_SERVER_URL="http://${VM_BRIDGE_IP}:${WEB_SERVER_PORT}" start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" -scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 +# Skip the scenario if platform is ARM, as the igb driver is not supported. +check_platform() { + if [[ "${UNAME_M}" =~ aarch64 ]] ; then + record_junit "setup" "scenario_create_vms" "SKIPPED" + exit 0 fi +} + +scenario_create_vms() { + check_platform + exit_if_commit_not_found "${start_image}" + # Three nics - one for sriov, one for macvlan, another for ipvlan (they cannot enslave the same interface) prepare_kickstart host1 kickstart.ks.template "${start_image}" - # Two nics - one for macvlan, another for ipvlan (they cannot enslave the same interface) - launch_vm --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK}" + launch_vm --network "${VM_MULTUS_NETWORK},${VM_MULTUS_NETWORK},sriov" } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + check_platform + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + check_platform + exit_if_commit_not_found "${start_image}" # Generic Device Plugin suite is excluded because getting serialsim for ostree would require: # - getting the version of the kernel of ostree image, @@ -43,11 +45,8 @@ scenario_run_tests() { # - including the RPM in the ostree blueprint # GDP suite is tested with bootc images instead. run_tests host1 \ - --variable "PROMETHEUS_HOST:$(hostname)" \ - --variable "PROMETHEUS_PORT:9092" \ - --variable "LOKI_HOST:$(hostname)" \ - --variable "LOKI_PORT:3200" \ - --variable "PROM_EXPORTER_PORT:8889" \ - --exclude generic-device-plugin \ - suites/optional/ + --variable "PROMETHEUS_HOST:$(hostname)" \ + --variable "LOKI_HOST:$(hostname)" \ + --exclude generic-device-plugin \ + suites/optional/ } diff --git a/test/scenarios/releases/el96-lrel@osconfig.sh b/test/scenarios/releases/el96-lrel@osconfig.sh index 0bffbac7a5..5588ecb226 100644 --- a/test/scenarios/releases/el96-lrel@osconfig.sh +++ b/test/scenarios/releases/el96-lrel@osconfig.sh @@ -5,29 +5,20 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" run_tests host1 \ suites/osconfig/clusterid.robot \ diff --git a/test/scenarios/releases/el96-lrel@router.sh b/test/scenarios/releases/el96-lrel@router.sh index c0804584b7..5a4d1d8a1f 100644 --- a/test/scenarios/releases/el96-lrel@router.sh +++ b/test/scenarios/releases/el96-lrel@router.sh @@ -5,29 +5,20 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" run_tests host1 \ suites/router diff --git a/test/scenarios/releases/el96-lrel@standard1.sh b/test/scenarios/releases/el96-lrel@standard1.sh index 03ddb91ce7..4b33ddee11 100644 --- a/test/scenarios/releases/el96-lrel@standard1.sh +++ b/test/scenarios/releases/el96-lrel@standard1.sh @@ -5,29 +5,20 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" run_tests host1 \ --variable "EXPECTED_OS_VERSION:9.6" \ diff --git a/test/scenarios/releases/el96-lrel@standard2.sh b/test/scenarios/releases/el96-lrel@standard2.sh index 154cdffe5c..fe60c9679e 100644 --- a/test/scenarios/releases/el96-lrel@standard2.sh +++ b/test/scenarios/releases/el96-lrel@standard2.sh @@ -5,29 +5,20 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" run_tests host1 suites/standard2/ } diff --git a/test/scenarios/releases/el96-lrel@storage.sh b/test/scenarios/releases/el96-lrel@storage.sh index 4ec333499d..9a4aec2977 100644 --- a/test/scenarios/releases/el96-lrel@storage.sh +++ b/test/scenarios/releases/el96-lrel@storage.sh @@ -5,29 +5,20 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" run_tests host1 suites/storage/ } diff --git a/test/scenarios/releases/el96-lrel@tlsv13-standard1.sh b/test/scenarios/releases/el96-lrel@tlsv13-standard1.sh index a920211c92..da3e73bb95 100644 --- a/test/scenarios/releases/el96-lrel@tlsv13-standard1.sh +++ b/test/scenarios/releases/el96-lrel@tlsv13-standard1.sh @@ -2,32 +2,23 @@ # Sourced from scenario.sh and uses functions defined there. -start_image="rhel-9.6-microshift-brew-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" +start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" # Apply TLS v1.3 configuration via drop-in config run_command_on_vm host1 "sudo mkdir -p /etc/microshift/config.d" diff --git a/test/scenarios/releases/el96-lrel@tlsv13-standard2.sh b/test/scenarios/releases/el96-lrel@tlsv13-standard2.sh index 7d02613c4a..0b1e648be8 100644 --- a/test/scenarios/releases/el96-lrel@tlsv13-standard2.sh +++ b/test/scenarios/releases/el96-lrel@tlsv13-standard2.sh @@ -2,32 +2,23 @@ # Sourced from scenario.sh and uses functions defined there. -start_image="rhel-9.6-microshift-brew-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" +start_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" # Apply TLS v1.3 configuration via drop-in config run_command_on_vm host1 "sudo mkdir -p /etc/microshift/config.d" diff --git a/test/scenarios/releases/el96-yminus1@el96-lrel@lvms.sh b/test/scenarios/releases/el96-yminus1@el96-lrel@lvms.sh index 3e73200a96..25caf78eb5 100644 --- a/test/scenarios/releases/el96-yminus1@el96-lrel@lvms.sh +++ b/test/scenarios/releases/el96-yminus1@el96-lrel@lvms.sh @@ -7,44 +7,32 @@ export TEST_RANDOMIZATION=none start_image="rhel-9.6-microshift-brew-optionals-4.${PREVIOUS_MINOR_VERSION}-zstream" -dest_image="rhel-9.6-microshift-brew-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" +dest_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" + exit_if_commit_not_found "${dest_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" + exit_if_commit_not_found "${dest_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" + exit_if_commit_not_found "${dest_image}" + + # Wait for MicroShift to be ready + wait_for_microshift_to_be_ready host1 + + # Setup oc client and kubeconfig for ginkgo tests + setup_oc_and_kubeconfig host1 # Pre-upgrade: Create LVMS workloads and validate LVMS is working echo "INFO: Creating LVMS workloads before upgrade..." diff --git a/test/scenarios/releases/el96-yminus1@el96-lrel@standard1.sh b/test/scenarios/releases/el96-yminus1@el96-lrel@standard1.sh index 6228054991..b83968e146 100644 --- a/test/scenarios/releases/el96-yminus1@el96-lrel@standard1.sh +++ b/test/scenarios/releases/el96-yminus1@el96-lrel@standard1.sh @@ -9,29 +9,20 @@ export TEST_RANDOMIZATION=none start_image="rhel-9.6-microshift-brew-optionals-4.${PREVIOUS_MINOR_VERSION}-zstream" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" run_tests host1 \ --variable "TARGET_REF:rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" \ diff --git a/test/scenarios/releases/el96-yminus1@el96-lrel@standard2.sh b/test/scenarios/releases/el96-yminus1@el96-lrel@standard2.sh index d259cd43fc..2389e00362 100644 --- a/test/scenarios/releases/el96-yminus1@el96-lrel@standard2.sh +++ b/test/scenarios/releases/el96-yminus1@el96-lrel@standard2.sh @@ -9,29 +9,20 @@ export TEST_RANDOMIZATION=none start_image="rhel-9.6-microshift-brew-optionals-4.${PREVIOUS_MINOR_VERSION}-zstream" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" run_tests host1 \ --variable "TARGET_REF:rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" \ diff --git a/test/scenarios/releases/el96-yminus2@el96-lrel@lvms.sh b/test/scenarios/releases/el96-yminus2@el96-lrel@lvms.sh index ff9f06c4d5..5ab0fd731c 100644 --- a/test/scenarios/releases/el96-yminus2@el96-lrel@lvms.sh +++ b/test/scenarios/releases/el96-yminus2@el96-lrel@lvms.sh @@ -10,41 +10,29 @@ start_image="rhel-9.6-microshift-brew-optionals-4.${YMINUS2_MINOR_VERSION}-zstre dest_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" + exit_if_commit_not_found "${dest_image}" prepare_kickstart host1 kickstart.ks.template "${start_image}" launch_vm --vm_disksize 30 } scenario_remove_vms() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" + exit_if_commit_not_found "${dest_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${start_image}"; then - echo "Image '${start_image}' not found - skipping test" - return 0 - fi - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${start_image}" + exit_if_commit_not_found "${dest_image}" + + # Wait for MicroShift to be ready + wait_for_microshift_to_be_ready host1 + + # Setup oc client and kubeconfig for ginkgo tests + setup_oc_and_kubeconfig host1 # Pre-upgrade: Create LVMS workloads and validate LVMS is working echo "INFO: Creating LVMS workloads before upgrade..." @@ -67,7 +55,7 @@ scenario_run_tests() { run_command_on_vm host1 'bash -s' < "${TESTDIR}/../scripts/lvms-helpers/checkLvmsResources.sh" # Run ginkgo tests to validate functionality - run_gingko_tests host1 "~Disruptive" + run_ginkgo_tests host1 "~Disruptive" # Cleanup LVMS workloads echo "INFO: Cleaning up LVMS workloads..." diff --git a/test/scenarios/releases/el96-yminus2@el96-lrel@standard1.sh b/test/scenarios/releases/el96-yminus2@el96-lrel@standard1.sh index 8984fde273..48b1dcf50e 100644 --- a/test/scenarios/releases/el96-yminus2@el96-lrel@standard1.sh +++ b/test/scenarios/releases/el96-yminus2@el96-lrel@standard1.sh @@ -9,29 +9,20 @@ export TEST_RANDOMIZATION=none dest_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${dest_image}" prepare_kickstart host1 kickstart.ks.template "rhel-9.6-microshift-brew-optionals-4.${YMINUS2_MINOR_VERSION}-zstream" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${dest_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${dest_image}" run_tests host1 \ --variable "TARGET_REF:${dest_image}" \ diff --git a/test/scenarios/releases/el96-yminus2@el96-lrel@standard2.sh b/test/scenarios/releases/el96-yminus2@el96-lrel@standard2.sh index e6ae2f03e7..fc46b46815 100644 --- a/test/scenarios/releases/el96-yminus2@el96-lrel@standard2.sh +++ b/test/scenarios/releases/el96-yminus2@el96-lrel@standard2.sh @@ -9,32 +9,23 @@ export TEST_RANDOMIZATION=none dest_image="rhel-9.6-microshift-brew-optionals-4.${MINOR_VERSION}-${LATEST_RELEASE_TYPE}" scenario_create_vms() { - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${dest_image}" prepare_kickstart host1 kickstart.ks.template "rhel-9.6-microshift-brew-optionals-4.${YMINUS2_MINOR_VERSION}-zstream" launch_vm } scenario_remove_vms() { - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${dest_image}" remove_vm host1 } scenario_run_tests() { - if ! does_commit_exist "${dest_image}"; then - echo "Image '${dest_image}' not found - skipping test" - return 0 - fi + exit_if_commit_not_found "${dest_image}" run_tests host1 \ - --variable "TARGET_REF:${dest_image}" \ - suites/upgrade/upgrade-successful.robot \ - suites/standard2/ + --variable "TARGET_REF:${dest_image}" \ + suites/upgrade/upgrade-successful.robot \ + suites/standard2/ } diff --git a/test/suites/ipv6/dualstack.robot b/test/suites/ipv6/dualstack.robot index 18ff896310..cae96566be 100644 --- a/test/suites/ipv6/dualstack.robot +++ b/test/suites/ipv6/dualstack.robot @@ -88,13 +88,9 @@ Verify Host Network Pods Get Dual Stack IP Addresses [Setup] Run Keywords ... Migrate To Dual Stack - ${pod_ips}= Oc Get JsonPath - ... pod - ... openshift-dns - ... -l dns.operator.openshift.io/daemonset-node-resolver - ... .items[*].status.podIPs[*].ip - Should Contain ${pod_ips} ${USHIFT_HOST_IP1} - Should Contain ${pod_ips} ${USHIFT_HOST_IP2} + # Wait a bit, as this is updated by kubelet and may not be immediate. + Wait Until Keyword Succeeds 10x 6s + ... Host Network Pods Should Have Dual Stack IPs [Teardown] Run Keywords ... Remove Dual Stack Config Drop In @@ -170,3 +166,13 @@ Restart Router ... downtime and might need a restart (after the apiserver is ready) to resync all the routes. Run With Kubeconfig oc rollout restart deployment router-default -n openshift-ingress Named Deployment Should Be Available router-default openshift-ingress 5m + +Host Network Pods Should Have Dual Stack IPs + [Documentation] Check a system hostNetwork enabled pod for dual stack IP addresses + ${pod_ips}= Oc Get JsonPath + ... pod + ... openshift-dns + ... -l dns.operator.openshift.io/daemonset-node-resolver + ... .items[*].status.podIPs[*].ip + Should Contain ${pod_ips} ${USHIFT_HOST_IP1} + Should Contain ${pod_ips} ${USHIFT_HOST_IP2} diff --git a/test/suites/optional/cert-manager.robot b/test/suites/optional/cert-manager.robot index ca40e19ed3..9cf81efbc4 100644 --- a/test/suites/optional/cert-manager.robot +++ b/test/suites/optional/cert-manager.robot @@ -5,10 +5,15 @@ Library Collections Library OperatingSystem Library Process Library String +Library ../../resources/journalctl.py Resource ../../resources/common.resource +Resource ../../resources/hosts.resource Resource ../../resources/kubeconfig.resource Resource ../../resources/oc.resource +Resource ../../resources/microshift-config.resource Resource ../../resources/microshift-network.resource +Resource ../../resources/microshift-process.resource +Resource ../../resources/ostree-health.resource Suite Setup Setup Suite With Namespace Suite Teardown Teardown Suite With Namespace @@ -36,12 +41,18 @@ ${HTTP01_ISSUER_NAME} letsencrypt-http01 ${HTTP01_CERT_NAME} cert-from-${HTTP01_ISSUER_NAME} ${HTTP01_SECRET_NAME} ${HTTP01_CERT_NAME} ${PEBBLE_DEPLOYMENT_FILE} ./assets/cert-manager/pebble-server.yaml +${HOSTSFILE_ENABLED} SEPARATOR=\n +... --- +... dns: +... \ \ hosts: +... \ \ \ \ status: Enabled *** Test Cases *** Create Ingress route with Custom certificate [Documentation] Create route with a custom certificate [Setup] Run Keywords + Verify Cert Manager Kustomization Success ${cert_issuer_yaml}= Create Cert Issuer YAML Apply YAML Manifest ${cert_issuer_yaml} Oc Wait -n ${NAMESPACE} clusterissuer ${ISSUER_NAME} --for="condition=Ready" --timeout=120s @@ -53,7 +64,7 @@ Create Ingress route with Custom certificate Deploy Hello MicroShift ${route_yaml}= Create Ingress Route YAML Apply YAML Manifest ${route_yaml} - Oc Wait -n ${NAMESPACE} route ${ROUTE_NAME} --for=jsonpath='.status.ingress' --timeout=60s + Oc Wait -n ${NAMESPACE} route ${ROUTE_NAME} --for=jsonpath='.status.ingress' --timeout=120s [Teardown] Run Keywords ... Remove ClusterIssuer @@ -63,7 +74,7 @@ Test Cert manager with local acme server [Setup] Setup Pebble Server ${NAMESPACE} ${dns_name}= Generate Random HostName - Configure DNS For Domain ${USHIFT_HOST} ${dns_name} + Setup DNS For Test ${USHIFT_HOST} ${dns_name} Oc Get JsonPath ingressclass ${EMPTY} openshift-ingress .metadata.name ${http01_issuer_yaml}= Create HTTP01 Issuer YAML Apply YAML Manifest ${http01_issuer_yaml} @@ -77,7 +88,7 @@ Test Cert manager with local acme server [Teardown] Run Keywords ... Cleanup HTTP01 Resources - ... AND Remove DNS Configuration + ... AND Cleanup DNS For Test ${dns_name} *** Keywords *** @@ -364,3 +375,53 @@ Remove DNS Configuration Oc Wait ... -n openshift-dns pod -l dns.operator.openshift.io/daemonset-dns=default ... --for=condition=Ready --timeout=60s + +Verify Cert Manager Kustomization Success + [Documentation] Verify that cert-manager kustomization was successfully applied by checking journalctl logs + ${cursor}= Get Journal Cursor + Restart MicroShift + Pattern Should Appear In Log Output + ... ${cursor} + ... Applying kustomization at /usr/lib/microshift/manifests.d/060-microshift-cert-manager was successful + ... unit=microshift + ... retries=30 + ... wait=10 + +Resolve Host From Pod + [Documentation] Resolve host from pod + [Arguments] ${hostname} + Wait Until Keyword Succeeds 40x 2s + ... Router Should Resolve Hostname ${hostname} + +Router Should Resolve Hostname + [Documentation] Check if the router pod resolves the given hostname + [Arguments] ${hostname} + ${fuse_device}= Oc Exec router-default nslookup ${hostname} openshift-ingress deployment + Should Contain ${fuse_device} Name: ${hostname} + +Setup DNS For Test + [Documentation] Setup DNS using CoreDNS hosts feature if available, otherwise use legacy method + [Arguments] ${ip_address} ${dns_name} + ${config}= Show Config default + TRY + VAR ${hosts}= ${config}[dns][hosts] + Add Entry To Hosts ${ip_address} ${dns_name} /etc/hosts + Drop In MicroShift Config ${HOSTSFILE_ENABLED} 20-dns + Restart MicroShift + Restart Greenboot And Wait For Success + EXCEPT + Configure DNS For Domain ${ip_address} ${dns_name} + END + +Cleanup DNS For Test + [Documentation] Cleanup DNS configuration based on method used + [Arguments] ${dns_name} + ${config}= Show Config default + TRY + VAR ${hosts}= ${config}[dns][hosts] + Remove Entry From Hosts ${dns_name} + Remove Drop In MicroShift Config 20-dns + Restart MicroShift + EXCEPT + Remove DNS Configuration + END diff --git a/test/suites/optional/gateway-api.robot b/test/suites/optional/gateway-api.robot index 58d2d06540..4e9c4f551d 100644 --- a/test/suites/optional/gateway-api.robot +++ b/test/suites/optional/gateway-api.robot @@ -23,7 +23,8 @@ Test Simple HTTP Route ... Deploy Hello MicroShift Create Gateway ${GATEWAY_HOSTNAME} ${GATEWAY_PORT} ${NS_GATEWAY} Create HTTP Route ${GATEWAY_HOSTNAME} ${NS_GATEWAY} - Access Hello MicroShift Success ushift_port=${GATEWAY_PORT} hostname=${GATEWAY_HOSTNAME} + Wait Until Keyword Succeeds 10x 6s + ... Access Hello MicroShift Success ushift_port=${GATEWAY_PORT} hostname=${GATEWAY_HOSTNAME} [Teardown] Run Keywords ... Delete Namespace diff --git a/test/suites/optional/observability.robot b/test/suites/optional/observability.robot index 44a7346bc7..b552be84e4 100644 --- a/test/suites/optional/observability.robot +++ b/test/suites/optional/observability.robot @@ -11,6 +11,7 @@ Resource ../../resources/kubeconfig.resource Resource ../../resources/common.resource Resource ../../resources/systemd.resource Resource ../../resources/observability.resource +Resource ../../resources/microshift-network.resource Suite Setup Setup Suite And Prepare Test Host Suite Teardown Teardown Suite And Revert Test Host @@ -27,7 +28,7 @@ ${TEST_CONFIG_PATH} assets/observability/otel_config.yaml Host Metrics Are Exported [Documentation] The opentelemetry-collector should be able to export host metrics. - VAR ${METRIC} system_cpu_time_seconds_total{cpu="cpu0",state="idle"} scope=TEST + VAR ${METRIC} system_cpu_time_seconds_total scope=TEST Check Prometheus Query ${PROMETHEUS_HOST} ${PROMETHEUS_PORT} ${METRIC} Check Prometheus Exporter ${USHIFT_HOST} ${PROM_EXPORTER_PORT} ${METRIC} @@ -45,12 +46,12 @@ Kube Metrics Are Exported Journald Logs Are Exported [Documentation] The opentelemetry-collector should be able to export journald logs. - Check Loki Query ${LOKI_HOST} ${LOKI_PORT} {job="journald",exporter="OTLP"} + Check Loki Query ${LOKI_HOST} ${LOKI_PORT} {service_name="journald"} Kube Events Logs Are Exported [Documentation] The opentelemetry-collector should be able to export Kubernetes events. - Check Loki Query ${LOKI_HOST} ${LOKI_PORT} {job="kube_events",exporter="OTLP"} + Check Loki Query ${LOKI_HOST} ${LOKI_PORT} {service_name="kube_events"} Logs Should Not Contain Receiver Errors [Documentation] Internal receiver errors are not treated as fatal. Typically these are due to a misconfiguration @@ -65,11 +66,12 @@ Logs Should Not Contain Receiver Errors Setup Suite And Prepare Test Host [Documentation] The service starts after MicroShift starts and thus will start generating pertinent log data ... right away. When the suite is executed, immediately get the cursor for the microshift-observability unit. - Start Prometheus Server ${PROMETHEUS_PORT} - Start Loki Server ${LOKI_PORT} - Setup Suite + Setup Suite With Namespace Check Required Observability Variables Set Test OTEL Configuration + # We need to do something to the cluster to generate new kube events. + Create Hello MicroShift Pod + Expose Hello MicroShift ${cur} Get Journal Cursor unit=microshift-observability VAR ${JOURNAL_CUR} ${cur} scope=SUITE @@ -79,10 +81,8 @@ Check Required Observability Variables ${string_value} Convert To String ${PROMETHEUS_PORT} Should Not Be Empty ${string_value} PROMETHEUS_PORT variable is required Should Not Be Empty ${LOKI_HOST} LOKI_HOST variable is required - ${string_value} Convert To String ${LOKI_PORT} - Should Not Be Empty ${string_value} LOKI_PORT variable is required - ${string_value} Convert To String ${PROM_EXPORTER_PORT} - Should Not Be Empty ${string_value} PROM_EXPORTER_PORT variable is required + ${string_value} Convert To String ${LOKI_HOST} + Should Not Be Empty ${string_value} LOKI_HOST variable is required Set Test OTEL Configuration [Documentation] Set Test OTEL Configuration @@ -97,9 +97,7 @@ Set Test OTEL Configuration Teardown Suite And Revert Test Host [Documentation] Set back original OTEL config and teardown Suite Set Back Original OTEL Configuration - Teardown Suite - Stop Loki Server ${LOKI_PORT} - Stop Prometheus Server ${PROMETHEUS_PORT} + Teardown Suite With Namespace Set Back Original OTEL Configuration [Documentation] Set Back Original OTEL Configuration diff --git a/test/suites/optional/sriov.robot b/test/suites/optional/sriov.robot new file mode 100644 index 0000000000..ec203ed8f2 --- /dev/null +++ b/test/suites/optional/sriov.robot @@ -0,0 +1,72 @@ +*** Settings *** +Documentation MicroShift SR-IOV tests + +Resource ../../resources/microshift-process.resource + +Suite Setup Setup Suite +Suite Teardown Teardown Suite + +Test Tags optional sriov slow + + +*** Variables *** +${TEMPLATE_PATH} ${CURDIR}/../../assets/sriov/sriov-network-policy-template.yaml + + +*** Test Cases *** +Create VFs And Verify + [Documentation] Deploys sriovnetworknodepolicy and verifies the VF configuration + + VAR ${cmd_pci_address}= + ... oc get sriovnetworknodestate -n sriov-network-operator -o json | jq -r '.items[].status.interfaces[0].pciAddress' + ${pci_address}= Run With Kubeconfig ${cmd_pci_address} + + VAR ${cmd_device_id}= + ... oc get sriovnetworknodestate -n sriov-network-operator -o json | jq -r '.items[].status.interfaces[0].deviceID' + ${device_id}= Run With Kubeconfig ${cmd_device_id} + + ${template_content}= OperatingSystem.Get File ${TEMPLATE_PATH} + ${partial_yaml}= Replace String ${template_content} PLACEHOLDER_PCI_ADDRESS ${pci_address} + ${final_yaml}= Replace String ${partial_yaml} PLACEHOLDER_DEVICE_ID ${device_id} + + Create File ${OUTPUT DIR}/final-sriov-policy.yaml ${final_yaml} + Oc Apply -f ${OUTPUT_DIR}/final-sriov-policy.yaml -n sriov-network-operator + + Wait Until Resource Exists sriovnetworknodepolicy policy-1 sriov-network-operator + + ${stdout}= Execute Command sudo ls -l /run/cni/bin + Should Contain ${stdout} sriov + + Wait Until Keyword Succeeds 5min 5s + ... Verify VF Count 2 + + Wait Until Keyword Succeeds 5min 5s + ... Device Plugin Should Be Running + + [Teardown] Cleanup SR-IOV Policy + + +*** Keywords *** +Cleanup SR-IOV Policy + [Documentation] Deletes the policy + Run With Kubeconfig oc delete -f ${OUTPUT_DIR}/final-sriov-policy.yaml -n sriov-network-operator + +Verify VF Count + [Documentation] Checks if the number of VFs matches the expected count + [Arguments] ${expected_vfs} + + ${matching_vfs}= Run With Kubeconfig + ... oc get sriovnetworknodestate -n sriov-network-operator -o json | jq -r '.items[].status.interfaces[].Vfs | length' + Should Be Equal As Integers ${matching_vfs} ${expected_vfs} + + ${allocatable}= Run With Kubeconfig + ... oc get node -o=jsonpath='{ .items[].status.allocatable.openshift\\.io/intelnics }' + Log Allocatable openshift.io/intelnics: ${allocatable} + Should Be Equal As Integers ${expected_vfs} ${allocatable} + +Device Plugin Should Be Running + [Documentation] Checks if the device plugin is running + + ${device_plugin}= Run With Kubeconfig + ... oc get daemonset -n sriov-network-operator sriov-device-plugin -o jsonpath='{ .status.numberReady }' + Should Be Equal As Integers ${device_plugin} 1 diff --git a/test/suites/standard1/dns.robot b/test/suites/standard1/dns.robot new file mode 100644 index 0000000000..992a1fb6c5 --- /dev/null +++ b/test/suites/standard1/dns.robot @@ -0,0 +1,162 @@ +*** Settings *** +Documentation Core DNS smoke tests + +Resource ../../resources/common.resource +Resource ../../resources/oc.resource +Resource ../../resources/microshift-network.resource +Resource ../../resources/microshift-config.resource +Resource ../../resources/microshift-process.resource +Resource ../../resources/hosts.resource + +Suite Setup Run Keywords +... Setup Suite With Namespace +... AND Check CoreDNS Hosts Feature +Suite Teardown Teardown Suite With Namespace + +Test Tags slow + + +*** Variables *** +${FAKE_LISTEN_IP} 99.99.99.99 +${CUSTOM_HOSTS_FILE} /tmp/hosts23 +${PODS_HOSTS_FILE} /tmp/hosts/hosts +${HOSTNAME} ${EMPTY} +${SYNC_FREQUENCY} ${EMPTY} +${HOSTSFILE_ENABLED} SEPARATOR=\n +... --- +... dns: +... \ \ hosts: +... \ \ \ status: Enabled +${HOSTSFILE_DISABLED} SEPARATOR=\n +... --- +... dns: +... \ \ hosts: +... \ \ \ status: Disabled + + +*** Test Cases *** +Resolve Host from Default Hosts File + [Documentation] Resolve host from default hosts file + [Setup] Setup With Custom Config ${HOSTSFILE_ENABLED} /etc/hosts + Resolve Host From Pod ${HOSTNAME} + [Teardown] Teardown Hosts File ${HOSTNAME} + +Resolve Host from Non-Default Hosts File + [Documentation] Resolve host from default hosts file + [Setup] Setup With Custom Hosts File + Resolve Host From Pod ${HOSTNAME} + [Teardown] Teardown Hosts File ${HOSTNAME} + +Dynamic Hosts File Update Without Restart + [Documentation] Verify hosts file changes are reflected without MicroShift or pod restarts + [Setup] Setup With Custom Hosts File + Resolve Host From Pod ${HOSTNAME} + ${updated_hostname}= Generate Random HostName + Add Entry To Hosts ${FAKE_LISTEN_IP} ${updated_hostname} ${CUSTOM_HOSTS_FILE} + Resolve Host From Pod ${updated_hostname} + [Teardown] Run Keywords + ... Remove Entry From Hosts ${updated_hostname} ${CUSTOM_HOSTS_FILE} + ... AND Teardown Hosts File ${HOSTNAME} + +Disable CoreDNS Hosts And Verify ConfigMap Removed + [Documentation] Enable CoreDNS hosts, then disable it and verify hosts-file configmap is removed + [Tags] robot:exclude + [Setup] Setup With Custom Config ${HOSTSFILE_ENABLED} /etc/hosts + Disable CoreDNS Hosts + Run Keyword And Expect Error 1 != 0 + ... Oc Get configmap openshift-dns hosts-file + [Teardown] Teardown Hosts File ${HOSTNAME} + + +*** Keywords *** +Get Hosts Config Custom + [Documentation] Build hosts config with optional syncFrequency + ... syncFrequency is configurable in order to speed up the ConfigMap synchronization time + ... for the pods that mount it. + IF "${SYNC_FREQUENCY}" != "${EMPTY}" + ${config}= Catenate SEPARATOR=\n + ... --- + ... kubelet: + ... \ \ syncFrequency: ${SYNC_FREQUENCY} + ... dns: + ... \ \ hosts: + ... \ \ \ status: Enabled + ... \ \ \ file: ${CUSTOM_HOSTS_FILE} + ELSE + ${config}= Catenate SEPARATOR=\n + ... --- + ... dns: + ... \ \ hosts: + ... \ \ \ status: Enabled + ... \ \ \ file: ${CUSTOM_HOSTS_FILE} + END + RETURN ${config} + +Resolve Host From Pod + [Documentation] Resolve host from pod + [Arguments] ${hostname} + Wait Until Keyword Succeeds 40x 5s + ... Router Should Resolve Hostname ${hostname} + +Router Should Resolve Hostname + [Documentation] Check if the router pod resolves the given hostname + [Arguments] ${hostname} + ${fuse_device}= Oc Exec router-default nslookup ${hostname} openshift-ingress deployment + Should Contain ${fuse_device} Name: ${hostname} + +Setup With Custom Config + [Documentation] Install a custom config and restart MicroShift + [Arguments] ${config_content} ${hostsFile} + ${HOSTNAME}= Generate Random HostName + VAR ${HOSTNAME}= ${HOSTNAME} scope=SUITE + Add Fake IP To NIC ${FAKE_LISTEN_IP} + Add Entry To Hosts ${FAKE_LISTEN_IP} ${HOSTNAME} ${hostsFile} + Drop In MicroShift Config ${config_content} 20-dns + Restart MicroShift + +Setup With Custom Hosts File + [Documentation] Get custom hosts config and setup with it + ${config}= Get Hosts Config Custom + Setup With Custom Config ${config} ${CUSTOM_HOSTS_FILE} + +Teardown Hosts File + [Documentation] Teardown the hosts file + [Arguments] ${hostname} + Run Keywords + ... Remove Entry From Hosts ${hostname} + ... AND + ... Remove Fake IP From NIC ${FAKE_LISTEN_IP} + ... AND + ... Remove Drop In MicroShift Config 20-dns + +Add Fake IP To NIC + [Documentation] Add the given IP to the given NIC temporarily. + [Arguments] ${ip_address}=${FAKE_LISTEN_IP} ${nic_name}=br-ex + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command + ... ip address add ${ip_address}/32 dev ${nic_name} + ... sudo=True return_rc=True return_stderr=True return_stdout=True + Log Many ${stdout} ${stderr} + Should Be Equal As Integers 0 ${rc} + +Remove Fake IP From NIC + [Documentation] Remove the given IP from the given NIC. + [Arguments] ${ip_address}=${FAKE_LISTEN_IP} ${nic_name}=br-ex + ${stdout} ${stderr} ${rc}= SSHLibrary.Execute Command + ... ip address delete ${ip_address}/32 dev ${nic_name} + ... sudo=True return_rc=True return_stderr=True return_stdout=True + Log Many ${stdout} ${stderr} + Should Be Equal As Integers 0 ${rc} + +Check CoreDNS Hosts Feature + [Documentation] Skip suite if CoreDNS hosts feature is not available + ${config}= Show Config default + TRY + VAR ${hosts}= ${config}[dns][hosts] + EXCEPT + Skip CoreDNS hosts feature not available in this MicroShift version + END + +Disable CoreDNS Hosts + [Documentation] Disable CoreDNS hosts feature + Drop In MicroShift Config ${HOSTSFILE_DISABLED} 20-dns + Restart MicroShift diff --git a/test/suites/standard1/tls-configuration.robot b/test/suites/standard1/tls-configuration.robot index 64315be2e3..9c72a121c8 100644 --- a/test/suites/standard1/tls-configuration.robot +++ b/test/suites/standard1/tls-configuration.robot @@ -113,7 +113,6 @@ Setup Teardown [Documentation] Test suite teardown - Restart MicroShift Logout MicroShift Host Remove Kubeconfig diff --git a/test/suites/standard1/version.robot b/test/suites/standard1/version.robot index c7c7d111ae..cf4e2d0908 100644 --- a/test/suites/standard1/version.robot +++ b/test/suites/standard1/version.robot @@ -11,6 +11,8 @@ Library ../../resources/DataFormats.py Suite Setup Setup Suite Teardown Teardown +Test Tags version + *** Variables *** ${USHIFT_HOST} ${EMPTY} diff --git a/test/suites/standard2/configuration.robot b/test/suites/standard2/configuration.robot index 1a2d1f9698..5d497daa10 100644 --- a/test/suites/standard2/configuration.robot +++ b/test/suites/standard2/configuration.robot @@ -55,6 +55,7 @@ ${APISERVER_ETCD_CLIENT_CERT} /var/lib/microshift/certs/etcd-signer/apiser MicroShift Starts Using Default Config [Documentation] Default (example) config should not fail to be parsed ... and prevent MicroShift from starting. + [Tags] default-config # Copy existing config.yaml as a drop-in because it has subjectAltNames # required by the `Restart MicroShift` keyword (sets up required kubeconfig). [Setup] Run Keywords diff --git a/test/suites/standard2/feature-gates.robot b/test/suites/standard2/feature-gates.robot new file mode 100644 index 0000000000..be81f79227 --- /dev/null +++ b/test/suites/standard2/feature-gates.robot @@ -0,0 +1,139 @@ +*** Settings *** +Documentation Tests for feature gate configuration + +Resource ../../resources/common.resource +Resource ../../resources/microshift-config.resource +Resource ../../resources/microshift-process.resource +Library ../../resources/journalctl.py + +Suite Setup Setup +Suite Teardown Teardown + +Test Tags restart slow + + +*** Variables *** +${CURSOR} ${EMPTY} # The journal cursor before restarting MicroShift +${CUSTOM_FEATURE_GATES} SEPARATOR=\n +... apiServer: +... \ \ featureGates: +... \ \ \ \ featureSet: CustomNoUpgrade +... \ \ \ \ customNoUpgrade: +... \ \ \ \ \ \ enabled: +... \ \ \ \ \ \ \ \ - TestFeatureEnabled +... \ \ \ \ \ \ disabled: +... \ \ \ \ \ \ \ \ - TestFeatureDisabled +${DIFFERENT_FEATURE_GATES} SEPARATOR=\n +... apiServer: +... \ \ featureGates: +... \ \ \ \ featureSet: CustomNoUpgrade +... \ \ \ \ customNoUpgrade: +... \ \ \ \ \ \ enabled: +... \ \ \ \ \ \ \ \ - DifferentTestFeature +${FEATURE_GATE_LOCK_FILE} /var/lib/microshift/no-upgrade + + +*** Test Cases *** +Custom Feature Gates Are Passed To Kube APIServer + [Documentation] Check that custom feature gates specified in the MicroShift config are passed to and logged by the + ... kube-apiserver. This test verifies that arbitrary feature gate values are correctly propagated from the + ... MicroShift configuration to the kube-apiserver, regardless of whether the feature gates are valid or have any effect. + [Setup] Setup Custom Feature Gates Test + Wait Until Keyword Succeeds 2 min 5 sec + ... Pattern Should Appear In Log Output ${CURSOR} kube:feature-gates=.*TestFeatureEnabled=true + Wait Until Keyword Succeeds 2 min 5 sec + ... Pattern Should Appear In Log Output ${CURSOR} kube:feature-gates=.*TestFeatureDisabled=false + [Teardown] Teardown Custom Feature Gates Test + +Feature Gate Lock File Created With Custom Feature Gates + [Documentation] Verify that feature gate lock file is created when custom feature gates are configured. + ... The lock file prevents upgrades and configuration changes when CustomNoUpgrade feature set is used. + [Setup] Setup Custom Feature Gates Test + Wait Until Keyword Succeeds 2 min 5 sec + ... Feature Gate Lock File Should Exist + Feature Gate Lock File Should Contain Feature Gates CustomNoUpgrade TestFeatureEnabled + [Teardown] Teardown Custom Feature Gates Test + +Feature Gate Config Change Blocked After Lock Created + [Documentation] Verify that changing feature gate config is blocked after lock file exists. + ... MicroShift must refuse to start if feature gates change after CustomNoUpgrade is set. + [Setup] Setup Custom Feature Gates Test + + Stop MicroShift + Drop In MicroShift Config ${DIFFERENT_FEATURE_GATES} 10-featuregates + Save Journal Cursor + MicroShift Should Fail To Start + Pattern Should Appear In Log Output ${CURSOR} feature gate configuration has changed + # Restore original config and verify that MicroShift starts + Drop In MicroShift Config ${CUSTOM_FEATURE_GATES} 10-featuregates + Start MicroShift + [Teardown] Teardown Custom Feature Gates Test + +Feature Gate Lock File Persists Across Restarts With Same Config + [Documentation] Verify that feature gate lock file persists and validation succeeds across restarts + ... when the same feature gate configuration is maintained. + [Setup] Setup Custom Feature Gates Test + Wait Until Keyword Succeeds 2 min 5 sec + ... Feature Gate Lock File Should Exist + Restart MicroShift + Feature Gate Lock File Should Exist + [Teardown] Teardown Custom Feature Gates Test + + +*** Keywords *** +Setup + [Documentation] Test suite setup + Check Required Env Variables + Login MicroShift Host + Setup Kubeconfig # for readiness checks + +Teardown + [Documentation] Test suite teardown + Restart MicroShift + Logout MicroShift Host + Remove Kubeconfig + +Save Journal Cursor + [Documentation] + ... Save the journal cursor then restart MicroShift so we capture the + ... shutdown messages and startup messages. + ${cursor}= Get Journal Cursor + VAR ${CURSOR}= ${cursor} scope=SUITE + +Setup Custom Feature Gates Test + [Documentation] Drop in custom feature gates config and restart MicroShift + Drop In MicroShift Config ${CUSTOM_FEATURE_GATES} 10-featuregates + Save Journal Cursor + Restart MicroShift + Feature Gate Lock File Should Exist + +Teardown Custom Feature Gates Test + [Documentation] Remove custom feature gates config and restart MicroShift + Remove Drop In MicroShift Config 10-featuregates + Remove Feature Gate Lock File If Exists + Restart MicroShift + +Remove Feature Gate Lock File If Exists + [Documentation] Remove the feature gate lock file if it exists, for test cleanup + Command Should Work rm -f ${FEATURE_GATE_LOCK_FILE} + +Feature Gate Lock File Should Exist + [Documentation] Verify that the feature gate lock file exists + Command Should Work test -f ${FEATURE_GATE_LOCK_FILE} + +Feature Gate Lock File Should Contain Feature Gates + [Documentation] Verify that feature gate lock file contains the expected feature gate configuration + [Arguments] ${feature_set} ${feature_name} + ${contents}= Command Should Work cat ${FEATURE_GATE_LOCK_FILE} + Should Contain ${contents} ${feature_set} + Should Contain ${contents} ${feature_name} + +MicroShift Should Fail To Start + [Documentation] Verify that MicroShift fails to start and returns a non-zero exit code. + ... This keyword is unique and differs from a composite keyword like + ... Run Keyword And Expect Error 1 != 0 Start MicroShift + ... because there is no need to poll the service for an "active" state, which Start MicroShift does. + ${stdout} ${stderr} ${rc}= Execute Command sudo systemctl start microshift.service + ... sudo=True return_stdout=True return_stderr=True return_rc=True + Log Many ${stdout} ${stderr} ${rc} + Should Be Equal As Integers 1 ${rc} diff --git a/test/suites/standard2/validate-custom-certificates.robot b/test/suites/standard2/validate-custom-certificates.robot index 7c7013c69a..1f3ca9e147 100644 --- a/test/suites/standard2/validate-custom-certificates.robot +++ b/test/suites/standard2/validate-custom-certificates.robot @@ -4,6 +4,7 @@ Documentation Tests custom certificates functionality Resource ../../resources/microshift-config.resource Resource ../../resources/microshift-process.resource Resource ../../resources/openssl.resource +Resource ../../resources/hosts.resource Library ../../resources/journalctl.py Suite Setup Setup @@ -42,10 +43,10 @@ Test Expired Cert Upload Certificates Configure Named Certificates ${TMPDIR}/server.crt ${TMPDIR}/server.key Restart MicroShift - Add Entry To Hosts ${USHIFT_HOST} ${hostname} + Add Entry To Local Hosts ${USHIFT_HOST} ${hostname} Setup Custom Kubeconfig ${hostname} OC Should Fail To Connect With Expired Cert - [Teardown] Remove Entry From Hosts ${hostname} + [Teardown] Remove Entry From Local Hosts ${hostname} Test Local Cert [Documentation] localhost certs should be ignored with a warning @@ -70,11 +71,11 @@ Test SAN Cert Upload Certificates Configure Named Certificates ${TMPDIR}/server.crt ${TMPDIR}/server.key test Restart MicroShift - Add Entry To Hosts ${USHIFT_HOST} ${hostname} + Add Entry To Local Hosts ${USHIFT_HOST} ${hostname} Setup Custom Kubeconfig ${hostname} OC Should Fail To Connect With Unknown CA MicroShift Is Live With Custom CA ${TMPDIR}/ca.crt - [Teardown] Remove Entry From Hosts ${hostname} + [Teardown] Remove Entry From Local Hosts ${hostname} Test Wildcard Only Cert [Documentation] Create WildCard only certificate @@ -85,12 +86,12 @@ Test Wildcard Only Cert Upload Certificates Configure Named Certificates ${TMPDIR}/server.crt ${TMPDIR}/server.key Restart MicroShift - Add Entry To Hosts ${USHIFT_HOST} ${hostname} + Add Entry To Local Hosts ${USHIFT_HOST} ${hostname} Setup Custom Kubeconfig TestCN Replace Server In Kubeconfig ${hostname} OC Should Fail To Connect With Unknown CA MicroShift Is Live With Custom CA ${TMPDIR}/ca.crt - [Teardown] Remove Entry From Hosts ${hostname} + [Teardown] Remove Entry From Local Hosts ${hostname} Test Wildcard With Names Cert [Documentation] Create WildCard certificate with additional config name @@ -101,11 +102,11 @@ Test Wildcard With Names Cert Upload Certificates Configure Named Certificates ${TMPDIR}/server.crt ${TMPDIR}/server.key ${hostname} Restart MicroShift - Add Entry To Hosts ${USHIFT_HOST} ${hostname} + Add Entry To Local Hosts ${USHIFT_HOST} ${hostname} Setup Custom Kubeconfig ${hostname} OC Should Fail To Connect With Unknown CA MicroShift Is Live With Custom CA ${TMPDIR}/ca.crt - [Teardown] Remove Entry From Hosts ${hostname} + [Teardown] Remove Entry From Local Hosts ${hostname} *** Keywords *** @@ -176,25 +177,6 @@ Configure Named Certificates END Drop In MicroShift Config ${subject_alt_names} 10-subjectAltNames -Generate Random HostName - [Documentation] Generate Random Hostname - ${rand}= Generate Random String - ${rand}= Convert To Lower Case ${rand} - RETURN ${rand}.api.com - -Add Entry To Hosts - [Documentation] Add new entry to local /etc/hosts - [Arguments] ${ip} ${host} - VAR ${ttt}= ${ip}\t${host} # RF test marker\n - ${result}= Run Process sudo tee -a /etc/hosts shell=True stdin=${ttt} - Should Be Equal As Integers ${result.rc} 0 - -Remove Entry From Hosts - [Documentation] Removes entry from local /etc/hosts - [Arguments] ${host} - ${result}= Run Process sudo sed -i "/${host} # RF test marker/d" /etc/hosts shell=True - Should Be Equal As Integers ${result.rc} 0 - Replace Server In Kubeconfig [Documentation] replace the server part of kubeconfig [Arguments] ${fqdn} diff --git a/test/suites/telemetry/telemetry.robot b/test/suites/telemetry/telemetry.robot index 69f938c636..0d9be3f0f1 100644 --- a/test/suites/telemetry/telemetry.robot +++ b/test/suites/telemetry/telemetry.robot @@ -20,7 +20,6 @@ Test Tags restart slow ${PROXY_HOST} ${EMPTY} ${PROXY_PORT} ${EMPTY} ${PROMETHEUS_HOST} ${EMPTY} -${PROMETHEUS_PORT} ${EMPTY} ${TELEMETRY_WRITE_ENDPOINT} https://infogw.api.openshift.com/metrics/v1/receive ${PROXY_ENDPOINT} http://${PROXY_HOST}:${PROXY_PORT}/api/v1/write ${ENABLE_TELEMETRY} SEPARATOR=\n @@ -71,23 +70,12 @@ MicroShift Reports Metrics To Default Server Through Proxy MicroShift Fails to Report Metrics To Prometheus Server With Telemetry Disabled [Documentation] Check MicroShift is not able to send metrics to the telemetry server when it is disabled. - [Setup] Run Keywords - ... Start Prometheus Server ${PROMETHEUS_PORT} - ... AND - ... Setup Telemetry Configuration ${DISABLE_TELEMETRY_TO_PROMETHEUS} ${PULL_SECRET_METRICS} + [Setup] Setup Telemetry Configuration ${DISABLE_TELEMETRY_TO_PROMETHEUS} ${PULL_SECRET_METRICS} Should Find Metrics In Journal Log Success Telemetry is disabled Should Find Metrics In Journal Log Fails Metrics sent successfully - @{metrics_to_check}= Get List Prometheus Metrics To Check - FOR ${metric} IN @{metrics_to_check} - Check Prometheus Query Is Missing ${PROMETHEUS_HOST} ${PROMETHEUS_PORT} ${metric} - END - - [Teardown] Run Keywords - ... Remove Telemetry Configuration - ... AND - ... Stop Prometheus Server ${PROMETHEUS_PORT} + [Teardown] Remove Telemetry Configuration MicroShift Fails to Report Metrics To Default Server With Wrong Pull Secret [Documentation] Check MicroShift is not able to send metrics to the telemetry server when the pull secret is wrong. @@ -100,22 +88,16 @@ MicroShift Fails to Report Metrics To Default Server With Wrong Pull Secret MicroShift Reports Metrics To Prometheus Server [Documentation] Check the expected metrics are sent to the local server. - [Setup] Run Keywords - ... Start Prometheus Server ${PROMETHEUS_PORT} - ... AND - ... Setup Telemetry Configuration ${ENABLE_TELEMETRY_TO_PROMETHUS} ${PULL_SECRET_METRICS} + [Setup] Setup Telemetry Configuration ${ENABLE_TELEMETRY_TO_PROMETHUS} ${PULL_SECRET_METRICS} Should Find Metrics In Journal Log Success Metrics sent successfully @{metrics_to_check}= Get List Prometheus Metrics To Check FOR ${metric} IN @{metrics_to_check} - Check Prometheus Query ${PROMETHEUS_HOST} ${PROMETHEUS_PORT} ${metric} + Check Prometheus Query ${PROMETHEUS_HOST} ${PROMETHEUS_PORT} ${metric} add_hostname_filter=${False} END - [Teardown] Run Keywords - ... Remove Telemetry Configuration - ... AND - ... Stop Prometheus Server ${PROMETHEUS_PORT} + [Teardown] Remove Telemetry Configuration *** Keywords *** @@ -139,7 +121,7 @@ Check Required Telemetry Variables Should Not Be Empty ${PROMETHEUS_HOST} PROMETHEUS_HOST variable is required ${string_value}= Convert To String ${PROMETHEUS_PORT} Should Not Be Empty ${string_value} PROMETHEUS_PORT variable is required - Should Not Be Empty ${PROXY_HOST} PROXY_HOST variable is required + Should Not Be Empty ${PROXY_PORT} PROXY_PORT variable is required ${string_value}= Convert To String ${PROXY_PORT} Should Not Be Empty ${string_value} PROXY_PORT variable is required diff --git a/test/suites/tuned/uncore-cache.robot b/test/suites/tuned/uncore-cache.robot new file mode 100644 index 0000000000..7f23269988 --- /dev/null +++ b/test/suites/tuned/uncore-cache.robot @@ -0,0 +1,86 @@ +*** Settings *** +Documentation Tests for Workload partitioning + +Library ../../resources/journalctl.py +Resource ../../resources/microshift-config.resource +Resource ../../resources/common.resource +Resource ../../resources/microshift-process.resource + +Suite Setup Run Keywords +... Setup Suite +... AND Check FeatureGates Is Enabled +Suite Teardown Teardown Suite + + +*** Variables *** +${MANAGEMENT_CPU} 0 +${KUBELET_CPU_STATE_FILE} /var/lib/kubelet/cpu_manager_state + + +*** Test Cases *** +Workload Partitioning Should Work With Uncore-cache + [Documentation] Verify that all the Control Plane pods are properly annotated. + [Setup] Configure Kubelet For Uncore-Cache ${MANAGEMENT_CPU} + Verify Uncore-cache Feature Is Enabled + [Teardown] Teardown For Workload Partitioning With Uncore-cache + + +*** Keywords *** +Teardown For Workload Partitioning With Uncore-cache + [Documentation] Teardown for Workload Partitioning with Uncore-cache + Remove Drop In MicroShift Config 11-kubelet-uncore-cache + Cleanup CPU State + Restart MicroShift + +Configure Kubelet For Uncore-Cache + [Documentation] configure microshift with kubelet CPU configuration + [Arguments] ${cpus} + + ${kubelet_config}= CATENATE SEPARATOR=\n + ... --- + ... apiServer: + ... \ \ featureGates: + ... \ \ \ \ featureSet: "CustomNoUpgrade" + ... \ \ \ \ customNoUpgrade: + ... \ \ \ \ \ \ enabled: ["CPUManagerPolicyBetaOptions"] + ... kubelet: + ... \ \ reservedSystemCPUs: "${cpus}" + ... \ \ cpuManagerPolicy: static + ... \ \ cpuManagerPolicyOptions: + ... \ \ \ \ prefer-align-cpus-by-uncorecache: "true" + Drop In MicroShift Config ${kubelet_config} 11-kubelet-uncore-cache + Cleanup CPU State + +Verify Uncore-cache Feature Is Enabled + [Documentation] Verify that the kubelet uncore-cache feature is enabled + ${cursor}= Get Journal Cursor + Restart MicroShift + Pattern Should Appear In Log Output + ... ${cursor} + ... kube-apiserver I.*CPUManagerPolicyBetaOptions=true + ... unit=microshift + ... wait=5 + Pattern Should Appear In Log Output + ... ${cursor} + ... kubelet I.*CPUManagerPolicyBetaOptions:true + ... unit=microshift + ... wait=5 + Pattern Should Appear In Log Output + ... ${cursor} + ... kubelet I.*prefer-align-cpus-by-uncorecache":"true" + ... unit=microshift + ... wait=5 + +Cleanup CPU State + [Documentation] cleanup microshift and recreate the namespace for workloads + Cleanup MicroShift --all --keep-images + Remove Files ${KUBELET_CPU_STATE_FILE} + +Check FeatureGates Is Enabled + [Documentation] Skip suite if CoreDNS hosts feature is not available + ${config}= Show Config default + TRY + VAR ${featuregates}= ${config}[apiServer][featureGates] + EXCEPT + Skip CoreDNS hosts feature not available in this MicroShift version + END diff --git a/test/suites/tuned/workload-partitioning.robot b/test/suites/tuned/workload-partitioning.robot index f567f6ad78..d45512e3cf 100644 --- a/test/suites/tuned/workload-partitioning.robot +++ b/test/suites/tuned/workload-partitioning.robot @@ -247,16 +247,6 @@ Crio Process ID Log ${stderr} RETURN ${stdout} -Remove Files - [Documentation] removes files from the microshit host - [Arguments] @{files} - Log ${files} - ${files_path}= Catenate SEPARATOR=${SPACE} @{files} - ${stdout} ${stderr} ${rc}= Execute Command - ... rm -f ${files_path} - ... sudo=True return_stdout=True return_stderr=True return_rc=True - Should Be Equal As Integers ${rc} 0 - Cleanup And Create NS [Documentation] cleanup microshift and recreate the namespace for workloads Cleanup MicroShift --all --keep-images diff --git a/vendor/github.com/openshift/api/.golangci.yaml b/vendor/github.com/openshift/api/.golangci.yaml index 649f9bed35..8da22c5e51 100644 --- a/vendor/github.com/openshift/api/.golangci.yaml +++ b/vendor/github.com/openshift/api/.golangci.yaml @@ -11,7 +11,9 @@ linters: settings: linters: enable: + - forbiddenmarkers - maxlength + - namingconventions - nobools - nomaps - statussubresource @@ -20,6 +22,13 @@ linters: isFirstField: Warn usePatchStrategy: Ignore useProtobuf: Ignore + forbiddenmarkers: + markers: + - identifier: "openshift:enable:FeatureSets" + - identifier: "openshift:validation:FeatureSetAwareEnum" + - identifier: "openshift:validation:FeatureSetAwareXValidation" + - identifier: "kubebuilder:validation:UniqueItems" + - identifier: "kubebuilder:validation:Pattern" # Use CEL expressions instead optionalfields: pointers: preference: WhenRequired @@ -33,7 +42,7 @@ linters: # This will force omitzero on optional struct fields. # This means they can be omitted correctly and prevents the need for pointers to structs. policy: SuggestFix - requiredFields: + requiredfields: pointers: # This will force pointers when the field is required, but only when the zero # value is a valid user choice, and has a semantic difference to being omitted (e.g. replicas allows 0). @@ -47,7 +56,18 @@ linters: # This will force omitzero on required struct fields. # This means they can be omitted correctly and prevents the need for pointers to structs. policy: SuggestFix - uniqueMarkers: + namingconventions: + conventions: + - name: norefs + violationMatcher: "(?i)ref(erence)?s?$" + operation: Drop + message: "reference fields should not need to be named ref(s)/reference(s)" + - name: nokind + violationMatcher: "^Kind$" + operation: Replacement + replacement: "Resource" + message: "API Kinds can be ambiguous and should be replaced with Resource" + uniquemarkers: customMarkers: - identifier: "openshift:validation:FeatureGateAwareEnum" attributes: diff --git a/vendor/github.com/openshift/api/AGENTS.md b/vendor/github.com/openshift/api/AGENTS.md index a009bbb2de..0e39032433 100644 --- a/vendor/github.com/openshift/api/AGENTS.md +++ b/vendor/github.com/openshift/api/AGENTS.md @@ -32,6 +32,21 @@ make clean # Clean build artifacts make update # Alias for update-codegen-crds ``` +#### Targeted Code Generation +When working on a specific API group/version, you can regenerate only the affected CRDs instead of all CRDs: + +```bash +# Regenerate CRDs for a specific API group/version +make update-codegen-crds API_GROUP_VERSIONS=operator.openshift.io/v1alpha1 +make update-codegen-crds API_GROUP_VERSIONS=config.openshift.io/v1 +make update-codegen-crds API_GROUP_VERSIONS=route.openshift.io/v1 + +# Multiple API groups can be specified with comma separation +make update-codegen-crds API_GROUP_VERSIONS=operator.openshift.io/v1alpha1,config.openshift.io/v1 +``` + +This is more efficient than running `make update` (which regenerates all CRDs) when you're only working on specific API groups. + ### Testing ```bash make test-unit # Run unit tests diff --git a/vendor/github.com/openshift/api/Makefile b/vendor/github.com/openshift/api/Makefile index fd4268a789..c069d80401 100644 --- a/vendor/github.com/openshift/api/Makefile +++ b/vendor/github.com/openshift/api/Makefile @@ -1,7 +1,7 @@ all: build .PHONY: all -update: update-codegen-crds +update: update-non-codegen update-codegen RUNTIME ?= podman RUNTIME_IMAGE_NAME ?= registry.ci.openshift.org/openshift/release:rhel-9-release-golang-1.24-openshift-4.20 @@ -17,10 +17,8 @@ test-unit: # # BEGIN: Update codegen-crds. Defaults to generating updates for all API packages. # To run a subset of packages: -# - Filter by group with make update-codegen-crds- -# E.g. make update-codegen-crds-machine -# - Set API_GROUP_VERSIONS to a space separated list of /. -# E.g. API_GROUP_VERSIONS="apps/v1 build/v1" make update-codegen-crds. +# - Set API_GROUP_VERSIONS to a space separated list of fully qualified /. +# E.g. API_GROUP_VERSIONS="apps.openshift.io/v1 build.openshift.io/v1" make update-codegen-crds. # FeatureSet generation is controlled at the group level by the # .codegen.yaml file. # @@ -57,23 +55,28 @@ verify-lint-fix: make lint-fix 2>/dev/null || true git diff --exit-code -.PHONY: verify-scripts -verify-scripts: - bash -x hack/verify-deepcopy.sh - bash -x hack/verify-openapi.sh +# Verify codegen runs all verifiers in the order they are defined in the root.go file. +# This includes all generators defined in update-codegen, but also the crd-schema-checker and crdify verifiers. +.PHONY: verify-codegen +verify-codegen: + EXTRA_ARGS=--verify hack/update-codegen.sh + +.PHONY: verify-non-codegen +verify-non-codegen: bash -x hack/verify-protobuf.sh - bash -x hack/verify-swagger-docs.sh hack/verify-crds.sh bash -x hack/verify-types.sh - bash -x hack/verify-compatibility.sh bash -x hack/verify-integration-tests.sh bash -x hack/verify-group-versions.sh bash -x hack/verify-prerelease-lifecycle-gen.sh hack/verify-payload-crds.sh hack/verify-payload-featuregates.sh +.PHONY: verify-scripts +verify-scripts: verify-non-codegen verify-codegen + .PHONY: verify -verify: verify-scripts lint verify-crd-schema verify-crdify verify-codegen-crds +verify: verify-scripts lint .PHONY: verify-codegen-crds verify-codegen-crds: @@ -99,8 +102,8 @@ verify-%: ################################################################################################ # # BEGIN: Update scripts. Defaults to generating updates for all API packages. -# Set API_GROUP_VERSIONS to a space separated list of / to limit -# the scope of the updates. Eg API_GROUP_VERSIONS="apps/v1 build/v1" make update-scripts. +# Set API_GROUP_VERSIONS to a space separated list of fully qualified / to limit +# the scope of the updates. Eg API_GROUP_VERSIONS="apps.openshift.io/v1 build.openshift.io/v1" make update-scripts. # Note: Protobuf generation is handled separately, see hack/lib/init.sh. # ################################################################################################ @@ -108,6 +111,19 @@ verify-%: .PHONY: update-scripts update-scripts: update-compatibility update-openapi update-deepcopy update-protobuf update-swagger-docs tests-vendor update-prerelease-lifecycle-gen update-payload-featuregates +# Update codegen runs all generators in the order they are defined in the root.go file. +# The per group generators are:[compatibility, deepcopy, swagger-docs, empty-partial-schema, schema-patch, crd-manifest-merge] +# The multi group generators are:[openapi] +.PHONY: update-codegen +update-codegen: + hack/update-codegen.sh + +# Update non-codegen runs all generators that are not part of the codegen utility, or +# are part of it, but are not run by default when invoking codegen without a specific generator. +# E.g. the payload feature gates which is not part of the generator style, but is still a subcommand. +.PHONY: update-non-codegen +update-non-codegen: update-protobuf tests-vendor update-prerelease-lifecycle-gen update-payload-crds update-payload-featuregates + .PHONY: update-compatibility update-compatibility: hack/update-compatibility.sh diff --git a/vendor/github.com/openshift/api/config/v1/types_cluster_version.go b/vendor/github.com/openshift/api/config/v1/types_cluster_version.go index cfac9689e4..e5aad151ea 100644 --- a/vendor/github.com/openshift/api/config/v1/types_cluster_version.go +++ b/vendor/github.com/openshift/api/config/v1/types_cluster_version.go @@ -72,8 +72,10 @@ type ClusterVersionSpec struct { // // If an upgrade fails the operator will halt and report status // about the failing component. Setting the desired update value back to - // the previous version will cause a rollback to be attempted. Not all - // rollbacks will succeed. + // the previous version will cause a rollback to be attempted if the + // previous version is within the current minor version. Not all + // rollbacks will succeed, and some may unrecoverably break the + // cluster. // // +optional DesiredUpdate *Update `json:"desiredUpdate,omitempty"` @@ -718,10 +720,14 @@ type Update struct { Image string `json:"image"` // force allows an administrator to update to an image that has failed - // verification or upgradeable checks. This option should only - // be used when the authenticity of the provided image has been verified out - // of band because the provided image will run with full administrative access - // to the cluster. Do not use this flag with images that comes from unknown + // verification or upgradeable checks that are designed to keep your + // cluster safe. Only use this if: + // * you are testing unsigned release images in short-lived test clusters or + // * you are working around a known bug in the cluster-version + // operator and you have verified the authenticity of the provided + // image yourself. + // The provided image will run with full administrative access + // to the cluster. Do not use this flag with images that come from unknown // or potentially malicious sources. // // +optional diff --git a/vendor/github.com/openshift/api/config/v1/types_infrastructure.go b/vendor/github.com/openshift/api/config/v1/types_infrastructure.go index effafde644..2f80945d38 100644 --- a/vendor/github.com/openshift/api/config/v1/types_infrastructure.go +++ b/vendor/github.com/openshift/api/config/v1/types_infrastructure.go @@ -183,6 +183,17 @@ const ( LoadBalancerTypeOpenShiftManagedDefault PlatformLoadBalancerType = "OpenShiftManagedDefault" ) +// DNSRecordsType defines whether api, api-int, and ingress records are provided by +// the internal DNS infrastructure or must be configured external to the cluster. +// +kubebuilder:validation:Enum=Internal;External +// +enum +type DNSRecordsType string + +const ( + DNSRecordsTypeExternal DNSRecordsType = "External" + DNSRecordsTypeInternal DNSRecordsType = "Internal" +) + // PlatformType is a specific supported infrastructure provider. // +kubebuilder:validation:Enum="";AWS;Azure;BareMetal;GCP;Libvirt;OpenStack;None;VSphere;oVirt;IBMCloud;KubeVirt;EquinixMetal;PowerVS;AlibabaCloud;Nutanix;External type PlatformType string @@ -491,6 +502,21 @@ type AWSServiceEndpoint struct { URL string `json:"url"` } +// IPFamilyType represents the IP protocol family that cloud platform resources should use. +// +kubebuilder:validation:Enum=IPv4;DualStackIPv6Primary;DualStackIPv4Primary +type IPFamilyType string + +const ( + // IPv4 indicates that cloud platform resources should use IPv4 addressing only. + IPv4 IPFamilyType = "IPv4" + + // DualStackIPv6Primary indicates that cloud platform resources should use dual-stack networking with IPv6 as primary. + DualStackIPv6Primary IPFamilyType = "DualStackIPv6Primary" + + // DualStackIPv4Primary indicates that cloud platform resources should use dual-stack networking with IPv4 as primary. + DualStackIPv4Primary IPFamilyType = "DualStackIPv4Primary" +) + // AWSPlatformSpec holds the desired state of the Amazon Web Services infrastructure provider. // This only includes fields that can be modified in the cluster. type AWSPlatformSpec struct { @@ -536,6 +562,18 @@ type AWSPlatformStatus struct { // +optional // +nullable CloudLoadBalancerConfig *CloudLoadBalancerConfig `json:"cloudLoadBalancerConfig,omitempty"` + + // ipFamily specifies the IP protocol family that should be used for AWS + // network resources. This controls whether AWS resources are created with + // IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary + // protocol family. + // + // +default="IPv4" + // +kubebuilder:default="IPv4" + // +kubebuilder:validation:XValidation:rule="oldSelf == '' || self == oldSelf",message="ipFamily is immutable once set" + // +openshift:enable:FeatureGate=AWSDualStackInstall + // +optional + IPFamily IPFamilyType `json:"ipFamily,omitempty"` } // AWSResourceTag is a tag to apply to AWS resources created for the cluster. @@ -607,6 +645,18 @@ type AzurePlatformStatus struct { // +openshift:enable:FeatureGate=AzureClusterHostedDNSInstall // +optional CloudLoadBalancerConfig *CloudLoadBalancerConfig `json:"cloudLoadBalancerConfig,omitempty"` + + // ipFamily specifies the IP protocol family that should be used for Azure + // network resources. This controls whether Azure resources are created with + // IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary + // protocol family. + // + // +default="IPv4" + // +kubebuilder:default="IPv4" + // +kubebuilder:validation:XValidation:rule="oldSelf == '' || self == oldSelf",message="ipFamily is immutable once set" + // +openshift:enable:FeatureGate=AzureDualStackInstall + // +optional + IPFamily IPFamilyType `json:"ipFamily,omitempty"` } // AzureResourceTag is a tag to apply to Azure resources created for the cluster. @@ -983,6 +1033,7 @@ type BareMetalPlatformSpec struct { // BareMetalPlatformStatus holds the current status of the BareMetal infrastructure provider. // For more information about the network architecture used with the BareMetal platform type, see: // https://github.com/openshift/installer/blob/master/docs/design/baremetal/networking-infrastructure.md +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type BareMetalPlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -1035,6 +1086,22 @@ type BareMetalPlatformStatus struct { // +optional LoadBalancer *BareMetalPlatformLoadBalancer `json:"loadBalancer,omitempty"` + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` + // machineNetworks are IP networks used to connect all the OpenShift cluster nodes. // +listType=atomic // +kubebuilder:validation:MaxItems=32 @@ -1111,6 +1178,7 @@ type OpenStackPlatformSpec struct { } // OpenStackPlatformStatus holds the current status of the OpenStack infrastructure provider. +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type OpenStackPlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -1167,6 +1235,22 @@ type OpenStackPlatformStatus struct { // +optional LoadBalancer *OpenStackPlatformLoadBalancer `json:"loadBalancer,omitempty"` + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` + // machineNetworks are IP networks used to connect all the OpenShift cluster nodes. // +listType=atomic // +kubebuilder:validation:MaxItems=32 @@ -1201,6 +1285,7 @@ type OvirtPlatformLoadBalancer struct { type OvirtPlatformSpec struct{} // OvirtPlatformStatus holds the current status of the oVirt infrastructure provider. +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type OvirtPlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -1247,6 +1332,22 @@ type OvirtPlatformStatus struct { // +kubebuilder:default={"type": "OpenShiftManagedDefault"} // +optional LoadBalancer *OvirtPlatformLoadBalancer `json:"loadBalancer,omitempty"` + + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` } // VSpherePlatformLoadBalancer defines the load balancer used by the cluster on VSphere platform. @@ -1644,6 +1745,7 @@ type VSpherePlatformSpec struct { } // VSpherePlatformStatus holds the current status of the vSphere infrastructure provider. +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type VSpherePlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -1696,6 +1798,22 @@ type VSpherePlatformStatus struct { // +optional LoadBalancer *VSpherePlatformLoadBalancer `json:"loadBalancer,omitempty"` + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` + // machineNetworks are IP networks used to connect all the OpenShift cluster nodes. // +listType=atomic // +kubebuilder:validation:MaxItems=32 @@ -2069,6 +2187,7 @@ type NutanixPrismElementEndpoint struct { } // NutanixPlatformStatus holds the current status of the Nutanix infrastructure provider. +// +openshift:validation:FeatureGateAwareXValidation:featureGate=OnPremDNSRecords,rule="!has(self.dnsRecordsType) || self.dnsRecordsType == 'Internal' || (has(self.loadBalancer) && self.loadBalancer.type == 'UserManaged')",message="dnsRecordsType may only be set to External when loadBalancer.type is UserManaged" type NutanixPlatformStatus struct { // apiServerInternalIP is an IP address to contact the Kubernetes API server that can be used // by components inside the cluster, like kubelets using the infrastructure rather @@ -2112,6 +2231,22 @@ type NutanixPlatformStatus struct { // +kubebuilder:default={"type": "OpenShiftManagedDefault"} // +optional LoadBalancer *NutanixPlatformLoadBalancer `json:"loadBalancer,omitempty"` + + // dnsRecordsType determines whether records for api, api-int, and ingress + // are provided by the internal DNS service or externally. + // Allowed values are `Internal`, `External`, and omitted. + // When set to `Internal`, records are provided by the internal infrastructure and + // no additional user configuration is required for the cluster to function. + // When set to `External`, records are not provided by the internal infrastructure + // and must be configured by the user on a DNS server outside the cluster. + // Cluster nodes must use this external server for their upstream DNS requests. + // This value may only be set when loadBalancer.type is set to UserManaged. + // When omitted, this means the user has no opinion and the platform is left + // to choose reasonable defaults. These defaults are subject to change over time. + // The current default is `Internal`. + // +openshift:enable:FeatureGate=OnPremDNSRecords + // +optional + DNSRecordsType DNSRecordsType `json:"dnsRecordsType,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml b/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml index d8d6b502ee..a1d37f65d0 100644 --- a/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml +++ b/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml @@ -362,7 +362,9 @@ infrastructures.config.openshift.io: Category: "" FeatureGates: - AWSClusterHostedDNSInstall + - AWSDualStackInstall - AzureClusterHostedDNSInstall + - AzureDualStackInstall - DualReplica - DyanmicServiceEndpointIBMCloud - GCPClusterHostedDNSInstall @@ -370,6 +372,7 @@ infrastructures.config.openshift.io: - HighlyAvailableArbiter - HighlyAvailableArbiter+DualReplica - NutanixMultiSubnets + - OnPremDNSRecords - VSphereHostVMGroupZonal - VSphereMultiNetworks FilenameOperatorName: config-operator diff --git a/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go index 31aab4dfe8..b9d0799fbd 100644 --- a/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go @@ -777,7 +777,7 @@ func (ClusterVersionList) SwaggerDoc() map[string]string { var map_ClusterVersionSpec = map[string]string{ "": "ClusterVersionSpec is the desired version state of the cluster. It includes the version the cluster should be at, how the cluster is identified, and where the cluster should look for version updates.", "clusterID": "clusterID uniquely identifies this cluster. This is expected to be an RFC4122 UUID value (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx in hexadecimal values). This is a required field.", - "desiredUpdate": "desiredUpdate is an optional field that indicates the desired value of the cluster version. Setting this value will trigger an upgrade (if the current version does not match the desired version). The set of recommended update values is listed as part of available updates in status, and setting values outside that range may cause the upgrade to fail.\n\nSome of the fields are inter-related with restrictions and meanings described here. 1. image is specified, version is specified, architecture is specified. API validation error. 2. image is specified, version is specified, architecture is not specified. The version extracted from the referenced image must match the specified version. 3. image is specified, version is not specified, architecture is specified. API validation error. 4. image is specified, version is not specified, architecture is not specified. image is used. 5. image is not specified, version is specified, architecture is specified. version and desired architecture are used to select an image. 6. image is not specified, version is specified, architecture is not specified. version and current architecture are used to select an image. 7. image is not specified, version is not specified, architecture is specified. API validation error. 8. image is not specified, version is not specified, architecture is not specified. API validation error.\n\nIf an upgrade fails the operator will halt and report status about the failing component. Setting the desired update value back to the previous version will cause a rollback to be attempted. Not all rollbacks will succeed.", + "desiredUpdate": "desiredUpdate is an optional field that indicates the desired value of the cluster version. Setting this value will trigger an upgrade (if the current version does not match the desired version). The set of recommended update values is listed as part of available updates in status, and setting values outside that range may cause the upgrade to fail.\n\nSome of the fields are inter-related with restrictions and meanings described here. 1. image is specified, version is specified, architecture is specified. API validation error. 2. image is specified, version is specified, architecture is not specified. The version extracted from the referenced image must match the specified version. 3. image is specified, version is not specified, architecture is specified. API validation error. 4. image is specified, version is not specified, architecture is not specified. image is used. 5. image is not specified, version is specified, architecture is specified. version and desired architecture are used to select an image. 6. image is not specified, version is specified, architecture is not specified. version and current architecture are used to select an image. 7. image is not specified, version is not specified, architecture is specified. API validation error. 8. image is not specified, version is not specified, architecture is not specified. API validation error.\n\nIf an upgrade fails the operator will halt and report status about the failing component. Setting the desired update value back to the previous version will cause a rollback to be attempted if the previous version is within the current minor version. Not all rollbacks will succeed, and some may unrecoverably break the cluster.", "upstream": "upstream may be used to specify the preferred update server. By default it will use the appropriate update server for the cluster and region.", "channel": "channel is an identifier for explicitly requesting a non-default set of updates to be applied to this cluster. The default channel will contain stable updates that are appropriate for production clusters.", "capabilities": "capabilities configures the installation of optional, core cluster components. A null value here is identical to an empty object; see the child properties for default semantics.", @@ -878,7 +878,7 @@ var map_Update = map[string]string{ "architecture": "architecture is an optional field that indicates the desired value of the cluster architecture. In this context cluster architecture means either a single architecture or a multi architecture. architecture can only be set to Multi thereby only allowing updates from single to multi architecture. If architecture is set, image cannot be set and version must be set. Valid values are 'Multi' and empty.", "version": "version is a semantic version identifying the update version. version is required if architecture is specified. If both version and image are set, the version extracted from the referenced image must match the specified version.", "image": "image is a container image location that contains the update. image should be used when the desired version does not exist in availableUpdates or history. When image is set, architecture cannot be specified. If both version and image are set, the version extracted from the referenced image must match the specified version.", - "force": "force allows an administrator to update to an image that has failed verification or upgradeable checks. This option should only be used when the authenticity of the provided image has been verified out of band because the provided image will run with full administrative access to the cluster. Do not use this flag with images that comes from unknown or potentially malicious sources.", + "force": "force allows an administrator to update to an image that has failed verification or upgradeable checks that are designed to keep your cluster safe. Only use this if: * you are testing unsigned release images in short-lived test clusters or * you are working around a known bug in the cluster-version\n operator and you have verified the authenticity of the provided\n image yourself.\nThe provided image will run with full administrative access to the cluster. Do not use this flag with images that come from unknown or potentially malicious sources.", } func (Update) SwaggerDoc() map[string]string { @@ -1410,6 +1410,7 @@ var map_AWSPlatformStatus = map[string]string{ "serviceEndpoints": "serviceEndpoints list contains custom endpoints which will override default service endpoint of AWS Services. There must be only one ServiceEndpoint for a service.", "resourceTags": "resourceTags is a list of additional tags to apply to AWS resources created for the cluster. See https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for information on tagging AWS resources. AWS supports a maximum of 50 tags per resource. OpenShift reserves 25 tags for its use, leaving 25 tags available for the user.", "cloudLoadBalancerConfig": "cloudLoadBalancerConfig holds configuration related to DNS and cloud load balancers. It allows configuration of in-cluster DNS as an alternative to the platform default DNS implementation. When using the ClusterHosted DNS type, Load Balancer IP addresses must be provided for the API and internal API load balancers as well as the ingress load balancer.", + "ipFamily": "ipFamily specifies the IP protocol family that should be used for AWS network resources. This controls whether AWS resources are created with IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary protocol family.", } func (AWSPlatformStatus) SwaggerDoc() map[string]string { @@ -1481,6 +1482,7 @@ var map_AzurePlatformStatus = map[string]string{ "armEndpoint": "armEndpoint specifies a URL to use for resource management in non-soverign clouds such as Azure Stack.", "resourceTags": "resourceTags is a list of additional tags to apply to Azure resources created for the cluster. See https://docs.microsoft.com/en-us/rest/api/resources/tags for information on tagging Azure resources. Due to limitations on Automation, Content Delivery Network, DNS Azure resources, a maximum of 15 tags may be applied. OpenShift reserves 5 tags for internal use, allowing 10 tags for user configuration.", "cloudLoadBalancerConfig": "cloudLoadBalancerConfig holds configuration related to DNS and cloud load balancers. It allows configuration of in-cluster DNS as an alternative to the platform default DNS implementation. When using the ClusterHosted DNS type, Load Balancer IP addresses must be provided for the API and internal API load balancers as well as the ingress load balancer.", + "ipFamily": "ipFamily specifies the IP protocol family that should be used for Azure network resources. This controls whether Azure resources are created with IPv4-only, or dual-stack networking with IPv4 or IPv6 as the primary protocol family.", } func (AzurePlatformStatus) SwaggerDoc() map[string]string { @@ -1525,6 +1527,7 @@ var map_BareMetalPlatformStatus = map[string]string{ "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "nodeDNSIP": "nodeDNSIP is the IP address for the internal DNS used by the nodes. Unlike the one managed by the DNS operator, `NodeDNSIP` provides name resolution for the nodes themselves. There is no DNS-as-a-service for BareMetal deployments. In order to minimize necessary changes to the datacenter DNS, a DNS service is hosted as a static pod to serve those hostnames to the nodes in the cluster.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", "machineNetworks": "machineNetworks are IP networks used to connect all the OpenShift cluster nodes.", } @@ -1787,6 +1790,7 @@ var map_NutanixPlatformStatus = map[string]string{ "ingressIP": "ingressIP is an external IP which routes to the default ingress controller. The IP is a suitable target of a wildcard DNS record used to resolve default route host names.\n\nDeprecated: Use IngressIPs instead.", "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", } func (NutanixPlatformStatus) SwaggerDoc() map[string]string { @@ -1853,6 +1857,7 @@ var map_OpenStackPlatformStatus = map[string]string{ "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "nodeDNSIP": "nodeDNSIP is the IP address for the internal DNS used by the nodes. Unlike the one managed by the DNS operator, `NodeDNSIP` provides name resolution for the nodes themselves. There is no DNS-as-a-service for OpenStack deployments. In order to minimize necessary changes to the datacenter DNS, a DNS service is hosted as a static pod to serve those hostnames to the nodes in the cluster.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", "machineNetworks": "machineNetworks are IP networks used to connect all the OpenShift cluster nodes.", } @@ -1885,6 +1890,7 @@ var map_OvirtPlatformStatus = map[string]string{ "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "nodeDNSIP": "deprecated: as of 4.6, this field is no longer set or honored. It will be removed in a future release.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", } func (OvirtPlatformStatus) SwaggerDoc() map[string]string { @@ -2067,6 +2073,7 @@ var map_VSpherePlatformStatus = map[string]string{ "ingressIPs": "ingressIPs are the external IPs which route to the default ingress controller. The IPs are suitable targets of a wildcard DNS record used to resolve default route host names. In dual stack clusters this list contains two IPs otherwise only one.", "nodeDNSIP": "nodeDNSIP is the IP address for the internal DNS used by the nodes. Unlike the one managed by the DNS operator, `NodeDNSIP` provides name resolution for the nodes themselves. There is no DNS-as-a-service for vSphere deployments. In order to minimize necessary changes to the datacenter DNS, a DNS service is hosted as a static pod to serve those hostnames to the nodes in the cluster.", "loadBalancer": "loadBalancer defines how the load balancer used by the cluster is configured.", + "dnsRecordsType": "dnsRecordsType determines whether records for api, api-int, and ingress are provided by the internal DNS service or externally. Allowed values are `Internal`, `External`, and omitted. When set to `Internal`, records are provided by the internal infrastructure and no additional user configuration is required for the cluster to function. When set to `External`, records are not provided by the internal infrastructure and must be configured by the user on a DNS server outside the cluster. Cluster nodes must use this external server for their upstream DNS requests. This value may only be set when loadBalancer.type is set to UserManaged. When omitted, this means the user has no opinion and the platform is left to choose reasonable defaults. These defaults are subject to change over time. The current default is `Internal`.", "machineNetworks": "machineNetworks are IP networks used to connect all the OpenShift cluster nodes.", } diff --git a/vendor/github.com/openshift/api/envtest-releases.yaml b/vendor/github.com/openshift/api/envtest-releases.yaml index e8688e2b06..e495e02796 100644 --- a/vendor/github.com/openshift/api/envtest-releases.yaml +++ b/vendor/github.com/openshift/api/envtest-releases.yaml @@ -64,3 +64,16 @@ releases: envtest-v1.33.2-linux-arm64.tar.gz: hash: 9936eba66fd0170808268da4c0609b7e7d4d1b0de8607b0d3a9091539b4ec881041a9e08e7b4839708b11139bcc850acd34dfc0305ed955cc61fc3fae9da58f5 selfLink: https://storage.googleapis.com/openshift-kubebuilder-tools/envtest-v1.33.2-linux-arm64.tar.gz + v1.34.1: + envtest-v1.34.1-darwin-amd64.tar.gz: + hash: 3bf575e77d35803b81685969915d70ae23f2267bafd1fe17087126d6fcdfe67590d2f51ce59ff8f0d06e5d94b0f4d0ac3c16de1544008e9c617499cfc51844c5 + selfLink: https://storage.googleapis.com/openshift-kubebuilder-tools/envtest-v1.34.1-darwin-amd64.tar.gz + envtest-v1.34.1-darwin-arm64.tar.gz: + hash: 3c9c1d457d3fbb5c5cfb6e6c4ac31b41172cf413b9a81f8f53ac717a643f730d135d4d09549f9d78685c23704a7e3f12c891896dc23c4b1a211a10e1fd9bc043 + selfLink: https://storage.googleapis.com/openshift-kubebuilder-tools/envtest-v1.34.1-darwin-arm64.tar.gz + envtest-v1.34.1-linux-amd64.tar.gz: + hash: e5aeda6d9f9456e27c5c001bc4476a0bccc06f1431c2a9752a2ac040f69671927204dcc254bba8ebb2fb91d0e32620abfaba6daad6a80dbe376d93e57fcd2431 + selfLink: https://storage.googleapis.com/openshift-kubebuilder-tools/envtest-v1.34.1-linux-amd64.tar.gz + envtest-v1.34.1-linux-arm64.tar.gz: + hash: e2ee7e47ceeba56624fd869922ab9851200482ef835c09fe3dd57c9806a992a7e1f56641906510ebb095514953aa8a3af68d45a82be45b94981a50e894ac6e42 + selfLink: https://storage.googleapis.com/openshift-kubebuilder-tools/envtest-v1.34.1-linux-arm64.tar.gz diff --git a/vendor/github.com/openshift/api/features.md b/vendor/github.com/openshift/api/features.md index 54c9fd3dea..64a97692ef 100644 --- a/vendor/github.com/openshift/api/features.md +++ b/vendor/github.com/openshift/api/features.md @@ -5,17 +5,16 @@ | MachineAPIOperatorDisableMachineHealthCheckController| | | | | | | | MultiArchInstallAzure| | | | | | | | ShortCertRotation| | | | | | | -| BootImageSkewEnforcement| | | Enabled | Enabled | | | | ClusterAPIMachineManagementVSphere| | | Enabled | Enabled | | | | Example2| | | Enabled | Enabled | | | | ExternalSnapshotMetadata| | | Enabled | Enabled | | | +| IngressControllerDynamicConfigurationManager| | | Enabled | Enabled | | | | NewOLMCatalogdAPIV1Metas| | | | Enabled | | Enabled | | NewOLMOwnSingleNamespace| | | | Enabled | | Enabled | | NewOLMPreflightPermissionChecks| | | | Enabled | | Enabled | -| NewOLMWebhookProviderOpenshiftServiceCA| | | | Enabled | | Enabled | | NoRegistryClusterOperations| | | | Enabled | | Enabled | -| VSphereMixedNodeEnv| | | Enabled | Enabled | | | | NewOLM| | Enabled | | Enabled | | Enabled | +| NewOLMWebhookProviderOpenshiftServiceCA| | Enabled | | Enabled | | Enabled | | AWSClusterHostedDNS| | | Enabled | Enabled | Enabled | Enabled | | AWSClusterHostedDNSInstall| | | Enabled | Enabled | Enabled | Enabled | | AWSDedicatedHosts| | | Enabled | Enabled | Enabled | Enabled | @@ -26,11 +25,14 @@ | AzureDedicatedHosts| | | Enabled | Enabled | Enabled | Enabled | | AzureDualStackInstall| | | Enabled | Enabled | Enabled | Enabled | | AzureMultiDisk| | | Enabled | Enabled | Enabled | Enabled | +| BootImageSkewEnforcement| | | Enabled | Enabled | Enabled | Enabled | | BootcNodeManagement| | | Enabled | Enabled | Enabled | Enabled | | CBORServingAndStorage| | | Enabled | Enabled | Enabled | Enabled | +| CRDCompatibilityRequirementOperator| | | Enabled | Enabled | Enabled | Enabled | | ClientsAllowCBOR| | | Enabled | Enabled | Enabled | Enabled | | ClientsPreferCBOR| | | Enabled | Enabled | Enabled | Enabled | | ClusterAPIInstallIBMCloud| | | Enabled | Enabled | Enabled | Enabled | +| ClusterAPIMachineManagement| | | Enabled | Enabled | Enabled | Enabled | | ClusterMonitoringConfig| | | Enabled | Enabled | Enabled | Enabled | | ClusterVersionOperatorConfiguration| | | Enabled | Enabled | Enabled | Enabled | | DNSNameResolver| | | Enabled | Enabled | Enabled | Enabled | @@ -46,29 +48,29 @@ | GCPDualStackInstall| | | Enabled | Enabled | Enabled | Enabled | | ImageModeStatusReporting| | | Enabled | Enabled | Enabled | Enabled | | ImageStreamImportMode| | | Enabled | Enabled | Enabled | Enabled | -| IngressControllerDynamicConfigurationManager| | | Enabled | Enabled | Enabled | Enabled | | InsightsConfig| | | Enabled | Enabled | Enabled | Enabled | | InsightsOnDemandDataGather| | | Enabled | Enabled | Enabled | Enabled | | IrreconcilableMachineConfig| | | Enabled | Enabled | Enabled | Enabled | | KMSEncryptionProvider| | | Enabled | Enabled | Enabled | Enabled | | MachineAPIMigration| | | Enabled | Enabled | Enabled | Enabled | -| ManagedBootImagesAzure| | | Enabled | Enabled | Enabled | Enabled | | ManagedBootImagesCPMS| | | Enabled | Enabled | Enabled | Enabled | -| ManagedBootImagesvSphere| | | Enabled | Enabled | Enabled | Enabled | | MaxUnavailableStatefulSet| | | Enabled | Enabled | Enabled | Enabled | | MinimumKubeletVersion| | | Enabled | Enabled | Enabled | Enabled | | MixedCPUsAllocation| | | Enabled | Enabled | Enabled | Enabled | | MultiDiskSetup| | | Enabled | Enabled | Enabled | Enabled | +| MutableCSINodeAllocatableCount| | | Enabled | Enabled | Enabled | Enabled | | MutatingAdmissionPolicy| | | Enabled | Enabled | Enabled | Enabled | | NutanixMultiSubnets| | | Enabled | Enabled | Enabled | Enabled | +| OSStreams| | | Enabled | Enabled | Enabled | Enabled | | OVNObservability| | | Enabled | Enabled | Enabled | Enabled | -| PreconfiguredUDNAddresses| | | Enabled | Enabled | Enabled | Enabled | +| OnPremDNSRecords| | | Enabled | Enabled | Enabled | Enabled | | SELinuxMount| | | Enabled | Enabled | Enabled | Enabled | | SignatureStores| | | Enabled | Enabled | Enabled | Enabled | | SigstoreImageVerificationPKI| | | Enabled | Enabled | Enabled | Enabled | | TranslateStreamCloseWebsocketRequests| | | Enabled | Enabled | Enabled | Enabled | | VSphereConfigurableMaxAllowedBlockVolumesPerNode| | | Enabled | Enabled | Enabled | Enabled | | VSphereHostVMGroupZonal| | | Enabled | Enabled | Enabled | Enabled | +| VSphereMixedNodeEnv| | | Enabled | Enabled | Enabled | Enabled | | VolumeGroupSnapshot| | | Enabled | Enabled | Enabled | Enabled | | AdditionalRoutingCapabilities| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | AdminNetworkPolicy| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | @@ -88,12 +90,15 @@ | MachineConfigNodes| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | ManagedBootImages| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | ManagedBootImagesAWS| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | +| ManagedBootImagesAzure| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | +| ManagedBootImagesvSphere| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | MetricsCollectionProfiles| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | NetworkDiagnosticsConfig| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | NetworkLiveMigration| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | NetworkSegmentation| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | OpenShiftPodSecurityAdmission| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | PinnedImages| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | +| PreconfiguredUDNAddresses| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | ProcMountType| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | RouteAdvertisements| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | | RouteExternalCertificate| Enabled | Enabled | Enabled | Enabled | Enabled | Enabled | diff --git a/vendor/github.com/openshift/api/features/features.go b/vendor/github.com/openshift/api/features/features.go index 5d3836a436..9c74d4c2df 100644 --- a/vendor/github.com/openshift/api/features/features.go +++ b/vendor/github.com/openshift/api/features/features.go @@ -342,7 +342,7 @@ var ( contactPerson("rsaini"). productScope(ocpSpecific). enhancementPR("https://github.com/openshift/enhancements/pull/1496"). - enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() FeatureGateManagedBootImagesAzure = newFeatureGate("ManagedBootImagesAzure"). @@ -350,7 +350,7 @@ var ( contactPerson("djoshy"). productScope(ocpSpecific). enhancementPR("https://github.com/openshift/enhancements/pull/1761"). - enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + enableIn(configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() FeatureGateManagedBootImagesCPMS = newFeatureGate("ManagedBootImagesCPMS"). @@ -366,7 +366,7 @@ var ( contactPerson("djoshy"). productScope(ocpSpecific). enhancementPR("https://github.com/openshift/enhancements/pull/1761"). - enableIn(configv1.DevPreviewNoUpgrade). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() FeatureGateBootcNodeManagement = newFeatureGate("BootcNodeManagement"). @@ -509,8 +509,8 @@ var ( reportProblemsToJiraComponent("olm"). contactPerson("pegoncal"). productScope(ocpSpecific). - enhancementPR("https://github.com/openshift/enhancements/pull/1799"). - enableForClusterProfile(SelfManaged, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + enhancementPR("https://github.com/openshift/enhancements/pull/1844"). + enableForClusterProfile(SelfManaged, configv1.Default, configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() FeatureGateInsightsOnDemandDataGather = newFeatureGate("InsightsOnDemandDataGather"). @@ -553,6 +553,14 @@ var ( enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() + FeatureGateClusterAPIMachineManagement = newFeatureGate("ClusterAPIMachineManagement"). + reportProblemsToJiraComponent("Cloud Compute / Cluster API Providers"). + contactPerson("ddonati"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1465"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + FeatureGateClusterAPIMachineManagementVSphere = newFeatureGate("ClusterAPIMachineManagementVSphere"). reportProblemsToJiraComponent("SPLAT"). contactPerson("jcpowermac"). @@ -624,7 +632,7 @@ var ( contactPerson("miciah"). productScope(ocpSpecific). enhancementPR(legacyFeatureGateWithoutEnhancement). - enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + enableIn(configv1.DevPreviewNoUpgrade). mustRegister() FeatureGateMinimumKubeletVersion = newFeatureGate("MinimumKubeletVersion"). @@ -752,8 +760,8 @@ var ( mustRegister() FeatureGateAWSDedicatedHosts = newFeatureGate("AWSDedicatedHosts"). - reportProblemsToJiraComponent("Installer"). - contactPerson("faermanj"). + reportProblemsToJiraComponent("splat"). + contactPerson("rvanderp3"). productScope(ocpSpecific). enhancementPR("https://github.com/openshift/enhancements/pull/1781"). enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). @@ -764,7 +772,7 @@ var ( contactPerson("vr4manta"). productScope(ocpSpecific). enhancementPR("https://github.com/openshift/enhancements/pull/1772"). - enableIn(configv1.DevPreviewNoUpgrade). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() FeatureGatePreconfiguredUDNAddresses = newFeatureGate("PreconfiguredUDNAddresses"). @@ -772,7 +780,7 @@ var ( contactPerson("kyrtapz"). productScope(ocpSpecific). enhancementPR("https://github.com/openshift/enhancements/pull/1793"). - enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade, configv1.Default). mustRegister() FeatureGateAWSServiceLBNetworkSecurityGroup = newFeatureGate("AWSServiceLBNetworkSecurityGroup"). @@ -885,4 +893,34 @@ var ( enhancementPR("https://github.com/openshift/enhancements/pull/1857"). enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() + + FeatureGateMutableCSINodeAllocatableCount = newFeatureGate("MutableCSINodeAllocatableCount"). + reportProblemsToJiraComponent("Storage / Kubernetes External Components"). + contactPerson("jsafrane"). + productScope(kubernetes). + enhancementPR("https://github.com/kubernetes/enhancements/issues/4876"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + FeatureGateOSStreams = newFeatureGate("OSStreams"). + reportProblemsToJiraComponent("MachineConfigOperator"). + contactPerson("pabrodri"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1874"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + + FeatureGateCRDCompatibilityRequirementOperator = newFeatureGate("CRDCompatibilityRequirementOperator"). + reportProblemsToJiraComponent("Cloud Compute / Cluster API Providers"). + contactPerson("ddonati"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1845"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + FeatureGateOnPremDNSRecords = newFeatureGate("OnPremDNSRecords"). + reportProblemsToJiraComponent("Networking / On-Prem DNS"). + contactPerson("bnemec"). + productScope(ocpSpecific). + enhancementPR("https://github.com/openshift/enhancements/pull/1803"). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() ) diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_awsprovider.go b/vendor/github.com/openshift/api/machine/v1beta1/types_awsprovider.go index b3b38bc6cc..161f2324c2 100644 --- a/vendor/github.com/openshift/api/machine/v1beta1/types_awsprovider.go +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_awsprovider.go @@ -114,6 +114,14 @@ type AWSMachineProviderConfig struct { // If this value is selected, capacityReservationID must be specified to identify the target reservation. // +optional MarketType MarketType `json:"marketType,omitempty"` + + // hostPlacement configures placement on AWS Dedicated Hosts. This allows admins to assign instances to specific host + // for a variety of needs including for regulatory compliance, to leverage existing per-socket or per-core software licenses (BYOL), + // and to gain visibility and control over instance placement on a physical server. + // When omitted, the instance is not constrained to a dedicated host. + // +openshift:enable:FeatureGate=AWSDedicatedHosts + // +optional + HostPlacement *HostPlacement `json:"hostPlacement,omitempty"` } // AWSConfidentialComputePolicy represents the confidential compute configuration for the instance. @@ -393,3 +401,46 @@ const ( // When set to CapacityBlock the instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations. MarketTypeCapacityBlock MarketType = "CapacityBlock" ) + +// HostPlacement is the type that will be used to configure the placement of AWS instances. +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.affinity == 'DedicatedHost' ? has(self.dedicatedHost) : !has(self.dedicatedHost)",message="dedicatedHost is required when affinity is DedicatedHost, and forbidden otherwise" +// +union +type HostPlacement struct { + // affinity specifies the affinity setting for the instance. + // Allowed values are AnyAvailable and DedicatedHost. + // When Affinity is set to DedicatedHost, an instance started onto a specific host always restarts on the same host if stopped. In this scenario, the `dedicatedHost` field must be set. + // When Affinity is set to AnyAvailable, and you stop and restart the instance, it can be restarted on any available host. + // +required + // +unionDiscriminator + Affinity *HostAffinity `json:"affinity,omitempty"` + + // dedicatedHost specifies the exact host that an instance should be restarted on if stopped. + // dedicatedHost is required when 'affinity' is set to DedicatedHost, and forbidden otherwise. + // +optional + // +unionMember + DedicatedHost *DedicatedHost `json:"dedicatedHost,omitempty"` +} + +// HostAffinity selects how an instance should be placed on AWS Dedicated Hosts. +// +kubebuilder:validation:Enum:=DedicatedHost;AnyAvailable +type HostAffinity string + +const ( + // HostAffinityAnyAvailable lets the platform select any available dedicated host. + HostAffinityAnyAvailable HostAffinity = "AnyAvailable" + + // HostAffinityDedicatedHost requires specifying a particular host via dedicatedHost.host.hostID. + HostAffinityDedicatedHost HostAffinity = "DedicatedHost" +) + +// DedicatedHost represents the configuration for the usage of dedicated host. +type DedicatedHost struct { + // id identifies the AWS Dedicated Host on which the instance must run. + // The value must start with "h-" followed by 17 lowercase hexadecimal characters (0-9 and a-f). + // Must be exactly 19 characters in length. + // +kubebuilder:validation:XValidation:rule="self.matches('^h-[0-9a-f]{17}$')",message="hostID must start with 'h-' followed by 17 lowercase hexadecimal characters (0-9 and a-f)" + // +kubebuilder:validation:MinLength=19 + // +kubebuilder:validation:MaxLength=19 + // +required + ID string `json:"id,omitempty"` +} diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_gcpprovider.go b/vendor/github.com/openshift/api/machine/v1beta1/types_gcpprovider.go index 72a31b5bdd..9713a4e4a8 100644 --- a/vendor/github.com/openshift/api/machine/v1beta1/types_gcpprovider.go +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_gcpprovider.go @@ -25,6 +25,14 @@ const ( RestartPolicyNever GCPRestartPolicyType = "Never" ) +// GCPProvisioningModelType is a type representing acceptable values for ProvisioningModel field in GCPMachineProviderSpec +type GCPProvisioningModelType string + +const ( + // GCPSpotInstance enables the GCP instances as spot instances which provide significant cost savings but may be preempted by Google Cloud Platform when resources are needed elsewhere. + GCPSpotInstance GCPProvisioningModelType = "Spot" +) + // SecureBootPolicy represents the secure boot configuration for the GCP machine. type SecureBootPolicy string @@ -129,6 +137,14 @@ type GCPMachineProviderSpec struct { // preemptible indicates if created instance is preemptible. // +optional Preemptible bool `json:"preemptible,omitempty"` + // provisioningModel is an optional field that determines the provisioning model for the GCP machine instance. + // Valid values are "Spot" and omitted. + // When set to Spot, the instance runs as a Google Cloud Spot instance which provides significant cost savings but may be preempted by Google Cloud Platform when resources are needed elsewhere. + // When omitted, the machine will be provisioned as a standard on-demand instance. + // This field cannot be used together with the preemptible field. + // +optional + // +kubebuilder:validation:Enum=Spot + ProvisioningModel *GCPProvisioningModelType `json:"provisioningModel,omitempty"` // onHostMaintenance determines the behavior when a maintenance event occurs that might cause the instance to reboot. // This is required to be set to "Terminate" if you want to provision machine with attached GPUs. // Otherwise, allowed values are "Migrate" and "Terminate". diff --git a/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.deepcopy.go index 5aa4f90a49..92586dcdf1 100644 --- a/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.deepcopy.go @@ -85,6 +85,11 @@ func (in *AWSMachineProviderConfig) DeepCopyInto(out *AWSMachineProviderConfig) *out = new(int32) **out = **in } + if in.HostPlacement != nil { + in, out := &in.HostPlacement, &out.HostPlacement + *out = new(HostPlacement) + (*in).DeepCopyInto(*out) + } return } @@ -509,6 +514,22 @@ func (in *DataDiskManagedDiskParameters) DeepCopy() *DataDiskManagedDiskParamete return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DedicatedHost) DeepCopyInto(out *DedicatedHost) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DedicatedHost. +func (in *DedicatedHost) DeepCopy() *DedicatedHost { + if in == nil { + return nil + } + out := new(DedicatedHost) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DiskEncryptionSetParameters) DeepCopyInto(out *DiskEncryptionSetParameters) { *out = *in @@ -762,6 +783,11 @@ func (in *GCPMachineProviderSpec) DeepCopyInto(out *GCPMachineProviderSpec) { *out = make([]GCPGPUConfig, len(*in)) copy(*out, *in) } + if in.ProvisioningModel != nil { + in, out := &in.ProvisioningModel, &out.ProvisioningModel + *out = new(GCPProvisioningModelType) + **out = **in + } out.ShieldedInstanceConfig = in.ShieldedInstanceConfig if in.ResourceManagerTags != nil { in, out := &in.ResourceManagerTags, &out.ResourceManagerTags @@ -898,6 +924,32 @@ func (in *GCPShieldedInstanceConfig) DeepCopy() *GCPShieldedInstanceConfig { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *HostPlacement) DeepCopyInto(out *HostPlacement) { + *out = *in + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(HostAffinity) + **out = **in + } + if in.DedicatedHost != nil { + in, out := &in.DedicatedHost, &out.DedicatedHost + *out = new(DedicatedHost) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostPlacement. +func (in *HostPlacement) DeepCopy() *HostPlacement { + if in == nil { + return nil + } + out := new(HostPlacement) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Image) DeepCopyInto(out *Image) { *out = *in diff --git a/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.swagger_doc_generated.go index 4a1b969a81..23b6eddd37 100644 --- a/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.swagger_doc_generated.go @@ -35,6 +35,7 @@ var map_AWSMachineProviderConfig = map[string]string{ "placementGroupPartition": "placementGroupPartition is the partition number within the placement group in which to launch the instance. This must be an integer value between 1 and 7. It is only valid if the placement group, referred in `PlacementGroupName` was created with strategy set to partition.", "capacityReservationId": "capacityReservationId specifies the target Capacity Reservation into which the instance should be launched. The field size should be greater than 0 and the field input must start with cr-***", "marketType": "marketType specifies the type of market for the EC2 instance. Valid values are OnDemand, Spot, CapacityBlock and omitted.\n\nDefaults to OnDemand. When SpotMarketOptions is provided, the marketType defaults to \"Spot\".\n\nWhen set to OnDemand the instance runs as a standard OnDemand instance. When set to Spot the instance runs as a Spot instance. When set to CapacityBlock the instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations. If this value is selected, capacityReservationID must be specified to identify the target reservation.", + "hostPlacement": "hostPlacement configures placement on AWS Dedicated Hosts. This allows admins to assign instances to specific host for a variety of needs including for regulatory compliance, to leverage existing per-socket or per-core software licenses (BYOL), and to gain visibility and control over instance placement on a physical server. When omitted, the instance is not constrained to a dedicated host.", } func (AWSMachineProviderConfig) SwaggerDoc() map[string]string { @@ -92,6 +93,15 @@ func (CPUOptions) SwaggerDoc() map[string]string { return map_CPUOptions } +var map_DedicatedHost = map[string]string{ + "": "DedicatedHost represents the configuration for the usage of dedicated host.", + "id": "id identifies the AWS Dedicated Host on which the instance must run. The value must start with \"h-\" followed by 17 lowercase hexadecimal characters (0-9 and a-f). Must be exactly 19 characters in length.", +} + +func (DedicatedHost) SwaggerDoc() map[string]string { + return map_DedicatedHost +} + var map_EBSBlockDeviceSpec = map[string]string{ "": "EBSBlockDeviceSpec describes a block device for an EBS volume. https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/EbsBlockDevice", "deleteOnTermination": "Indicates whether the EBS volume is deleted on machine termination.\n\nDeprecated: setting this field has no effect.", @@ -116,6 +126,16 @@ func (Filter) SwaggerDoc() map[string]string { return map_Filter } +var map_HostPlacement = map[string]string{ + "": "HostPlacement is the type that will be used to configure the placement of AWS instances.", + "affinity": "affinity specifies the affinity setting for the instance. Allowed values are AnyAvailable and DedicatedHost. When Affinity is set to DedicatedHost, an instance started onto a specific host always restarts on the same host if stopped. In this scenario, the `dedicatedHost` field must be set. When Affinity is set to AnyAvailable, and you stop and restart the instance, it can be restarted on any available host.", + "dedicatedHost": "dedicatedHost specifies the exact host that an instance should be restarted on if stopped. dedicatedHost is required when 'affinity' is set to DedicatedHost, and forbidden otherwise.", +} + +func (HostPlacement) SwaggerDoc() map[string]string { + return map_HostPlacement +} + var map_LoadBalancerReference = map[string]string{ "": "LoadBalancerReference is a reference to a load balancer on AWS.", } @@ -452,6 +472,7 @@ var map_GCPMachineProviderSpec = map[string]string{ "projectID": "projectID is the project in which the GCP machine provider will create the VM.", "gpus": "gpus is a list of GPUs to be attached to the VM.", "preemptible": "preemptible indicates if created instance is preemptible.", + "provisioningModel": "provisioningModel is an optional field that determines the provisioning model for the GCP machine instance. Valid values are \"Spot\" and omitted. When set to Spot, the instance runs as a Google Cloud Spot instance which provides significant cost savings but may be preempted by Google Cloud Platform when resources are needed elsewhere. When omitted, the machine will be provisioned as a standard on-demand instance. This field cannot be used together with the preemptible field.", "onHostMaintenance": "onHostMaintenance determines the behavior when a maintenance event occurs that might cause the instance to reboot. This is required to be set to \"Terminate\" if you want to provision machine with attached GPUs. Otherwise, allowed values are \"Migrate\" and \"Terminate\". If omitted, the platform chooses a default, which is subject to change over time, currently that default is \"Migrate\".", "restartPolicy": "restartPolicy determines the behavior when an instance crashes or the underlying infrastructure provider stops the instance as part of a maintenance event (default \"Always\"). Cannot be \"Always\" with preemptible instances. Otherwise, allowed values are \"Always\" and \"Never\". If omitted, the platform chooses a default, which is subject to change over time, currently that default is \"Always\". RestartPolicy represents AutomaticRestart in GCP compute api", "shieldedInstanceConfig": "shieldedInstanceConfig is the Shielded VM configuration for the VM", diff --git a/vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go b/vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go index 2799904482..53c71aabb6 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go +++ b/vendor/github.com/openshift/api/operator/v1/types_csi_cluster_driver.go @@ -81,7 +81,6 @@ const ( CinderCSIDriver CSIDriverName = "cinder.csi.openstack.org" VSphereCSIDriver CSIDriverName = "csi.vsphere.vmware.com" ManilaCSIDriver CSIDriverName = "manila.csi.openstack.org" - OvirtCSIDriver CSIDriverName = "csi.ovirt.org" KubevirtCSIDriver CSIDriverName = "csi.kubevirt.io" SharedResourcesCSIDriver CSIDriverName = "csi.sharedresource.openshift.io" AlibabaDiskCSIDriver CSIDriverName = "diskplugin.csi.alibabacloud.com" diff --git a/vendor/github.com/openshift/api/operator/v1/types_ingress.go b/vendor/github.com/openshift/api/operator/v1/types_ingress.go index 2dac08f099..46b906518d 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_ingress.go +++ b/vendor/github.com/openshift/api/operator/v1/types_ingress.go @@ -35,6 +35,7 @@ import ( // // Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). // +openshift:compatibility-gen:level=1 +// +kubebuilder:validation:XValidation:rule="!has(self.spec.domain) || size('router-' + self.metadata.name + '.' + self.spec.domain) <= 253",message="The combined 'router-' + metadata.name + '.' + .spec.domain cannot exceed 253 characters" type IngressController struct { metav1.TypeMeta `json:",inline"` @@ -68,6 +69,22 @@ type IngressControllerSpec struct { // // If empty, defaults to ingress.config.openshift.io/cluster .spec.domain. // + // The domain value must be a valid DNS name. It must consist of lowercase + // alphanumeric characters, '-' or '.', and each label must start and end + // with an alphanumeric character and not exceed 63 characters. Maximum + // length of a valid DNS domain is 253 characters. + // + // The implementation may add a prefix such as "router-default." to the domain + // when constructing the router canonical hostname. To ensure the resulting + // hostname does not exceed the DNS maximum length of 253 characters, + // the domain length is additionally validated at the IngressController object + // level. For the maximum length of the domain value itself, the shortest + // possible variant of the prefix and the ingress controller name was considered + // for example "router-a." + // + // +kubebuilder:validation:MaxLength=244 + // +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="domain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character" + // +kubebuilder:validation:XValidation:rule="self.split('.').all(label, size(label) <= 63)",message="each DNS label must not exceed 63 characters" // +optional Domain string `json:"domain,omitempty"` diff --git a/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go index 483d9720da..d3475d9024 100644 --- a/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.go @@ -1063,7 +1063,7 @@ func (IngressControllerSetHTTPHeader) SwaggerDoc() map[string]string { var map_IngressControllerSpec = map[string]string{ "": "IngressControllerSpec is the specification of the desired behavior of the IngressController.", - "domain": "domain is a DNS name serviced by the ingress controller and is used to configure multiple features:\n\n* For the LoadBalancerService endpoint publishing strategy, domain is\n used to configure DNS records. See endpointPublishingStrategy.\n\n* When using a generated default certificate, the certificate will be valid\n for domain and its subdomains. See defaultCertificate.\n\n* The value is published to individual Route statuses so that end-users\n know where to target external DNS records.\n\ndomain must be unique among all IngressControllers, and cannot be updated.\n\nIf empty, defaults to ingress.config.openshift.io/cluster .spec.domain.", + "domain": "domain is a DNS name serviced by the ingress controller and is used to configure multiple features:\n\n* For the LoadBalancerService endpoint publishing strategy, domain is\n used to configure DNS records. See endpointPublishingStrategy.\n\n* When using a generated default certificate, the certificate will be valid\n for domain and its subdomains. See defaultCertificate.\n\n* The value is published to individual Route statuses so that end-users\n know where to target external DNS records.\n\ndomain must be unique among all IngressControllers, and cannot be updated.\n\nIf empty, defaults to ingress.config.openshift.io/cluster .spec.domain.\n\nThe domain value must be a valid DNS name. It must consist of lowercase alphanumeric characters, '-' or '.', and each label must start and end with an alphanumeric character and not exceed 63 characters. Maximum length of a valid DNS domain is 253 characters.\n\nThe implementation may add a prefix such as \"router-default.\" to the domain when constructing the router canonical hostname. To ensure the resulting hostname does not exceed the DNS maximum length of 253 characters, the domain length is additionally validated at the IngressController object level. For the maximum length of the domain value itself, the shortest possible variant of the prefix and the ingress controller name was considered for example \"router-a.\"", "httpErrorCodePages": "httpErrorCodePages specifies a configmap with custom error pages. The administrator must create this configmap in the openshift-config namespace. This configmap should have keys in the format \"error-page-.http\", where is an HTTP error code. For example, \"error-page-503.http\" defines an error page for HTTP 503 responses. Currently only error pages for 503 and 404 responses can be customized. Each value in the configmap should be the full response, including HTTP headers. Eg- https://raw.githubusercontent.com/openshift/router/fadab45747a9b30cc3f0a4b41ad2871f95827a93/images/router/haproxy/conf/error-page-503.http If this field is empty, the ingress controller uses the default error pages.", "replicas": "replicas is the desired number of ingress controller replicas. If unset, the default depends on the value of the defaultPlacement field in the cluster config.openshift.io/v1/ingresses status.\n\nThe value of replicas is set based on the value of a chosen field in the Infrastructure CR. If defaultPlacement is set to ControlPlane, the chosen field will be controlPlaneTopology. If it is set to Workers the chosen field will be infrastructureTopology. Replicas will then be set to 1 or 2 based whether the chosen field's value is SingleReplica or HighlyAvailable, respectively.\n\nThese defaults are subject to change.", "endpointPublishingStrategy": "endpointPublishingStrategy is used to publish the ingress controller endpoints to other networks, enable load balancer integrations, etc.\n\nIf unset, the default is based on infrastructure.config.openshift.io/cluster .status.platform:\n\n AWS: LoadBalancerService (with External scope)\n Azure: LoadBalancerService (with External scope)\n GCP: LoadBalancerService (with External scope)\n IBMCloud: LoadBalancerService (with External scope)\n AlibabaCloud: LoadBalancerService (with External scope)\n Libvirt: HostNetwork\n\nAny other platform types (including None) default to HostNetwork.\n\nendpointPublishingStrategy cannot be updated.", diff --git a/vendor/github.com/openshift/api/route/v1/generated.proto b/vendor/github.com/openshift/api/route/v1/generated.proto index e055eb0d26..85018b16b7 100644 --- a/vendor/github.com/openshift/api/route/v1/generated.proto +++ b/vendor/github.com/openshift/api/route/v1/generated.proto @@ -413,10 +413,12 @@ message RouterShard { // +kubebuilder:validation:XValidation:rule="has(self.termination) && has(self.insecureEdgeTerminationPolicy) ? !((self.termination=='passthrough') && (self.insecureEdgeTerminationPolicy=='Allow')) : true", message="cannot have both spec.tls.termination: passthrough and spec.tls.insecureEdgeTerminationPolicy: Allow" // +openshift:validation:FeatureGateAwareXValidation:featureGate=RouteExternalCertificate,rule="!(has(self.certificate) && has(self.externalCertificate))", message="cannot have both spec.tls.certificate and spec.tls.externalCertificate" message TLSConfig { - // termination indicates termination type. + // termination indicates the TLS termination type. // // * edge - TLS termination is done by the router and http is used to communicate with the backend (default) + // // * passthrough - Traffic is sent straight to the destination without the router providing TLS termination + // // * reencrypt - TLS termination is done by the router and https is used to communicate with the backend // // Note: passthrough termination is incompatible with httpHeader actions diff --git a/vendor/github.com/openshift/api/route/v1/types.go b/vendor/github.com/openshift/api/route/v1/types.go index 5a61f477e7..35c4064825 100644 --- a/vendor/github.com/openshift/api/route/v1/types.go +++ b/vendor/github.com/openshift/api/route/v1/types.go @@ -424,10 +424,12 @@ type RouterShard struct { // +kubebuilder:validation:XValidation:rule="has(self.termination) && has(self.insecureEdgeTerminationPolicy) ? !((self.termination=='passthrough') && (self.insecureEdgeTerminationPolicy=='Allow')) : true", message="cannot have both spec.tls.termination: passthrough and spec.tls.insecureEdgeTerminationPolicy: Allow" // +openshift:validation:FeatureGateAwareXValidation:featureGate=RouteExternalCertificate,rule="!(has(self.certificate) && has(self.externalCertificate))", message="cannot have both spec.tls.certificate and spec.tls.externalCertificate" type TLSConfig struct { - // termination indicates termination type. + // termination indicates the TLS termination type. // // * edge - TLS termination is done by the router and http is used to communicate with the backend (default) + // // * passthrough - Traffic is sent straight to the destination without the router providing TLS termination + // // * reencrypt - TLS termination is done by the router and https is used to communicate with the backend // // Note: passthrough termination is incompatible with httpHeader actions diff --git a/vendor/github.com/openshift/api/route/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/route/v1/zz_generated.swagger_doc_generated.go index e6c44a6b02..4c8f9eeddf 100644 --- a/vendor/github.com/openshift/api/route/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/route/v1/zz_generated.swagger_doc_generated.go @@ -173,7 +173,7 @@ func (RouterShard) SwaggerDoc() map[string]string { var map_TLSConfig = map[string]string{ "": "TLSConfig defines config used to secure a route and provide termination", - "termination": "termination indicates termination type.\n\n* edge - TLS termination is done by the router and http is used to communicate with the backend (default) * passthrough - Traffic is sent straight to the destination without the router providing TLS termination * reencrypt - TLS termination is done by the router and https is used to communicate with the backend\n\nNote: passthrough termination is incompatible with httpHeader actions", + "termination": "termination indicates the TLS termination type.\n\n* edge - TLS termination is done by the router and http is used to communicate with the backend (default)\n\n* passthrough - Traffic is sent straight to the destination without the router providing TLS termination\n\n* reencrypt - TLS termination is done by the router and https is used to communicate with the backend\n\nNote: passthrough termination is incompatible with httpHeader actions", "certificate": "certificate provides certificate contents. This should be a single serving certificate, not a certificate chain. Do not include a CA certificate.", "key": "key provides key file contents", "caCertificate": "caCertificate provides the cert authority certificate contents", diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go index 88bd00b251..0b52c3a324 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/admissionregistration.go @@ -415,3 +415,51 @@ func ApplyValidatingAdmissionPolicyBindingV1(ctx context.Context, client admissi cache.UpdateCachedResourceMetadata(requiredOriginal, actual) return actual, true, nil } + +func DeleteValidatingAdmissionPolicyV1beta1(ctx context.Context, client admissionregistrationclientv1beta1.ValidatingAdmissionPoliciesGetter, recorder events.Recorder, required *admissionregistrationv1beta1.ValidatingAdmissionPolicy) (*admissionregistrationv1beta1.ValidatingAdmissionPolicy, bool, error) { + err := client.ValidatingAdmissionPolicies().Delete(ctx, required.Name, metav1.DeleteOptions{}) + if err != nil && apierrors.IsNotFound(err) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + resourcehelper.ReportDeleteEvent(recorder, required, err) + return nil, true, nil +} + +func DeleteValidatingAdmissionPolicyBindingV1beta1(ctx context.Context, client admissionregistrationclientv1beta1.ValidatingAdmissionPolicyBindingsGetter, recorder events.Recorder, required *admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding) (*admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding, bool, error) { + err := client.ValidatingAdmissionPolicyBindings().Delete(ctx, required.Name, metav1.DeleteOptions{}) + if err != nil && apierrors.IsNotFound(err) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + resourcehelper.ReportDeleteEvent(recorder, required, err) + return nil, true, nil +} + +func DeleteValidatingAdmissionPolicyV1(ctx context.Context, client admissionregistrationclientv1.ValidatingAdmissionPoliciesGetter, recorder events.Recorder, required *admissionregistrationv1.ValidatingAdmissionPolicy) (*admissionregistrationv1.ValidatingAdmissionPolicy, bool, error) { + err := client.ValidatingAdmissionPolicies().Delete(ctx, required.Name, metav1.DeleteOptions{}) + if err != nil && apierrors.IsNotFound(err) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + resourcehelper.ReportDeleteEvent(recorder, required, err) + return nil, true, nil +} + +func DeleteValidatingAdmissionPolicyBindingV1(ctx context.Context, client admissionregistrationclientv1.ValidatingAdmissionPolicyBindingsGetter, recorder events.Recorder, required *admissionregistrationv1.ValidatingAdmissionPolicyBinding) (*admissionregistrationv1.ValidatingAdmissionPolicyBinding, bool, error) { + err := client.ValidatingAdmissionPolicyBindings().Delete(ctx, required.Name, metav1.DeleteOptions{}) + if err != nil && apierrors.IsNotFound(err) { + return nil, false, nil + } + if err != nil { + return nil, false, err + } + resourcehelper.ReportDeleteEvent(recorder, required, err) + return nil, true, nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go index 9105464bd0..58f49823f3 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/generic.go @@ -147,7 +147,7 @@ func ApplyDirectly(ctx context.Context, clients *ClientHolder, recorder events.R if clients.kubeClient == nil { result.Error = fmt.Errorf("missing kubeClient") } else { - result.Result, result.Changed, result.Error = ApplyNetworkPolicy(ctx, clients.kubeClient.NetworkingV1(), recorder, t) + result.Result, result.Changed, result.Error = ApplyNetworkPolicy(ctx, clients.kubeClient.NetworkingV1(), recorder, t, cache) } case *rbacv1.ClusterRole: if clients.kubeClient == nil { @@ -380,6 +380,30 @@ func DeleteAll(ctx context.Context, clients *ClientHolder, recorder events.Recor } else { _, result.Changed, result.Error = DeleteValidatingWebhookConfiguration(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t) } + case *admissionregistrationv1beta1.ValidatingAdmissionPolicy: + if clients.kubeClient == nil { + result.Error = fmt.Errorf("missing kubeClient") + } else { + _, result.Changed, result.Error = DeleteValidatingAdmissionPolicyV1beta1(ctx, clients.kubeClient.AdmissionregistrationV1beta1(), recorder, t) + } + case *admissionregistrationv1beta1.ValidatingAdmissionPolicyBinding: + if clients.kubeClient == nil { + result.Error = fmt.Errorf("missing kubeClient") + } else { + _, result.Changed, result.Error = DeleteValidatingAdmissionPolicyBindingV1beta1(ctx, clients.kubeClient.AdmissionregistrationV1beta1(), recorder, t) + } + case *admissionregistrationv1.ValidatingAdmissionPolicy: + if clients.kubeClient == nil { + result.Error = fmt.Errorf("missing kubeClient") + } else { + _, result.Changed, result.Error = DeleteValidatingAdmissionPolicyV1(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t) + } + case *admissionregistrationv1.ValidatingAdmissionPolicyBinding: + if clients.kubeClient == nil { + result.Error = fmt.Errorf("missing kubeClient") + } else { + _, result.Changed, result.Error = DeleteValidatingAdmissionPolicyBindingV1(ctx, clients.kubeClient.AdmissionregistrationV1(), recorder, t) + } case *storagev1.CSIDriver: if clients.kubeClient == nil { result.Error = fmt.Errorf("missing kubeClient") diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/networking.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/networking.go index 0a3df326e4..cc2de17ff3 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/networking.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/networking.go @@ -15,34 +15,44 @@ import ( "github.com/openshift/library-go/pkg/operator/resource/resourcemerge" ) -// ApplyClusterRole merges objectmeta, does not worry about anything else -func ApplyNetworkPolicy(ctx context.Context, client networkingclientv1.NetworkPoliciesGetter, recorder events.Recorder, required *networkingv1.NetworkPolicy) (*networkingv1.NetworkPolicy, bool, error) { +// ApplyNetworkPolicy merges objectmeta and requires spec +func ApplyNetworkPolicy(ctx context.Context, client networkingclientv1.NetworkPoliciesGetter, recorder events.Recorder, required *networkingv1.NetworkPolicy, cache ResourceCache) (*networkingv1.NetworkPolicy, bool, error) { existing, err := client.NetworkPolicies(required.Namespace).Get(ctx, required.Name, metav1.GetOptions{}) if apierrors.IsNotFound(err) { requiredCopy := required.DeepCopy() actual, err := client.NetworkPolicies(required.Namespace).Create( ctx, resourcemerge.WithCleanLabelsAndAnnotations(requiredCopy).(*networkingv1.NetworkPolicy), metav1.CreateOptions{}) resourcehelper.ReportCreateEvent(recorder, required, err) + cache.UpdateCachedResourceMetadata(required, actual) return actual, true, err } if err != nil { return nil, false, err } + if cache.SafeToSkipApply(required, existing) { + return existing, false, nil + } + modified := false existingCopy := existing.DeepCopy() resourcemerge.EnsureObjectMeta(&modified, &existingCopy.ObjectMeta, required.ObjectMeta) - if equality.Semantic.DeepEqual(existingCopy.Spec, required.Spec) && !modified { + specContentSame := equality.Semantic.DeepEqual(existingCopy.Spec, required.Spec) + if specContentSame && !modified { + cache.UpdateCachedResourceMetadata(required, existingCopy) return existingCopy, false, nil } + existingCopy.Spec = required.Spec + if klog.V(2).Enabled() { klog.Infof("NetworkPolicy %q changes: %v", required.Name, JSONPatchNoError(existing, existingCopy)) } actual, err := client.NetworkPolicies(existingCopy.Namespace).Update(ctx, existingCopy, metav1.UpdateOptions{}) resourcehelper.ReportUpdateEvent(recorder, required, err) + cache.UpdateCachedResourceMetadata(required, actual) return actual, true, err } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/storage.go b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/storage.go index d44a5d571a..afbdc53ee9 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/storage.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/resource/resourceapply/storage.go @@ -135,9 +135,10 @@ func storageClassNeedsRecreate(oldSC, newSC *storagev1.StorageClass) bool { return false } -// ApplyCSIDriver merges objectmeta, does not worry about anything else +// ApplyCSIDriver merges objectmeta and tries to update spec if any of the required fields were cleared by the API server. +// It assumes they were cleared due to a feature gate not enabled in the API server and it will be enabled soon. +// When used by StaticResourceController, it will retry periodically and eventually save the spec with the field. func ApplyCSIDriver(ctx context.Context, client storageclientv1.CSIDriversGetter, recorder events.Recorder, requiredOriginal *storagev1.CSIDriver) (*storagev1.CSIDriver, bool, error) { - required := requiredOriginal.DeepCopy() if required.Annotations == nil { required.Annotations = map[string]string{} @@ -173,14 +174,40 @@ func ApplyCSIDriver(ctx context.Context, client storageclientv1.CSIDriversGetter } } - metadataModified := false + needsUpdate := false + // Most CSIDriver fields are immutable. Any change to them should trigger Delete() + Create() calls. + needsRecreate := false + existingCopy := existing.DeepCopy() - resourcemerge.EnsureObjectMeta(&metadataModified, &existingCopy.ObjectMeta, required.ObjectMeta) + // Metadata change should need just Update() call. + resourcemerge.EnsureObjectMeta(&needsUpdate, &existingCopy.ObjectMeta, required.ObjectMeta) requiredSpecHash := required.Annotations[specHashAnnotation] existingSpecHash := existing.Annotations[specHashAnnotation] - sameSpec := requiredSpecHash == existingSpecHash - if sameSpec && !metadataModified { + // Assume whole re-create is needed on any spec change. + // We don't keep a track of which field is mutable. + needsRecreate = requiredSpecHash != existingSpecHash + + // TODO: remove when CSIDriver spec.nodeAllocatableUpdatePeriodSeconds is enabled by default + // (https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/4876-mutable-csinode-allocatable) + if !needsRecreate && !alphaFieldsSaved(existingCopy, required) { + // The required spec is the same as in previous succesful call, however, + // the API server must have cleared some alpha/beta fields in it. + // Try to save the object again. In case the fields are cleared again, + // the caller (typically StaticResourceController) must retry periodically. + klog.V(4).Infof("Detected CSIDriver %q field cleared by the API server, updating", required.Name) + + // Assumption: the alpha fields are **mutable**, so only Update() is needed. + // Update() with the same spec as before + the field cleared by the API server + // won't generate any informer events. StaticResourceController will retry with + // periodic retry (1 minute.) + // We cannot use needsRecreate=true, as it will generate informer events and + // StaticResourceController will retry immediately, leading to a busy loop. + needsUpdate = true + existingCopy.Spec = required.Spec + } + + if !needsUpdate && !needsRecreate { return existing, false, nil } @@ -188,16 +215,16 @@ func ApplyCSIDriver(ctx context.Context, client storageclientv1.CSIDriversGetter klog.Infof("CSIDriver %q changes: %v", required.Name, JSONPatchNoError(existing, existingCopy)) } - if sameSpec { - // Update metadata by a simple Update call + if !needsRecreate { + // only needsUpdate is true, update the object by a simple Update call actual, err := client.CSIDrivers().Update(ctx, existingCopy, metav1.UpdateOptions{}) resourcehelper.ReportUpdateEvent(recorder, required, err) return actual, true, err } + // needsRecreate is true, needsUpdate does not matter. Delete and re-create the object. existingCopy.Spec = required.Spec existingCopy.ObjectMeta.ResourceVersion = "" - // Spec is read-only after creation. Delete and re-create the object err = client.CSIDrivers().Delete(ctx, existingCopy.Name, metav1.DeleteOptions{}) resourcehelper.ReportDeleteEvent(recorder, existingCopy, err, "Deleting CSIDriver to re-create it with updated parameters") if err != nil && !apierrors.IsNotFound(err) { @@ -214,10 +241,17 @@ func ApplyCSIDriver(ctx context.Context, client storageclientv1.CSIDriversGetter } else if err != nil { err = fmt.Errorf("failed to re-create CSIDriver %s: %s", existingCopy.Name, err) } - resourcehelper.ReportCreateEvent(recorder, existingCopy, err) + resourcehelper.ReportCreateEvent(recorder, actual, err) return actual, true, err } +// alphaFieldsSaved checks that all required fields in the CSIDriver required spec are present and equal in the actual spec. +func alphaFieldsSaved(actual, required *storagev1.CSIDriver) bool { + // DeepDerivative checks that all fields in "required" are present and equal in "actual" + // Fields not present in "required" are ignored. + return equality.Semantic.DeepDerivative(required.Spec, actual.Spec) +} + func validateRequiredCSIDriverLabels(required *storagev1.CSIDriver) error { supportsEphemeralVolumes := false for _, mode := range required.Spec.VolumeLifecycleModes { diff --git a/vendor/github.com/openshift/route-controller-manager/pkg/route/ingress/ingress.go b/vendor/github.com/openshift/route-controller-manager/pkg/route/ingress/ingress.go index dee50de296..82e02ff93d 100644 --- a/vendor/github.com/openshift/route-controller-manager/pkg/route/ingress/ingress.go +++ b/vendor/github.com/openshift/route-controller-manager/pkg/route/ingress/ingress.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "reflect" + "strconv" "strings" "sync" "time" @@ -415,6 +416,18 @@ func (c *Controller) sync(key queueKey) error { old = append(old, route) } + // In case the annotation does not contain a valid value, the reconciliation + // should continue, so we don't return the error, but instead register an + // event of InvalidAnnotationValue. + propagateLabels, err := shouldPropagateLabelsToRoute(ingress.Annotations) + if err != nil { + c.eventRecorder.Eventf(&corev1.ObjectReference{ + Kind: "Ingress", + Namespace: key.namespace, + Name: key.name, + }, corev1.EventTypeNormal, "InvalidAnnotationValue", "Invalid value on annotation %q due to: %q", routecontroller.PropagateIngressLabelFlag, err) + } + // walk the ingress and identify whether any of the child routes need to be updated, deleted, // or created, as efficiently as possible. var creates, updates, matches []*routev1.Route @@ -463,7 +476,7 @@ func (c *Controller) sync(key queueKey) error { continue } - match, err := routeMatchesIngress(existing, ingress, &rule, &path, c.secretLister, c.serviceLister, host, hostIsWildcard) + match, err := routeMatchesIngress(existing, ingress, &rule, &path, c.secretLister, c.serviceLister, host, hostIsWildcard, propagateLabels) if err != nil { incompleteIngressToRouteRules = append(incompleteIngressToRouteRules, fmt.Sprintf("%s at index %d, path index %d", err.Error(), i, j)) } @@ -496,22 +509,36 @@ func (c *Controller) sync(key queueKey) error { // update any existing routes in place for _, route := range updates { - data, err := json.Marshal(&route.Spec) - if err != nil { - return err + patchOperations := []map[string]any{ + { + "op": "replace", + "path": "/spec", + "value": &route.Spec, + }, + { + "op": "replace", + "path": "/metadata/annotations", + "value": &route.Annotations, + }, + { + "op": "replace", + "path": "/metadata/ownerReferences", + "value": &route.OwnerReferences, + }, } - annotations, err := json.Marshal(&route.Annotations) - if err != nil { - return err + + if propagateLabels { + patchOperations = append(patchOperations, map[string]any{ + "op": "replace", + "path": "/metadata/labels", + "value": &route.Labels, + }) } - ownerRefs, err := json.Marshal(&route.OwnerReferences) + + data, err := json.Marshal(patchOperations) if err != nil { return err } - data = []byte(fmt.Sprintf(`[{"op":"replace","path":"/spec","value":%s},`+ - `{"op":"replace","path":"/metadata/annotations","value":%s},`+ - `{"op":"replace","path":"/metadata/ownerReferences","value":%s}]`, - data, annotations, ownerRefs)) _, err = c.routeClient.Routes(route.Namespace).Patch(context.TODO(), route.Name, types.JSONPatchType, data, metav1.PatchOptions{}) if err != nil { errs = append(errs, err) @@ -709,11 +736,13 @@ func routeMatchesIngress( serviceLister corelisters.ServiceLister, host string, hostIsWildcard bool, + propagateLabels bool, ) (bool, error) { wildcardPolicy := routev1.WildcardPolicyNone if hostIsWildcard { wildcardPolicy = routev1.WildcardPolicySubdomain } + match := route.Spec.Host == host && route.Spec.Path == path.Path && route.Spec.To.Name == path.Backend.Service.Name && @@ -721,7 +750,9 @@ func routeMatchesIngress( len(route.Spec.AlternateBackends) == 0 && route.Spec.WildcardPolicy == wildcardPolicy && reflect.DeepEqual(route.Annotations, ingress.Annotations) && - route.OwnerReferences[0].APIVersion == "networking.k8s.io/v1" + route.OwnerReferences[0].APIVersion == "networking.k8s.io/v1" && + // Matching labels is conditional on the 'reconcile-labels' annotation's being set to 'true' + (!propagateLabels || reflect.DeepEqual(route.Labels, ingress.Labels)) if !match { return false, nil @@ -973,3 +1004,22 @@ func destinationCACertificateForIngress(ingress *networkingv1.Ingress, secretLis } return nil } + +// shouldPropagateLabelsToRoute verifies if annotation map contains the key +// 'router.openshift.io/reconcile-labels' and if its value is a non-empty +// parseable boolean (true, false, t, T, f, F, etc). +// In case the annotation exists but the value is invalid, it will return "false" +// and the parsing error. +// Otherwise it returns the underlying boolean value. +func shouldPropagateLabelsToRoute(annotations map[string]string) (bool, error) { + propagateLabelsFlag, ok := annotations[routecontroller.PropagateIngressLabelFlag] + if !ok { + return false, nil + } + + shouldPropagate, err := strconv.ParseBool(strings.TrimSpace(propagateLabelsFlag)) + if err != nil { + return false, err + } + return shouldPropagate, nil +} diff --git a/vendor/github.com/openshift/route-controller-manager/pkg/routecontroller/wellknown.go b/vendor/github.com/openshift/route-controller-manager/pkg/routecontroller/wellknown.go index 63a9e58821..8c7d2f4090 100644 --- a/vendor/github.com/openshift/route-controller-manager/pkg/routecontroller/wellknown.go +++ b/vendor/github.com/openshift/route-controller-manager/pkg/routecontroller/wellknown.go @@ -14,6 +14,12 @@ var ( // TerminationPolicyAnnotationKey defines what TLSTerminationType should be used // on the Route being created TerminationPolicyAnnotationKey = routev1.GroupName + "/termination" + // PropagateIngressLabelFlag defines if the labels of the Ingress resource + // should be used to replace the labels on the generated Route resource. + // In case this feature/annotation is enabled, any existing label on the + // underlying route resource will be replaced by the labels from the parent + // ingress resource + PropagateIngressLabelFlag = routev1.GroupName + "/reconcile-labels" // IngressClassAnnotation is the legacy annotation used to define which // controller/class should reconcile an ingress resource. // In case of a conversion from an ingress to route, if the ingress specifies diff --git a/vendor/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock.go b/vendor/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock.go index 5d2054155c..79a748b74d 100644 --- a/vendor/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock.go +++ b/vendor/k8s.io/client-go/tools/leaderelection/resourcelock/leaselock.go @@ -77,6 +77,9 @@ func (ll *LeaseLock) Update(ctx context.Context, ler LeaderElectionRecord) error ll.lease.Spec = LeaderElectionRecordToLeaseSpec(&ler) if ll.Labels != nil { + if ll.lease.Labels == nil { + ll.lease.Labels = map[string]string{} + } // Only overwrite the labels that are specifically set for k, v := range ll.Labels { ll.lease.Labels[k] = v diff --git a/vendor/k8s.io/client-go/util/cert/cert.go b/vendor/k8s.io/client-go/util/cert/cert.go index 1220461264..48c78b595e 100644 --- a/vendor/k8s.io/client-go/util/cert/cert.go +++ b/vendor/k8s.io/client-go/util/cert/cert.go @@ -75,13 +75,15 @@ func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, erro CommonName: cfg.CommonName, Organization: cfg.Organization, }, - DNSNames: []string{cfg.CommonName}, NotBefore: notBefore, NotAfter: now.Add(duration365d * 10).UTC(), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, BasicConstraintsValid: true, IsCA: true, } + if len(cfg.CommonName) > 0 { + tmpl.DNSNames = []string{cfg.CommonName} + } certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &tmpl, &tmpl, key.Public(), key) if err != nil { diff --git a/vendor/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go b/vendor/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go index 84218307c6..6b3c69b791 100644 --- a/vendor/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go +++ b/vendor/k8s.io/dynamic-resource-allocation/structured/internal/experimental/allocator_experimental.go @@ -388,6 +388,11 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } // Populate configs. + + // Each class config gets added only once. + // We need to keep track of which class configs have already been added and at which position in the allocationResult.Devices.Config. + type configRange struct{ start, end int } + configIndexesForClass := make(map[string]configRange) // Key: class name / Value: position of the configs for the class in allocationResult.Devices.Config. for requestIndex := range claim.Spec.Devices.Requests { requestKey := requestIndices{claimIndex: claimIndex, requestIndex: requestIndex} requestData := alloc.requestData[requestKey] @@ -398,15 +403,29 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } class := requestData.class - if class != nil { - for _, config := range class.Spec.Config { - allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ - Source: resourceapi.AllocationConfigSourceClass, - Requests: nil, // All of them... - DeviceConfiguration: config.DeviceConfiguration, - }) + if class == nil { + continue + } + configIndexes, exists := configIndexesForClass[class.Name] + if exists { + // The configs for the class have already been added. + // Just append the request name for the request class. + for i := configIndexes.start; i < configIndexes.end; i++ { + allocationResult.Devices.Config[i].Requests = append(allocationResult.Devices.Config[i].Requests, requestData.requestName()) } + continue } + + // Add all configs for the class once. + initialConfigLen := len(allocationResult.Devices.Config) + for _, config := range class.Spec.Config { + allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ + Source: resourceapi.AllocationConfigSourceClass, + Requests: []string{requestData.requestName()}, + DeviceConfiguration: config.DeviceConfiguration, + }) + } + configIndexesForClass[class.Name] = configRange{start: initialConfigLen, end: len(allocationResult.Devices.Config)} } for _, config := range claim.Spec.Devices.Config { // If Requests are empty, it applies to all. So it can just be included. @@ -646,6 +665,13 @@ type requestData struct { allDevices []deviceWithID } +func (rd *requestData) requestName() string { + if rd.parentRequest != nil { + return fmt.Sprintf("%s/%s", rd.parentRequest.name(), rd.request.name()) + } + return rd.request.name() +} + type deviceWithID struct { *draapi.Device id DeviceID diff --git a/vendor/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go b/vendor/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go index d65235e35b..b3b4f7d2c6 100644 --- a/vendor/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go +++ b/vendor/k8s.io/dynamic-resource-allocation/structured/internal/incubating/allocator_incubating.go @@ -295,6 +295,11 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } // Populate configs. + + // Each class config gets added only once. + // We need to keep track of which class configs have already been added and at which position in the allocationResult.Devices.Config. + type configRange struct{ start, end int } + configIndexesForClass := make(map[string]configRange) // Key: class name / Value: position of the configs for the class in allocationResult.Devices.Config. for requestIndex := range claim.Spec.Devices.Requests { requestKey := requestIndices{claimIndex: claimIndex, requestIndex: requestIndex} requestData := alloc.requestData[requestKey] @@ -305,15 +310,29 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } class := requestData.class - if class != nil { - for _, config := range class.Spec.Config { - allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ - Source: resourceapi.AllocationConfigSourceClass, - Requests: nil, // All of them... - DeviceConfiguration: config.DeviceConfiguration, - }) + if class == nil { + continue + } + configIndexes, exists := configIndexesForClass[class.Name] + if exists { + // The configs for the class have already been added. + // Just append the request name for the request class. + for i := configIndexes.start; i < configIndexes.end; i++ { + allocationResult.Devices.Config[i].Requests = append(allocationResult.Devices.Config[i].Requests, requestData.requestName()) } + continue } + + // Add all configs for the class once. + initialConfigLen := len(allocationResult.Devices.Config) + for _, config := range class.Spec.Config { + allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ + Source: resourceapi.AllocationConfigSourceClass, + Requests: []string{requestData.requestName()}, + DeviceConfiguration: config.DeviceConfiguration, + }) + } + configIndexesForClass[class.Name] = configRange{start: initialConfigLen, end: len(allocationResult.Devices.Config)} } for _, config := range claim.Spec.Devices.Config { // If Requests are empty, it applies to all. So it can just be included. @@ -535,6 +554,13 @@ type requestData struct { allDevices []deviceWithID } +func (rd *requestData) requestName() string { + if rd.parentRequest != nil { + return fmt.Sprintf("%s/%s", rd.parentRequest.name(), rd.request.name()) + } + return rd.request.name() +} + type deviceWithID struct { *draapi.Device id DeviceID diff --git a/vendor/k8s.io/dynamic-resource-allocation/structured/internal/stable/allocator_stable.go b/vendor/k8s.io/dynamic-resource-allocation/structured/internal/stable/allocator_stable.go index d5b118e931..54440746b7 100644 --- a/vendor/k8s.io/dynamic-resource-allocation/structured/internal/stable/allocator_stable.go +++ b/vendor/k8s.io/dynamic-resource-allocation/structured/internal/stable/allocator_stable.go @@ -286,6 +286,11 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } // Populate configs. + + // Each class config gets added only once. + // We need to keep track of which class configs have already been added and at which position in the allocationResult.Devices.Config. + type configRange struct{ start, end int } + configIndexesForClass := make(map[string]configRange) // Key: class name / Value: position of the configs for the class in allocationResult.Devices.Config. for requestIndex := range claim.Spec.Devices.Requests { requestKey := requestIndices{claimIndex: claimIndex, requestIndex: requestIndex} requestData := alloc.requestData[requestKey] @@ -296,15 +301,29 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node, claims []*resou } class := requestData.class - if class != nil { - for _, config := range class.Spec.Config { - allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ - Source: resourceapi.AllocationConfigSourceClass, - Requests: nil, // All of them... - DeviceConfiguration: config.DeviceConfiguration, - }) + if class == nil { + continue + } + configIndexes, exists := configIndexesForClass[class.Name] + if exists { + // The configs for the class have already been added. + // Just append the request name for the request class. + for i := configIndexes.start; i < configIndexes.end; i++ { + allocationResult.Devices.Config[i].Requests = append(allocationResult.Devices.Config[i].Requests, requestData.requestName()) } + continue } + + // Add all configs for the class once. + initialConfigLen := len(allocationResult.Devices.Config) + for _, config := range class.Spec.Config { + allocationResult.Devices.Config = append(allocationResult.Devices.Config, resourceapi.DeviceAllocationConfiguration{ + Source: resourceapi.AllocationConfigSourceClass, + Requests: []string{requestData.requestName()}, + DeviceConfiguration: config.DeviceConfiguration, + }) + } + configIndexesForClass[class.Name] = configRange{start: initialConfigLen, end: len(allocationResult.Devices.Config)} } for _, config := range claim.Spec.Devices.Config { // If Requests are empty, it applies to all. So it can just be included. @@ -517,6 +536,13 @@ type requestData struct { allDevices []deviceWithID } +func (rd *requestData) requestName() string { + if rd.parentRequest != nil { + return fmt.Sprintf("%s/%s", rd.parentRequest.name(), rd.request.name()) + } + return rd.request.name() +} + type deviceWithID struct { *draapi.Device id DeviceID diff --git a/vendor/k8s.io/kubectl/pkg/cmd/apiresources/apiresources.go b/vendor/k8s.io/kubectl/pkg/cmd/apiresources/apiresources.go index 1959cc1109..9a45cd907d 100644 --- a/vendor/k8s.io/kubectl/pkg/cmd/apiresources/apiresources.go +++ b/vendor/k8s.io/kubectl/pkg/cmd/apiresources/apiresources.go @@ -229,6 +229,9 @@ func (o *APIResourceOptions) RunAPIResources() error { allResources = append(allResources, apiList) } + if len(allResources) == 0 { + return utilerrors.NewAggregate(errs) + } flatList := &metav1.APIResourceList{ TypeMeta: metav1.TypeMeta{ APIVersion: allResources[0].APIVersion, diff --git a/vendor/k8s.io/kubernetes/pkg/api/service/warnings.go b/vendor/k8s.io/kubernetes/pkg/api/service/warnings.go index 41e69704bc..92fef3afa9 100644 --- a/vendor/k8s.io/kubernetes/pkg/api/service/warnings.go +++ b/vendor/k8s.io/kubernetes/pkg/api/service/warnings.go @@ -48,7 +48,7 @@ func GetWarningsForService(service, oldService *api.Service) []string { if len(service.Spec.ExternalIPs) > 0 { warnings = append(warnings, "spec.externalIPs is ignored for headless services") } - if service.Spec.SessionAffinity != "" { + if service.Spec.SessionAffinity != api.ServiceAffinityNone { warnings = append(warnings, "spec.SessionAffinity is ignored for headless services") } } diff --git a/vendor/k8s.io/kubernetes/pkg/apis/batch/validation/validation.go b/vendor/k8s.io/kubernetes/pkg/apis/batch/validation/validation.go index 5203c837ec..17ffbbe4b4 100644 --- a/vendor/k8s.io/kubernetes/pkg/apis/batch/validation/validation.go +++ b/vendor/k8s.io/kubernetes/pkg/apis/batch/validation/validation.go @@ -913,6 +913,15 @@ func IsConditionTrue(list []batch.JobCondition, cType batch.JobConditionType) bo return false } +func IsConditionFalse(list []batch.JobCondition, cType batch.JobConditionType) bool { + for _, c := range list { + if c.Type == cType && c.Status == api.ConditionFalse { + return true + } + } + return false +} + func validateFailedIndexesNotOverlapCompleted(completedIndexesStr string, failedIndexesStr string, completions int32) error { if len(completedIndexesStr) == 0 || len(failedIndexesStr) == 0 { return nil diff --git a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go b/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go index c847ad4f22..c6c3b31f0d 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/controller_utils.go @@ -89,12 +89,9 @@ const ( // PodNodeNameKeyIndex is the name of the index used by PodInformer to index pods by their node name. PodNodeNameKeyIndex = "spec.nodeName" - // OrphanPodIndexKey is used to index all Orphan pods to this key - OrphanPodIndexKey = "_ORPHAN_POD" - - // podControllerUIDIndex is the name for the Pod store's index function, - // which is to index by pods's controllerUID. - PodControllerUIDIndex = "podControllerUID" + // PodControllerIndex is the name for the Pod store's index function, + // which indexes by the key returned from PodControllerIndexKey. + PodControllerIndex = "podController" ) var UpdateTaintBackoff = wait.Backoff{ @@ -1139,43 +1136,59 @@ func AddPodNodeNameIndexer(podInformer cache.SharedIndexInformer) error { }) } -// OrphanPodIndexKeyForNamespace returns the orphan pod index key for a specific namespace. -func OrphanPodIndexKeyForNamespace(namespace string) string { - return OrphanPodIndexKey + "/" + namespace +// PodControllerIndexKey returns the index key to locate pods with the specified controller ownerReference. +// If ownerReference is nil, the returned key locates pods in the namespace without a controller ownerReference. +func PodControllerIndexKey(namespace string, ownerReference *metav1.OwnerReference) string { + if ownerReference == nil { + return namespace + } + return namespace + "/" + ownerReference.Kind + "/" + ownerReference.Name + "/" + string(ownerReference.UID) } -// AddPodControllerUIDIndexer adds an indexer for Pod's controllerRef.UID to the given PodInformer. +// AddPodControllerIndexer adds an indexer for Pod's controllerRef.UID to the given PodInformer. // This indexer is used to efficiently look up pods by their ControllerRef.UID -func AddPodControllerUIDIndexer(podInformer cache.SharedIndexInformer) error { - if _, exists := podInformer.GetIndexer().GetIndexers()[PodControllerUIDIndex]; exists { +func AddPodControllerIndexer(podInformer cache.SharedIndexInformer) error { + if _, exists := podInformer.GetIndexer().GetIndexers()[PodControllerIndex]; exists { // indexer already exists, do nothing return nil } return podInformer.AddIndexers(cache.Indexers{ - PodControllerUIDIndex: func(obj interface{}) ([]string, error) { + PodControllerIndex: func(obj interface{}) ([]string, error) { pod, ok := obj.(*v1.Pod) if !ok { return nil, nil } - // Get the ControllerRef of the Pod to check if it's managed by a controller - if ref := metav1.GetControllerOf(pod); ref != nil { - return []string{string(ref.UID)}, nil - } - // If the Pod has no controller (i.e., it's orphaned), index it with the OrphanPodIndexKeyForNamespace - // This helps identify orphan pods for reconciliation and adoption by controllers - return []string{OrphanPodIndexKeyForNamespace(pod.Namespace)}, nil + // Get the ControllerRef of the Pod to check if it's managed by a controller. + // Index with a non-nil controller (indicating an owned pod) or a nil controller (indicating an orphan pod). + return []string{PodControllerIndexKey(pod.Namespace, metav1.GetControllerOf(pod))}, nil }, }) } // FilterPodsByOwner gets the Pods managed by an owner or orphan Pods in the owner's namespace -func FilterPodsByOwner(podIndexer cache.Indexer, owner *metav1.ObjectMeta) ([]*v1.Pod, error) { +func FilterPodsByOwner(podIndexer cache.Indexer, owner *metav1.ObjectMeta, ownerKind string, includeOrphanedPods bool) ([]*v1.Pod, error) { result := []*v1.Pod{} - // Iterate over two keys: - // - the UID of the owner, which identifies Pods that are controlled by the owner - // - the OrphanPodIndexKey, which identifies orphaned Pods in the owner's namespace and might be adopted by the owner later - for _, key := range []string{string(owner.UID), OrphanPodIndexKeyForNamespace(owner.Namespace)} { - pods, err := podIndexer.ByIndex(PodControllerUIDIndex, key) + + if len(owner.Namespace) == 0 { + return nil, fmt.Errorf("no owner namespace provided") + } + if len(owner.Name) == 0 { + return nil, fmt.Errorf("no owner name provided") + } + if len(owner.UID) == 0 { + return nil, fmt.Errorf("no owner uid provided") + } + if len(ownerKind) == 0 { + return nil, fmt.Errorf("no owner kind provided") + } + // Always include the owner key, which identifies Pods that are controlled by the owner + keys := []string{PodControllerIndexKey(owner.Namespace, &metav1.OwnerReference{Name: owner.Name, Kind: ownerKind, UID: owner.UID})} + if includeOrphanedPods { + // Optionally include the unowned key, which identifies orphaned Pods in the owner's namespace and might be adopted by the owner later + keys = append(keys, PodControllerIndexKey(owner.Namespace, nil)) + } + for _, key := range keys { + pods, err := podIndexer.ByIndex(PodControllerIndex, key) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller.go index 4965cb75c8..0ab4290ae5 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/daemon/daemon_controller.go @@ -223,7 +223,7 @@ func NewDaemonSetsController( dsc.podLister = podInformer.Lister() dsc.podStoreSynced = podInformer.Informer().HasSynced controller.AddPodNodeNameIndexer(podInformer.Informer()) - controller.AddPodControllerUIDIndexer(podInformer.Informer()) + controller.AddPodControllerIndexer(podInformer.Informer()) dsc.podIndexer = podInformer.Informer().GetIndexer() nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ @@ -710,7 +710,7 @@ func (dsc *DaemonSetsController) getDaemonPods(ctx context.Context, ds *apps.Dae return nil, err } // List all pods indexed to DS UID and Orphan pods - pods, err := controller.FilterPodsByOwner(dsc.podIndexer, &ds.ObjectMeta) + pods, err := controller.FilterPodsByOwner(dsc.podIndexer, &ds.ObjectMeta, "DaemonSet", true) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/history/controller_history.go b/vendor/k8s.io/kubernetes/pkg/controller/history/controller_history.go index 19ae0999af..9f4f82223a 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/history/controller_history.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/history/controller_history.go @@ -111,27 +111,9 @@ func SortControllerRevisions(revisions []*apps.ControllerRevision) { // EqualRevision returns true if lhs and rhs are either both nil, or both point to non-nil ControllerRevisions that // contain semantically equivalent data. Otherwise this method returns false. func EqualRevision(lhs *apps.ControllerRevision, rhs *apps.ControllerRevision) bool { - var lhsHash, rhsHash *uint32 if lhs == nil || rhs == nil { return lhs == rhs } - if hs, found := lhs.Labels[ControllerRevisionHashLabel]; found { - hash, err := strconv.ParseInt(hs, 10, 32) - if err == nil { - lhsHash = new(uint32) - *lhsHash = uint32(hash) - } - } - if hs, found := rhs.Labels[ControllerRevisionHashLabel]; found { - hash, err := strconv.ParseInt(hs, 10, 32) - if err == nil { - rhsHash = new(uint32) - *rhsHash = uint32(hash) - } - } - if lhsHash != nil && rhsHash != nil && *lhsHash != *rhsHash { - return false - } return bytes.Equal(lhs.Data.Raw, rhs.Data.Raw) && apiequality.Semantic.DeepEqual(lhs.Data.Object, rhs.Data.Object) } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller.go b/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller.go index 6a74ee0bd5..4de4bdc302 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/job/job_controller.go @@ -226,7 +226,7 @@ func newControllerWithClock(ctx context.Context, podInformer coreinformers.PodIn jm.podStore = podInformer.Lister() jm.podStoreSynced = podInformer.Informer().HasSynced - err := controller.AddPodControllerUIDIndexer(podInformer.Informer()) + err := controller.AddPodControllerIndexer(podInformer.Informer()) if err != nil { return nil, fmt.Errorf("adding Pod controller UID indexer: %w", err) } @@ -769,7 +769,7 @@ func (jm *Controller) getPodsForJob(ctx context.Context, j *batch.Job) ([]*v1.Po } // list all pods managed by this Job using the pod indexer - pods, err := controller.FilterPodsByOwner(jm.podIndexer, &j.ObjectMeta) + pods, err := controller.FilterPodsByOwner(jm.podIndexer, &j.ObjectMeta, "Job", true) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go index 8934bd4605..204f4c46a6 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/replicaset/replica_set.go @@ -220,7 +220,7 @@ func NewBaseController(logger klog.Logger, rsInformer appsinformers.ReplicaSetIn }) rsc.podLister = podInformer.Lister() rsc.podListerSynced = podInformer.Informer().HasSynced - controller.AddPodControllerUIDIndexer(podInformer.Informer()) //nolint:errcheck + controller.AddPodControllerIndexer(podInformer.Informer()) //nolint:errcheck rsc.podIndexer = podInformer.Informer().GetIndexer() rsc.syncHandler = rsc.syncReplicaSet @@ -728,7 +728,7 @@ func (rsc *ReplicaSetController) syncReplicaSet(ctx context.Context, key string) } // List all pods indexed to RS UID and Orphan pods - allRSPods, err := controller.FilterPodsByOwner(rsc.podIndexer, &rs.ObjectMeta) + allRSPods, err := controller.FilterPodsByOwner(rsc.podIndexer, &rs.ObjectMeta, rsc.Kind, true) if err != nil { return err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set.go b/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set.go index 36e49ca084..007766df25 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set.go @@ -131,7 +131,7 @@ func NewStatefulSetController( }) ssc.podLister = podInformer.Lister() ssc.podListerSynced = podInformer.Informer().HasSynced - controller.AddPodControllerUIDIndexer(podInformer.Informer()) + controller.AddPodControllerIndexer(podInformer.Informer()) ssc.podIndexer = podInformer.Informer().GetIndexer() setInformer.Informer().AddEventHandler( cache.ResourceEventHandlerFuncs{ @@ -312,7 +312,7 @@ func (ssc *StatefulSetController) deletePod(logger klog.Logger, obj interface{}) // NOTE: Returned Pods are pointers to objects from the cache. // If you need to modify one, you need to copy it first. func (ssc *StatefulSetController) getPodsForStatefulSet(ctx context.Context, set *apps.StatefulSet, selector labels.Selector) ([]*v1.Pod, error) { - podsForSts, err := controller.FilterPodsByOwner(ssc.podIndexer, &set.ObjectMeta) + podsForSts, err := controller.FilterPodsByOwner(ssc.podIndexer, &set.ObjectMeta, "StatefulSet", true) if err != nil { return nil, err } diff --git a/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set_control.go b/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set_control.go index 7d4f4990ba..78dd40081e 100644 --- a/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set_control.go +++ b/vendor/k8s.io/kubernetes/pkg/controller/statefulset/stateful_set_control.go @@ -21,13 +21,17 @@ import ( "sort" "sync" + "k8s.io/klog/v2" + "k8s.io/utils/lru" + apps "k8s.io/api/apps/v1" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" utilerrors "k8s.io/apimachinery/pkg/util/errors" utilfeature "k8s.io/apiserver/pkg/util/feature" - "k8s.io/klog/v2" + "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/controller/history" "k8s.io/kubernetes/pkg/features" ) @@ -61,13 +65,15 @@ func NewDefaultStatefulSetControl( podControl *StatefulPodControl, statusUpdater StatefulSetStatusUpdaterInterface, controllerHistory history.Interface) StatefulSetControlInterface { - return &defaultStatefulSetControl{podControl, statusUpdater, controllerHistory} + return &defaultStatefulSetControl{podControl, statusUpdater, controllerHistory, lru.New(maxRevisionEqualityCacheEntries)} } type defaultStatefulSetControl struct { podControl *StatefulPodControl statusUpdater StatefulSetStatusUpdaterInterface controllerHistory history.Interface + + revisionEqualityCache *lru.Cache } // UpdateStatefulSet executes the core logic loop for a stateful set, applying the predictable and @@ -207,6 +213,49 @@ func (ssc *defaultStatefulSetControl) truncateHistory( return nil } +// maxRevisionEqualityCacheEntries is the size of the memory cache for equal set/controllerrevisions. +// Allowing up to 10,000 entries takes ~1MB. Each entry consumes up to ~111 bytes: +// - 40 bytes for the cache key (revisionEqualityKey{}) +// - 16 for the cache value (interface{} --> struct{}{}) +// - 36 bytes for the setUID string +// - 19 bytes for the revisionResourceVersion string +const maxRevisionEqualityCacheEntries = 10_000 + +// revisionEqualityKey is the cache key for remembering a particular revision RV +// is equal to the revision that results from a particular set UID at a particular set generation. +type revisionEqualityKey struct { + setUID types.UID + setGeneration int64 + revisionResourceVersion string +} + +// setMatchesLatestExistingRevision returns true if the set/proposedRevision already matches what would be produced from restoring latestExistingRevision. +func setMatchesLatestExistingRevision(set *apps.StatefulSet, proposedRevision *apps.ControllerRevision, latestExistingRevision *apps.ControllerRevision, memory *lru.Cache) bool { + if !utilfeature.DefaultFeatureGate.Enabled(features.StatefulSetSemanticRevisionComparison) { + return false + } + equalityCacheKey := revisionEqualityKey{setUID: set.UID, setGeneration: set.Generation, revisionResourceVersion: latestExistingRevision.ResourceVersion} + if _, ok := memory.Get(equalityCacheKey); ok { + return true + } + // see if reverting to the latest existing revision would produce the same thing as proposedRevision + latestSet, err := ApplyRevision(set, latestExistingRevision) + if err != nil { + return false + } + legacyscheme.Scheme.Default(latestSet) + reconstructedLatestRevision, err := newRevision(latestSet, -1, nil) + if err != nil { + return false + } + // if they match, cache this combination of set(uid,generation)+revision(resourceVersion) to minimize expensive comparisons in steady state + if history.EqualRevision(proposedRevision, reconstructedLatestRevision) { + memory.Add(equalityCacheKey, struct{}{}) + return true + } + return false +} + // getStatefulSetRevisions returns the current and update ControllerRevisions for set. It also // returns a collision count that records the number of name collisions set saw when creating // new ControllerRevisions. This count is incremented on every name collision and is used in @@ -250,6 +299,9 @@ func (ssc *defaultStatefulSetControl) getStatefulSetRevisions( if err != nil { return nil, nil, collisionCount, err } + } else if revisionCount > 0 && setMatchesLatestExistingRevision(set, updateRevision, revisions[revisionCount-1], ssc.revisionEqualityCache) { + // the update revision has not changed + updateRevision = revisions[revisionCount-1] } else { //if there is no equivalent revision we create a new one updateRevision, err = ssc.controllerHistory.CreateControllerRevision(set, updateRevision, &collisionCount) diff --git a/vendor/k8s.io/kubernetes/pkg/features/kube_features.go b/vendor/k8s.io/kubernetes/pkg/features/kube_features.go index a3b55db585..5b7794431e 100644 --- a/vendor/k8s.io/kubernetes/pkg/features/kube_features.go +++ b/vendor/k8s.io/kubernetes/pkg/features/kube_features.go @@ -941,6 +941,12 @@ const ( // Enables policies controlling deletion of PVCs created by a StatefulSet. StatefulSetAutoDeletePVC featuregate.Feature = "StatefulSetAutoDeletePVC" + // owner: @liggitt + // + // Mitigates spurious statefulset rollouts due to controller revision comparison mismatches + // which are not semantically significant (e.g. serialization differences or missing defaulted fields). + StatefulSetSemanticRevisionComparison = "StatefulSetSemanticRevisionComparison" + // owner: @cupnes // kep: https://kep.k8s.io/4049 // @@ -1679,7 +1685,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate }, SchedulerAsyncAPICalls: { - {Version: version.MustParse("1.34"), Default: true, PreRelease: featuregate.Beta}, + {Version: version.MustParse("1.34"), Default: false, PreRelease: featuregate.Beta}, }, SchedulerAsyncPreemption: { @@ -1755,6 +1761,12 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate {Version: version.MustParse("1.32"), Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // GA in 1.32, remove in 1.35 }, + StatefulSetSemanticRevisionComparison: { + // This is a mitigation for a 1.34 regression due to serialization differences that cannot be feature-gated, + // so this mitigation should not auto-disable even if emulating versions prior to 1.34 with --emulation-version. + {Version: version.MustParse("1.0"), Default: true, PreRelease: featuregate.Beta}, + }, + StorageCapacityScoring: { {Version: version.MustParse("1.33"), Default: false, PreRelease: featuregate.Alpha}, }, diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_manager.go b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_manager.go index 2b76d3bd34..5305546ccf 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_manager.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/cm/dra/plugin/dra_plugin_manager.go @@ -62,6 +62,9 @@ type DRAPluginManager struct { wipingDelay time.Duration streamHandler StreamHandler + // withIdleTimeout is only for unit testing, ignore if <= 0. + withIdleTimeout time.Duration + wg sync.WaitGroup mutex sync.RWMutex @@ -115,7 +118,13 @@ func (m *monitoredPlugin) HandleConn(_ context.Context, stats grpcstats.ConnStat case *grpcstats.ConnEnd: // We have to ask for a reconnect, otherwise gRPC wouldn't try and // thus we wouldn't be notified about a restart of the plugin. - m.conn.Connect() + // + // This must be done in a goroutine because gRPC deadlocks + // when called directly from inside HandleConn when a connection + // goes idle (and only then). It looks like cc.idlenessMgr.ExitIdleMode + // in Connect tries to lock a mutex that is already locked by + // the caller of HandleConn. + go m.conn.Connect() default: return } @@ -361,12 +370,15 @@ func (pm *DRAPluginManager) add(driverName string, endpoint string, chosenServic // The gRPC connection gets created once. gRPC then connects to the gRPC server on demand. target := "unix:" + endpoint logger.V(4).Info("Creating new gRPC connection", "target", target) - conn, err := grpc.NewClient( - target, + options := []grpc.DialOption{ grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithChainUnaryInterceptor(newMetricsInterceptor(driverName)), grpc.WithStatsHandler(mp), - ) + } + if pm.withIdleTimeout > 0 { + options = append(options, grpc.WithIdleTimeout(pm.withIdleTimeout)) + } + conn, err := grpc.NewClient(target, options...) if err != nil { return fmt.Errorf("create gRPC connection to DRA driver %s plugin at endpoint %s: %w", driverName, endpoint, err) } diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go index a1d9453f89..c837212d98 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -56,6 +56,7 @@ import ( "k8s.io/kubernetes/pkg/kubelet/cm" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/events" + "k8s.io/kubernetes/pkg/kubelet/managed" proberesults "k8s.io/kubernetes/pkg/kubelet/prober/results" "k8s.io/kubernetes/pkg/kubelet/types" "k8s.io/kubernetes/pkg/kubelet/util/format" @@ -625,6 +626,8 @@ func (m *kubeGenericRuntimeManager) getPodContainerStatuses(ctx context.Context, return nil, nil, err } + isManagedPod := managed.IsManagedPodFromRuntimeService(ctx, m.runtimeService, activePodSandboxID) + statuses := []*kubecontainer.Status{} activeContainerStatuses := []*kubecontainer.Status{} // TODO: optimization: set maximum number of containers per container name to examine. @@ -647,6 +650,9 @@ func (m *kubeGenericRuntimeManager) getPodContainerStatuses(ctx context.Context, return nil, nil, remote.ErrContainerStatusNil } cStatus := m.convertToKubeContainerStatus(ctx, status) + if isManagedPod && cStatus.Resources != nil { // Clear CPU resources for managed pods (workload-pinned) + cStatus.Resources.CPURequest, cStatus.Resources.CPULimit = nil, nil + } statuses = append(statuses, cStatus) if c.PodSandboxId == activePodSandboxID { activeContainerStatuses = append(activeContainerStatuses, cStatus) diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/managed/managed.go b/vendor/k8s.io/kubernetes/pkg/kubelet/managed/managed.go index d9266e440f..bd78adeee1 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/managed/managed.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/managed/managed.go @@ -17,6 +17,7 @@ limitations under the License. package managed import ( + "context" "encoding/json" "fmt" "os" @@ -24,6 +25,7 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1" ) var ( @@ -88,6 +90,40 @@ func IsPodManaged(pod *v1.Pod) (bool, string, string) { return false, "", "" } +// podSandboxStatusGetter is an interface for getting pod sandbox status +type podSandboxStatusGetter interface { + PodSandboxStatus(ctx context.Context, podSandboxID string, verbose bool) (*runtimeapi.PodSandboxStatusResponse, error) +} + +// IsPodSandboxManagedPod checks if a pod sandbox belongs to a managed pod +// by looking for workload pinning annotations. +func IsPodSandboxManagedPod(sandboxAnnotations map[string]string) bool { + if sandboxAnnotations == nil { + return false + } + for annotation := range sandboxAnnotations { + if strings.HasPrefix(annotation, WorkloadsAnnotationPrefix) { + return true + } + } + return false +} + +// IsManagedPodFromRuntimeService checks if a pod is managed by fetching the pod sandbox +// status and checking for workload pinning annotations. +func IsManagedPodFromRuntimeService(ctx context.Context, runtimeService podSandboxStatusGetter, podSandboxID string) bool { + if podSandboxID == "" { + return false + } + + sandboxResp, err := runtimeService.PodSandboxStatus(ctx, podSandboxID, false) + if err != nil || sandboxResp == nil || sandboxResp.GetStatus() == nil { + return false + } + + return IsPodSandboxManagedPod(sandboxResp.GetStatus().Annotations) +} + // ModifyStaticPodForPinnedManagement will modify a pod for pod management func ModifyStaticPodForPinnedManagement(pod *v1.Pod) (*v1.Pod, string, error) { pod = pod.DeepCopy() diff --git a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker.go b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker.go index 8578c415d4..60461165bd 100644 --- a/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker.go +++ b/vendor/k8s.io/kubernetes/pkg/kubelet/prober/worker.go @@ -83,6 +83,16 @@ type worker struct { proberDurationUnknownMetricLabels metrics.Labels } +// isInitContainer checks if the worker's container is in the pod's init containers +func (w *worker) isInitContainer() bool { + for _, initContainer := range w.pod.Spec.InitContainers { + if initContainer.Name == w.container.Name { + return true + } + } + return false +} + // Creates and starts a new probe worker. func newWorker( m *manager, @@ -253,12 +263,17 @@ func (w *worker) doProbe(ctx context.Context) (keepGoing bool) { if !w.containerID.IsEmpty() { w.resultsManager.Set(w.containerID, results.Failure, w.pod) } + + isRestartableInitContainer := w.isInitContainer() && + w.container.RestartPolicy != nil && *w.container.RestartPolicy == v1.ContainerRestartPolicyAlways + // Abort if the container will not be restarted. if utilfeature.DefaultFeatureGate.Enabled(features.ContainerRestartRules) { return c.State.Terminated != nil || podutil.IsContainerRestartable(w.pod.Spec, w.container) } return c.State.Terminated == nil || - w.pod.Spec.RestartPolicy != v1.RestartPolicyNever + w.pod.Spec.RestartPolicy != v1.RestartPolicyNever || + isRestartableInitContainer } // Graceful shutdown of the pod. diff --git a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/strategy.go b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/strategy.go index 8bde82debf..23f343e754 100644 --- a/vendor/k8s.io/kubernetes/pkg/registry/batch/job/strategy.go +++ b/vendor/k8s.io/kubernetes/pkg/registry/batch/job/strategy.go @@ -380,6 +380,11 @@ func getStatusValidationOptions(newJob, oldJob *batch.Job) batchvalidation.JobSt isReadyChanged := !ptr.Equal(oldJob.Status.Ready, newJob.Status.Ready) isTerminatingChanged := !ptr.Equal(oldJob.Status.Terminating, newJob.Status.Terminating) isSuspendedWithZeroCompletions := ptr.Equal(newJob.Spec.Suspend, ptr.To(true)) && ptr.Equal(newJob.Spec.Completions, ptr.To[int32](0)) + // Detect job resume via condition changes (JobSuspended: True -> False) + // This handles the case where the controller updates status after the user has already + // changed spec.suspend=false, which is the scenario from https://github.com/kubernetes/kubernetes/issues/134521 + isJobResuming := batchvalidation.IsConditionTrue(oldJob.Status.Conditions, batch.JobSuspended) && + batchvalidation.IsConditionFalse(newJob.Status.Conditions, batch.JobSuspended) return batchvalidation.JobStatusValidationOptions{ // We allow to decrease the counter for succeeded pods for jobs which @@ -397,7 +402,7 @@ func getStatusValidationOptions(newJob, oldJob *batch.Job) batchvalidation.JobSt RejectFinishedJobWithActivePods: isJobFinishedChanged || isActiveChanged, RejectFinishedJobWithoutStartTime: (isJobFinishedChanged || isStartTimeChanged) && !isSuspendedWithZeroCompletions, RejectFinishedJobWithUncountedTerminatedPods: isJobFinishedChanged || isUncountedTerminatedPodsChanged, - RejectStartTimeUpdateForUnsuspendedJob: isStartTimeChanged, + RejectStartTimeUpdateForUnsuspendedJob: isStartTimeChanged && !isJobResuming, RejectCompletionTimeBeforeStartTime: isStartTimeChanged || isCompletionTimeChanged, RejectMutatingCompletionTime: true, RejectNotCompleteJobWithCompletionTime: isJobCompleteChanged || isCompletionTimeChanged, diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration.go b/vendor/k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration.go index 9e75df58db..48b9f2fc86 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/framework/plugins/tainttoleration/taint_toleration.go @@ -116,8 +116,8 @@ func (pl *TaintToleration) Filter(ctx context.Context, state fwk.CycleState, pod return nil } - errReason := fmt.Sprintf("node(s) had untolerated taint {%s: %s}", taint.Key, taint.Value) - return fwk.NewStatus(fwk.UnschedulableAndUnresolvable, errReason) + klog.FromContext(ctx).V(4).Info("node had untolerated taints", "node", klog.KObj(node), "pod", klog.KObj(pod), "untoleratedTaint", taint) + return fwk.NewStatus(fwk.UnschedulableAndUnresolvable, "node(s) had untolerated taint(s)") } // preScoreState computed at PreScore and used at Score. diff --git a/vendor/k8s.io/kubernetes/pkg/scheduler/framework/preemption/preemption.go b/vendor/k8s.io/kubernetes/pkg/scheduler/framework/preemption/preemption.go index 9bcd91592f..ee98910ef9 100644 --- a/vendor/k8s.io/kubernetes/pkg/scheduler/framework/preemption/preemption.go +++ b/vendor/k8s.io/kubernetes/pkg/scheduler/framework/preemption/preemption.go @@ -189,12 +189,12 @@ func NewEvaluator(pluginName string, fh framework.Handle, i Interface, enableAsy } } if err := util.DeletePod(ctx, ev.Handler.ClientSet(), victim); err != nil { - if apierrors.IsNotFound(err) { - logger.V(2).Info("Victim Pod is already deleted", "preemptor", klog.KObj(preemptor), "victim", klog.KObj(victim), "node", c.Name()) - } else { + if !apierrors.IsNotFound(err) { logger.Error(err, "Tried to preempted pod", "pod", klog.KObj(victim), "preemptor", klog.KObj(preemptor)) + return err } - return err + logger.V(2).Info("Victim Pod is already deleted", "preemptor", klog.KObj(preemptor), "victim", klog.KObj(victim), "node", c.Name()) + return nil } logger.V(2).Info("Preemptor Pod preempted victim Pod", "preemptor", klog.KObj(preemptor), "victim", klog.KObj(victim), "node", c.Name()) } @@ -436,14 +436,7 @@ func (ev *Evaluator) prepareCandidate(ctx context.Context, c Candidate, pod *v1. logger := klog.FromContext(ctx) errCh := parallelize.NewErrorChannel() fh.Parallelizer().Until(ctx, len(c.Victims().Pods), func(index int) { - victimPod := c.Victims().Pods[index] - if victimPod.DeletionTimestamp != nil { - // If the victim Pod is already being deleted, we don't have to make another deletion api call. - logger.V(2).Info("Victim Pod is already deleted, skipping the API call for it", "preemptor", klog.KObj(pod), "node", c.Name(), "victim", klog.KObj(victimPod)) - return - } - - if err := ev.PreemptPod(ctx, c, pod, victimPod, pluginName); err != nil && !apierrors.IsNotFound(err) { + if err := ev.PreemptPod(ctx, c, pod, c.Victims().Pods[index], pluginName); err != nil { errCh.SendErrorWithCancel(err, cancel) } }, ev.PluginName) @@ -504,34 +497,11 @@ func (ev *Evaluator) prepareCandidateAsync(c Candidate, pod *v1.Pod, pluginName // Intentionally create a new context, not using a ctx from the scheduling cycle, to create ctx, // because this process could continue even after this scheduling cycle finishes. ctx, cancel := context.WithCancel(context.Background()) - logger := klog.FromContext(ctx) - victimPods := make([]*v1.Pod, 0, len(c.Victims().Pods)) - for _, victim := range c.Victims().Pods { - if victim.DeletionTimestamp != nil { - // If the victim Pod is already being deleted, we don't have to make another deletion api call. - logger.V(2).Info("Victim Pod is already deleted, skipping the API call for it", "preemptor", klog.KObj(pod), "node", c.Name(), "victim", klog.KObj(victim)) - continue - } - victimPods = append(victimPods, victim) - } - if len(victimPods) == 0 { - cancel() - return - } - errCh := parallelize.NewErrorChannel() - // Whether all victim pods are already deleted before making API call. - var allPodsAlreadyDeleted atomic.Bool - allPodsAlreadyDeleted.Store(true) preemptPod := func(index int) { - victim := victimPods[index] - err := ev.PreemptPod(ctx, c, pod, victim, pluginName) - switch { - case err != nil && !apierrors.IsNotFound(err): - // We don't have to handle NotFound error here, because it means the victim Pod is already deleted, and the preemption didn't have to remove it. + victim := c.Victims().Pods[index] + if err := ev.PreemptPod(ctx, c, pod, victim, pluginName); err != nil { errCh.SendErrorWithCancel(err, cancel) - case err == nil: - allPodsAlreadyDeleted.Store(false) } } @@ -539,24 +509,21 @@ func (ev *Evaluator) prepareCandidateAsync(c Candidate, pod *v1.Pod, pluginName ev.preempting.Insert(pod.UID) ev.mu.Unlock() + logger := klog.FromContext(ctx) go func() { startTime := time.Now() result := metrics.GoroutineResultSuccess - defer metrics.PreemptionGoroutinesDuration.WithLabelValues(result).Observe(metrics.SinceInSeconds(startTime)) defer metrics.PreemptionGoroutinesExecutionTotal.WithLabelValues(result).Inc() defer func() { - // When API call isn't successful, the Pod may get stuck in the unschedulable pod pool in the worst case. - // So, we should move the Pod to the activeQ. - if result == metrics.GoroutineResultError || - // When all pods are already deleted (which is very rare, but could happen in theory), - // it's safe to activate the preemptor Pod because it might miss Pod/delete event that requeues the pod. - allPodsAlreadyDeleted.Load() { + if result == metrics.GoroutineResultError { + // When API call isn't successful, the Pod may get stuck in the unschedulable pod pool in the worst case. + // So, we should move the Pod to the activeQ. ev.Handler.Activate(logger, map[string]*v1.Pod{pod.Name: pod}) } }() defer cancel() - logger.V(2).Info("Start the preemption asynchronously", "preemptor", klog.KObj(pod), "node", c.Name(), "numVictims", len(c.Victims().Pods), "numVictimsToDelete", len(victimPods)) + logger.V(2).Info("Start the preemption asynchronously", "preemptor", klog.KObj(pod), "node", c.Name(), "numVictims", len(c.Victims().Pods)) // Lower priority pods nominated to run on this node, may no longer fit on // this node. So, we should remove their nomination. Removing their @@ -569,32 +536,33 @@ func (ev *Evaluator) prepareCandidateAsync(c Candidate, pod *v1.Pod, pluginName // We do not return as this error is not critical. } - if len(victimPods) > 1 { - // We can evict all victims in parallel, but the last one. - // We have to remove the pod from the preempting map before the last one is evicted - // because, otherwise, the pod removal might be notified to the scheduling queue before - // we remove this pod from the preempting map, - // and the pod could end up stucking at the unschedulable pod pool - // by all the pod removal events being ignored. - ev.Handler.Parallelizer().Until(ctx, len(victimPods)-1, preemptPod, ev.PluginName) - if err := errCh.ReceiveError(); err != nil { - utilruntime.HandleErrorWithContext(ctx, err, "Error occurred during async preemption") - result = metrics.GoroutineResultError - } + if len(c.Victims().Pods) == 0 { + ev.mu.Lock() + delete(ev.preempting, pod.UID) + ev.mu.Unlock() + + return + } + + // We can evict all victims in parallel, but the last one. + // We have to remove the pod from the preempting map before the last one is evicted + // because, otherwise, the pod removal might be notified to the scheduling queue before + // we remove this pod from the preempting map, + // and the pod could end up stucking at the unschedulable pod pool + // by all the pod removal events being ignored. + ev.Handler.Parallelizer().Until(ctx, len(c.Victims().Pods)-1, preemptPod, ev.PluginName) + if err := errCh.ReceiveError(); err != nil { + utilruntime.HandleErrorWithContext(ctx, err, "Error occurred during async preemption") + result = metrics.GoroutineResultError } ev.mu.Lock() delete(ev.preempting, pod.UID) ev.mu.Unlock() - err := ev.PreemptPod(ctx, c, pod, victimPods[len(victimPods)-1], pluginName) - switch { - case err != nil && !apierrors.IsNotFound(err): - // We don't have to handle NotFound error here, because it means the victim Pod is already deleted, and the preemption didn't have to remove it. + if err := ev.PreemptPod(ctx, c, pod, c.Victims().Pods[len(c.Victims().Pods)-1], pluginName); err != nil { utilruntime.HandleErrorWithContext(ctx, err, "Error occurred during async preemption") result = metrics.GoroutineResultError - case err == nil: - allPodsAlreadyDeleted.Store(false) } logger.V(2).Info("Async Preemption finished completely", "preemptor", klog.KObj(pod), "node", c.Name(), "result", result) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher.go b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher.go index 314fe68a85..c4fd435064 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/csi/csi_attacher.go @@ -252,7 +252,7 @@ func (c *csiAttacher) VolumesAreAttached(specs []*volume.Spec, nodeName types.No } func (c *csiAttacher) GetDeviceMountPath(spec *volume.Spec) (string, error) { - klog.V(4).Info(log("attacher.GetDeviceMountPath(%v)", spec)) + klog.V(4).Info(log("attacher.GetDeviceMountPath for volume(%s)", spec.Name())) deviceMountPath, err := makeDeviceMountPath(c.plugin, spec) if err != nil { return "", errors.New(log("attacher.GetDeviceMountPath failed to make device mount path: %v", err)) diff --git a/vendor/k8s.io/kubernetes/pkg/volume/plugins.go b/vendor/k8s.io/kubernetes/pkg/volume/plugins.go index a6426cbd9d..24b661493f 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/plugins.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/plugins.go @@ -997,7 +997,7 @@ func NewPersistentVolumeRecyclerPodTemplate() *v1.Pod { Containers: []v1.Container{ { Name: "pv-recycler", - Image: "registry.k8s.io/build-image/debian-base:bookworm-v1.0.4", + Image: "registry.k8s.io/build-image/debian-base:bookworm-v1.0.6", Command: []string{"/bin/sh"}, Args: []string{"-c", "test -e /scrub && find /scrub -mindepth 1 -delete && test -z \"$(ls -A /scrub)\" || exit 1"}, VolumeMounts: []v1.VolumeMount{ diff --git a/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go b/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go index c41f06b3a0..f8d4c348c4 100644 --- a/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go +++ b/vendor/k8s.io/kubernetes/pkg/volume/portworx/portworx.go @@ -308,8 +308,9 @@ func (b *portworxVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterAr notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) klog.Infof("Portworx Volume set up. Dir: %s %v %v", dir, !notMnt, err) if err != nil && !os.IsNotExist(err) { - klog.Errorf("Cannot validate mountpoint: %s", dir) - return err + // don't log error details from client calls in events + klog.V(4).Infof("Cannot validate mountpoint %s: %v", dir, err) + return fmt.Errorf("failed to validate mountpoint: see kube-controller-manager.log for details") } if !notMnt { return nil @@ -319,7 +320,9 @@ func (b *portworxVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterAr attachOptions[attachContextKey] = dir attachOptions[attachHostKey] = b.plugin.host.GetHostName() if _, err := b.manager.AttachVolume(b, attachOptions); err != nil { - return err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to attach volume %s: %v", b.volumeID, err) + return fmt.Errorf("failed to attach volume: see kube-controller-manager.log for details") } klog.V(4).Infof("Portworx Volume %s attached", b.volumeID) @@ -329,7 +332,9 @@ func (b *portworxVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterAr } if err := b.manager.MountVolume(b, dir); err != nil { - return err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to mount volume %s: %v", b.volumeID, err) + return fmt.Errorf("failed to mount volume: see kube-controller-manager.log for details") } if !b.readOnly { // Since portworxVolume is in process of being removed from in-tree, we avoid larger refactor to add progress tracking for ownership operation @@ -362,12 +367,16 @@ func (c *portworxVolumeUnmounter) TearDownAt(dir string) error { klog.Infof("Portworx Volume TearDown of %s", dir) if err := c.manager.UnmountVolume(c, dir); err != nil { - return err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to unmount volume %s: %v", c.volumeID, err) + return fmt.Errorf("failed to unmount volume: see kube-controller-manager.log for details") } // Call Portworx Detach Volume. if err := c.manager.DetachVolume(c); err != nil { - return err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to detach volume %s: %v", c.volumeID, err) + return fmt.Errorf("failed to detach volume: see kube-controller-manager.log for details") } return nil @@ -384,7 +393,13 @@ func (d *portworxVolumeDeleter) GetPath() string { } func (d *portworxVolumeDeleter) Delete() error { - return d.manager.DeleteVolume(d) + err := d.manager.DeleteVolume(d) + if err != nil { + // don't log error details from client calls in events + klog.V(4).Infof("Failed to delete volume %s: %v", d.volumeID, err) + return fmt.Errorf("failed to delete volume: see kube-controller-manager.log for details") + } + return nil } type portworxVolumeProvisioner struct { @@ -405,7 +420,9 @@ func (c *portworxVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopo volumeID, sizeGiB, labels, err := c.manager.CreateVolume(c) if err != nil { - return nil, err + // don't log error details from client calls in events + klog.V(4).Infof("Failed to create volume: %v", err) + return nil, fmt.Errorf("failed to create volume: see kube-controller-manager.log for details") } pv := &v1.PersistentVolume{ diff --git a/vendor/k8s.io/utils/net/multi_listen.go b/vendor/k8s.io/utils/net/multi_listen.go index 7cb7795bec..e5d508055d 100644 --- a/vendor/k8s.io/utils/net/multi_listen.go +++ b/vendor/k8s.io/utils/net/multi_listen.go @@ -21,6 +21,7 @@ import ( "fmt" "net" "sync" + "sync/atomic" ) // connErrPair pairs conn and error which is returned by accept on sub-listeners. @@ -38,6 +39,7 @@ type multiListener struct { connCh chan connErrPair // stopCh communicates from parent to child listeners. stopCh chan struct{} + closed atomic.Bool } // compile time check to ensure *multiListener implements net.Listener @@ -150,10 +152,8 @@ func (ml *multiListener) Accept() (net.Conn, error) { // the go-routines to exit. func (ml *multiListener) Close() error { // Make sure this can be called repeatedly without explosions. - select { - case <-ml.stopCh: + if !ml.closed.CompareAndSwap(false, true) { return fmt.Errorf("use of closed network connection") - default: } // Tell all sub-listeners to stop. diff --git a/vendor/modules.txt b/vendor/modules.txt index 32d4402208..daf6a4fca3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -138,8 +138,6 @@ github.com/fsnotify/fsnotify/internal # github.com/fxamacker/cbor/v2 v2.9.0 ## explicit; go 1.20 github.com/fxamacker/cbor/v2 -# github.com/ghodss/yaml v1.0.0 -## explicit # github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 ## explicit; go 1.13 github.com/go-asn1-ber/asn1-ber @@ -178,8 +176,6 @@ github.com/go-openapi/jsonreference/internal github.com/go-openapi/swag # github.com/go-stack/stack v1.8.1 ## explicit; go 1.17 -# github.com/go-viper/mapstructure/v2 v2.4.0 -## explicit; go 1.18 # github.com/godbus/dbus/v5 v5.1.0 ## explicit; go 1.12 github.com/godbus/dbus/v5 @@ -351,8 +347,6 @@ github.com/mistifyio/go-zfs # github.com/mitchellh/go-wordwrap v1.0.1 ## explicit; go 1.14 github.com/mitchellh/go-wordwrap -# github.com/mitchellh/mapstructure v1.5.0 -## explicit; go 1.14 # github.com/moby/spdystream v0.5.0 ## explicit; go 1.13 github.com/moby/spdystream @@ -419,7 +413,7 @@ github.com/opencontainers/runtime-spec/specs-go github.com/opencontainers/selinux/go-selinux github.com/opencontainers/selinux/go-selinux/label github.com/opencontainers/selinux/pkg/pwalkdir -# github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7 +# github.com/openshift/api v0.0.0-20251117165054-348370f055bf ## explicit; go 1.24.0 github.com/openshift/api github.com/openshift/api/annotations @@ -514,7 +508,7 @@ github.com/openshift/apiserver-library-go/pkg/securitycontextconstraints/sysctl github.com/openshift/apiserver-library-go/pkg/securitycontextconstraints/user github.com/openshift/apiserver-library-go/pkg/securitycontextconstraints/util github.com/openshift/apiserver-library-go/pkg/securitycontextconstraints/util/sort -# github.com/openshift/build-machinery-go v0.0.0-20250602125535-1b6d00b8c37c +# github.com/openshift/build-machinery-go v0.0.0-20251023084048-5d77c1a5e5af ## explicit; go 1.22.0 github.com/openshift/build-machinery-go github.com/openshift/build-machinery-go/make @@ -663,7 +657,7 @@ github.com/openshift/client-go/user/informers/externalversions/internalinterface github.com/openshift/client-go/user/informers/externalversions/user github.com/openshift/client-go/user/informers/externalversions/user/v1 github.com/openshift/client-go/user/listers/user/v1 -# github.com/openshift/cluster-policy-controller v0.0.0-20251007100337-ef703966fe6e +# github.com/openshift/cluster-policy-controller v0.0.0-20251120141414-8b775487512f ## explicit; go 1.24.0 github.com/openshift/cluster-policy-controller/pkg/client/genericinformers github.com/openshift/cluster-policy-controller/pkg/cmd/cluster-policy-controller @@ -676,7 +670,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-20251015151611-6fc7a74b67c5 +# github.com/openshift/library-go v0.0.0-20251112091634-ab97ebb73f0f ## explicit; go 1.24.0 github.com/openshift/library-go/pkg/apiserver/admission/admissionrestconfig github.com/openshift/library-go/pkg/apiserver/admission/admissiontimeout @@ -726,7 +720,7 @@ 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-20251008111043-c337cf413bbb +# github.com/openshift/route-controller-manager v0.0.0-20251106134803-8a69194a461d ## explicit; go 1.24.0 github.com/openshift/route-controller-manager/pkg/cmd/controller github.com/openshift/route-controller-manager/pkg/cmd/route-controller-manager @@ -734,8 +728,6 @@ github.com/openshift/route-controller-manager/pkg/route/ingress github.com/openshift/route-controller-manager/pkg/route/ingressip github.com/openshift/route-controller-manager/pkg/routecontroller github.com/openshift/route-controller-manager/pkg/version -# github.com/pelletier/go-toml/v2 v2.2.4 -## explicit; go 1.21.0 # github.com/peterbourgon/diskv v2.0.1+incompatible ## explicit github.com/peterbourgon/diskv @@ -791,25 +783,15 @@ github.com/robfig/cron/v3 # github.com/russross/blackfriday/v2 v2.1.0 ## explicit github.com/russross/blackfriday/v2 -# github.com/sagikazarmark/locafero v0.11.0 -## explicit; go 1.23.0 # github.com/sirupsen/logrus v1.9.3 ## explicit; go 1.13 github.com/sirupsen/logrus -# github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 -## explicit; go 1.20 -# github.com/spf13/afero v1.15.0 -## explicit; go 1.23.0 -# github.com/spf13/cast v1.10.0 -## explicit; go 1.21.0 # github.com/spf13/cobra v1.9.1 ## explicit; go 1.15 github.com/spf13/cobra # github.com/spf13/pflag v1.0.10 ## explicit; go 1.12 github.com/spf13/pflag -# github.com/spf13/viper v1.21.0 -## explicit; go 1.23.0 # github.com/squat/generic-device-plugin v0.0.0-20251019101956-043a51e18f31 ## explicit; go 1.24.0 github.com/squat/generic-device-plugin/absolute @@ -822,8 +804,6 @@ github.com/stoewer/go-strcase github.com/stretchr/testify/assert github.com/stretchr/testify/assert/yaml github.com/stretchr/testify/require -# github.com/subosito/gotenv v1.6.0 -## explicit; go 1.18 # github.com/vishvananda/netlink v1.3.1 ## explicit; go 1.12 github.com/vishvananda/netlink @@ -1210,7 +1190,7 @@ gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3 -# k8s.io/api v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/api +# k8s.io/api v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/api ## explicit; go 1.24.0 k8s.io/api/admission/v1 k8s.io/api/admission/v1beta1 @@ -1272,7 +1252,7 @@ k8s.io/api/storage/v1 k8s.io/api/storage/v1alpha1 k8s.io/api/storage/v1beta1 k8s.io/api/storagemigration/v1alpha1 -# k8s.io/apiextensions-apiserver v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver +# k8s.io/apiextensions-apiserver v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiextensions-apiserver ## explicit; go 1.24.0 k8s.io/apiextensions-apiserver/pkg/apihelpers k8s.io/apiextensions-apiserver/pkg/apis/apiextensions @@ -1319,7 +1299,7 @@ k8s.io/apiextensions-apiserver/pkg/generated/openapi k8s.io/apiextensions-apiserver/pkg/registry/customresource k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition -# k8s.io/apimachinery v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery +# k8s.io/apimachinery v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/apimachinery ## explicit; go 1.24.0 k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/api/errors @@ -1397,7 +1377,7 @@ k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/third_party/forked/golang/json k8s.io/apimachinery/third_party/forked/golang/netutil k8s.io/apimachinery/third_party/forked/golang/reflect -# k8s.io/apiserver v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiserver +# k8s.io/apiserver v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/apiserver ## explicit; go 1.24.0 k8s.io/apiserver/pkg/admission k8s.io/apiserver/pkg/admission/configuration @@ -1584,13 +1564,13 @@ k8s.io/apiserver/plugin/pkg/authenticator/token/oidc k8s.io/apiserver/plugin/pkg/authenticator/token/webhook k8s.io/apiserver/plugin/pkg/authorizer/webhook k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics -# k8s.io/cli-runtime v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime +# k8s.io/cli-runtime v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cli-runtime ## explicit; go 1.24.0 k8s.io/cli-runtime/pkg/genericclioptions k8s.io/cli-runtime/pkg/genericiooptions k8s.io/cli-runtime/pkg/printers k8s.io/cli-runtime/pkg/resource -# k8s.io/client-go v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go +# k8s.io/client-go v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/client-go ## explicit; go 1.24.0 k8s.io/client-go/applyconfigurations k8s.io/client-go/applyconfigurations/admissionregistration/v1 @@ -1958,7 +1938,7 @@ k8s.io/client-go/util/jsonpath k8s.io/client-go/util/keyutil k8s.io/client-go/util/retry k8s.io/client-go/util/workqueue -# k8s.io/cloud-provider v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider +# k8s.io/cloud-provider v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cloud-provider ## explicit; go 1.24.0 k8s.io/cloud-provider k8s.io/cloud-provider/api @@ -1976,14 +1956,14 @@ k8s.io/cloud-provider/service/helpers k8s.io/cloud-provider/volume k8s.io/cloud-provider/volume/errors k8s.io/cloud-provider/volume/helpers -# k8s.io/cluster-bootstrap v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap +# k8s.io/cluster-bootstrap v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cluster-bootstrap ## explicit; go 1.24.0 k8s.io/cluster-bootstrap/token/api k8s.io/cluster-bootstrap/token/jws k8s.io/cluster-bootstrap/token/util k8s.io/cluster-bootstrap/util/secrets k8s.io/cluster-bootstrap/util/tokens -# k8s.io/component-base v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/component-base +# k8s.io/component-base v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/component-base ## explicit; go 1.24.0 k8s.io/component-base/cli k8s.io/component-base/cli/flag @@ -2023,7 +2003,7 @@ k8s.io/component-base/zpages/features k8s.io/component-base/zpages/flagz k8s.io/component-base/zpages/httputil k8s.io/component-base/zpages/statusz -# k8s.io/component-helpers v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers +# k8s.io/component-helpers v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/component-helpers ## explicit; go 1.24.0 k8s.io/component-helpers/apimachinery/lease k8s.io/component-helpers/apps/poddisruptionbudget @@ -2037,7 +2017,7 @@ k8s.io/component-helpers/scheduling/corev1 k8s.io/component-helpers/scheduling/corev1/nodeaffinity k8s.io/component-helpers/storage/ephemeral k8s.io/component-helpers/storage/volume -# k8s.io/controller-manager v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager +# k8s.io/controller-manager v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/controller-manager ## explicit; go 1.24.0 k8s.io/controller-manager/app k8s.io/controller-manager/config @@ -2054,22 +2034,22 @@ k8s.io/controller-manager/pkg/informerfactory k8s.io/controller-manager/pkg/leadermigration k8s.io/controller-manager/pkg/leadermigration/config k8s.io/controller-manager/pkg/leadermigration/options -# k8s.io/cri-api v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cri-api +# k8s.io/cri-api v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cri-api ## explicit; go 1.24.0 k8s.io/cri-api/pkg/apis k8s.io/cri-api/pkg/apis/runtime/v1 k8s.io/cri-api/pkg/errors -# k8s.io/cri-client v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cri-client +# k8s.io/cri-client v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/cri-client ## explicit; go 1.24.0 k8s.io/cri-client/pkg k8s.io/cri-client/pkg/internal k8s.io/cri-client/pkg/logs k8s.io/cri-client/pkg/util -# k8s.io/csi-translation-lib v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib +# k8s.io/csi-translation-lib v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/csi-translation-lib ## explicit; go 1.24.0 k8s.io/csi-translation-lib k8s.io/csi-translation-lib/plugins -# k8s.io/dynamic-resource-allocation v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation +# k8s.io/dynamic-resource-allocation v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/dynamic-resource-allocation ## explicit; go 1.24.0 k8s.io/dynamic-resource-allocation/api k8s.io/dynamic-resource-allocation/cel @@ -2080,14 +2060,14 @@ k8s.io/dynamic-resource-allocation/structured/internal k8s.io/dynamic-resource-allocation/structured/internal/experimental k8s.io/dynamic-resource-allocation/structured/internal/incubating k8s.io/dynamic-resource-allocation/structured/internal/stable -# k8s.io/endpointslice v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/endpointslice +# k8s.io/endpointslice v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/endpointslice ## explicit; go 1.24.0 k8s.io/endpointslice k8s.io/endpointslice/metrics k8s.io/endpointslice/topologycache k8s.io/endpointslice/trafficdist k8s.io/endpointslice/util -# k8s.io/externaljwt v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/externaljwt +# k8s.io/externaljwt v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/externaljwt ## explicit; go 1.24.0 k8s.io/externaljwt/apis/v1 # k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f @@ -2109,13 +2089,13 @@ 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/kms v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kms +# k8s.io/kms v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kms ## explicit; go 1.24.0 k8s.io/kms/apis/v1beta1 k8s.io/kms/apis/v2 k8s.io/kms/pkg/service k8s.io/kms/pkg/util -# k8s.io/kube-aggregator v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator +# k8s.io/kube-aggregator v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kube-aggregator ## explicit; go 1.24.0 k8s.io/kube-aggregator/pkg/apis/apiregistration k8s.io/kube-aggregator/pkg/apis/apiregistration/install @@ -2148,7 +2128,7 @@ k8s.io/kube-aggregator/pkg/controllers/status/remote k8s.io/kube-aggregator/pkg/registry/apiservice k8s.io/kube-aggregator/pkg/registry/apiservice/etcd k8s.io/kube-aggregator/pkg/registry/apiservice/rest -# k8s.io/kube-controller-manager v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kube-controller-manager +# 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 @@ -2182,12 +2162,12 @@ k8s.io/kube-openapi/pkg/validation/spec k8s.io/kube-openapi/pkg/validation/strfmt k8s.io/kube-openapi/pkg/validation/strfmt/bson k8s.io/kube-openapi/pkg/validation/validate -# k8s.io/kube-scheduler v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler +# k8s.io/kube-scheduler v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kube-scheduler ## explicit; go 1.24.0 k8s.io/kube-scheduler/config/v1 k8s.io/kube-scheduler/extender/v1 k8s.io/kube-scheduler/framework -# k8s.io/kubectl v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubectl +# k8s.io/kubectl v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubectl ## explicit; go 1.24.0 k8s.io/kubectl/pkg/apps k8s.io/kubectl/pkg/cmd/apiresources @@ -2222,7 +2202,7 @@ k8s.io/kubectl/pkg/util/storage k8s.io/kubectl/pkg/util/templates k8s.io/kubectl/pkg/util/term k8s.io/kubectl/pkg/validation -# k8s.io/kubelet v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubelet +# k8s.io/kubelet v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/kubelet ## explicit; go 1.24.0 k8s.io/kubelet/config/v1 k8s.io/kubelet/config/v1alpha1 @@ -2245,7 +2225,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.1 => ./deps/github.com/openshift/kubernetes +# k8s.io/kubernetes v1.34.2 => ./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 @@ -3079,7 +3059,7 @@ k8s.io/kubernetes/third_party/forked/gonum/graph/simple k8s.io/kubernetes/third_party/forked/gonum/graph/traverse k8s.io/kubernetes/third_party/forked/libcontainer/apparmor k8s.io/kubernetes/third_party/forked/libcontainer/utils -# k8s.io/metrics v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/metrics +# k8s.io/metrics v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/metrics ## explicit; go 1.24.0 k8s.io/metrics/pkg/apis/custom_metrics k8s.io/metrics/pkg/apis/custom_metrics/v1beta1 @@ -3094,10 +3074,10 @@ k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1 k8s.io/metrics/pkg/client/custom_metrics k8s.io/metrics/pkg/client/custom_metrics/scheme k8s.io/metrics/pkg/client/external_metrics -# k8s.io/mount-utils v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils +# k8s.io/mount-utils v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/mount-utils ## explicit; go 1.24.0 k8s.io/mount-utils -# k8s.io/pod-security-admission v1.34.1 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission +# k8s.io/pod-security-admission v1.34.2 => ./deps/github.com/openshift/kubernetes/staging/src/k8s.io/pod-security-admission ## explicit; go 1.24.0 k8s.io/pod-security-admission/admission k8s.io/pod-security-admission/admission/api @@ -3110,7 +3090,7 @@ k8s.io/pod-security-admission/admission/api/validation k8s.io/pod-security-admission/api k8s.io/pod-security-admission/metrics k8s.io/pod-security-admission/policy -# k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 +# k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 ## explicit; go 1.18 k8s.io/utils/buffer k8s.io/utils/clock From 293f2ebc86d266b7e88e10d7e5f49e311436b947 Mon Sep 17 00:00:00 2001 From: Alejandro Gullon Date: Wed, 17 Dec 2025 23:45:12 +0100 Subject: [PATCH 2/3] fix regexp expression --- test/assets/common_versions.sh.template | 18 +++++++++--------- test/bin/common_versions.sh | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/test/assets/common_versions.sh.template b/test/assets/common_versions.sh.template index f2d8ddbd3f..bdcb9102b1 100644 --- a/test/assets/common_versions.sh.template +++ b/test/assets/common_versions.sh.template @@ -142,26 +142,26 @@ export CNCF_SYSTEMD_LOGS_VERSION={CNCF_SYSTEMD_LOGS_VERSION} export GITOPS_VERSION={GITOPS_VERSION} # The brew release versions needed for release regression testing -Y0_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}$" | sort -V | tail -n1 || echo "")" -Y1_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{PREVIOUS_MINOR_VERSION}}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" -Y2_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{YMINUS2_MINOR_VERSION}}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" -Z1_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" -RC_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}-rc$" | sort -V | tail -n1 || echo "")" -EC_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}-ec$" | sort -V | tail -n1 || echo "")" -NIGHTLY_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]{1,2}-nightly$" | sort -V | tail -n1 || echo "")" +Y0_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*$" | sort -V | tail -n1 || echo "")" +Z1_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*$" | sort -V | head -n1 || echo "")" +Y1_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{PREVIOUS_MINOR_VERSION}}.[0-9]*$" | sort -V | head -n1 || echo "")" +Y2_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{YMINUS2_MINOR_VERSION}}.[0-9]*$" | sort -V | head -n1 || echo "")" +RC_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*-rc$" | sort -V | head -n1 || echo "")" +EC_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*-ec$" | sort -V | head -n1 || echo "")" +NIGHTLY_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*-nightly$" | sort -V | head -n1 || echo "")" BREW_Y0_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Y0_VERSION}}/{ARCH}/")" +BREW_Z1_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Z1_VERSION}}/{ARCH}/")" BREW_Y1_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Y1_VERSION}}/{ARCH}/")" BREW_Y2_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Y2_VERSION}}/{ARCH}/")" -BREW_Z1_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Z1_VERSION}}/{ARCH}/")" BREW_RC_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{RC_VERSION}}/{ARCH}/")" BREW_EC_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{EC_VERSION}}/{ARCH}/")" BREW_NIGHTLY_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{NIGHTLY_VERSION}}/{ARCH}/")" export BREW_Y0_RELEASE_VERSION +export BREW_Z1_RELEASE_VERSION export BREW_Y1_RELEASE_VERSION export BREW_Y2_RELEASE_VERSION -export BREW_Z1_RELEASE_VERSION export BREW_RC_RELEASE_VERSION export BREW_EC_RELEASE_VERSION export BREW_NIGHTLY_RELEASE_VERSION diff --git a/test/bin/common_versions.sh b/test/bin/common_versions.sh index 3525542234..16fc5ceb1d 100644 --- a/test/bin/common_versions.sh +++ b/test/bin/common_versions.sh @@ -142,26 +142,26 @@ export CNCF_SYSTEMD_LOGS_VERSION=v0.4 export GITOPS_VERSION=1.16 # The brew release versions needed for release regression testing -Y0_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}$" | sort -V | tail -n1 || echo "")" -Y1_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${PREVIOUS_MINOR_VERSION}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" -Y2_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${YMINUS2_MINOR_VERSION}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" -Z1_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}$" | sort -V | head -n1 || echo "")" -RC_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}-rc$" | sort -V | tail -n1 || echo "")" -EC_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}-ec$" | sort -V | tail -n1 || echo "")" -NIGHTLY_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]{1,2}-nightly$" | sort -V | tail -n1 || echo "")" +Y0_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*$" | sort -V | tail -n1 || echo "")" +Z1_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*$" | sort -V | head -n1 || echo "")" +Y1_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${PREVIOUS_MINOR_VERSION}.[0-9]*$" | sort -V | head -n1 || echo "")" +Y2_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${YMINUS2_MINOR_VERSION}.[0-9]*$" | sort -V | head -n1 || echo "")" +RC_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*-rc$" | sort -V | head -n1 || echo "")" +EC_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*-ec$" | sort -V | head -n1 || echo "")" +NIGHTLY_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*-nightly$" | sort -V | head -n1 || echo "")" BREW_Y0_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Y0_VERSION}/${UNAME_M}/")" +BREW_Z1_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Z1_VERSION}/${UNAME_M}/")" BREW_Y1_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Y1_VERSION}/${UNAME_M}/")" BREW_Y2_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Y2_VERSION}/${UNAME_M}/")" -BREW_Z1_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Z1_VERSION}/${UNAME_M}/")" BREW_RC_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${RC_VERSION}/${UNAME_M}/")" BREW_EC_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${EC_VERSION}/${UNAME_M}/")" BREW_NIGHTLY_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${NIGHTLY_VERSION}/${UNAME_M}/")" export BREW_Y0_RELEASE_VERSION +export BREW_Z1_RELEASE_VERSION export BREW_Y1_RELEASE_VERSION export BREW_Y2_RELEASE_VERSION -export BREW_Z1_RELEASE_VERSION export BREW_RC_RELEASE_VERSION export BREW_EC_RELEASE_VERSION export BREW_NIGHTLY_RELEASE_VERSION From 8091e88b42e42183f005d5af833935f36000cf38 Mon Sep 17 00:00:00 2001 From: Alejandro Gullon Date: Thu, 18 Dec 2025 09:25:48 +0100 Subject: [PATCH 3/3] fix shellcheck --- test/assets/common_versions.sh.template | 14 +++++++------- test/bin/common_versions.sh | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test/assets/common_versions.sh.template b/test/assets/common_versions.sh.template index bdcb9102b1..026ff0ee02 100644 --- a/test/assets/common_versions.sh.template +++ b/test/assets/common_versions.sh.template @@ -142,13 +142,13 @@ export CNCF_SYSTEMD_LOGS_VERSION={CNCF_SYSTEMD_LOGS_VERSION} export GITOPS_VERSION={GITOPS_VERSION} # The brew release versions needed for release regression testing -Y0_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*$" | sort -V | tail -n1 || echo "")" -Z1_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*$" | sort -V | head -n1 || echo "")" -Y1_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{PREVIOUS_MINOR_VERSION}}.[0-9]*$" | sort -V | head -n1 || echo "")" -Y2_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{YMINUS2_MINOR_VERSION}}.[0-9]*$" | sort -V | head -n1 || echo "")" -RC_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*-rc$" | sort -V | head -n1 || echo "")" -EC_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*-ec$" | sort -V | head -n1 || echo "")" -NIGHTLY_VERSION="$(ls "${{BREW_RPM_SOURCE}}" | grep -E "(4|5).${{MINOR_VERSION}}.[0-9]*-nightly$" | sort -V | head -n1 || echo "")" +Y0_VERSION="$(find "${{BREW_RPM_SOURCE}}" -maxdepth 1 -type d -regex ".*/[45]\.${{MINOR_VERSION}}\.[0-9]+$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +Z1_VERSION="$(find "${{BREW_RPM_SOURCE}}" -maxdepth 1 -type d -regex ".*/[45]\.${{MINOR_VERSION}}\.[0-9]+$" -printf '%f\n' | sort -V | head -n1 || echo "")" +Y1_VERSION="$(find "${{BREW_RPM_SOURCE}}" -maxdepth 1 -type d -regex ".*/[45]\.${{PREVIOUS_MINOR_VERSION}}\.[0-9]+$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +Y2_VERSION="$(find "${{BREW_RPM_SOURCE}}" -maxdepth 1 -type d -regex ".*/[45]\.${{YMINUS2_MINOR_VERSION}}\.[0-9]+$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +RC_VERSION="$(find "${{BREW_RPM_SOURCE}}" -maxdepth 1 -type d -regex ".*/[45]\.${{MINOR_VERSION}}\.[0-9]*-rc$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +EC_VERSION="$(find "${{BREW_RPM_SOURCE}}" -maxdepth 1 -type d -regex ".*/[45]\.${{MINOR_VERSION}}\.[0-9]*-ec$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +NIGHTLY_VERSION="$(find "${{BREW_RPM_SOURCE}}" -maxdepth 1 -type d -regex ".*/[45]\.${{MINOR_VERSION}}\.[0-9]*-nightly$" -printf '%f\n' | sort -V | tail -n1 || echo "")" BREW_Y0_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Y0_VERSION}}/{ARCH}/")" BREW_Z1_RELEASE_VERSION="$(get_vrel_from_rpm "${{BREW_RPM_SOURCE}}/${{Z1_VERSION}}/{ARCH}/")" diff --git a/test/bin/common_versions.sh b/test/bin/common_versions.sh index 16fc5ceb1d..84a87bc753 100644 --- a/test/bin/common_versions.sh +++ b/test/bin/common_versions.sh @@ -142,13 +142,13 @@ export CNCF_SYSTEMD_LOGS_VERSION=v0.4 export GITOPS_VERSION=1.16 # The brew release versions needed for release regression testing -Y0_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*$" | sort -V | tail -n1 || echo "")" -Z1_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*$" | sort -V | head -n1 || echo "")" -Y1_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${PREVIOUS_MINOR_VERSION}.[0-9]*$" | sort -V | head -n1 || echo "")" -Y2_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${YMINUS2_MINOR_VERSION}.[0-9]*$" | sort -V | head -n1 || echo "")" -RC_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*-rc$" | sort -V | head -n1 || echo "")" -EC_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*-ec$" | sort -V | head -n1 || echo "")" -NIGHTLY_VERSION="$(ls "${BREW_RPM_SOURCE}" | grep -E "(4|5).${MINOR_VERSION}.[0-9]*-nightly$" | sort -V | head -n1 || echo "")" +Y0_VERSION="$(find "${BREW_RPM_SOURCE}" -maxdepth 1 -type d -regex ".*/[45]\.${MINOR_VERSION}\.[0-9]+$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +Z1_VERSION="$(find "${BREW_RPM_SOURCE}" -maxdepth 1 -type d -regex ".*/[45]\.${MINOR_VERSION}\.[0-9]+$" -printf '%f\n' | sort -V | head -n1 || echo "")" +Y1_VERSION="$(find "${BREW_RPM_SOURCE}" -maxdepth 1 -type d -regex ".*/[45]\.${PREVIOUS_MINOR_VERSION}\.[0-9]+$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +Y2_VERSION="$(find "${BREW_RPM_SOURCE}" -maxdepth 1 -type d -regex ".*/[45]\.${YMINUS2_MINOR_VERSION}\.[0-9]+$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +RC_VERSION="$(find "${BREW_RPM_SOURCE}" -maxdepth 1 -type d -regex ".*/[45]\.${MINOR_VERSION}\.[0-9]*-rc$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +EC_VERSION="$(find "${BREW_RPM_SOURCE}" -maxdepth 1 -type d -regex ".*/[45]\.${MINOR_VERSION}\.[0-9]*-ec$" -printf '%f\n' | sort -V | tail -n1 || echo "")" +NIGHTLY_VERSION="$(find "${BREW_RPM_SOURCE}" -maxdepth 1 -type d -regex ".*/[45]\.${MINOR_VERSION}\.[0-9]*-nightly$" -printf '%f\n' | sort -V | tail -n1 || echo "")" BREW_Y0_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Y0_VERSION}/${UNAME_M}/")" BREW_Z1_RELEASE_VERSION="$(get_vrel_from_rpm "${BREW_RPM_SOURCE}/${Z1_VERSION}/${UNAME_M}/")"