From 461a15446965d45530876d5a5d33a676c6468be3 Mon Sep 17 00:00:00 2001 From: "red-hat-konflux[bot]" <126015336+red-hat-konflux[bot]@users.noreply.github.com> Date: Sat, 25 Apr 2026 01:48:26 +0000 Subject: [PATCH] fix(deps): update non-k8s-go-dependencies Signed-off-by: red-hat-konflux <126015336+red-hat-konflux[bot]@users.noreply.github.com> --- go.mod | 67 +- go.sum | 419 +--- vendor/github.com/fatih/color/color.go | 112 +- .../github.com/fatih/color/color_windows.go | 3 + .../fxamacker/cbor/v2/.golangci.yml | 176 +- vendor/github.com/fxamacker/cbor/v2/README.md | 11 +- vendor/github.com/fxamacker/cbor/v2/cache.go | 257 ++- vendor/github.com/fxamacker/cbor/v2/decode.go | 440 ++-- .../fxamacker/cbor/v2/decode_map_utils.go | 98 + .../github.com/fxamacker/cbor/v2/diagnose.go | 25 +- vendor/github.com/fxamacker/cbor/v2/encode.go | 55 +- .../fxamacker/cbor/v2/simplevalue.go | 2 +- vendor/github.com/fxamacker/cbor/v2/stream.go | 48 +- .../fxamacker/cbor/v2/structfields.go | 65 +- vendor/github.com/fxamacker/cbor/v2/valid.go | 20 +- .../go-openapi/jsonpointer/.gitignore | 6 +- .../go-openapi/jsonpointer/.golangci.yml | 107 +- .../go-openapi/jsonpointer/CODE_OF_CONDUCT.md | 6 +- .../go-openapi/jsonpointer/CONTRIBUTORS.md | 25 + .../github.com/go-openapi/jsonpointer/LICENSE | 1 - .../github.com/go-openapi/jsonpointer/NOTICE | 39 + .../go-openapi/jsonpointer/README.md | 171 +- .../go-openapi/jsonpointer/SECURITY.md | 37 + .../go-openapi/jsonpointer/errors.go | 49 +- .../go-openapi/jsonpointer/ifaces.go | 47 + .../go-openapi/jsonpointer/options.go | 86 + .../go-openapi/jsonpointer/pointer.go | 837 ++++--- .../go-openapi/jsonreference/.editorconfig | 26 + .../go-openapi/jsonreference/.gitignore | 7 +- .../go-openapi/jsonreference/.golangci.yml | 112 +- .../jsonreference/CODE_OF_CONDUCT.md | 6 +- .../go-openapi/jsonreference/CONTRIBUTORS.md | 21 + .../go-openapi/jsonreference/NOTICE | 39 + .../go-openapi/jsonreference/README.md | 128 +- .../go-openapi/jsonreference/SECURITY.md | 37 + .../jsonreference/internal/normalize_url.go | 11 +- .../go-openapi/jsonreference/reference.go | 112 +- .../github.com/go-openapi/swag/.codecov.yml | 4 + vendor/github.com/go-openapi/swag/.gitignore | 1 + .../github.com/go-openapi/swag/.golangci.yml | 118 +- .../github.com/go-openapi/swag/.mockery.yml | 30 + .../go-openapi/swag/CODE_OF_CONDUCT.md | 6 +- .../go-openapi/swag/CONTRIBUTORS.md | 36 + vendor/github.com/go-openapi/swag/README.md | 231 +- vendor/github.com/go-openapi/swag/SECURITY.md | 37 + .../swag/cmdutils}/LICENSE | 1 + .../go-openapi/swag/cmdutils/cmd_utils.go | 13 + .../go-openapi/swag/cmdutils/doc.go | 5 + .../go-openapi/swag/cmdutils_iface.go | 11 + .../github.com/go-openapi/swag/conv/LICENSE | 202 ++ .../go-openapi/swag/conv/convert.go | 161 ++ .../go-openapi/swag/conv/convert_types.go | 72 + vendor/github.com/go-openapi/swag/conv/doc.go | 15 + .../github.com/go-openapi/swag/conv/format.go | 28 + .../github.com/go-openapi/swag/conv/sizeof.go | 20 + .../go-openapi/swag/conv/type_constraints.go | 29 + .../github.com/go-openapi/swag/conv_iface.go | 486 ++++ vendor/github.com/go-openapi/swag/convert.go | 208 -- .../go-openapi/swag/convert_types.go | 730 ------ vendor/github.com/go-openapi/swag/doc.go | 70 +- vendor/github.com/go-openapi/swag/errors.go | 15 - vendor/github.com/go-openapi/swag/file.go | 33 - .../go-openapi/swag/fileutils/LICENSE | 202 ++ .../go-openapi/swag/fileutils/doc.go | 10 + .../go-openapi/swag/fileutils/file.go | 22 + .../go-openapi/swag/{ => fileutils}/path.go | 29 +- .../go-openapi/swag/fileutils_iface.go | 33 + .../go-openapi/swag/initialism_index.go | 202 -- vendor/github.com/go-openapi/swag/json.go | 313 --- .../go-openapi/swag/jsonname/LICENSE | 202 ++ .../go-openapi/swag/jsonname/doc.go | 5 + .../swag/jsonname/go_name_provider.go | 286 +++ .../go-openapi/swag/jsonname/ifaces.go | 14 + .../go-openapi/swag/jsonname/name_provider.go | 140 ++ .../go-openapi/swag/jsonname_iface.go | 24 + .../go-openapi/swag/jsonutils/LICENSE | 202 ++ .../go-openapi/swag/jsonutils/README.md | 109 + .../go-openapi/swag/jsonutils/adapters/doc.go | 8 + .../swag/jsonutils/adapters/ifaces/doc.go | 5 + .../swag/jsonutils/adapters/ifaces/ifaces.go | 84 + .../adapters/ifaces/registry_iface.go | 91 + .../swag/jsonutils/adapters/registry.go | 229 ++ .../jsonutils/adapters/stdlib/json/adapter.go | 115 + .../jsonutils/adapters/stdlib/json/doc.go | 5 + .../jsonutils/adapters/stdlib/json/lexer.go | 320 +++ .../adapters/stdlib/json/ordered_map.go | 266 +++ .../jsonutils/adapters/stdlib/json/pool.go | 143 ++ .../adapters/stdlib/json/register.go | 26 + .../jsonutils/adapters/stdlib/json/writer.go | 75 + .../go-openapi/swag/jsonutils/concat.go | 92 + .../go-openapi/swag/jsonutils/doc.go | 7 + .../go-openapi/swag/jsonutils/json.go | 116 + .../go-openapi/swag/jsonutils/ordered_map.go | 114 + .../go-openapi/swag/jsonutils_iface.go | 65 + .../go-openapi/swag/loading/LICENSE | 202 ++ .../github.com/go-openapi/swag/loading/doc.go | 5 + .../go-openapi/swag/loading/errors.go | 15 + .../go-openapi/swag/loading/json.go | 25 + .../go-openapi/swag/{ => loading}/loading.go | 88 +- .../go-openapi/swag/loading/options.go | 125 + .../go-openapi/swag/loading/yaml.go | 37 + .../go-openapi/swag/loading_iface.go | 91 + .../swag/{ => mangling}/BENCHMARK.md | 48 +- .../go-openapi/swag/mangling/LICENSE | 202 ++ .../go-openapi/swag/mangling/doc.go | 25 + .../swag/mangling/initialism_index.go | 270 +++ .../go-openapi/swag/mangling/name_lexem.go | 186 ++ .../go-openapi/swag/mangling/name_mangler.go | 370 +++ .../go-openapi/swag/mangling/options.go | 150 ++ .../go-openapi/swag/mangling/pools.go | 123 + .../go-openapi/swag/mangling/split.go | 341 +++ .../swag/{ => mangling}/string_bytes.go | 5 +- .../go-openapi/swag/mangling/util.go | 118 + .../go-openapi/swag/mangling_iface.go | 69 + .../github.com/go-openapi/swag/name_lexem.go | 93 - vendor/github.com/go-openapi/swag/net.go | 38 - .../go-openapi/swag/netutils/LICENSE | 202 ++ .../go-openapi/swag/netutils/doc.go | 5 + .../go-openapi/swag/netutils/net.go | 31 + .../go-openapi/swag/netutils_iface.go | 13 + vendor/github.com/go-openapi/swag/split.go | 508 ----- .../go-openapi/swag/stringutils/LICENSE | 202 ++ .../swag/stringutils/collection_formats.go | 74 + .../go-openapi/swag/stringutils/doc.go | 5 + .../go-openapi/swag/stringutils/strings.go | 23 + .../go-openapi/swag/stringutils_iface.go | 34 + .../go-openapi/swag/typeutils/LICENSE | 202 ++ .../go-openapi/swag/typeutils/doc.go | 5 + .../go-openapi/swag/typeutils/types.go | 80 + .../go-openapi/swag/typeutils_iface.go | 12 + vendor/github.com/go-openapi/swag/util.go | 364 --- vendor/github.com/go-openapi/swag/yaml.go | 481 ---- .../go-openapi/swag/yamlutils/LICENSE | 202 ++ .../go-openapi/swag/yamlutils/doc.go | 13 + .../go-openapi/swag/yamlutils/errors.go | 15 + .../go-openapi/swag/yamlutils/ordered_map.go | 316 +++ .../go-openapi/swag/yamlutils/yaml.go | 211 ++ .../go-openapi/swag/yamlutils_iface.go | 20 + .../gnostic-models/extensions/extension.proto | 2 +- .../gnostic-models/openapiv2/OpenAPIv2.proto | 2 +- .../gnostic-models/openapiv3/OpenAPIv3.proto | 2 +- .../openapiv3/annotations.proto | 2 +- vendor/github.com/hashicorp/go-hclog/LICENSE | 4 +- .../github.com/hashicorp/go-hclog/README.md | 15 +- .../hashicorp/go-hclog/colorize_unix.go | 39 +- .../hashicorp/go-hclog/colorize_windows.go | 42 +- .../github.com/hashicorp/go-hclog/context.go | 3 + .../github.com/hashicorp/go-hclog/exclude.go | 3 + .../github.com/hashicorp/go-hclog/global.go | 9 +- .../hashicorp/go-hclog/interceptlogger.go | 115 +- .../hashicorp/go-hclog/intlogger.go | 522 ++++- .../github.com/hashicorp/go-hclog/logger.go | 108 +- .../hashicorp/go-hclog/nulllogger.go | 5 + .../github.com/hashicorp/go-hclog/stdlog.go | 26 +- .../github.com/hashicorp/go-hclog/writer.go | 3 + .../hashicorp/go-plugin/.go-version | 1 + .../hashicorp/go-plugin/CHANGELOG.md | 32 +- .../github.com/hashicorp/go-plugin/client.go | 104 +- .../hashicorp/go-plugin/grpc_broker.go | 23 +- .../hashicorp/go-plugin/grpc_client.go | 14 +- .../hashicorp/go-plugin/grpc_server.go | 4 +- .../hashicorp/go-plugin/grpc_stdio.go | 2 +- .../internal/cmdrunner/cmd_reattach.go | 3 +- .../internal/cmdrunner/cmd_runner.go | 2 +- .../internal/cmdrunner/notes_unix.go | 6 +- .../hashicorp/go-plugin/log_entry.go | 12 +- .../hashicorp/go-plugin/mux_broker.go | 16 +- .../hashicorp/go-plugin/rpc_client.go | 14 +- .../hashicorp/go-plugin/rpc_server.go | 10 +- .../github.com/hashicorp/go-plugin/server.go | 12 +- .../github.com/hashicorp/go-plugin/testing.go | 22 +- vendor/github.com/hashicorp/yamux/LICENSE | 2 + vendor/github.com/hashicorp/yamux/mux.go | 8 +- vendor/github.com/hashicorp/yamux/session.go | 21 +- vendor/github.com/hashicorp/yamux/spec.md | 2 +- vendor/github.com/hashicorp/yamux/stream.go | 34 +- vendor/github.com/hashicorp/yamux/util.go | 7 + vendor/github.com/josharian/intern/README.md | 5 - vendor/github.com/josharian/intern/intern.go | 44 - vendor/github.com/josharian/intern/license.md | 21 - vendor/github.com/mailru/easyjson/LICENSE | 7 - .../github.com/mailru/easyjson/buffer/pool.go | 278 --- .../mailru/easyjson/jlexer/bytestostr.go | 21 - .../easyjson/jlexer/bytestostr_nounsafe.go | 13 - .../mailru/easyjson/jlexer/error.go | 15 - .../mailru/easyjson/jlexer/lexer.go | 1257 ---------- .../mailru/easyjson/jwriter/writer.go | 417 ---- .../mattn/go-isatty/isatty_others.go | 4 +- .../mattn/go-isatty/isatty_windows.go | 10 +- .../go-testing-interface/.travis.yml | 13 - .../mitchellh/go-testing-interface/LICENSE | 21 - .../mitchellh/go-testing-interface/README.md | 52 - .../mitchellh/go-testing-interface/testing.go | 84 - .../go-testing-interface/testing_go19.go | 108 - vendor/github.com/oklog/run/.travis.yml | 12 - vendor/github.com/oklog/run/LICENSE | 2 +- vendor/github.com/oklog/run/README.md | 40 +- vendor/github.com/oklog/run/actors.go | 96 + .../openshift/api/config/v1/types.go | 5 + .../api/config/v1/types_apiserver.go | 63 + .../api/config/v1/types_authentication.go | 15 +- .../api/config/v1/types_cluster_version.go | 26 + .../openshift/api/config/v1/types_dns.go | 9 +- .../api/config/v1/types_infrastructure.go | 9 +- .../openshift/api/config/v1/types_ingress.go | 1 + .../api/config/v1/zz_generated.deepcopy.go | 1 + ..._generated.featuregated-crd-manifests.yaml | 8 +- .../v1/zz_generated.swagger_doc_generated.go | 12 +- .../openshift/api/machine/v1/Makefile | 3 + .../openshift/api/machine/v1/common.go | 13 + .../openshift/api/machine/v1/doc.go | 7 + .../openshift/api/machine/v1/register.go | 40 + .../api/machine/v1/types_alibabaprovider.go | 376 +++ .../openshift/api/machine/v1/types_aws.go | 51 + .../v1/types_controlplanemachineset.go | 486 ++++ .../api/machine/v1/types_nutanixprovider.go | 345 +++ .../api/machine/v1/types_powervsprovider.go | 225 ++ .../api/machine/v1/zz_generated.deepcopy.go | 1123 +++++++++ ..._generated.featuregated-crd-manifests.yaml | 52 + .../v1/zz_generated.swagger_doc_generated.go | 490 ++++ .../openshift/api/machine/v1beta1/Makefile | 3 + .../openshift/api/machine/v1beta1/doc.go | 7 + .../openshift/api/machine/v1beta1/register.go | 44 + .../api/machine/v1beta1/types_awsprovider.go | 557 +++++ .../machine/v1beta1/types_azureprovider.go | 577 +++++ .../api/machine/v1beta1/types_gcpprovider.go | 362 +++ .../api/machine/v1beta1/types_machine.go | 468 ++++ .../v1beta1/types_machinehealthcheck.go | 152 ++ .../api/machine/v1beta1/types_machineset.go | 209 ++ .../api/machine/v1beta1/types_provider.go | 228 ++ .../machine/v1beta1/types_vsphereprovider.go | 277 +++ .../machine/v1beta1/zz_generated.deepcopy.go | 2032 +++++++++++++++++ ..._generated.featuregated-crd-manifests.yaml | 140 ++ .../zz_generated.swagger_doc_generated.go | 901 ++++++++ .../operator/v1/types_csi_cluster_driver.go | 10 +- .../api/operator/v1/types_ingress.go | 43 + .../operator/v1/types_machineconfiguration.go | 8 +- .../api/operator/v1/types_network.go | 115 + .../api/operator/v1/zz_generated.deepcopy.go | 34 + ..._generated.featuregated-crd-manifests.yaml | 10 +- .../v1/zz_generated.swagger_doc_generated.go | 26 +- .../conditions/v1/conditions.go | 114 - .../conditions/v1/doc.go | 9 - .../conditions/v1/types.go | 51 - .../conditions/v1/zz_generated.deepcopy.go | 23 - .../openshift/hive/apis/hive/v1/agent/doc.go | 3 +- .../openshift/hive/apis/hive/v1/aws/doc.go | 2 +- .../hive/apis/hive/v1/aws/metadata.go | 2 + .../openshift/hive/apis/hive/v1/azure/doc.go | 3 +- .../hive/apis/hive/v1/azure/machinepool.go | 43 + .../hive/apis/hive/v1/azure/metadata.go | 2 + .../hive/apis/hive/v1/baremetal/doc.go | 3 +- .../apis/hive/v1/clusterdeployment_types.go | 46 +- .../clusterdeploymentcustomization_types.go | 82 +- .../apis/hive/v1/clusterdeprovision_types.go | 41 +- .../hive/apis/hive/v1/clusterpool_types.go | 12 + .../openshift/hive/apis/hive/v1/doc.go | 4 +- .../openshift/hive/apis/hive/v1/gcp/doc.go | 3 +- .../hive/apis/hive/v1/gcp/machinepools.go | 17 +- .../hive/apis/hive/v1/gcp/metadata.go | 2 + .../hive/apis/hive/v1/gcp/platform.go | 95 +- .../apis/hive/v1/gcp/zz_generated.deepcopy.go | 131 ++ .../hive/apis/hive/v1/hiveconfig_types.go | 84 + .../hive/apis/hive/v1/ibmcloud/doc.go | 3 +- .../hive/apis/hive/v1/machinepool_types.go | 47 +- .../hive/apis/hive/v1/metricsconfig/doc.go | 3 +- .../openshift/hive/apis/hive/v1/none/doc.go | 3 +- .../hive/apis/hive/v1/nutanix/doc.go | 3 + .../hive/apis/hive/v1/nutanix/machinepools.go | 78 + .../hive/apis/hive/v1/nutanix/platform.go | 95 + .../hive/v1/nutanix/zz_generated.deepcopy.go | 179 ++ .../hive/apis/hive/v1/openstack/doc.go | 3 +- .../apis/hive/v1/openstack/machinepools.go | 6 + .../v1/openstack/zz_generated.deepcopy.go | 5 + .../openshift/hive/apis/hive/v1/ovirt/doc.go | 4 - .../hive/apis/hive/v1/ovirt/machinepool.go | 61 - .../hive/apis/hive/v1/ovirt/platform.go | 22 - .../hive/v1/ovirt/zz_generated.deepcopy.go | 82 - .../hive/v1/syncidentityprovider_types.go | 8 +- .../hive/apis/hive/v1/syncset_types.go | 24 +- .../hive/apis/hive/v1/vsphere/doc.go | 2 +- .../hive/apis/hive/v1/vsphere/machinepools.go | 4 + .../hive/v1/vsphere/zz_generated.deepcopy.go | 5 + .../apis/hive/v1/zz_generated.deepcopy.go | 276 ++- .../apis/hive/v1/zz_generated.defaults.go | 17 + .../hypershift/api/hypershift/v1beta1/gcp.go | 17 + .../prometheus/procfs/.golangci.yml | 36 +- vendor/github.com/prometheus/procfs/Makefile | 2 +- .../prometheus/procfs/Makefile.common | 262 ++- vendor/github.com/prometheus/procfs/arp.go | 9 +- .../github.com/prometheus/procfs/buddyinfo.go | 10 +- .../github.com/prometheus/procfs/cmdline.go | 2 +- .../github.com/prometheus/procfs/cpuinfo.go | 5 +- .../prometheus/procfs/cpuinfo_armx.go | 4 +- .../prometheus/procfs/cpuinfo_loong64.go | 3 +- .../prometheus/procfs/cpuinfo_mipsx.go | 4 +- .../prometheus/procfs/cpuinfo_others.go | 3 +- .../prometheus/procfs/cpuinfo_ppcx.go | 4 +- .../prometheus/procfs/cpuinfo_riscvx.go | 4 +- .../prometheus/procfs/cpuinfo_s390x.go | 3 +- .../prometheus/procfs/cpuinfo_x86.go | 4 +- vendor/github.com/prometheus/procfs/crypto.go | 2 +- vendor/github.com/prometheus/procfs/doc.go | 2 +- vendor/github.com/prometheus/procfs/fs.go | 2 +- .../prometheus/procfs/fs_statfs_notype.go | 3 +- .../prometheus/procfs/fs_statfs_type.go | 3 +- .../github.com/prometheus/procfs/fscache.go | 9 +- .../prometheus/procfs/internal/fs/fs.go | 2 +- .../prometheus/procfs/internal/util/parse.go | 2 +- .../procfs/internal/util/readfile.go | 2 +- .../procfs/internal/util/sysreadfile.go | 4 +- .../internal/util/sysreadfile_compat.go | 3 +- .../procfs/internal/util/valueparser.go | 2 +- vendor/github.com/prometheus/procfs/ipvs.go | 2 +- .../prometheus/procfs/kernel_hung.go | 44 + .../prometheus/procfs/kernel_random.go | 3 +- .../github.com/prometheus/procfs/loadavg.go | 2 +- vendor/github.com/prometheus/procfs/mdstat.go | 121 +- .../github.com/prometheus/procfs/meminfo.go | 35 +- .../github.com/prometheus/procfs/mountinfo.go | 23 +- .../prometheus/procfs/mountstats.go | 4 +- .../prometheus/procfs/net_conntrackstat.go | 2 +- .../github.com/prometheus/procfs/net_dev.go | 2 +- .../prometheus/procfs/net_dev_snmp6.go | 7 +- .../prometheus/procfs/net_ip_socket.go | 2 +- .../prometheus/procfs/net_protocols.go | 4 +- .../github.com/prometheus/procfs/net_route.go | 2 +- .../prometheus/procfs/net_sockstat.go | 5 +- .../prometheus/procfs/net_softnet.go | 2 +- .../github.com/prometheus/procfs/net_tcp.go | 6 +- .../prometheus/procfs/net_tls_stat.go | 2 +- .../github.com/prometheus/procfs/net_udp.go | 2 +- .../github.com/prometheus/procfs/net_unix.go | 2 +- .../prometheus/procfs/net_wireless.go | 2 +- .../github.com/prometheus/procfs/net_xfrm.go | 2 +- .../github.com/prometheus/procfs/netstat.go | 2 +- .../prometheus/procfs/nfnetlink_queue.go | 85 + vendor/github.com/prometheus/procfs/proc.go | 4 +- .../prometheus/procfs/proc_cgroup.go | 2 +- .../prometheus/procfs/proc_cgroups.go | 8 +- .../prometheus/procfs/proc_environ.go | 2 +- .../prometheus/procfs/proc_fdinfo.go | 13 +- .../prometheus/procfs/proc_interrupts.go | 4 +- .../github.com/prometheus/procfs/proc_io.go | 2 +- .../prometheus/procfs/proc_limits.go | 7 +- .../github.com/prometheus/procfs/proc_maps.go | 4 +- .../prometheus/procfs/proc_netstat.go | 2 +- .../github.com/prometheus/procfs/proc_ns.go | 2 +- .../github.com/prometheus/procfs/proc_psi.go | 2 +- .../prometheus/procfs/proc_smaps.go | 3 +- .../github.com/prometheus/procfs/proc_snmp.go | 2 +- .../prometheus/procfs/proc_snmp6.go | 2 +- .../github.com/prometheus/procfs/proc_stat.go | 14 +- .../prometheus/procfs/proc_statm.go | 117 + .../prometheus/procfs/proc_status.go | 52 +- .../github.com/prometheus/procfs/proc_sys.go | 2 +- .../github.com/prometheus/procfs/schedstat.go | 2 +- vendor/github.com/prometheus/procfs/slab.go | 2 +- .../github.com/prometheus/procfs/softirqs.go | 2 +- vendor/github.com/prometheus/procfs/stat.go | 5 +- vendor/github.com/prometheus/procfs/swaps.go | 2 +- vendor/github.com/prometheus/procfs/thread.go | 2 +- vendor/github.com/prometheus/procfs/vm.go | 3 +- .../github.com/prometheus/procfs/zoneinfo.go | 9 +- vendor/golang.org/x/net/http2/hpack/tables.go | 13 +- vendor/golang.org/x/net/http2/transport.go | 9 +- .../golang.org/x/sys/windows/dll_windows.go | 37 +- .../x/sys/windows/security_windows.go | 6 +- .../googleapis/rpc/status/status.pb.go | 7 +- .../grpc/attributes/attributes.go | 77 +- .../grpc/balancer/balancer.go | 34 +- .../grpc/balancer/base/balancer.go | 6 +- .../endpointsharding/endpointsharding.go | 11 +- .../balancer/pickfirst/internal/internal.go | 2 + .../grpc/balancer/pickfirst/pickfirst.go | 69 +- .../grpc/balancer/subconn.go | 14 - .../grpc/balancer_wrapper.go | 6 +- .../grpc_binarylog_v1/binarylog.pb.go | 2 +- vendor/google.golang.org/grpc/clientconn.go | 164 +- .../google.golang.org/grpc/credentials/tls.go | 22 +- vendor/google.golang.org/grpc/dialoptions.go | 9 +- .../grpc/encoding/encoding.go | 4 - .../grpc/experimental/stats/metricregistry.go | 39 + .../grpc/experimental/stats/metrics.go | 76 +- .../grpc/health/grpc_health_v1/health.pb.go | 2 +- .../health/grpc_health_v1/health_grpc.pb.go | 2 +- vendor/google.golang.org/grpc/interceptor.go | 12 +- .../balancer/gracefulswitch/gracefulswitch.go | 12 + .../grpc/internal/balancer/weight/weight.go | 66 + .../grpc/internal/envconfig/envconfig.go | 65 +- .../grpc/internal/experimental.go | 7 + .../grpc/internal/idle/idle.go | 77 +- .../grpc/internal/internal.go | 29 +- .../grpc/internal/mem/buffer_pool.go | 338 +++ .../internal/resolver/dns/dns_resolver.go | 15 +- .../internal/stats/metrics_recorder_list.go | 60 + .../grpc/internal/transport/client_stream.go | 10 +- .../grpc/internal/transport/controlbuf.go | 24 +- .../grpc/internal/transport/defaults.go | 1 + .../grpc/internal/transport/http2_client.go | 44 +- .../grpc/internal/transport/http2_server.go | 100 +- .../grpc/internal/transport/http_util.go | 6 - .../grpc/internal/transport/transport.go | 40 +- .../google.golang.org/grpc/mem/buffer_pool.go | 160 +- vendor/google.golang.org/grpc/mem/buffers.go | 65 +- .../google.golang.org/grpc/picker_wrapper.go | 4 +- .../grpc_reflection_v1/reflection.pb.go | 2 +- .../grpc_reflection_v1/reflection_grpc.pb.go | 2 +- .../grpc_reflection_v1alpha/reflection.pb.go | 2 +- .../reflection_grpc.pb.go | 2 +- vendor/google.golang.org/grpc/resolver/map.go | 34 + .../grpc/resolver/resolver.go | 1 + .../grpc/resolver_wrapper.go | 1 + vendor/google.golang.org/grpc/rpc_util.go | 115 +- vendor/google.golang.org/grpc/server.go | 62 +- vendor/google.golang.org/grpc/stream.go | 87 +- vendor/google.golang.org/grpc/version.go | 2 +- vendor/modules.txt | 134 +- 418 files changed, 25138 insertions(+), 8600 deletions(-) create mode 100644 vendor/github.com/fxamacker/cbor/v2/decode_map_utils.go create mode 100644 vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md create mode 100644 vendor/github.com/go-openapi/jsonpointer/NOTICE create mode 100644 vendor/github.com/go-openapi/jsonpointer/SECURITY.md create mode 100644 vendor/github.com/go-openapi/jsonpointer/ifaces.go create mode 100644 vendor/github.com/go-openapi/jsonpointer/options.go create mode 100644 vendor/github.com/go-openapi/jsonreference/.editorconfig create mode 100644 vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md create mode 100644 vendor/github.com/go-openapi/jsonreference/NOTICE create mode 100644 vendor/github.com/go-openapi/jsonreference/SECURITY.md create mode 100644 vendor/github.com/go-openapi/swag/.codecov.yml create mode 100644 vendor/github.com/go-openapi/swag/.mockery.yml create mode 100644 vendor/github.com/go-openapi/swag/CONTRIBUTORS.md create mode 100644 vendor/github.com/go-openapi/swag/SECURITY.md rename vendor/github.com/{openshift/custom-resource-status => go-openapi/swag/cmdutils}/LICENSE (99%) create mode 100644 vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go create mode 100644 vendor/github.com/go-openapi/swag/cmdutils/doc.go create mode 100644 vendor/github.com/go-openapi/swag/cmdutils_iface.go create mode 100644 vendor/github.com/go-openapi/swag/conv/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/conv/convert.go create mode 100644 vendor/github.com/go-openapi/swag/conv/convert_types.go create mode 100644 vendor/github.com/go-openapi/swag/conv/doc.go create mode 100644 vendor/github.com/go-openapi/swag/conv/format.go create mode 100644 vendor/github.com/go-openapi/swag/conv/sizeof.go create mode 100644 vendor/github.com/go-openapi/swag/conv/type_constraints.go create mode 100644 vendor/github.com/go-openapi/swag/conv_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/convert.go delete mode 100644 vendor/github.com/go-openapi/swag/convert_types.go delete mode 100644 vendor/github.com/go-openapi/swag/errors.go delete mode 100644 vendor/github.com/go-openapi/swag/file.go create mode 100644 vendor/github.com/go-openapi/swag/fileutils/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/fileutils/doc.go create mode 100644 vendor/github.com/go-openapi/swag/fileutils/file.go rename vendor/github.com/go-openapi/swag/{ => fileutils}/path.go (58%) create mode 100644 vendor/github.com/go-openapi/swag/fileutils_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/initialism_index.go delete mode 100644 vendor/github.com/go-openapi/swag/json.go create mode 100644 vendor/github.com/go-openapi/swag/jsonname/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/jsonname/doc.go create mode 100644 vendor/github.com/go-openapi/swag/jsonname/go_name_provider.go create mode 100644 vendor/github.com/go-openapi/swag/jsonname/ifaces.go create mode 100644 vendor/github.com/go-openapi/swag/jsonname/name_provider.go create mode 100644 vendor/github.com/go-openapi/swag/jsonname_iface.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/README.md create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/concat.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/doc.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/json.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go create mode 100644 vendor/github.com/go-openapi/swag/jsonutils_iface.go create mode 100644 vendor/github.com/go-openapi/swag/loading/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/loading/doc.go create mode 100644 vendor/github.com/go-openapi/swag/loading/errors.go create mode 100644 vendor/github.com/go-openapi/swag/loading/json.go rename vendor/github.com/go-openapi/swag/{ => loading}/loading.go (61%) create mode 100644 vendor/github.com/go-openapi/swag/loading/options.go create mode 100644 vendor/github.com/go-openapi/swag/loading/yaml.go create mode 100644 vendor/github.com/go-openapi/swag/loading_iface.go rename vendor/github.com/go-openapi/swag/{ => mangling}/BENCHMARK.md (53%) create mode 100644 vendor/github.com/go-openapi/swag/mangling/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/mangling/doc.go create mode 100644 vendor/github.com/go-openapi/swag/mangling/initialism_index.go create mode 100644 vendor/github.com/go-openapi/swag/mangling/name_lexem.go create mode 100644 vendor/github.com/go-openapi/swag/mangling/name_mangler.go create mode 100644 vendor/github.com/go-openapi/swag/mangling/options.go create mode 100644 vendor/github.com/go-openapi/swag/mangling/pools.go create mode 100644 vendor/github.com/go-openapi/swag/mangling/split.go rename vendor/github.com/go-openapi/swag/{ => mangling}/string_bytes.go (60%) create mode 100644 vendor/github.com/go-openapi/swag/mangling/util.go create mode 100644 vendor/github.com/go-openapi/swag/mangling_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/name_lexem.go delete mode 100644 vendor/github.com/go-openapi/swag/net.go create mode 100644 vendor/github.com/go-openapi/swag/netutils/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/netutils/doc.go create mode 100644 vendor/github.com/go-openapi/swag/netutils/net.go create mode 100644 vendor/github.com/go-openapi/swag/netutils_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/split.go create mode 100644 vendor/github.com/go-openapi/swag/stringutils/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/stringutils/collection_formats.go create mode 100644 vendor/github.com/go-openapi/swag/stringutils/doc.go create mode 100644 vendor/github.com/go-openapi/swag/stringutils/strings.go create mode 100644 vendor/github.com/go-openapi/swag/stringutils_iface.go create mode 100644 vendor/github.com/go-openapi/swag/typeutils/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/typeutils/doc.go create mode 100644 vendor/github.com/go-openapi/swag/typeutils/types.go create mode 100644 vendor/github.com/go-openapi/swag/typeutils_iface.go delete mode 100644 vendor/github.com/go-openapi/swag/util.go delete mode 100644 vendor/github.com/go-openapi/swag/yaml.go create mode 100644 vendor/github.com/go-openapi/swag/yamlutils/LICENSE create mode 100644 vendor/github.com/go-openapi/swag/yamlutils/doc.go create mode 100644 vendor/github.com/go-openapi/swag/yamlutils/errors.go create mode 100644 vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go create mode 100644 vendor/github.com/go-openapi/swag/yamlutils/yaml.go create mode 100644 vendor/github.com/go-openapi/swag/yamlutils_iface.go create mode 100644 vendor/github.com/hashicorp/go-plugin/.go-version delete mode 100644 vendor/github.com/josharian/intern/README.md delete mode 100644 vendor/github.com/josharian/intern/intern.go delete mode 100644 vendor/github.com/josharian/intern/license.md delete mode 100644 vendor/github.com/mailru/easyjson/LICENSE delete mode 100644 vendor/github.com/mailru/easyjson/buffer/pool.go delete mode 100644 vendor/github.com/mailru/easyjson/jlexer/bytestostr.go delete mode 100644 vendor/github.com/mailru/easyjson/jlexer/bytestostr_nounsafe.go delete mode 100644 vendor/github.com/mailru/easyjson/jlexer/error.go delete mode 100644 vendor/github.com/mailru/easyjson/jlexer/lexer.go delete mode 100644 vendor/github.com/mailru/easyjson/jwriter/writer.go delete mode 100644 vendor/github.com/mitchellh/go-testing-interface/.travis.yml delete mode 100644 vendor/github.com/mitchellh/go-testing-interface/LICENSE delete mode 100644 vendor/github.com/mitchellh/go-testing-interface/README.md delete mode 100644 vendor/github.com/mitchellh/go-testing-interface/testing.go delete mode 100644 vendor/github.com/mitchellh/go-testing-interface/testing_go19.go delete mode 100644 vendor/github.com/oklog/run/.travis.yml create mode 100644 vendor/github.com/oklog/run/actors.go create mode 100644 vendor/github.com/openshift/api/machine/v1/Makefile create mode 100644 vendor/github.com/openshift/api/machine/v1/common.go create mode 100644 vendor/github.com/openshift/api/machine/v1/doc.go create mode 100644 vendor/github.com/openshift/api/machine/v1/register.go create mode 100644 vendor/github.com/openshift/api/machine/v1/types_alibabaprovider.go create mode 100644 vendor/github.com/openshift/api/machine/v1/types_aws.go create mode 100644 vendor/github.com/openshift/api/machine/v1/types_controlplanemachineset.go create mode 100644 vendor/github.com/openshift/api/machine/v1/types_nutanixprovider.go create mode 100644 vendor/github.com/openshift/api/machine/v1/types_powervsprovider.go create mode 100644 vendor/github.com/openshift/api/machine/v1/zz_generated.deepcopy.go create mode 100644 vendor/github.com/openshift/api/machine/v1/zz_generated.featuregated-crd-manifests.yaml create mode 100644 vendor/github.com/openshift/api/machine/v1/zz_generated.swagger_doc_generated.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/Makefile create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/doc.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/register.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/types_awsprovider.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/types_azureprovider.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/types_gcpprovider.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/types_machine.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/types_machinehealthcheck.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/types_machineset.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/types_provider.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/types_vsphereprovider.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/zz_generated.deepcopy.go create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/zz_generated.featuregated-crd-manifests.yaml create mode 100644 vendor/github.com/openshift/api/machine/v1beta1/zz_generated.swagger_doc_generated.go delete mode 100644 vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go delete mode 100644 vendor/github.com/openshift/custom-resource-status/conditions/v1/doc.go delete mode 100644 vendor/github.com/openshift/custom-resource-status/conditions/v1/types.go delete mode 100644 vendor/github.com/openshift/custom-resource-status/conditions/v1/zz_generated.deepcopy.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/nutanix/doc.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/nutanix/machinepools.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/nutanix/platform.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/nutanix/zz_generated.deepcopy.go delete mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/ovirt/doc.go delete mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/ovirt/machinepool.go delete mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/ovirt/platform.go delete mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/ovirt/zz_generated.deepcopy.go create mode 100644 vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.defaults.go create mode 100644 vendor/github.com/prometheus/procfs/kernel_hung.go create mode 100644 vendor/github.com/prometheus/procfs/nfnetlink_queue.go create mode 100644 vendor/github.com/prometheus/procfs/proc_statm.go create mode 100644 vendor/google.golang.org/grpc/internal/balancer/weight/weight.go create mode 100644 vendor/google.golang.org/grpc/internal/mem/buffer_pool.go diff --git a/go.mod b/go.mod index 9bd0637dd..1463c18be 100644 --- a/go.mod +++ b/go.mod @@ -2,15 +2,15 @@ module github.com/openshift/hypershift-oadp-plugin go 1.25.7 -toolchain go1.25.8 +toolchain go1.26.2 require ( github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 github.com/onsi/gomega v1.39.1 - github.com/openshift/hive/apis v0.0.0-20241220022629-3f49f26197ff - github.com/openshift/hypershift/api v0.0.0-20260417092826-5431b93cee3c + github.com/openshift/hive/apis v0.0.0-20260424180847-6c66e2052422 + github.com/openshift/hypershift/api v0.0.0-20260424195428-c1a8bb61ff14 github.com/sirupsen/logrus v1.9.4 - github.com/vmware-tanzu/velero v1.14.0 + github.com/vmware-tanzu/velero v1.18.0 k8s.io/api v0.35.3 k8s.io/apiextensions-apiserver v0.35.3 sigs.k8s.io/controller-runtime v0.23.3 @@ -21,20 +21,30 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/evanphx/json-patch/v5 v5.9.11 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/fxamacker/cbor/v2 v2.9.0 // indirect + github.com/fxamacker/cbor/v2 v2.9.1 // indirect + github.com/go-openapi/swag/cmdutils v0.26.0 // indirect + github.com/go-openapi/swag/conv v0.26.0 // indirect + github.com/go-openapi/swag/fileutils v0.26.0 // indirect + github.com/go-openapi/swag/jsonname v0.26.0 // indirect + github.com/go-openapi/swag/jsonutils v0.26.0 // indirect + github.com/go-openapi/swag/loading v0.26.0 // indirect + github.com/go-openapi/swag/mangling v0.26.0 // indirect + github.com/go-openapi/swag/netutils v0.26.0 // indirect + github.com/go-openapi/swag/stringutils v0.26.0 // indirect + github.com/go-openapi/swag/typeutils v0.26.0 // indirect + github.com/go-openapi/swag/yamlutils v0.26.0 // indirect github.com/google/btree v1.1.3 // indirect - github.com/google/gnostic-models v0.7.0 // indirect + github.com/google/gnostic-models v0.7.1 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect - github.com/openshift/api v0.0.0-20260304122341-cf5d8996109f // indirect - github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87 // indirect + github.com/openshift/api v0.0.0-20260424174501-4f63a40a2970 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.23.2 // indirect github.com/prometheus/client_model v0.6.2 // indirect github.com/prometheus/common v0.67.5 // indirect - github.com/prometheus/procfs v0.16.1 // indirect + github.com/prometheus/procfs v0.20.1 // indirect github.com/x448/float16 v0.8.4 // indirect - go.yaml.in/yaml/v2 v2.4.3 // indirect + go.yaml.in/yaml/v2 v2.4.4 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/sync v0.20.0 // indirect gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect @@ -46,38 +56,35 @@ require ( require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.12.2 // indirect - github.com/fatih/color v1.18.0 // indirect + github.com/fatih/color v1.19.0 // indirect github.com/go-logr/logr v1.4.3 // indirect - github.com/go-openapi/jsonpointer v0.21.1 // indirect - github.com/go-openapi/jsonreference v0.21.0 // indirect - github.com/go-openapi/swag v0.23.1 // indirect + github.com/go-openapi/jsonpointer v0.23.1 // indirect + github.com/go-openapi/jsonreference v0.21.5 // indirect + github.com/go-openapi/swag v0.26.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/hashicorp/go-hclog v0.14.1 // indirect - github.com/hashicorp/go-plugin v1.6.0 // indirect - github.com/hashicorp/yamux v0.1.1 // indirect + github.com/hashicorp/go-hclog v1.6.3 // indirect + github.com/hashicorp/go-plugin v1.7.0 // indirect + github.com/hashicorp/yamux v0.1.2 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.9.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mitchellh/go-testing-interface v1.0.0 // indirect + github.com/mattn/go-isatty v0.0.21 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/oklog/run v1.0.0 // indirect + github.com/oklog/run v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/spf13/cobra v1.10.2 // indirect github.com/spf13/pflag v1.0.10 // indirect - golang.org/x/net v0.52.0 // indirect - golang.org/x/oauth2 v0.35.0 // indirect - golang.org/x/sys v0.42.0 // indirect - golang.org/x/term v0.41.0 // indirect - golang.org/x/text v0.35.0 // indirect - golang.org/x/time v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect - google.golang.org/grpc v1.77.0 // indirect + golang.org/x/net v0.53.0 // indirect + golang.org/x/oauth2 v0.36.0 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/term v0.42.0 // indirect + golang.org/x/text v0.36.0 // indirect + golang.org/x/time v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 // indirect + google.golang.org/grpc v1.80.0 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 919e020a7..1ba0f92f8 100644 --- a/go.sum +++ b/go.sum @@ -1,214 +1,138 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= -github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/FBatYVw= +github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c= 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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.15.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 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.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.11 h1:/8HVnzMq13/3x9TPvjG08wUGqBTmZBsCWzjTM0wiaDU= github.com/evanphx/json-patch/v5 v5.9.11/go.mod h1:3j+LviiESTElxA4p3EMKAB9HXj3/XEtnUf6OZxqIQTM= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= +github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= 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/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ= +github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= -github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= -github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= -github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-openapi/jsonpointer v0.23.1 h1:1HBACs7XIwR2RcmItfdSFlALhGbe6S92p0ry4d1GWg4= +github.com/go-openapi/jsonpointer v0.23.1/go.mod h1:iWRmZTrGn7XwYhtPt/fvdSFj1OfNBngqRT2UG3BxSqY= +github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE= +github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw= +github.com/go-openapi/swag v0.26.0 h1:GVDXCmfvhfu1BxiHo8/FA+BbKmhecHnG3varjON5/RI= +github.com/go-openapi/swag v0.26.0/go.mod h1:82g3193sZJRbocs7bNCqGfIgq8pkuwVwCfhKIRlEQF0= +github.com/go-openapi/swag/cmdutils v0.26.0 h1:iowihOcvq7y4egO8cOq0dmfohz6wfeQ63U1EnuhO2TU= +github.com/go-openapi/swag/cmdutils v0.26.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM= +github.com/go-openapi/swag/conv v0.26.0 h1:5yGGsPYI1ZCva93U0AoKi/iZrNhaJEjr324YVsiD89I= +github.com/go-openapi/swag/conv v0.26.0/go.mod h1:tpAmIL7X58VPnHHiSO4uE3jBeRamGsFsfdDeDtb5ECE= +github.com/go-openapi/swag/fileutils v0.26.0 h1:WJoPRvsA7QRiiWluowkLJa9jaYR7FCuxmDvnCgaRRxU= +github.com/go-openapi/swag/fileutils v0.26.0/go.mod h1:0WDJ7lp67eNjPMO50wAWYlKvhOb6CQ37rzR7wrgI8Tc= +github.com/go-openapi/swag/jsonname v0.26.0 h1:gV1NFX9M8avo0YSpmWogqfQISigCmpaiNci8cGECU5w= +github.com/go-openapi/swag/jsonname v0.26.0/go.mod h1:urBBR8bZNoDYGr653ynhIx+gTeIz0ARZxHkAPktJK2M= +github.com/go-openapi/swag/jsonutils v0.26.0 h1:FawFML2iAXsPqmERscuMPIHmFsoP1tOqWkxBaKNMsnA= +github.com/go-openapi/swag/jsonutils v0.26.0/go.mod h1:2VmA0CJlyFqgawOaPI9psnjFDqzyivIqLYN34t9p91E= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0 h1:apqeINu/ICHouqiRZbyFvuDge5jCmmLTqGQ9V95EaOM= +github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0/go.mod h1:AyM6QT8uz5IdKxk5akv0y6u4QvcL9GWERt0Jx/F/R8Y= +github.com/go-openapi/swag/loading v0.26.0 h1:Apg6zaKhCJurpJer0DCxq99qwmhFddBhaMX7kilDcko= +github.com/go-openapi/swag/loading v0.26.0/go.mod h1:dBxQ/6V2uBaAQdevN18VELE6xSpJWZxLX4txe12JwDg= +github.com/go-openapi/swag/mangling v0.26.0 h1:Du2YC4YLA/Y5m/YKQd7AnY5qq0wRKSFZTTt8ktFaXcQ= +github.com/go-openapi/swag/mangling v0.26.0/go.mod h1:jifS7W9vbg+pw63bT+GI53otluMQL3CeemuyCHKwVx0= +github.com/go-openapi/swag/netutils v0.26.0 h1:CmZp+ZT7HrmFwrC3GdGsXBq2+42T1bjKBapcqVpIs3c= +github.com/go-openapi/swag/netutils v0.26.0/go.mod h1:5iK+Ok3ZohWWex1C50BFTPexi03UaPwjW4Oj8kgrpwo= +github.com/go-openapi/swag/stringutils v0.26.0 h1:qZQngLxs5s7SLijc3N2ZO+fUq2o8LjuWAASSrJuh+xg= +github.com/go-openapi/swag/stringutils v0.26.0/go.mod h1:sWn5uY+QIIspwPhvgnqJsH8xqFT2ZbYcvbcFanRyhFE= +github.com/go-openapi/swag/typeutils v0.26.0 h1:2kdEwdiNWy+JJdOvu5MA2IIg2SylWAFuuyQIKYybfq4= +github.com/go-openapi/swag/typeutils v0.26.0/go.mod h1:oovDuIUvTrEHVMqWilQzKzV4YlSKgyZmFh7AlfABNVE= +github.com/go-openapi/swag/yamlutils v0.26.0 h1:H7O8l/8NJJQ/oiReEN+oMpnGMyt8G0hl460nRZxhLMQ= +github.com/go-openapi/swag/yamlutils v0.26.0/go.mod h1:1evKEGAtP37Pkwcc7EWMF0hedX0/x3Rkvei2wtG/TbU= +github.com/go-openapi/testify/enable/yaml/v2 v2.4.2 h1:5zRca5jw7lzVREKCZVNBpysDNBjj74rBh0N2BGQbSR0= +github.com/go-openapi/testify/enable/yaml/v2 v2.4.2/go.mod h1:XVevPw5hUXuV+5AkI1u1PeAm27EQVrhXTTCPAF85LmE= +github.com/go-openapi/testify/v2 v2.4.2 h1:tiByHpvE9uHrrKjOszax7ZvKB7QOgizBWGBLuq0ePx4= +github.com/go-openapi/testify/v2 v2.4.2/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw= 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/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -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.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c= +github.com/google/gnostic-models v0.7.1/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ= 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/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= -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/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU= -github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= -github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= -github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= -github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-plugin v1.7.0 h1:YghfQH/0QmPNc/AZMTFE3ac8fipZyZECHdDPshfk+mA= +github.com/hashicorp/go-plugin v1.7.0/go.mod h1:BExt6KEaIYx804z8k4gRzRLEvxKVb+kn0NMcihqOqb8= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= -github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= +github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk= github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0 h1:bMqrb3UHgHbP+PW9VwiejfDJU1R0PpXVZNMdeH8WYKI= github.com/kubernetes-csi/external-snapshotter/client/v8 v8.4.0/go.mod h1:E3vdYxHj2C2q6qo8/Da4g7P+IcwqRZyy3gJBzYybV9Y= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= -github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= +github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +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/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= -github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= -github.com/openshift/api v0.0.0-20260304122341-cf5d8996109f h1:M8y0oBq/KRkuSNFlUMQRAn2MrXJh1mzTCFgbLpPWQbM= -github.com/openshift/api v0.0.0-20260304122341-cf5d8996109f/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY= -github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87 h1:cHyxR+Y8rAMT6m1jQCaYGRwikqahI0OjjUDhFNf3ySQ= -github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87/go.mod h1:DB/Mf2oTeiAmVVX1gN+NEqweonAPY0TKUwADizj8+ZA= -github.com/openshift/hive/apis v0.0.0-20241220022629-3f49f26197ff h1:6C1z4xMAruyeiTFGqahxNDpI1cXPCjpaFeIeIodty08= -github.com/openshift/hive/apis v0.0.0-20241220022629-3f49f26197ff/go.mod h1:1vBNCcWNpQyFCz83PWYT/lHUFJ9ost2t5FijHElh6gQ= -github.com/openshift/hypershift/api v0.0.0-20260417092826-5431b93cee3c h1:f4yyfNyAWbWQDdOMzawbglzZZvPFfpIl1p9MjdTx3oM= -github.com/openshift/hypershift/api v0.0.0-20260417092826-5431b93cee3c/go.mod h1:mC9+bqb81FmG924VOO+7P0ofKQgvY1SdPhFp0oJ9U44= +github.com/openshift/api v0.0.0-20260424174501-4f63a40a2970 h1:xyz8VL2VnskV4YTDaHrAmBxFLyyPjxOt5dYZRBeAvmk= +github.com/openshift/api v0.0.0-20260424174501-4f63a40a2970/go.mod h1:pyVjK0nZ4sRs4fuQVQ4rubsJdahI1PB94LnQ8sGdvxo= +github.com/openshift/hive/apis v0.0.0-20260424180847-6c66e2052422 h1:R8iA8JQ4k+2dNgseiFoLe3UkokexpUQTNHHb05UIuR4= +github.com/openshift/hive/apis v0.0.0-20260424180847-6c66e2052422/go.mod h1:98U/kA+A9nenhu0mCqaxaKyYJ+C/YEZoAUkPYDT/m+c= +github.com/openshift/hypershift/api v0.0.0-20260424195428-c1a8bb61ff14 h1:SPgMCz+qnXCu9mwYgch0nz3+0HmirCVhUPUChNHyXHY= +github.com/openshift/hypershift/api v0.0.0-20260424195428-c1a8bb61ff14/go.mod h1:mC9+bqb81FmG924VOO+7P0ofKQgvY1SdPhFp0oJ9U44= github.com/openshift/velero v0.10.2-0.20260323191807-216dd62a1caf h1:idCUwNL/RfZIeS1bpUvf6LaYZJSmKCSE2GP6tc1caYI= github.com/openshift/velero v0.10.2-0.20260323191807-216dd62a1caf/go.mod h1:vrmFMtokf4UjYmykfPvmI/xinTU3Ljz4F6JO3pLYxKs= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -218,45 +142,33 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= -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/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= 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/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.9/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/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 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/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= @@ -275,210 +187,73 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= -go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8= +go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= +go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/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/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= -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-20180906233101-161cd47e91fd/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-20190827160401-ba9fcec4b297/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-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= -golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= -golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= -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-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.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= +golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= +golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190222072716-a9d3bda3a223/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-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/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-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU= -golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= -golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= -golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= -golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= -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-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff/go.mod h1:YD9qOF0M9xpSpdWTBbzEl5e/RnCefISl8E5Noe10jFM= -golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= +golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= +golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= gomodules.xyz/jsonpatch/v2 v2.5.0 h1:JELs8RLM12qJGXU4u/TO3V25KW8GreMKl9pdkk14RM0= gomodules.xyz/jsonpatch/v2 v2.5.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -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/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-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 h1:tRPGkdGHuewF4UisLzzHHr1spKw92qLM98nIzxbC0wY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -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.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= -google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 h1:XF8+t6QQiS0o9ArVan/HW8Q7cycNPGsJf6GA2nXxYAg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo= gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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/api v0.23.3/go.mod h1:w258XdGyvCmnBj/vGzQMj6kzdufJZVUwEM1U2fRJwSQ= k8s.io/api v0.35.3 h1:pA2fiBc6+N9PDf7SAiluKGEBuScsTzd2uYBkA5RzNWQ= k8s.io/api v0.35.3/go.mod h1:9Y9tkBcFwKNq2sxwZTQh1Njh9qHl81D0As56tu42GA4= k8s.io/apiextensions-apiserver v0.35.3 h1:2fQUhEO7P17sijylbdwt0nBdXP0TvHrHj0KeqHD8FiU= k8s.io/apiextensions-apiserver v0.35.3/go.mod h1:tK4Kz58ykRpwAEkXUb634HD1ZAegEElktz/B3jgETd8= -k8s.io/apimachinery v0.23.3/go.mod h1:BEuFMMBaIbcOqVIJqNZJXGFTP4W6AycEpb5+m/97hrM= k8s.io/apimachinery v0.35.3 h1:MeaUwQCV3tjKP4bcwWGgZ/cp/vpsRnQzqO6J6tJyoF8= k8s.io/apimachinery v0.35.3/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= k8s.io/client-go v0.35.3 h1:s1lZbpN4uI6IxeTM2cpdtrwHcSOBML1ODNTCCfsP1pg= k8s.io/client-go v0.35.3/go.mod h1:RzoXkc0mzpWIDvBrRnD+VlfXP+lRzqQjCmKtiwZ8Q9c= -k8s.io/code-generator v0.23.3/go.mod h1:S0Q1JVA+kSzTI1oUvbKAxZY/DYbA/ZUb4Uknog12ETk= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= -k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= -k8s.io/kube-openapi v0.0.0-20220124234850-424119656bbf/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= k8s.io/kube-openapi v0.0.0-20260330154417-16be699c7b31 h1:V+sn9a/1fEYDGwnllCmqXBk8x7obZ+hl869Q3Abumkg= k8s.io/kube-openapi v0.0.0-20260330154417-16be699c7b31/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4iqwZ80= sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0= -sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= diff --git a/vendor/github.com/fatih/color/color.go b/vendor/github.com/fatih/color/color.go index ee39b408e..d3906bfbd 100644 --- a/vendor/github.com/fatih/color/color.go +++ b/vendor/github.com/fatih/color/color.go @@ -19,15 +19,15 @@ var ( // set (regardless of its value). This is a global option and affects all // colors. For more control over each color block use the methods // DisableColor() individually. - NoColor = noColorIsSet() || os.Getenv("TERM") == "dumb" || - (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) + NoColor = noColorIsSet() || os.Getenv("TERM") == "dumb" || !stdoutIsTerminal() // Output defines the standard output of the print functions. By default, - // os.Stdout is used. - Output = colorable.NewColorableStdout() + // stdOut() is used. + Output = stdOut() - // Error defines a color supporting writer for os.Stderr. - Error = colorable.NewColorableStderr() + // Error defines the standard error of the print functions. By default, + // stdErr() is used. + Error = stdErr() // colorsCache is used to reduce the count of created Color objects and // allows to reuse already created objects with required Attribute. @@ -40,6 +40,33 @@ func noColorIsSet() bool { return os.Getenv("NO_COLOR") != "" } +// stdoutIsTerminal returns true if os.Stdout is a terminal. +// Returns false if os.Stdout is nil (e.g., when running as a Windows service). +func stdoutIsTerminal() bool { + if os.Stdout == nil { + return false + } + return isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd()) +} + +// stdOut returns a writer for color output. +// Returns io.Discard if os.Stdout is nil (e.g., when running as a Windows service). +func stdOut() io.Writer { + if os.Stdout == nil { + return io.Discard + } + return colorable.NewColorableStdout() +} + +// stdErr returns a writer for color error output. +// Returns io.Discard if os.Stderr is nil (e.g., when running as a Windows service). +func stdErr() io.Writer { + if os.Stderr == nil { + return io.Discard + } + return colorable.NewColorableStderr() +} + // Color defines a custom color object which is defined by SGR parameters. type Color struct { params []Attribute @@ -220,26 +247,30 @@ func (c *Color) unset() { // a low-level function, and users should use the higher-level functions, such // as color.Fprint, color.Print, etc. func (c *Color) SetWriter(w io.Writer) *Color { + _, _ = c.setWriter(w) + return c +} + +func (c *Color) setWriter(w io.Writer) (int, error) { if c.isNoColorSet() { - return c + return 0, nil } - fmt.Fprint(w, c.format()) - return c + return fmt.Fprint(w, c.format()) } // UnsetWriter resets all escape attributes and clears the output with the give // io.Writer. Usually should be called after SetWriter(). func (c *Color) UnsetWriter(w io.Writer) { - if c.isNoColorSet() { - return - } + _, _ = c.unsetWriter(w) +} - if NoColor { - return +func (c *Color) unsetWriter(w io.Writer) (int, error) { + if c.isNoColorSet() { + return 0, nil } - fmt.Fprintf(w, "%s[%dm", escape, Reset) + return fmt.Fprintf(w, "%s[%dm", escape, Reset) } // Add is used to chain SGR parameters. Use as many as parameters to combine @@ -255,10 +286,20 @@ func (c *Color) Add(value ...Attribute) *Color { // On Windows, users should wrap w with colorable.NewColorable() if w is of // type *os.File. func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) { - c.SetWriter(w) - defer c.UnsetWriter(w) + n, err = c.setWriter(w) + if err != nil { + return n, err + } + + nn, err := fmt.Fprint(w, a...) + n += nn + if err != nil { + return + } - return fmt.Fprint(w, a...) + nn, err = c.unsetWriter(w) + n += nn + return n, err } // Print formats using the default formats for its operands and writes to @@ -278,10 +319,20 @@ func (c *Color) Print(a ...interface{}) (n int, err error) { // On Windows, users should wrap w with colorable.NewColorable() if w is of // type *os.File. func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { - c.SetWriter(w) - defer c.UnsetWriter(w) + n, err = c.setWriter(w) + if err != nil { + return n, err + } + + nn, err := fmt.Fprintf(w, format, a...) + n += nn + if err != nil { + return + } - return fmt.Fprintf(w, format, a...) + nn, err = c.unsetWriter(w) + n += nn + return n, err } // Printf formats according to a format specifier and writes to standard output. @@ -475,27 +526,24 @@ func (c *Color) Equals(c2 *Color) bool { if c == nil || c2 == nil { return false } + if len(c.params) != len(c2.params) { return false } + counts := make(map[Attribute]int, len(c.params)) for _, attr := range c.params { - if !c2.attrExists(attr) { - return false - } + counts[attr]++ } - return true -} - -func (c *Color) attrExists(a Attribute) bool { - for _, attr := range c.params { - if attr == a { - return true + for _, attr := range c2.params { + if counts[attr] == 0 { + return false } + counts[attr]-- } - return false + return true } func boolPtr(v bool) *bool { diff --git a/vendor/github.com/fatih/color/color_windows.go b/vendor/github.com/fatih/color/color_windows.go index be01c558e..97e5a765a 100644 --- a/vendor/github.com/fatih/color/color_windows.go +++ b/vendor/github.com/fatih/color/color_windows.go @@ -9,6 +9,9 @@ import ( func init() { // Opt-in for ansi color support for current process. // https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#output-sequences + if os.Stdout == nil { + return + } var outMode uint32 out := windows.Handle(os.Stdout.Fd()) if err := windows.GetConsoleMode(out, &outMode); err != nil { diff --git a/vendor/github.com/fxamacker/cbor/v2/.golangci.yml b/vendor/github.com/fxamacker/cbor/v2/.golangci.yml index 38cb9ae10..08081fbde 100644 --- a/vendor/github.com/fxamacker/cbor/v2/.golangci.yml +++ b/vendor/github.com/fxamacker/cbor/v2/.golangci.yml @@ -1,104 +1,116 @@ -# Do not delete linter settings. Linters like gocritic can be enabled on the command line. - -linters-settings: - depguard: - rules: - prevent_unmaintained_packages: - list-mode: strict - files: - - $all - - "!$test" - allow: - - $gostd - - github.com/x448/float16 - deny: - - pkg: io/ioutil - desc: "replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil" - dupl: - threshold: 100 - funlen: - lines: 100 - statements: 50 - goconst: - ignore-tests: true - min-len: 2 - min-occurrences: 3 - gocritic: - enabled-tags: - - diagnostic - - experimental - - opinionated - - performance - - style - disabled-checks: - - commentedOutCode - - dupImport # https://github.com/go-critic/go-critic/issues/845 - - ifElseChain - - octalLiteral - - paramTypeCombine - - whyNoLint - gofmt: - simplify: false - goimports: - local-prefixes: github.com/fxamacker/cbor - golint: - min-confidence: 0 - govet: - check-shadowing: true - lll: - line-length: 140 - maligned: - suggest-new: true - misspell: - locale: US - staticcheck: - checks: ["all"] - +version: "2" linters: - disable-all: true + default: none enable: - asciicheck - bidichk - depguard - errcheck - - exportloopref + - forbidigo - goconst - gocritic - gocyclo - - gofmt - - goimports - goprintffuncname - gosec - - gosimple - govet - ineffassign - misspell - nilerr - revive - staticcheck - - stylecheck - - typecheck - unconvert - unused - + settings: + depguard: + rules: + prevent_unmaintained_packages: + list-mode: strict + files: + - $all + - '!$test' + allow: + - $gostd + - github.com/x448/float16 + deny: + - pkg: io/ioutil + desc: 'replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil' + dupl: + threshold: 100 + funlen: + lines: 100 + statements: 50 + goconst: + min-len: 2 + min-occurrences: 3 + gocritic: + disabled-checks: + - commentedOutCode + - dupImport + - ifElseChain + - octalLiteral + - paramTypeCombine + - whyNoLint + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + govet: + enable: + - shadow + lll: + line-length: 140 + misspell: + locale: US + staticcheck: + checks: + - all + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - path: decode.go + text: string ` overflows ` has (\d+) occurrences, make it a constant + - path: decode.go + text: string ` \(range is \[` has (\d+) occurrences, make it a constant + - path: decode.go + text: string `, ` has (\d+) occurrences, make it a constant + - path: decode.go + text: string ` overflows Go's int64` has (\d+) occurrences, make it a constant + - path: decode.go + text: string `\]\)` has (\d+) occurrences, make it a constant + - path: valid.go + text: string ` for type ` has (\d+) occurrences, make it a constant + - path: valid.go + text: 'string `cbor: ` has (\d+) occurrences, make it a constant' + - linters: + - goconst + path: (.+)_test\.go + paths: + - third_party$ + - builtin$ + - examples$ issues: - # max-issues-per-linter default is 50. Set to 0 to disable limit. max-issues-per-linter: 0 - # max-same-issues default is 3. Set to 0 to disable limit. max-same-issues: 0 - - exclude-rules: - - path: decode.go - text: "string ` overflows ` has (\\d+) occurrences, make it a constant" - - path: decode.go - text: "string ` \\(range is \\[` has (\\d+) occurrences, make it a constant" - - path: decode.go - text: "string `, ` has (\\d+) occurrences, make it a constant" - - path: decode.go - text: "string ` overflows Go's int64` has (\\d+) occurrences, make it a constant" - - path: decode.go - text: "string `\\]\\)` has (\\d+) occurrences, make it a constant" - - path: valid.go - text: "string ` for type ` has (\\d+) occurrences, make it a constant" - - path: valid.go - text: "string `cbor: ` has (\\d+) occurrences, make it a constant" +formatters: + enable: + - gofmt + - goimports + settings: + gofmt: + simplify: false + goimports: + local-prefixes: + - github.com/fxamacker/cbor + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/vendor/github.com/fxamacker/cbor/v2/README.md b/vendor/github.com/fxamacker/cbor/v2/README.md index d072b81c7..f9ae78ec9 100644 --- a/vendor/github.com/fxamacker/cbor/v2/README.md +++ b/vendor/github.com/fxamacker/cbor/v2/README.md @@ -702,21 +702,20 @@ Default limits may need to be increased for systems handling very large data (e. ## Status -[v2.9.0](https://github.com/fxamacker/cbor/releases/tag/v2.9.0) (Jul 13, 2025) improved interoperability/transcoding between CBOR & JSON, refactored tests, and improved docs. -- Add opt-in support for `encoding.TextMarshaler` and `encoding.TextUnmarshaler` to encode and decode from CBOR text string. -- Add opt-in support for `json.Marshaler` and `json.Unmarshaler` via user-provided transcoding function. -- Update docs for TimeMode, Tag, RawTag, and add example for Embedded JSON Tag for CBOR. +v2.9.1 (Mar 29-30, 2026) includes important bugfixes, defensive checks, improved code quality, and more tests. Although not public, the fuzzer was also improved by adding more fuzz tests. -v2.9.0 passed fuzz tests and is production quality. +v2.9.1 passed fuzz tests and is production quality. The minimum version of Go required to build: - v2.8.0 and newer releases require go 1.20+. - v2.7.1 and older releases require go 1.17+. -For more details, see [release notes](https://github.com/fxamacker/cbor/releases). +For more details, see [v2.9.1 release notes](https://github.com/fxamacker/cbor/releases). ### Prior Releases +[v2.9.0](https://github.com/fxamacker/cbor/releases/tag/v2.9.0) (Jul 13, 2025) improved interoperability/transcoding between CBOR & JSON, refactored tests, and improved docs. It passed fuzz tests (billions of executions) and is production quality. + [v2.8.0](https://github.com/fxamacker/cbor/releases/tag/v2.8.0) (March 30, 2025) is a small release primarily to add `omitzero` option to struct field tags and fix bugs. It passed fuzz tests (billions of executions) and is production quality. [v2.7.0](https://github.com/fxamacker/cbor/releases/tag/v2.7.0) (June 23, 2024) adds features and improvements that help large projects (e.g. Kubernetes) use CBOR as an alternative to JSON and Protocol Buffers. Other improvements include speedups, improved memory use, bug fixes, new serialization options, etc. It passed fuzz tests (5+ billion executions) and is production quality. diff --git a/vendor/github.com/fxamacker/cbor/v2/cache.go b/vendor/github.com/fxamacker/cbor/v2/cache.go index 5051f110f..5743f3eb2 100644 --- a/vendor/github.com/fxamacker/cbor/v2/cache.go +++ b/vendor/github.com/fxamacker/cbor/v2/cache.go @@ -92,94 +92,126 @@ func newTypeInfo(t reflect.Type) *typeInfo { } type decodingStructType struct { - fields fields - fieldIndicesByName map[string]int - err error - toArray bool + fields decodingFields + fieldIndicesByName map[string]int // Only populated if toArray is false + fieldIndicesByIntKey map[int64]int // Only populated if toArray is false + err error + toArray bool } -// The stdlib errors.Join was introduced in Go 1.20, and we still support Go 1.17, so instead, -// here's a very basic implementation of an aggregated error. -type multierror []error - -func (m multierror) Error() string { - var sb strings.Builder - for i, err := range m { - sb.WriteString(err.Error()) - if i < len(m)-1 { - sb.WriteString(", ") - } - } - return sb.String() -} - -func getDecodingStructType(t reflect.Type) *decodingStructType { +func getDecodingStructType(t reflect.Type) (*decodingStructType, error) { if v, _ := decodingStructTypeCache.Load(t); v != nil { - return v.(*decodingStructType) + structType := v.(*decodingStructType) + if structType.err != nil { + return nil, structType.err + } + return structType, nil } flds, structOptions := getFields(t) toArray := hasToArrayOption(structOptions) - var errs []error - for i := 0; i < len(flds); i++ { - if flds[i].keyAsInt { - nameAsInt, numErr := strconv.Atoi(flds[i].name) - if numErr != nil { - errs = append(errs, errors.New("cbor: failed to parse field name \""+flds[i].name+"\" to int ("+numErr.Error()+")")) - break + if toArray { + return getDecodingStructToArrayType(t, flds) + } + + fieldIndicesByName := make(map[string]int, len(flds)) + var fieldIndicesByIntKey map[int64]int + + decFlds := make(decodingFields, len(flds)) + for i, f := range flds { + // nameAsInt is set in getFields() except for fields with an unparsable tagged name. + // Atoi() is called here to catch and save parsing errors. + if f.keyAsInt && f.nameAsInt == 0 { + if _, numErr := strconv.Atoi(f.name); numErr != nil { + structType := &decodingStructType{ + err: errors.New("cbor: failed to parse field name \"" + f.name + "\" to int (" + numErr.Error() + ")"), + } + decodingStructTypeCache.Store(t, structType) + return nil, structType.err } - flds[i].nameAsInt = int64(nameAsInt) } - flds[i].typInfo = getTypeInfo(flds[i].typ) - } + if f.keyAsInt { + if fieldIndicesByIntKey == nil { + fieldIndicesByIntKey = make(map[int64]int, len(flds)) + } + // The duplication check is only a safeguard, since getFields() already deduplicates fields. + if _, ok := fieldIndicesByIntKey[f.nameAsInt]; ok { + structType := &decodingStructType{ + err: fmt.Errorf("cbor: two or more fields of %v have the same keyasint value %d", t, f.nameAsInt), + } + decodingStructTypeCache.Store(t, structType) + return nil, structType.err + } + fieldIndicesByIntKey[f.nameAsInt] = i + } else { + // The duplication check is only a safeguard, since getFields() already deduplicates fields. + if _, ok := fieldIndicesByName[f.name]; ok { + structType := &decodingStructType{ + err: fmt.Errorf("cbor: two or more fields of %v have the same name %q", t, f.name), + } + decodingStructTypeCache.Store(t, structType) + return nil, structType.err + } + fieldIndicesByName[f.name] = i + } - fieldIndicesByName := make(map[string]int, len(flds)) - for i, fld := range flds { - if _, ok := fieldIndicesByName[fld.name]; ok { - errs = append(errs, fmt.Errorf("cbor: two or more fields of %v have the same name %q", t, fld.name)) - continue + decFlds[i] = &decodingField{ + field: *f, + typInfo: getTypeInfo(f.typ), } - fieldIndicesByName[fld.name] = i } - var err error - { - var multi multierror - for _, each := range errs { - if each != nil { - multi = append(multi, each) + structType := &decodingStructType{ + fields: decFlds, + fieldIndicesByName: fieldIndicesByName, + fieldIndicesByIntKey: fieldIndicesByIntKey, + } + decodingStructTypeCache.Store(t, structType) + return structType, nil +} + +func getDecodingStructToArrayType(t reflect.Type, flds fields) (*decodingStructType, error) { + decFlds := make(decodingFields, len(flds)) + for i, f := range flds { + // nameAsInt is set in getFields() except for fields with an unparsable tagged name. + // Atoi() is called here to catch and save parsing errors. + if f.keyAsInt && f.nameAsInt == 0 { + if _, numErr := strconv.Atoi(f.name); numErr != nil { + structType := &decodingStructType{ + err: errors.New("cbor: failed to parse field name \"" + f.name + "\" to int (" + numErr.Error() + ")"), + } + decodingStructTypeCache.Store(t, structType) + return nil, structType.err } } - if len(multi) == 1 { - err = multi[0] - } else if len(multi) > 1 { - err = multi + + decFlds[i] = &decodingField{ + field: *f, + typInfo: getTypeInfo(f.typ), } } structType := &decodingStructType{ - fields: flds, - fieldIndicesByName: fieldIndicesByName, - err: err, - toArray: toArray, + fields: decFlds, + toArray: true, } decodingStructTypeCache.Store(t, structType) - return structType + return structType, nil } type encodingStructType struct { - fields fields - bytewiseFields fields - lengthFirstFields fields - omitEmptyFieldsIdx []int + fields encodingFields + bytewiseFields encodingFields // Only populated if toArray is false + lengthFirstFields encodingFields // Only populated if toArray is false + omitEmptyFieldsIdx []int // Only populated if toArray is false err error toArray bool } -func (st *encodingStructType) getFields(em *encMode) fields { +func (st *encodingStructType) getFields(em *encMode) encodingFields { switch em.sort { case SortNone, SortFastShuffle: return st.fields @@ -191,7 +223,7 @@ func (st *encodingStructType) getFields(em *encMode) fields { } type bytewiseFieldSorter struct { - fields fields + fields encodingFields } func (x *bytewiseFieldSorter) Len() int { @@ -203,11 +235,11 @@ func (x *bytewiseFieldSorter) Swap(i, j int) { } func (x *bytewiseFieldSorter) Less(i, j int) bool { - return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) <= 0 + return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) < 0 } type lengthFirstFieldSorter struct { - fields fields + fields encodingFields } func (x *lengthFirstFieldSorter) Len() int { @@ -222,13 +254,16 @@ func (x *lengthFirstFieldSorter) Less(i, j int) bool { if len(x.fields[i].cborName) != len(x.fields[j].cborName) { return len(x.fields[i].cborName) < len(x.fields[j].cborName) } - return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) <= 0 + return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) < 0 } func getEncodingStructType(t reflect.Type) (*encodingStructType, error) { if v, _ := encodingStructTypeCache.Load(t); v != nil { structType := v.(*encodingStructType) - return structType, structType.err + if structType.err != nil { + return nil, structType.err + } + return structType, nil } flds, structOptions := getFields(t) @@ -237,111 +272,119 @@ func getEncodingStructType(t reflect.Type) (*encodingStructType, error) { return getEncodingStructToArrayType(t, flds) } - var err error var hasKeyAsInt bool var hasKeyAsStr bool var omitEmptyIdx []int + + encFlds := make(encodingFields, len(flds)) + e := getEncodeBuffer() - for i := 0; i < len(flds); i++ { + defer putEncodeBuffer(e) + + for i, f := range flds { + encFlds[i] = &encodingField{field: *f} + ef := encFlds[i] + // Get field's encodeFunc - flds[i].ef, flds[i].ief, flds[i].izf = getEncodeFunc(flds[i].typ) - if flds[i].ef == nil { - err = &UnsupportedTypeError{t} - break + ef.ef, ef.ief, ef.izf = getEncodeFunc(f.typ) + if ef.ef == nil { + structType := &encodingStructType{err: &UnsupportedTypeError{t}} + encodingStructTypeCache.Store(t, structType) + return nil, structType.err } // Encode field name - if flds[i].keyAsInt { - nameAsInt, numErr := strconv.Atoi(flds[i].name) - if numErr != nil { - err = errors.New("cbor: failed to parse field name \"" + flds[i].name + "\" to int (" + numErr.Error() + ")") - break + if f.keyAsInt { + if f.nameAsInt == 0 { + // nameAsInt is set in getFields() except for fields with an unparsable tagged name. + // Atoi() is called here to catch and save parsing errors. + if _, numErr := strconv.Atoi(f.name); numErr != nil { + structType := &encodingStructType{ + err: errors.New("cbor: failed to parse field name \"" + f.name + "\" to int (" + numErr.Error() + ")"), + } + encodingStructTypeCache.Store(t, structType) + return nil, structType.err + } } - flds[i].nameAsInt = int64(nameAsInt) + nameAsInt := f.nameAsInt if nameAsInt >= 0 { - encodeHead(e, byte(cborTypePositiveInt), uint64(nameAsInt)) + encodeHead(e, byte(cborTypePositiveInt), uint64(nameAsInt)) //nolint:gosec } else { n := nameAsInt*(-1) - 1 - encodeHead(e, byte(cborTypeNegativeInt), uint64(n)) + encodeHead(e, byte(cborTypeNegativeInt), uint64(n)) //nolint:gosec } - flds[i].cborName = make([]byte, e.Len()) - copy(flds[i].cborName, e.Bytes()) + ef.cborName = make([]byte, e.Len()) + copy(ef.cborName, e.Bytes()) e.Reset() hasKeyAsInt = true } else { - encodeHead(e, byte(cborTypeTextString), uint64(len(flds[i].name))) - flds[i].cborName = make([]byte, e.Len()+len(flds[i].name)) - n := copy(flds[i].cborName, e.Bytes()) - copy(flds[i].cborName[n:], flds[i].name) + encodeHead(e, byte(cborTypeTextString), uint64(len(f.name))) + ef.cborName = make([]byte, e.Len()+len(f.name)) + n := copy(ef.cborName, e.Bytes()) + copy(ef.cborName[n:], f.name) e.Reset() // If cborName contains a text string, then cborNameByteString contains a // string that has the byte string major type but is otherwise identical to // cborName. - flds[i].cborNameByteString = make([]byte, len(flds[i].cborName)) - copy(flds[i].cborNameByteString, flds[i].cborName) + ef.cborNameByteString = make([]byte, len(ef.cborName)) + copy(ef.cborNameByteString, ef.cborName) // Reset encoded CBOR type to byte string, preserving the "additional // information" bits: - flds[i].cborNameByteString[0] = byte(cborTypeByteString) | - getAdditionalInformation(flds[i].cborNameByteString[0]) + ef.cborNameByteString[0] = byte(cborTypeByteString) | + getAdditionalInformation(ef.cborNameByteString[0]) hasKeyAsStr = true } // Check if field can be omitted when empty - if flds[i].omitEmpty { + if f.omitEmpty { omitEmptyIdx = append(omitEmptyIdx, i) } } - putEncodeBuffer(e) - - if err != nil { - structType := &encodingStructType{err: err} - encodingStructTypeCache.Store(t, structType) - return structType, structType.err - } // Sort fields by canonical order - bytewiseFields := make(fields, len(flds)) - copy(bytewiseFields, flds) + bytewiseFields := make(encodingFields, len(encFlds)) + copy(bytewiseFields, encFlds) sort.Sort(&bytewiseFieldSorter{bytewiseFields}) lengthFirstFields := bytewiseFields if hasKeyAsInt && hasKeyAsStr { - lengthFirstFields = make(fields, len(flds)) - copy(lengthFirstFields, flds) + lengthFirstFields = make(encodingFields, len(encFlds)) + copy(lengthFirstFields, encFlds) sort.Sort(&lengthFirstFieldSorter{lengthFirstFields}) } structType := &encodingStructType{ - fields: flds, + fields: encFlds, bytewiseFields: bytewiseFields, lengthFirstFields: lengthFirstFields, omitEmptyFieldsIdx: omitEmptyIdx, } encodingStructTypeCache.Store(t, structType) - return structType, structType.err + return structType, nil } func getEncodingStructToArrayType(t reflect.Type, flds fields) (*encodingStructType, error) { - for i := 0; i < len(flds); i++ { - // Get field's encodeFunc - flds[i].ef, flds[i].ief, flds[i].izf = getEncodeFunc(flds[i].typ) - if flds[i].ef == nil { + encFlds := make(encodingFields, len(flds)) + for i, f := range flds { + encFlds[i] = &encodingField{field: *f} + encFlds[i].ef, encFlds[i].ief, encFlds[i].izf = getEncodeFunc(f.typ) + if encFlds[i].ef == nil { structType := &encodingStructType{err: &UnsupportedTypeError{t}} encodingStructTypeCache.Store(t, structType) - return structType, structType.err + return nil, structType.err } } structType := &encodingStructType{ - fields: flds, + fields: encFlds, toArray: true, } encodingStructTypeCache.Store(t, structType) - return structType, structType.err + return structType, nil } func getEncodeFunc(t reflect.Type) (encodeFunc, isEmptyFunc, isZeroFunc) { diff --git a/vendor/github.com/fxamacker/cbor/v2/decode.go b/vendor/github.com/fxamacker/cbor/v2/decode.go index f0bdc3b38..03fd7f8b0 100644 --- a/vendor/github.com/fxamacker/cbor/v2/decode.go +++ b/vendor/github.com/fxamacker/cbor/v2/decode.go @@ -16,7 +16,6 @@ import ( "math/big" "reflect" "strconv" - "strings" "time" "unicode/utf8" @@ -326,14 +325,14 @@ func (dmkm DupMapKeyMode) valid() bool { return dmkm >= 0 && dmkm < maxDupMapKeyMode } -// IndefLengthMode specifies whether to allow indefinite length items. +// IndefLengthMode specifies whether to allow indefinite-length items. type IndefLengthMode int const ( - // IndefLengthAllowed allows indefinite length items. + // IndefLengthAllowed allows indefinite-length items. IndefLengthAllowed IndefLengthMode = iota - // IndefLengthForbidden disallows indefinite length items. + // IndefLengthForbidden disallows indefinite-length items. IndefLengthForbidden maxIndefLengthMode @@ -378,6 +377,7 @@ const ( // - int64 if value fits // - big.Int or *big.Int (see BigIntDecMode) if value < math.MinInt64 // - return UnmarshalTypeError if value > math.MaxInt64 + // // Deprecated: IntDecConvertSigned should not be used. // Please use other options, such as IntDecConvertSignedOrError, IntDecConvertSignedOrBigInt, IntDecConvertNone. IntDecConvertSigned @@ -811,7 +811,7 @@ type DecOptions struct { // Default is 128*1024=131072 and it can be set to [16, 2147483647] MaxMapPairs int - // IndefLength specifies whether to allow indefinite length CBOR items. + // IndefLength specifies whether to allow indefinite-length CBOR items. IndefLength IndefLengthMode // TagsMd specifies whether to allow CBOR tags (major type 6). @@ -1055,7 +1055,7 @@ func (opts DecOptions) decMode() (*decMode, error) { //nolint:gocritic // ignore } if !opts.ExtraReturnErrors.valid() { - return nil, errors.New("cbor: invalid ExtraReturnErrors " + strconv.Itoa(int(opts.ExtraReturnErrors))) + return nil, errors.New("cbor: invalid ExtraReturnErrors " + strconv.Itoa(int(opts.ExtraReturnErrors))) //nolint:gosec } if opts.DefaultMapType != nil && opts.DefaultMapType.Kind() != reflect.Map { @@ -1149,8 +1149,8 @@ func (opts DecOptions) decMode() (*decMode, error) { //nolint:gocritic // ignore unrecognizedTagToAny: opts.UnrecognizedTagToAny, timeTagToAny: opts.TimeTagToAny, simpleValues: simpleValues, - nanDec: opts.NaN, - infDec: opts.Inf, + nan: opts.NaN, + inf: opts.Inf, byteStringToTime: opts.ByteStringToTime, byteStringExpectedFormat: opts.ByteStringExpectedFormat, bignumTag: opts.BignumTag, @@ -1230,8 +1230,8 @@ type decMode struct { unrecognizedTagToAny UnrecognizedTagToAnyMode timeTagToAny TimeTagToAnyMode simpleValues *SimpleValueRegistry - nanDec NaNMode - infDec InfMode + nan NaNMode + inf InfMode byteStringToTime ByteStringToTimeMode byteStringExpectedFormat ByteStringExpectedFormatMode bignumTag BignumTagMode @@ -1272,8 +1272,8 @@ func (dm *decMode) DecOptions() DecOptions { UnrecognizedTagToAny: dm.unrecognizedTagToAny, TimeTagToAny: dm.timeTagToAny, SimpleValues: simpleValues, - NaN: dm.nanDec, - Inf: dm.infDec, + NaN: dm.nan, + Inf: dm.inf, ByteStringToTime: dm.byteStringToTime, ByteStringExpectedFormat: dm.byteStringExpectedFormat, BignumTag: dm.bignumTag, @@ -1583,11 +1583,11 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin _, ai, val := d.getHead() switch ai { case additionalInformationAsFloat16: - f := float64(float16.Frombits(uint16(val)).Float32()) + f := float64(float16.Frombits(uint16(val)).Float32()) //nolint:gosec return fillFloat(t, f, v) case additionalInformationAsFloat32: - f := float64(math.Float32frombits(uint32(val))) + f := float64(math.Float32frombits(uint32(val))) //nolint:gosec return fillFloat(t, f, v) case additionalInformationAsFloat64: @@ -1595,10 +1595,10 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin return fillFloat(t, f, v) default: // ai <= 24 - if d.dm.simpleValues.rejected[SimpleValue(val)] { + if d.dm.simpleValues.rejected[SimpleValue(val)] { //nolint:gosec return &UnacceptableDataItemError{ CBORType: t.String(), - Message: "simple value " + strconv.FormatInt(int64(val), 10) + " is not recognized", + Message: "simple value " + strconv.FormatInt(int64(val), 10) + " is not recognized", //nolint:gosec } } @@ -1677,20 +1677,23 @@ func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolin return d.parseToValue(v, tInfo) case cborTypeArray: - if tInfo.nonPtrKind == reflect.Slice { + switch tInfo.nonPtrKind { + case reflect.Slice: return d.parseArrayToSlice(v, tInfo) - } else if tInfo.nonPtrKind == reflect.Array { + case reflect.Array: return d.parseArrayToArray(v, tInfo) - } else if tInfo.nonPtrKind == reflect.Struct { + case reflect.Struct: return d.parseArrayToStruct(v, tInfo) } + d.skip() return &UnmarshalTypeError{CBORType: t.String(), GoType: tInfo.nonPtrType.String()} case cborTypeMap: - if tInfo.nonPtrKind == reflect.Struct { + switch tInfo.nonPtrKind { + case reflect.Struct: return d.parseMapToStruct(v, tInfo) - } else if tInfo.nonPtrKind == reflect.Map { + case reflect.Map: return d.parseMapToMap(v, tInfo) } d.skip() @@ -1745,8 +1748,8 @@ func (d *decoder) parseToTime() (time.Time, bool, error) { // Read tag number _, _, tagNum := d.getHead() if tagNum != 0 && tagNum != 1 { - d.skip() // skip tag content - return time.Time{}, false, errors.New("cbor: wrong tag number for time.Time, got " + strconv.Itoa(int(tagNum)) + ", expect 0 or 1") + d.skip() // skip tag content + return time.Time{}, false, errors.New("cbor: wrong tag number for time.Time, got " + strconv.Itoa(int(tagNum)) + ", expect 0 or 1") //nolint:gosec } } } else { @@ -1815,10 +1818,10 @@ func (d *decoder) parseToTime() (time.Time, bool, error) { var f float64 switch ai { case additionalInformationAsFloat16: - f = float64(float16.Frombits(uint16(val)).Float32()) + f = float64(float16.Frombits(uint16(val)).Float32()) //nolint:gosec case additionalInformationAsFloat32: - f = float64(math.Float32frombits(uint32(val))) + f = float64(math.Float32frombits(uint32(val))) //nolint:gosec case additionalInformationAsFloat64: f = math.Float64frombits(val) @@ -1832,6 +1835,13 @@ func (d *decoder) parseToTime() (time.Time, bool, error) { return time.Time{}, true, nil } seconds, fractional := math.Modf(f) + if seconds > math.MaxInt64 || seconds < math.MinInt64 { + return time.Time{}, false, &UnmarshalTypeError{ + CBORType: t.String(), + GoType: typeTime.String(), + errorMsg: fmt.Sprintf("%v overflows Go's int64", f), + } + } return time.Unix(int64(seconds), int64(fractional*1e9)), true, nil default: @@ -2145,14 +2155,14 @@ func (d *decoder) parse(skipSelfDescribedTag bool) (any, error) { //nolint:gocyc case cborTypePrimitives: _, ai, val := d.getHead() - if ai <= 24 && d.dm.simpleValues.rejected[SimpleValue(val)] { + if ai <= 24 && d.dm.simpleValues.rejected[SimpleValue(val)] { //nolint:gosec return nil, &UnacceptableDataItemError{ CBORType: t.String(), - Message: "simple value " + strconv.FormatInt(int64(val), 10) + " is not recognized", + Message: "simple value " + strconv.FormatInt(int64(val), 10) + " is not recognized", //nolint:gosec } } if ai < 20 || ai == 24 { - return SimpleValue(val), nil + return SimpleValue(val), nil //nolint:gosec } switch ai { @@ -2165,11 +2175,11 @@ func (d *decoder) parse(skipSelfDescribedTag bool) (any, error) { //nolint:gocyc return nil, nil case additionalInformationAsFloat16: - f := float64(float16.Frombits(uint16(val)).Float32()) + f := float64(float16.Frombits(uint16(val)).Float32()) //nolint:gosec return f, nil case additionalInformationAsFloat32: - f := float64(math.Float32frombits(uint32(val))) + f := float64(math.Float32frombits(uint32(val))) //nolint:gosec return f, nil case additionalInformationAsFloat64: @@ -2202,16 +2212,16 @@ func (d *decoder) parse(skipSelfDescribedTag bool) (any, error) { //nolint:gocyc func (d *decoder) parseByteString() ([]byte, bool) { _, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag() if !indefiniteLength { - b := d.data[d.off : d.off+int(val)] - d.off += int(val) + b := d.data[d.off : d.off+int(val)] //nolint:gosec + d.off += int(val) //nolint:gosec return b, false } - // Process indefinite length string chunks. + // Process indefinite-length string chunks. b := []byte{} for !d.foundBreak() { _, _, val = d.getHead() - b = append(b, d.data[d.off:d.off+int(val)]...) - d.off += int(val) + b = append(b, d.data[d.off:d.off+int(val)]...) //nolint:gosec + d.off += int(val) //nolint:gosec } return b, true } @@ -2300,19 +2310,19 @@ func (d *decoder) applyByteStringTextConversion( func (d *decoder) parseTextString() ([]byte, error) { _, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag() if !indefiniteLength { - b := d.data[d.off : d.off+int(val)] - d.off += int(val) + b := d.data[d.off : d.off+int(val)] //nolint:gosec + d.off += int(val) //nolint:gosec if d.dm.utf8 == UTF8RejectInvalid && !utf8.Valid(b) { return nil, &SemanticError{"cbor: invalid UTF-8 string"} } return b, nil } - // Process indefinite length string chunks. + // Process indefinite-length string chunks. b := []byte{} for !d.foundBreak() { _, _, val = d.getHead() - x := d.data[d.off : d.off+int(val)] - d.off += int(val) + x := d.data[d.off : d.off+int(val)] //nolint:gosec + d.off += int(val) //nolint:gosec if d.dm.utf8 == UTF8RejectInvalid && !utf8.Valid(x) { for !d.foundBreak() { d.skip() // Skip remaining chunk on error @@ -2327,7 +2337,7 @@ func (d *decoder) parseTextString() ([]byte, error) { func (d *decoder) parseArray() ([]any, error) { _, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag() hasSize := !indefiniteLength - count := int(val) + count := int(val) //nolint:gosec if !hasSize { count = d.numOfItemsUntilBreak() // peek ahead to get array size to preallocate slice for better performance } @@ -2349,7 +2359,7 @@ func (d *decoder) parseArray() ([]any, error) { func (d *decoder) parseArrayToSlice(v reflect.Value, tInfo *typeInfo) error { _, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag() hasSize := !indefiniteLength - count := int(val) + count := int(val) //nolint:gosec if !hasSize { count = d.numOfItemsUntilBreak() // peek ahead to get array size to preallocate slice for better performance } @@ -2371,7 +2381,7 @@ func (d *decoder) parseArrayToSlice(v reflect.Value, tInfo *typeInfo) error { func (d *decoder) parseArrayToArray(v reflect.Value, tInfo *typeInfo) error { _, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag() hasSize := !indefiniteLength - count := int(val) + count := int(val) //nolint:gosec gi := 0 vLen := v.Len() var err error @@ -2400,7 +2410,7 @@ func (d *decoder) parseArrayToArray(v reflect.Value, tInfo *typeInfo) error { func (d *decoder) parseMap() (any, error) { _, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag() hasSize := !indefiniteLength - count := int(val) + count := int(val) //nolint:gosec m := make(map[any]any) var k, e any var err, lastErr error @@ -2465,7 +2475,7 @@ func (d *decoder) parseMap() (any, error) { func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo _, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag() hasSize := !indefiniteLength - count := int(val) + count := int(val) //nolint:gosec if v.IsNil() { mapsize := count if !hasSize { @@ -2566,9 +2576,9 @@ func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //noli } func (d *decoder) parseArrayToStruct(v reflect.Value, tInfo *typeInfo) error { - structType := getDecodingStructType(tInfo.nonPtrType) - if structType.err != nil { - return structType.err + structType, structTypeErr := getDecodingStructType(tInfo.nonPtrType) + if structTypeErr != nil { + return structTypeErr } if !structType.toArray { @@ -2584,7 +2594,7 @@ func (d *decoder) parseArrayToStruct(v reflect.Value, tInfo *typeInfo) error { start := d.off _, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag() hasSize := !indefiniteLength - count := int(val) + count := int(val) //nolint:gosec if !hasSize { count = d.numOfItemsUntilBreak() // peek ahead to get array size } @@ -2637,11 +2647,72 @@ func (d *decoder) parseArrayToStruct(v reflect.Value, tInfo *typeInfo) error { return err } -// parseMapToStruct needs to be fast so gocyclo can be ignored for now. +// skipMapEntriesFromIndex skips remaining map entries starting from index i. +func (d *decoder) skipMapEntriesFromIndex(i, count int, hasSize bool) { + for ; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ { + d.skip() + d.skip() + } +} + +// skipMapForDupKey skips the current map value and all remaining map entries, +// then returns a DupMapKeyError for the given key at map index i. +func (d *decoder) skipMapForDupKey(dupKey any, i, count int, hasSize bool) error { + // Skip the value of the duplicate key. + d.skip() + // Skip all remaining map entries. + d.skipMapEntriesFromIndex(i+1, count, hasSize) + return &DupMapKeyError{dupKey, i} +} + +// skipMapForUnknownField skips the current map value and all remaining map entries, +// then returns a UnknownFieldError for the given key at map index i. +func (d *decoder) skipMapForUnknownField(i, count int, hasSize bool) error { + // Skip the value of the unknown key. + d.skip() + // Skip all remaining map entries. + d.skipMapEntriesFromIndex(i+1, count, hasSize) + return &UnknownFieldError{i} +} + +// decodeToStructField decodes the next CBOR value into the struct field f in v. +// If the field cannot be resolved, the CBOR value is skipped. +func (d *decoder) decodeToStructField(v reflect.Value, f *decodingField, tInfo *typeInfo) error { + var fv reflect.Value + + if len(f.idx) == 1 { + fv = v.Field(f.idx[0]) + } else { + var err error + fv, err = getFieldValue(v, f.idx, func(v reflect.Value) (reflect.Value, error) { + // Return a new value for embedded field null pointer to point to, or return error. + if !v.CanSet() { + return reflect.Value{}, errors.New("cbor: cannot set embedded pointer to unexported struct: " + v.Type().String()) + } + v.Set(reflect.New(v.Type().Elem())) + return v, nil + }) + if !fv.IsValid() { + d.skip() + return err + } + } + + err := d.parseToValue(fv, f.typInfo) + if err != nil { + if typeError, ok := err.(*UnmarshalTypeError); ok { + typeError.StructFieldName = tInfo.nonPtrType.String() + "." + f.name + } + return err + } + + return nil +} + func (d *decoder) parseMapToStruct(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo - structType := getDecodingStructType(tInfo.nonPtrType) - if structType.err != nil { - return structType.err + structType, structTypeErr := getDecodingStructType(tInfo.nonPtrType) + if structTypeErr != nil { + return structTypeErr } if structType.toArray { @@ -2654,14 +2725,12 @@ func (d *decoder) parseMapToStruct(v reflect.Value, tInfo *typeInfo) error { //n } } - var err, lastErr error - // Get CBOR map size _, _, val, indefiniteLength := d.getHeadWithIndefiniteLengthFlag() hasSize := !indefiniteLength - count := int(val) + count := int(val) //nolint:gosec - // Keeps track of matched struct fields + // Keep track of matched struct fields to detect duplicate map keys. var foundFldIdx []bool { const maxStackFields = 128 @@ -2675,99 +2744,80 @@ func (d *decoder) parseMapToStruct(v reflect.Value, tInfo *typeInfo) error { //n } } - // Keeps track of CBOR map keys to detect duplicate map key - keyCount := 0 - var mapKeys map[any]struct{} - - errOnUnknownField := (d.dm.extraReturnErrors & ExtraDecErrorUnknownField) > 0 + // Keep track of unmatched CBOR map keys to detect duplicate map keys. + var unmatchedMapKeys map[any]struct{} -MapEntryLoop: - for j := 0; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ { - var f *field + var err error - // If duplicate field detection is enabled and the key at index j did not match any - // field, k will hold the map key. - var k any + caseInsensitive := d.dm.fieldNameMatching == FieldNameMatchingPreferCaseSensitive + for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ { t := d.nextCBORType() - if t == cborTypeTextString || (t == cborTypeByteString && d.dm.fieldNameByteString == FieldNameByteStringAllowed) { + + // Reclassify disallowed byte string keys so they fall to the default case. + // keyType is only used for branch control. + keyType := t + if t == cborTypeByteString && d.dm.fieldNameByteString != FieldNameByteStringAllowed { + keyType = 0xff + } + + switch keyType { + case cborTypeTextString, cborTypeByteString: var keyBytes []byte if t == cborTypeTextString { - keyBytes, lastErr = d.parseTextString() - if lastErr != nil { + var parseErr error + keyBytes, parseErr = d.parseTextString() + if parseErr != nil { if err == nil { - err = lastErr + err = parseErr } - d.skip() // skip value + d.skip() // Skip value continue } } else { // cborTypeByteString keyBytes, _ = d.parseByteString() } - // Check for exact match on field name. - if i, ok := structType.fieldIndicesByName[string(keyBytes)]; ok { - fld := structType.fields[i] + // Find matching struct field (exact match, then case-insensitive fallback). + if fldIdx, ok := findStructFieldByKey(structType, keyBytes, caseInsensitive); ok { + fld := structType.fields[fldIdx] - if !foundFldIdx[i] { - f = fld - foundFldIdx[i] = true - } else if d.dm.dupMapKey == DupMapKeyEnforcedAPF { - err = &DupMapKeyError{fld.name, j} - d.skip() // skip value - j++ - // skip the rest of the map - for ; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ { - d.skip() - d.skip() + switch checkDupField(d.dm, foundFldIdx, fldIdx) { + case mapActionParseValueAndContinue: + if fieldErr := d.decodeToStructField(v, fld, tInfo); fieldErr != nil && err == nil { + err = fieldErr } - return err - } else { - // discard repeated match + continue + case mapActionSkipAllAndReturnError: + return d.skipMapForDupKey(string(keyBytes), i, count, hasSize) + case mapActionSkipValueAndContinue: d.skip() - continue MapEntryLoop + continue } } - // Find field with case-insensitive match - if f == nil && d.dm.fieldNameMatching == FieldNameMatchingPreferCaseSensitive { - keyLen := len(keyBytes) - keyString := string(keyBytes) - for i := 0; i < len(structType.fields); i++ { - fld := structType.fields[i] - if len(fld.name) == keyLen && strings.EqualFold(fld.name, keyString) { - if !foundFldIdx[i] { - f = fld - foundFldIdx[i] = true - } else if d.dm.dupMapKey == DupMapKeyEnforcedAPF { - err = &DupMapKeyError{keyString, j} - d.skip() // skip value - j++ - // skip the rest of the map - for ; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ { - d.skip() - d.skip() - } - return err - } else { - // discard repeated match - d.skip() - continue MapEntryLoop - } - break - } - } + // No matching struct field found. + if unmatchedErr := handleUnmatchedMapKey(d, string(keyBytes), i, count, hasSize, &unmatchedMapKeys); unmatchedErr != nil { + return unmatchedErr } - if d.dm.dupMapKey == DupMapKeyEnforcedAPF && f == nil { - k = string(keyBytes) - } - } else if t <= cborTypeNegativeInt { // uint/int + case cborTypePositiveInt, cborTypeNegativeInt: var nameAsInt int64 if t == cborTypePositiveInt { _, _, val := d.getHead() - nameAsInt = int64(val) + if val > math.MaxInt64 { + if err == nil { + err = &UnmarshalTypeError{ + CBORType: t.String(), + GoType: reflect.TypeOf(int64(0)).String(), + errorMsg: strconv.FormatUint(val, 10) + " overflows Go's int64", + } + } + d.skip() // skip value + continue + } + nameAsInt = int64(val) //nolint:gosec } else { _, _, val := d.getHead() if val > math.MaxInt64 { @@ -2781,39 +2831,35 @@ MapEntryLoop: d.skip() // skip value continue } - nameAsInt = int64(-1) ^ int64(val) - } - - // Find field - for i := 0; i < len(structType.fields); i++ { - fld := structType.fields[i] - if fld.keyAsInt && fld.nameAsInt == nameAsInt { - if !foundFldIdx[i] { - f = fld - foundFldIdx[i] = true - } else if d.dm.dupMapKey == DupMapKeyEnforcedAPF { - err = &DupMapKeyError{nameAsInt, j} - d.skip() // skip value - j++ - // skip the rest of the map - for ; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ { - d.skip() - d.skip() - } - return err - } else { - // discard repeated match - d.skip() - continue MapEntryLoop + nameAsInt = int64(-1) ^ int64(val) //nolint:gosec + } + + // Find field by integer key + if fldIdx, ok := structType.fieldIndicesByIntKey[nameAsInt]; ok { + fld := structType.fields[fldIdx] + + switch checkDupField(d.dm, foundFldIdx, fldIdx) { + case mapActionParseValueAndContinue: + if fieldErr := d.decodeToStructField(v, fld, tInfo); fieldErr != nil && err == nil { + err = fieldErr } - break + continue + case mapActionSkipAllAndReturnError: + return d.skipMapForDupKey(nameAsInt, i, count, hasSize) + case mapActionSkipValueAndContinue: + d.skip() + continue } } - if d.dm.dupMapKey == DupMapKeyEnforcedAPF && f == nil { - k = nameAsInt + // No matching struct field found. + if unmatchedErr := handleUnmatchedMapKey(d, nameAsInt, i, count, hasSize, &unmatchedMapKeys); unmatchedErr != nil { + return unmatchedErr } - } else { + + default: + // CBOR map keys that can't be matched to any struct field. + if err == nil { err = &UnmarshalTypeError{ CBORType: t.String(), @@ -2821,97 +2867,31 @@ MapEntryLoop: errorMsg: "map key is of type " + t.String() + " and cannot be used to match struct field name", } } + + var otherKey any if d.dm.dupMapKey == DupMapKeyEnforcedAPF { // parse key - k, lastErr = d.parse(true) - if lastErr != nil { + var parseErr error + otherKey, parseErr = d.parse(true) + if parseErr != nil { d.skip() // skip value continue } // Detect if CBOR map key can be used as Go map key. - if !isHashableValue(reflect.ValueOf(k)) { + if !isHashableValue(reflect.ValueOf(otherKey)) { d.skip() // skip value continue } } else { d.skip() // skip key } - } - - if f == nil { - if errOnUnknownField { - err = &UnknownFieldError{j} - d.skip() // Skip value - j++ - // skip the rest of the map - for ; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ { - d.skip() - d.skip() - } - return err - } - - // Two map keys that match the same struct field are immediately considered - // duplicates. This check detects duplicates between two map keys that do - // not match a struct field. If unknown field errors are enabled, then this - // check is never reached. - if d.dm.dupMapKey == DupMapKeyEnforcedAPF { - if mapKeys == nil { - mapKeys = make(map[any]struct{}, 1) - } - mapKeys[k] = struct{}{} - newKeyCount := len(mapKeys) - if newKeyCount == keyCount { - err = &DupMapKeyError{k, j} - d.skip() // skip value - j++ - // skip the rest of the map - for ; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ { - d.skip() - d.skip() - } - return err - } - keyCount = newKeyCount - } - - d.skip() // Skip value - continue - } - - // Get field value by index - var fv reflect.Value - if len(f.idx) == 1 { - fv = v.Field(f.idx[0]) - } else { - fv, lastErr = getFieldValue(v, f.idx, func(v reflect.Value) (reflect.Value, error) { - // Return a new value for embedded field null pointer to point to, or return error. - if !v.CanSet() { - return reflect.Value{}, errors.New("cbor: cannot set embedded pointer to unexported struct: " + v.Type().String()) - } - v.Set(reflect.New(v.Type().Elem())) - return v, nil - }) - if lastErr != nil && err == nil { - err = lastErr - } - if !fv.IsValid() { - d.skip() - continue - } - } - if lastErr = d.parseToValue(fv, f.typInfo); lastErr != nil { - if err == nil { - if typeError, ok := lastErr.(*UnmarshalTypeError); ok { - typeError.StructFieldName = tInfo.nonPtrType.String() + "." + f.name - err = typeError - } else { - err = lastErr - } + if unmatchedErr := handleUnmatchedMapKey(d, otherKey, i, count, hasSize, &unmatchedMapKeys); unmatchedErr != nil { + return unmatchedErr } } } + return err } @@ -2958,15 +2938,15 @@ func (d *decoder) skip() { switch t { case cborTypeByteString, cborTypeTextString: - d.off += int(val) + d.off += int(val) //nolint:gosec case cborTypeArray: - for i := 0; i < int(val); i++ { + for i := 0; i < int(val); i++ { //nolint:gosec d.skip() } case cborTypeMap: - for i := 0; i < int(val)*2; i++ { + for i := 0; i < int(val)*2; i++ { //nolint:gosec d.skip() } diff --git a/vendor/github.com/fxamacker/cbor/v2/decode_map_utils.go b/vendor/github.com/fxamacker/cbor/v2/decode_map_utils.go new file mode 100644 index 000000000..3c8c423ad --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/decode_map_utils.go @@ -0,0 +1,98 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +package cbor + +import "strings" + +// mapAction represents the next action during decoding a CBOR map to a Go struct. +type mapAction int + +const ( + mapActionParseValueAndContinue mapAction = iota // The caller should process the map value. + mapActionSkipValueAndContinue // The caller should skip the map value. + mapActionSkipAllAndReturnError // The caller should skip the rest of the map and return an error. +) + +// checkDupField checks if a struct field at index i has already been matched and returns the next action. +// If not matched, it marks the field as matched and returns mapActionParseValueAndContinue. +// If matched and DupMapKeyEnforcedAPF is specified in the given dm, it returns mapActionSkipAllAndReturnError. +// If matched and DupMapKeyEnforcedAPF is not specified in the given dm, it returns mapActionSkipValueAndContinue. +func checkDupField(dm *decMode, foundFldIdx []bool, i int) mapAction { + if !foundFldIdx[i] { + foundFldIdx[i] = true + return mapActionParseValueAndContinue + } + if dm.dupMapKey == DupMapKeyEnforcedAPF { + return mapActionSkipAllAndReturnError + } + return mapActionSkipValueAndContinue +} + +// findStructFieldByKey finds a struct field matching keyBytes by name. +// It tries an exact match first. If no exact match is found and +// caseInsensitive is true, it falls back to a case-insensitive search. +// findStructFieldByKey returns the field index and true, or -1 and false. +func findStructFieldByKey( + structType *decodingStructType, + keyBytes []byte, + caseInsensitive bool, +) (int, bool) { + if fldIdx, ok := structType.fieldIndicesByName[string(keyBytes)]; ok { + return fldIdx, true + } + if caseInsensitive { + return findFieldCaseInsensitive(structType.fields, string(keyBytes)) + } + return -1, false +} + +// findFieldCaseInsensitive returns the index of the first field whose name +// case-insensitively matches key, or -1 and false if no field matches. +func findFieldCaseInsensitive(flds decodingFields, key string) (int, bool) { + keyLen := len(key) + for i, f := range flds { + if f.keyAsInt { + continue + } + if len(f.name) == keyLen && strings.EqualFold(f.name, key) { + return i, true + } + } + return -1, false +} + +// handleUnmatchedMapKey handles a map entry whose key does not match any struct +// field. It can return UnknownFieldError or DupMapKeyError. +// handleUnmatchedMapKey consumes the CBOR value, so the caller doesn't need to skip any values. +// If an error is returned, the caller should abort parsing the map and return the error. +// If no error is returned, the caller should continue to process the next map pair. +func handleUnmatchedMapKey( + d *decoder, + key any, + i int, + count int, + hasSize bool, + // *map[any]struct{} is used here because we use lazy initialization for uks + uks *map[any]struct{}, //nolint:gocritic +) error { + errOnUnknownField := (d.dm.extraReturnErrors & ExtraDecErrorUnknownField) > 0 + + if errOnUnknownField { + return d.skipMapForUnknownField(i, count, hasSize) + } + + if d.dm.dupMapKey == DupMapKeyEnforcedAPF { + if *uks == nil { + *uks = make(map[any]struct{}) + } + if _, dup := (*uks)[key]; dup { + return d.skipMapForDupKey(key, i, count, hasSize) + } + (*uks)[key] = struct{}{} + } + + // Skip value. + d.skip() + return nil +} diff --git a/vendor/github.com/fxamacker/cbor/v2/diagnose.go b/vendor/github.com/fxamacker/cbor/v2/diagnose.go index 44afb8660..42a67ad11 100644 --- a/vendor/github.com/fxamacker/cbor/v2/diagnose.go +++ b/vendor/github.com/fxamacker/cbor/v2/diagnose.go @@ -51,11 +51,8 @@ const ( maxByteStringEncoding ) -func (bse ByteStringEncoding) valid() error { - if bse >= maxByteStringEncoding { - return errors.New("cbor: invalid ByteStringEncoding " + strconv.Itoa(int(bse))) - } - return nil +func (bse ByteStringEncoding) valid() bool { + return bse < maxByteStringEncoding } // DiagOptions specifies Diag options. @@ -104,8 +101,8 @@ func (opts DiagOptions) DiagMode() (DiagMode, error) { } func (opts DiagOptions) diagMode() (*diagMode, error) { - if err := opts.ByteStringEncoding.valid(); err != nil { - return nil, err + if !opts.ByteStringEncoding.valid() { + return nil, errors.New("cbor: invalid ByteStringEncoding " + strconv.Itoa(int(opts.ByteStringEncoding))) } decMode, err := DecOptions{ @@ -360,7 +357,7 @@ func (di *diagnose) item() error { //nolint:gocyclo case cborTypeArray: _, _, val := di.d.getHead() - count := int(val) + count := int(val) //nolint:gosec di.w.WriteByte('[') for i := 0; i < count; i++ { @@ -376,7 +373,7 @@ func (di *diagnose) item() error { //nolint:gocyclo case cborTypeMap: _, _, val := di.d.getHead() - count := int(val) + count := int(val) //nolint:gosec di.w.WriteByte('{') for i := 0; i < count; i++ { @@ -477,8 +474,8 @@ func (di *diagnose) item() error { //nolint:gocyclo func (di *diagnose) writeU16(val rune) { di.w.WriteString("\\u") var in [2]byte - in[0] = byte(val >> 8) - in[1] = byte(val) + in[0] = byte(val >> 8) //nolint:gosec + in[1] = byte(val) //nolint:gosec sz := hex.EncodedLen(len(in)) di.w.Grow(sz) dst := di.w.Bytes()[di.w.Len() : di.w.Len()+sz] @@ -608,7 +605,7 @@ func (di *diagnose) encodeTextString(val string, quote byte) error { c, size := utf8.DecodeRuneInString(val[i:]) switch { - case c == utf8.RuneError: + case c == utf8.RuneError && size == 1: return &SemanticError{"cbor: invalid UTF-8 string"} case c < utf16SurrSelf: @@ -631,7 +628,7 @@ func (di *diagnose) encodeFloat(ai byte, val uint64) error { f64 := float64(0) switch ai { case additionalInformationAsFloat16: - f16 := float16.Frombits(uint16(val)) + f16 := float16.Frombits(uint16(val)) //nolint:gosec switch { case f16.IsNaN(): di.w.WriteString("NaN") @@ -647,7 +644,7 @@ func (di *diagnose) encodeFloat(ai byte, val uint64) error { } case additionalInformationAsFloat32: - f32 := math.Float32frombits(uint32(val)) + f32 := math.Float32frombits(uint32(val)) //nolint:gosec switch { case f32 != f32: di.w.WriteString("NaN") diff --git a/vendor/github.com/fxamacker/cbor/v2/encode.go b/vendor/github.com/fxamacker/cbor/v2/encode.go index c550617c3..e65a29d8a 100644 --- a/vendor/github.com/fxamacker/cbor/v2/encode.go +++ b/vendor/github.com/fxamacker/cbor/v2/encode.go @@ -30,7 +30,7 @@ import ( // If value implements the Marshaler interface, Marshal calls its // MarshalCBOR method. // -// If value implements encoding.BinaryMarshaler, Marhsal calls its +// If value implements encoding.BinaryMarshaler, Marshal calls its // MarshalBinary method and encode it as CBOR byte string. // // Boolean values encode as CBOR booleans (type 7). @@ -343,7 +343,7 @@ const ( // non-UTC timezone then a "localtime - UTC" numeric offset will be included as specified in RFC3339. // NOTE: User applications can avoid including the RFC3339 numeric offset by: // - providing a time.Time value set to UTC, or - // - using the TimeUnix, TimeUnixMicro, or TimeUnixDynamic option instead of TimeRFC3339. + // - using the TimeUnix, TimeUnixMicro, TimeUnixDynamic, or TimeRFC3339NanoUTC option. TimeRFC3339 // TimeRFC3339Nano causes time.Time to encode to a CBOR time (tag 0) with a text string content @@ -351,9 +351,13 @@ const ( // non-UTC timezone then a "localtime - UTC" numeric offset will be included as specified in RFC3339. // NOTE: User applications can avoid including the RFC3339 numeric offset by: // - providing a time.Time value set to UTC, or - // - using the TimeUnix, TimeUnixMicro, or TimeUnixDynamic option instead of TimeRFC3339Nano. + // - using the TimeUnix, TimeUnixMicro, TimeUnixDynamic, or TimeRFC3339NanoUTC option. TimeRFC3339Nano + // TimeRFC3339NanoUTC causes time.Time to encode to a CBOR time (tag 0) with a text string content + // representing UTC time using nanosecond precision in RFC3339 format. + TimeRFC3339NanoUTC + maxTimeMode ) @@ -436,7 +440,7 @@ const ( // FieldNameToTextString encodes struct fields to CBOR text string (major type 3). FieldNameToTextString FieldNameMode = iota - // FieldNameToTextString encodes struct fields to CBOR byte string (major type 2). + // FieldNameToByteString encodes struct fields to CBOR byte string (major type 2). FieldNameToByteString maxFieldNameMode @@ -567,7 +571,7 @@ type EncOptions struct { // RFC3339 format gets tag number 0, and numeric epoch time tag number 1. TimeTag EncTagMode - // IndefLength specifies whether to allow indefinite length CBOR items. + // IndefLength specifies whether to allow indefinite-length CBOR items. IndefLength IndefLengthMode // NilContainers specifies how to encode nil slices and maps. @@ -1132,10 +1136,11 @@ func encodeFloat(e *bytes.Buffer, em *encMode, v reflect.Value) error { if fopt == ShortestFloat16 { var f16 float16.Float16 p := float16.PrecisionFromfloat32(f32) - if p == float16.PrecisionExact { + switch p { + case float16.PrecisionExact: // Roundtrip float32->float16->float32 test isn't needed. f16 = float16.Fromfloat32(f32) - } else if p == float16.PrecisionUnknown { + case float16.PrecisionUnknown: // Try roundtrip float32->float16->float32 to determine if float32 can fit into float16. f16 = float16.Fromfloat32(f32) if f16.Float32() == f32 { @@ -1293,10 +1298,10 @@ func encodeByteString(e *bytes.Buffer, em *encMode, v reflect.Value) error { if slen == 0 { return e.WriteByte(byte(cborTypeByteString)) } - encodeHead(e, byte(cborTypeByteString), uint64(slen)) + encodeHead(e, byte(cborTypeByteString), uint64(slen)) //nolint:gosec if vk == reflect.Array { for i := 0; i < slen; i++ { - e.WriteByte(byte(v.Index(i).Uint())) + e.WriteByte(byte(v.Index(i).Uint())) //nolint:gosec } return nil } @@ -1333,7 +1338,7 @@ func (ae arrayEncodeFunc) encode(e *bytes.Buffer, em *encMode, v reflect.Value) if alen == 0 { return e.WriteByte(byte(cborTypeArray)) } - encodeHead(e, byte(cborTypeArray), uint64(alen)) + encodeHead(e, byte(cborTypeArray), uint64(alen)) //nolint:gosec for i := 0; i < alen; i++ { if err := ae.f(e, em, v.Index(i)); err != nil { return err @@ -1364,7 +1369,7 @@ func (me mapEncodeFunc) encode(e *bytes.Buffer, em *encMode, v reflect.Value) er return e.WriteByte(byte(cborTypeMap)) } - encodeHead(e, byte(cborTypeMap), uint64(mlen)) + encodeHead(e, byte(cborTypeMap), uint64(mlen)) //nolint:gosec if em.sort == SortNone || em.sort == SortFastShuffle || mlen <= 1 { return me.e(e, em, v, nil) } @@ -1427,7 +1432,7 @@ func (x *bytewiseKeyValueSorter) Swap(i, j int) { func (x *bytewiseKeyValueSorter) Less(i, j int) bool { kvi, kvj := x.kvs[i], x.kvs[j] - return bytes.Compare(x.data[kvi.offset:kvi.valueOffset], x.data[kvj.offset:kvj.valueOffset]) <= 0 + return bytes.Compare(x.data[kvi.offset:kvi.valueOffset], x.data[kvj.offset:kvj.valueOffset]) < 0 } type lengthFirstKeyValueSorter struct { @@ -1448,7 +1453,7 @@ func (x *lengthFirstKeyValueSorter) Less(i, j int) bool { if keyLengthDifference := (kvi.valueOffset - kvi.offset) - (kvj.valueOffset - kvj.offset); keyLengthDifference != 0 { return keyLengthDifference < 0 } - return bytes.Compare(x.data[kvi.offset:kvi.valueOffset], x.data[kvj.offset:kvj.valueOffset]) <= 0 + return bytes.Compare(x.data[kvi.offset:kvi.valueOffset], x.data[kvj.offset:kvj.valueOffset]) < 0 } var keyValuePool = sync.Pool{} @@ -1535,8 +1540,8 @@ func encodeStruct(e *bytes.Buffer, em *encMode, v reflect.Value) (err error) { // Head is rewritten later if actual encoded field count is different from struct field count. encodedHeadLen := encodeHead(e, byte(cborTypeMap), uint64(len(flds))) - kvbegin := e.Len() - kvcount := 0 + kvBeginOffset := e.Len() + kvCount := 0 for offset := 0; offset < len(flds); offset++ { f := flds[(start+offset)%len(flds)] @@ -1582,10 +1587,10 @@ func encodeStruct(e *bytes.Buffer, em *encMode, v reflect.Value) (err error) { return err } - kvcount++ + kvCount++ } - if len(flds) == kvcount { + if len(flds) == kvCount { // Encoded element count in head is the same as actual element count. return nil } @@ -1593,8 +1598,8 @@ func encodeStruct(e *bytes.Buffer, em *encMode, v reflect.Value) (err error) { // Overwrite the bytes that were reserved for the head before encoding the map entries. var actualHeadLen int { - headbuf := *bytes.NewBuffer(e.Bytes()[kvbegin-encodedHeadLen : kvbegin-encodedHeadLen : kvbegin]) - actualHeadLen = encodeHead(&headbuf, byte(cborTypeMap), uint64(kvcount)) + headbuf := *bytes.NewBuffer(e.Bytes()[kvBeginOffset-encodedHeadLen : kvBeginOffset-encodedHeadLen : kvBeginOffset]) + actualHeadLen = encodeHead(&headbuf, byte(cborTypeMap), uint64(kvCount)) } if actualHeadLen == encodedHeadLen { @@ -1607,8 +1612,8 @@ func encodeStruct(e *bytes.Buffer, em *encMode, v reflect.Value) (err error) { // encoded. The encoded entries are offset to the right by the number of excess reserved // bytes. Shift the entries left to remove the gap. excessReservedBytes := encodedHeadLen - actualHeadLen - dst := e.Bytes()[kvbegin-excessReservedBytes : e.Len()-excessReservedBytes] - src := e.Bytes()[kvbegin:e.Len()] + dst := e.Bytes()[kvBeginOffset-excessReservedBytes : e.Len()-excessReservedBytes] + src := e.Bytes()[kvBeginOffset:e.Len()] copy(dst, src) // After shifting, the excess bytes are at the end of the output buffer and they are @@ -1633,7 +1638,7 @@ func encodeTime(e *bytes.Buffer, em *encMode, v reflect.Value) error { } if em.timeTag == EncTagRequired { tagNumber := 1 - if em.time == TimeRFC3339 || em.time == TimeRFC3339Nano { + if em.time == TimeRFC3339 || em.time == TimeRFC3339Nano || em.time == TimeRFC3339NanoUTC { tagNumber = 0 } encodeHead(e, byte(cborTypeTag), uint64(tagNumber)) @@ -1650,7 +1655,7 @@ func encodeTime(e *bytes.Buffer, em *encMode, v reflect.Value) error { case TimeUnixDynamic: t = t.UTC().Round(time.Microsecond) - secs, nsecs := t.Unix(), uint64(t.Nanosecond()) + secs, nsecs := t.Unix(), uint64(t.Nanosecond()) //nolint:gosec if nsecs == 0 { return encodeInt(e, em, reflect.ValueOf(secs)) } @@ -1661,6 +1666,10 @@ func encodeTime(e *bytes.Buffer, em *encMode, v reflect.Value) error { s := t.Format(time.RFC3339) return encodeString(e, em, reflect.ValueOf(s)) + case TimeRFC3339NanoUTC: + s := t.UTC().Format(time.RFC3339Nano) + return encodeString(e, em, reflect.ValueOf(s)) + default: // TimeRFC3339Nano s := t.Format(time.RFC3339Nano) return encodeString(e, em, reflect.ValueOf(s)) diff --git a/vendor/github.com/fxamacker/cbor/v2/simplevalue.go b/vendor/github.com/fxamacker/cbor/v2/simplevalue.go index 30f72814f..9912e855c 100644 --- a/vendor/github.com/fxamacker/cbor/v2/simplevalue.go +++ b/vendor/github.com/fxamacker/cbor/v2/simplevalue.go @@ -93,6 +93,6 @@ func (sv *SimpleValue) unmarshalCBOR(data []byte) error { // It is safe to cast val to uint8 here because // - data is already verified to be well-formed CBOR simple value and // - val is <= math.MaxUint8. - *sv = SimpleValue(val) + *sv = SimpleValue(val) //nolint:gosec return nil } diff --git a/vendor/github.com/fxamacker/cbor/v2/stream.go b/vendor/github.com/fxamacker/cbor/v2/stream.go index 7ac6d7d67..da4c8f210 100644 --- a/vendor/github.com/fxamacker/cbor/v2/stream.go +++ b/vendor/github.com/fxamacker/cbor/v2/stream.go @@ -171,14 +171,20 @@ func NewEncoder(w io.Writer) *Encoder { // Encode writes the CBOR encoding of v. func (enc *Encoder) Encode(v any) error { - if len(enc.indefTypes) > 0 && v != nil { - indefType := enc.indefTypes[len(enc.indefTypes)-1] - if indefType == cborTypeTextString { + if len(enc.indefTypes) > 0 { + switch enc.indefTypes[len(enc.indefTypes)-1] { + case cborTypeTextString: + if v == nil { + return errors.New("cbor: cannot encode nil for indefinite-length text string") + } k := reflect.TypeOf(v).Kind() if k != reflect.String { return errors.New("cbor: cannot encode item type " + k.String() + " for indefinite-length text string") } - } else if indefType == cborTypeByteString { + case cborTypeByteString: + if v == nil { + return errors.New("cbor: cannot encode nil for indefinite-length byte string") + } t := reflect.TypeOf(v) k := t.Kind() if (k != reflect.Array && k != reflect.Slice) || t.Elem().Kind() != reflect.Uint8 { @@ -198,35 +204,35 @@ func (enc *Encoder) Encode(v any) error { return err } -// StartIndefiniteByteString starts byte string encoding of indefinite length. +// StartIndefiniteByteString starts indefinite-length byte string encoding. // Subsequent calls of (*Encoder).Encode() encodes definite length byte strings // ("chunks") as one contiguous string until EndIndefinite is called. func (enc *Encoder) StartIndefiniteByteString() error { return enc.startIndefinite(cborTypeByteString) } -// StartIndefiniteTextString starts text string encoding of indefinite length. +// StartIndefiniteTextString starts indefinite-length text string encoding. // Subsequent calls of (*Encoder).Encode() encodes definite length text strings // ("chunks") as one contiguous string until EndIndefinite is called. func (enc *Encoder) StartIndefiniteTextString() error { return enc.startIndefinite(cborTypeTextString) } -// StartIndefiniteArray starts array encoding of indefinite length. +// StartIndefiniteArray starts indefinite-length array encoding. // Subsequent calls of (*Encoder).Encode() encodes elements of the array // until EndIndefinite is called. func (enc *Encoder) StartIndefiniteArray() error { return enc.startIndefinite(cborTypeArray) } -// StartIndefiniteMap starts array encoding of indefinite length. +// StartIndefiniteMap starts indefinite-length map encoding. // Subsequent calls of (*Encoder).Encode() encodes elements of the map // until EndIndefinite is called. func (enc *Encoder) StartIndefiniteMap() error { return enc.startIndefinite(cborTypeMap) } -// EndIndefinite closes last opened indefinite length value. +// EndIndefinite closes last opened indefinite-length value. func (enc *Encoder) EndIndefinite() error { if len(enc.indefTypes) == 0 { return errors.New("cbor: cannot encode \"break\" code outside indefinite length values") @@ -238,18 +244,22 @@ func (enc *Encoder) EndIndefinite() error { return err } -var cborIndefHeader = map[cborType][]byte{ - cborTypeByteString: {cborByteStringWithIndefiniteLengthHead}, - cborTypeTextString: {cborTextStringWithIndefiniteLengthHead}, - cborTypeArray: {cborArrayWithIndefiniteLengthHead}, - cborTypeMap: {cborMapWithIndefiniteLengthHead}, -} - func (enc *Encoder) startIndefinite(typ cborType) error { if enc.em.indefLength == IndefLengthForbidden { return &IndefiniteLengthError{typ} } - _, err := enc.w.Write(cborIndefHeader[typ]) + var head byte + switch typ { + case cborTypeByteString: + head = cborByteStringWithIndefiniteLengthHead + case cborTypeTextString: + head = cborTextStringWithIndefiniteLengthHead + case cborTypeArray: + head = cborArrayWithIndefiniteLengthHead + case cborTypeMap: + head = cborMapWithIndefiniteLengthHead + } + _, err := enc.w.Write([]byte{head}) if err == nil { enc.indefTypes = append(enc.indefTypes, typ) } @@ -262,7 +272,9 @@ type RawMessage []byte // MarshalCBOR returns m or CBOR nil if m is nil. func (m RawMessage) MarshalCBOR() ([]byte, error) { if len(m) == 0 { - return cborNil, nil + b := make([]byte, len(cborNil)) + copy(b, cborNil) + return b, nil } return m, nil } diff --git a/vendor/github.com/fxamacker/cbor/v2/structfields.go b/vendor/github.com/fxamacker/cbor/v2/structfields.go index cf0a922cd..b2d71f2e9 100644 --- a/vendor/github.com/fxamacker/cbor/v2/structfields.go +++ b/vendor/github.com/fxamacker/cbor/v2/structfields.go @@ -6,27 +6,43 @@ package cbor import ( "reflect" "sort" + "strconv" "strings" ) +// field holds shared struct field metadata returned by getFields(). type field struct { - name string - nameAsInt int64 // used to decoder to match field name with CBOR int + name string + nameAsInt int64 // used to match field name with CBOR int + idx []int + typ reflect.Type // used during cache building only + keyAsInt bool // used to encode/decode field name as int + tagged bool // used to choose dominant field (at the same level tagged fields dominate untagged fields) + omitEmpty bool // used to skip empty field + omitZero bool // used to skip zero field +} + +type fields []*field + +// encodingField extends field with encoding-specific data. +type encodingField struct { + field cborName []byte - cborNameByteString []byte // major type 2 name encoding iff cborName has major type 3 - idx []int - typ reflect.Type + cborNameByteString []byte // major type 2 name encoding if cborName has major type 3 ef encodeFunc ief isEmptyFunc izf isZeroFunc - typInfo *typeInfo // used to decoder to reuse type info - tagged bool // used to choose dominant field (at the same level tagged fields dominate untagged fields) - omitEmpty bool // used to skip empty field - omitZero bool // used to skip zero field - keyAsInt bool // used to encode/decode field name as int } -type fields []*field +type encodingFields []*encodingField + +// decodingField extends field with decoding-specific data. +type decodingField struct { + field + typInfo *typeInfo // used by decoder to reuse type info +} + +type decodingFields []*decodingField // indexFieldSorter sorts fields by field idx at each level, breaking ties with idx depth. type indexFieldSorter struct { @@ -48,7 +64,7 @@ func (x *indexFieldSorter) Less(i, j int) bool { return iIdx[k] < jIdx[k] } } - return len(iIdx) <= len(jIdx) + return len(iIdx) < len(jIdx) } // nameLevelAndTagFieldSorter sorts fields by field name, idx depth, and presence of tag. @@ -69,6 +85,10 @@ func (x *nameLevelAndTagFieldSorter) Less(i, j int) bool { if fi.name != fj.name { return fi.name < fj.name } + // Fields with the same name but different keyAsInt are in separate namespaces. + if fi.keyAsInt != fj.keyAsInt { + return fi.keyAsInt + } if len(fi.idx) != len(fj.idx) { return len(fi.idx) < len(fj.idx) } @@ -117,22 +137,37 @@ func getFields(t reflect.Type) (flds fields, structOptions string) { } } + // Normalize keyasint field names to their canonical integer string form. + // This ensures that "01", "+1", and "1" are treated as the same key + // during deduplication. + for _, f := range flds { + if f.keyAsInt { + nameAsInt, err := strconv.Atoi(f.name) + if err != nil { + continue // Leave invalid names for callers to report. + } + f.nameAsInt = int64(nameAsInt) + f.name = strconv.Itoa(nameAsInt) + } + } + sort.Sort(&nameLevelAndTagFieldSorter{flds}) // Keep visible fields. j := 0 // index of next unique field for i := 0; i < len(flds); { name := flds[i].name + keyAsInt := flds[i].keyAsInt if i == len(flds)-1 || // last field - name != flds[i+1].name || // field i has unique field name + name != flds[i+1].name || flds[i+1].keyAsInt != keyAsInt || // field i has unique (name, keyAsInt) len(flds[i].idx) < len(flds[i+1].idx) || // field i is at a less nested level than field i+1 (flds[i].tagged && !flds[i+1].tagged) { // field i is tagged while field i+1 is not flds[j] = flds[i] j++ } - // Skip fields with the same field name. - for i++; i < len(flds) && name == flds[i].name; i++ { //nolint:revive + // Skip fields with the same (name, keyAsInt). + for i++; i < len(flds) && name == flds[i].name && keyAsInt == flds[i].keyAsInt; i++ { //nolint:revive } } if j != len(flds) { diff --git a/vendor/github.com/fxamacker/cbor/v2/valid.go b/vendor/github.com/fxamacker/cbor/v2/valid.go index b40793b95..850b95019 100644 --- a/vendor/github.com/fxamacker/cbor/v2/valid.go +++ b/vendor/github.com/fxamacker/cbor/v2/valid.go @@ -54,7 +54,7 @@ func (e *MaxMapPairsError) Error() string { return "cbor: exceeded max number of key-value pairs " + strconv.Itoa(e.maxMapPairs) + " for CBOR map" } -// IndefiniteLengthError indicates found disallowed indefinite length items. +// IndefiniteLengthError indicates found disallowed indefinite-length items. type IndefiniteLengthError struct { t cborType } @@ -113,7 +113,7 @@ func (d *decoder) wellformedInternal(depth int, checkBuiltinTags bool) (int, err } return d.wellformedIndefiniteString(t, depth, checkBuiltinTags) } - valInt := int(val) + valInt := int(val) //nolint:gosec if valInt < 0 { // Detect integer overflow return 0, errors.New("cbor: " + t.String() + " length " + strconv.FormatUint(val, 10) + " is too large, causing integer overflow") @@ -136,7 +136,7 @@ func (d *decoder) wellformedInternal(depth int, checkBuiltinTags bool) (int, err return d.wellformedIndefiniteArrayOrMap(t, depth, checkBuiltinTags) } - valInt := int(val) + valInt := int(val) //nolint:gosec if valInt < 0 { // Detect integer overflow return 0, errors.New("cbor: " + t.String() + " length " + strconv.FormatUint(val, 10) + " is too large, it would cause integer overflow") @@ -212,7 +212,7 @@ func (d *decoder) wellformedInternal(depth int, checkBuiltinTags bool) (int, err return depth, nil } -// wellformedIndefiniteString checks indefinite length byte/text string's well-formedness and returns max depth and error. +// wellformedIndefiniteString checks indefinite-length byte/text string's well-formedness and returns max depth and error. func (d *decoder) wellformedIndefiniteString(t cborType, depth int, checkBuiltinTags bool) (int, error) { var err error for { @@ -223,7 +223,7 @@ func (d *decoder) wellformedIndefiniteString(t cborType, depth int, checkBuiltin d.off++ break } - // Peek ahead to get next type and indefinite length status. + // Peek ahead to get next type and indefinite-length status. nt, ai := parseInitialByte(d.data[d.off]) if t != nt { return 0, &SyntaxError{"cbor: wrong element type " + nt.String() + " for indefinite-length " + t.String()} @@ -238,7 +238,7 @@ func (d *decoder) wellformedIndefiniteString(t cborType, depth int, checkBuiltin return depth, nil } -// wellformedIndefiniteArrayOrMap checks indefinite length array/map's well-formedness and returns max depth and error. +// wellformedIndefiniteArrayOrMap checks indefinite-length array/map's well-formedness and returns max depth and error. func (d *decoder) wellformedIndefiniteArrayOrMap(t cborType, depth int, checkBuiltinTags bool) (int, error) { var err error maxDepth := depth @@ -326,7 +326,7 @@ func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error) val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+argumentSize])) d.off += argumentSize if t == cborTypePrimitives { - if err := d.acceptableFloat(float64(float16.Frombits(uint16(val)).Float32())); err != nil { + if err := d.acceptableFloat(float64(float16.Frombits(uint16(val)).Float32())); err != nil { //nolint:gosec return 0, 0, 0, err } } @@ -341,7 +341,7 @@ func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error) val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+argumentSize])) d.off += argumentSize if t == cborTypePrimitives { - if err := d.acceptableFloat(float64(math.Float32frombits(uint32(val)))); err != nil { + if err := d.acceptableFloat(float64(math.Float32frombits(uint32(val)))); err != nil { //nolint:gosec return 0, 0, 0, err } } @@ -379,12 +379,12 @@ func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error) func (d *decoder) acceptableFloat(f float64) error { switch { - case d.dm.nanDec == NaNDecodeForbidden && math.IsNaN(f): + case d.dm.nan == NaNDecodeForbidden && math.IsNaN(f): return &UnacceptableDataItemError{ CBORType: cborTypePrimitives.String(), Message: "floating-point NaN", } - case d.dm.infDec == InfDecodeForbidden && math.IsInf(f, 0): + case d.dm.inf == InfDecodeForbidden && math.IsInf(f, 0): return &UnacceptableDataItemError{ CBORType: cborTypePrimitives.String(), Message: "floating-point infinity", diff --git a/vendor/github.com/go-openapi/jsonpointer/.gitignore b/vendor/github.com/go-openapi/jsonpointer/.gitignore index 769c24400..d8f4186fe 100644 --- a/vendor/github.com/go-openapi/jsonpointer/.gitignore +++ b/vendor/github.com/go-openapi/jsonpointer/.gitignore @@ -1 +1,5 @@ -secrets.yml +*.out +*.cov +.idea +.env +.mcp.json diff --git a/vendor/github.com/go-openapi/jsonpointer/.golangci.yml b/vendor/github.com/go-openapi/jsonpointer/.golangci.yml index d2fafb8a2..dc7c96053 100644 --- a/vendor/github.com/go-openapi/jsonpointer/.golangci.yml +++ b/vendor/github.com/go-openapi/jsonpointer/.golangci.yml @@ -1,56 +1,67 @@ -linters-settings: - gocyclo: - min-complexity: 45 - dupl: - threshold: 200 - goconst: - min-len: 2 - min-occurrences: 3 - +version: "2" linters: - enable-all: true + default: all disable: - - recvcheck - - unparam - - lll - - gochecknoinits - - gochecknoglobals + - depguard - funlen - godox - - gocognit - - whitespace - - wsl - - wrapcheck - - testpackage + - exhaustruct - nlreturn - - errorlint - - nestif - - godot - - gofumpt + - nonamedreturns + - noinlineerr - paralleltest - - tparallel + - recvcheck + - testpackage - thelper - - exhaustruct + - tparallel - varnamelen - - gci - - depguard - - errchkjson - - inamedparam - - nonamedreturns - - musttag - - ireturn - - forcetypeassert - - cyclop - # deprecated linters - #- deadcode - #- interfacer - #- scopelint - #- varcheck - #- structcheck - #- golint - #- nosnakecase - #- maligned - #- goerr113 - #- ifshort - #- gomnd - #- exhaustivestruct + - whitespace + - wrapcheck + - wsl + - wsl_v5 + settings: + dupl: + threshold: 200 + goconst: + min-len: 2 + min-occurrences: 3 + cyclop: + max-complexity: 20 + gocyclo: + min-complexity: 20 + exhaustive: + default-signifies-exhaustive: true + default-case-required: true + lll: + line-length: 180 + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + - gofumpt + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ +issues: + # Maximum issues count per one linter. + # Set to 0 to disable. + # Default: 50 + max-issues-per-linter: 0 + # Maximum count of issues with the same text. + # Set to 0 to disable. + # Default: 3 + max-same-issues: 0 diff --git a/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md index 9322b065e..bac878f21 100644 --- a/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md +++ b/vendor/github.com/go-openapi/jsonpointer/CODE_OF_CONDUCT.md @@ -23,7 +23,9 @@ include: Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or + advances + * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic @@ -55,7 +57,7 @@ further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at ivan+abuse@flanders.co.nz. All +reported by contacting the project team at . All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. @@ -68,7 +70,7 @@ members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] +available at [][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md b/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md new file mode 100644 index 000000000..9990f4a35 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/CONTRIBUTORS.md @@ -0,0 +1,25 @@ +# Contributors + +- Repository: ['go-openapi/jsonpointer'] + +| Total Contributors | Total Contributions | +| --- | --- | +| 13 | 111 | + +| Username | All Time Contribution Count | All Commits | +| --- | --- | --- | +| @fredbi | 63 | | +| @casualjim | 33 | | +| @magodo | 3 | | +| @youyuanwu | 3 | | +| @gaiaz-iusipov | 1 | | +| @gbjk | 1 | | +| @gordallott | 1 | | +| @ianlancetaylor | 1 | | +| @mfleader | 1 | | +| @Neo2308 | 1 | | +| @alexandear | 1 | | +| @olivierlemasle | 1 | | +| @testwill | 1 | | + + _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/jsonpointer/LICENSE b/vendor/github.com/go-openapi/jsonpointer/LICENSE index d64569567..261eeb9e9 100644 --- a/vendor/github.com/go-openapi/jsonpointer/LICENSE +++ b/vendor/github.com/go-openapi/jsonpointer/LICENSE @@ -1,4 +1,3 @@ - Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/vendor/github.com/go-openapi/jsonpointer/NOTICE b/vendor/github.com/go-openapi/jsonpointer/NOTICE new file mode 100644 index 000000000..201908d2f --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/NOTICE @@ -0,0 +1,39 @@ +Copyright 2015-2025 go-swagger maintainers + +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +This software library, github.com/go-openapi/jsonpointer, includes software developed +by the go-swagger and go-openapi maintainers ("go-swagger maintainers"). + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this software except in compliance with the License. + +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0. + +This software is copied from, derived from, and inspired by other original software products. +It ships with copies of other software which license terms are recalled below. + +The original software was authored on 25-02-2013 by sigu-399 (https://github.com/sigu-399, sigu.399@gmail.com). + +github.com/sigu-399/jsonpointer +=========================== + +// SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) +// SPDX-License-Identifier: Apache-2.0 + +Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) + +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/vendor/github.com/go-openapi/jsonpointer/README.md b/vendor/github.com/go-openapi/jsonpointer/README.md index 0108f1d57..24fbe1bf6 100644 --- a/vendor/github.com/go-openapi/jsonpointer/README.md +++ b/vendor/github.com/go-openapi/jsonpointer/README.md @@ -1,19 +1,168 @@ -# gojsonpointer [![Build Status](https://github.com/go-openapi/jsonpointer/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/jsonpointer/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/jsonpointer/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonpointer) +# jsonpointer -[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) -[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonpointer/master/LICENSE) -[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/jsonpointer.svg)](https://pkg.go.dev/github.com/go-openapi/jsonpointer) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/jsonpointer)](https://goreportcard.com/report/github.com/go-openapi/jsonpointer) + +[![Tests][test-badge]][test-url] [![Coverage][cov-badge]][cov-url] [![CI vuln scan][vuln-scan-badge]][vuln-scan-url] [![CodeQL][codeql-badge]][codeql-url] + + + +[![Release][release-badge]][release-url] [![Go Report Card][gocard-badge]][gocard-url] [![CodeFactor Grade][codefactor-badge]][codefactor-url] [![License][license-badge]][license-url] + + +[![GoDoc][godoc-badge]][godoc-url] [![Discord Channel][discord-badge]][discord-url] [![go version][goversion-badge]][goversion-url] ![Top language][top-badge] ![Commits since latest release][commits-badge] -An implementation of JSON Pointer - Go language +--- + +An implementation of JSON Pointer for golang, which supports go `struct`. + +## Announcements + +* **2026-04-15** : added support for trailing "-" for arrays (v0.23.0) + * this brings full support of [RFC6901][RFC6901] + * this is supported for types relying on the reflection-based implemented + * API semantics remain essentially unaltered. Exception: `Pointer.Set(document any,value any) (document any, err error)` + can only perform a best-effort to mutate the input document in place. In the case of adding elements to an array with a + trailing "-", either pass a mutable array (`*[]T`) as the input document, or use the returned updated document instead. + * types that implement the `JSONSetable` interface may not implement the mutation implied by the trailing "-" + +* **2026-04-15** : added support for optional alternate JSON name providers + * for struct support the defaults might not suit all situations: there are known limitations + when it comes to handle untagged fields or embedded types. + * the default name provider in use is not fully aligned with go JSON stdlib + * exposed an option (or global setting) to change the provider that resolves a struct into json keys + * the default behavior is not altered + * a new alternate name provider is added (imported from `go-openapi/swag/jsonname`), aligned with JSON stdlib behavior ## Status -Completed YES -Tested YES +API is stable and feature-complete. + +## Import this library in your project + +```cmd +go get github.com/go-openapi/jsonpointer +``` + +## Basic usage + +See also some [examples](./examples_test.go) + +### Retrieving a value + +```go + import ( + "github.com/go-openapi/jsonpointer" + ) + + + var doc any + + ... + + pointer, err := jsonpointer.New("/foo/1") + if err != nil { + ... // error: e.g. invalid JSON pointer specification + } + + value, kind, err := pointer.Get(doc) + if err != nil { + ... // error: e.g. key not found, index out of bounds, etc. + } + + ... +``` + +### Setting a value + +```go + ... + var doc any + ... + pointer, err := jsonpointer.New("/foo/1") + if err != nil { + ... // error: e.g. invalid JSON pointer specification + } + + doc, err = p.Set(doc, "value") + if err != nil { + ... // error: e.g. key not found, index out of bounds, etc. + } +``` + +## Change log + +See ## References -http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07 -### Note -The 4.Evaluation part of the previous reference, starting with 'If the currently referenced value is a JSON array, the reference token MUST contain either...' is not implemented. + + +also known as [RFC6901][RFC6901]. + +## Licensing + +This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). + +See the license [NOTICE](./NOTICE), which recalls the licensing terms of all the pieces of software +on top of which it has been built. + +## Limitations + +* [RFC6901][RFC6901] is now fully supported, including trailing "-" semantics for arrays (for `Set` operations). +* Default behavior: JSON name detection in go `struct`s + - Unlike go standard marshaling, untagged fields do not default to the go field name and are ignored. + - anonymous fields are not traversed if untagged + - the above limitations may be overcome by calling `UseGoNameProvider()` at initialization time. + - alternatively, users may inject the desired custom behavior for naming fields as an option. + +## Other documentation + +* [All-time contributors](./CONTRIBUTORS.md) +* [Contributing guidelines][contributing-doc-site] +* [Maintainers documentation][maintainers-doc-site] +* [Code style][style-doc-site] + +## Cutting a new release + +Maintainers can cut a new release by either: + +* running [this workflow](https://github.com/go-openapi/jsonpointer/actions/workflows/bump-release.yml) +* or pushing a semver tag + * signed tags are preferred + * The tag message is prepended to release notes + + +[test-badge]: https://github.com/go-openapi/jsonpointer/actions/workflows/go-test.yml/badge.svg +[test-url]: https://github.com/go-openapi/jsonpointer/actions/workflows/go-test.yml +[cov-badge]: https://codecov.io/gh/go-openapi/jsonpointer/branch/master/graph/badge.svg +[cov-url]: https://codecov.io/gh/go-openapi/jsonpointer +[vuln-scan-badge]: https://github.com/go-openapi/jsonpointer/actions/workflows/scanner.yml/badge.svg +[vuln-scan-url]: https://github.com/go-openapi/jsonpointer/actions/workflows/scanner.yml +[codeql-badge]: https://github.com/go-openapi/jsonpointer/actions/workflows/codeql.yml/badge.svg +[codeql-url]: https://github.com/go-openapi/jsonpointer/actions/workflows/codeql.yml + +[release-badge]: https://badge.fury.io/gh/go-openapi%2Fjsonpointer.svg +[release-url]: https://badge.fury.io/gh/go-openapi%2Fjsonpointer + +[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/jsonpointer +[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/jsonpointer +[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/jsonpointer +[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/jsonpointer + +[godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/jsonpointer +[godoc-url]: http://pkg.go.dev/github.com/go-openapi/jsonpointer +[discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue +[discord-url]: https://discord.gg/FfnFYaC3k5 + + +[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg +[license-url]: https://github.com/go-openapi/jsonpointer/?tab=Apache-2.0-1-ov-file#readme + +[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/jsonpointer +[goversion-url]: https://github.com/go-openapi/jsonpointer/blob/master/go.mod +[top-badge]: https://img.shields.io/github/languages/top/go-openapi/jsonpointer +[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/jsonpointer/latest +[RFC6901]: https://www.rfc-editor.org/rfc/rfc6901 + +[contributing-doc-site]: https://go-openapi.github.io/doc-site/contributing/contributing/index.html +[maintainers-doc-site]: https://go-openapi.github.io/doc-site/maintainers/index.html +[style-doc-site]: https://go-openapi.github.io/doc-site/contributing/style/index.html diff --git a/vendor/github.com/go-openapi/jsonpointer/SECURITY.md b/vendor/github.com/go-openapi/jsonpointer/SECURITY.md new file mode 100644 index 000000000..1fea2c573 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/SECURITY.md @@ -0,0 +1,37 @@ +# Security Policy + +This policy outlines the commitment and practices of the go-openapi maintainers regarding security. + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| O.x | :white_check_mark: | + +## Vulnerability checks in place + +This repository uses automated vulnerability scans, at every merged commit and at least once a week. + +We use: + +* [`GitHub CodeQL`][codeql-url] +* [`trivy`][trivy-url] +* [`govulncheck`][govulncheck-url] + +Reports are centralized in github security reports and visible only to the maintainers. + +## Reporting a vulnerability + +If you become aware of a security vulnerability that affects the current repository, +**please report it privately to the maintainers** +rather than opening a publicly visible GitHub issue. + +Please follow the instructions provided by github to [Privately report a security vulnerability][github-guidance-url]. + +> [!NOTE] +> On Github, navigate to the project's "Security" tab then click on "Report a vulnerability". + +[codeql-url]: https://github.com/github/codeql +[trivy-url]: https://trivy.dev/docs/latest/getting-started +[govulncheck-url]: https://go.dev/blog/govulncheck +[github-guidance-url]: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability diff --git a/vendor/github.com/go-openapi/jsonpointer/errors.go b/vendor/github.com/go-openapi/jsonpointer/errors.go index b84343d9d..8813474d4 100644 --- a/vendor/github.com/go-openapi/jsonpointer/errors.go +++ b/vendor/github.com/go-openapi/jsonpointer/errors.go @@ -1,5 +1,10 @@ +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package jsonpointer +import "fmt" + type pointerError string func (e pointerError) Error() string { @@ -7,12 +12,48 @@ func (e pointerError) Error() string { } const ( - // ErrPointer is an error raised by the jsonpointer package + // ErrPointer is a sentinel error raised by all errors from this package. ErrPointer pointerError = "JSON pointer error" - // ErrInvalidStart states that a JSON pointer must start with a separator ("/") - ErrInvalidStart pointerError = `JSON pointer must be empty or start with a "` + pointerSeparator + // ErrInvalidStart states that a JSON pointer must start with a separator ("/"). + ErrInvalidStart pointerError = `JSON pointer must be empty or start with a "` + pointerSeparator + `"` - // ErrUnsupportedValueType indicates that a value of the wrong type is being set + // ErrUnsupportedValueType indicates that a value of the wrong type is being set. ErrUnsupportedValueType pointerError = "only structs, pointers, maps and slices are supported for setting values" + + // ErrDashToken indicates use of the RFC 6901 "-" reference token + // in a context where it cannot be resolved. + // + // Per RFC 6901 §4 the "-" token refers to the (nonexistent) element + // after the last array element. It may only be used as the terminal + // token of a [Pointer.Set] against a slice, where it means "append". + // Any other use (get, offset, intermediate traversal, non-slice target) + // is an error condition that wraps this sentinel. + ErrDashToken pointerError = `the "-" array token cannot be resolved here` //nolint:gosec // G101 false positive: this is a JSON Pointer reference token, not a credential. ) + +const dashToken = "-" + +func errNoKey(key string) error { + return fmt.Errorf("object has no key %q: %w", key, ErrPointer) +} + +func errOutOfBounds(length, idx int) error { + return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", length-1, idx, ErrPointer) +} + +func errInvalidReference(token string) error { + return fmt.Errorf("invalid token reference %q: %w", token, ErrPointer) +} + +func errDashOnGet() error { + return fmt.Errorf("cannot resolve %q token on get: %w: %w", dashToken, ErrDashToken, ErrPointer) +} + +func errDashIntermediate() error { + return fmt.Errorf("the %q token may only appear as the terminal token of a pointer: %w: %w", dashToken, ErrDashToken, ErrPointer) +} + +func errDashOnOffset() error { + return fmt.Errorf("cannot compute offset for %q token (nonexistent element): %w: %w", dashToken, ErrDashToken, ErrPointer) +} diff --git a/vendor/github.com/go-openapi/jsonpointer/ifaces.go b/vendor/github.com/go-openapi/jsonpointer/ifaces.go new file mode 100644 index 000000000..1e56ac044 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/ifaces.go @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonpointer + +import "reflect" + +// JSONPointable is an interface for structs to implement, +// when they need to customize the json pointer process or want to avoid the use of reflection. +type JSONPointable interface { + // JSONLookup returns a value pointed at this (unescaped) key. + JSONLookup(key string) (any, error) +} + +// JSONSetable is an interface for structs to implement, +// when they need to customize the json pointer process or want to avoid the use of reflection. +// +// # Handling of the RFC 6901 "-" token +// +// When a type implementing JSONSetable is the terminal parent of a [Pointer.Set] +// call, the library passes the raw reference token to JSONSet without +// interpretation. In particular, the RFC 6901 "-" token (which conventionally +// means "append" for arrays, per RFC 6902) is forwarded verbatim as the key +// argument. Implementations that model an array-like container are expected +// to give "-" the append semantics; implementations that do not should return +// an error wrapping [ErrDashToken] (or [ErrPointer]) for clarity. +// +// Implementations are responsible for any in-place mutation: the library does +// not attempt to rebind the result of JSONSet into a parent container. +type JSONSetable interface { + // JSONSet sets the value pointed at the (unescaped) key. + // + // The key may be the RFC 6901 "-" token when the pointer targets a + // slice-like member; see the interface documentation for details. + JSONSet(key string, value any) error +} + +// NameProvider knows how to resolve go struct fields into json names. +// +// The default provider is brought by [github.com/go-openapi/swag/jsonname.DefaultJSONNameProvider]. +type NameProvider interface { + // GetGoName gets the go name for a json property name + GetGoName(subject any, name string) (string, bool) + + // GetGoNameForType gets the go name for a given type for a json property name + GetGoNameForType(tpe reflect.Type, name string) (string, bool) +} diff --git a/vendor/github.com/go-openapi/jsonpointer/options.go b/vendor/github.com/go-openapi/jsonpointer/options.go new file mode 100644 index 000000000..d52caab22 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonpointer/options.go @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonpointer + +import ( + "sync" + + "github.com/go-openapi/swag/jsonname" +) + +// Option to tune the behavior of a JSON [Pointer]. +type Option func(*options) + +var ( + //nolint:gochecknoglobals // package level defaults are provided as a convenient, backward-compatible way to adopt options. + defaultOptions = options{ + provider: jsonname.DefaultJSONNameProvider, + } + //nolint:gochecknoglobals // guards defaultOptions against concurrent SetDefaultNameProvider / read races (testing) + defaultOptionsMu sync.RWMutex +) + +// SetDefaultNameProvider sets the [NameProvider] as a package-level default. +// +// By default, the default provider is [jsonname.DefaultJSONNameProvider]. +// +// It is safe to call concurrently with [Pointer.Get], [Pointer.Set], +// [GetForToken] and [SetForToken]. The typical usage is to call it once +// at initialization time. +// +// A nil provider is ignored. +func SetDefaultNameProvider(provider NameProvider) { + if provider == nil { + return + } + + defaultOptionsMu.Lock() + defer defaultOptionsMu.Unlock() + + defaultOptions.provider = provider +} + +// UseGoNameProvider sets the [NameProvider] as a package-level default +// to the alternative provider [jsonname.GoNameProvider], that covers a few areas +// not supported by the default name provider. +// +// This implementation supports untagged exported fields and embedded types in go struct. +// It follows strictly the behavior of the JSON standard library regarding field naming conventions. +// +// It is safe to call concurrently with [Pointer.Get], [Pointer.Set], +// [GetForToken] and [SetForToken]. The typical usage is to call it once +// at initialization time. +func UseGoNameProvider() { + SetDefaultNameProvider(jsonname.NewGoNameProvider()) +} + +// DefaultNameProvider returns the current package-level [NameProvider]. +func DefaultNameProvider() NameProvider { //nolint:ireturn // returning the interface is the point — callers pick their own implementation. + defaultOptionsMu.RLock() + defer defaultOptionsMu.RUnlock() + + return defaultOptions.provider +} + +// WithNameProvider injects a custom [NameProvider] to resolve json names from go struct types. +func WithNameProvider(provider NameProvider) Option { + return func(o *options) { + o.provider = provider + } +} + +type options struct { + provider NameProvider +} + +func optionsWithDefaults(opts []Option) options { + var o options + o.provider = DefaultNameProvider() + + for _, apply := range opts { + apply(&o) + } + + return o +} diff --git a/vendor/github.com/go-openapi/jsonpointer/pointer.go b/vendor/github.com/go-openapi/jsonpointer/pointer.go index a08cd68ac..2369c1827 100644 --- a/vendor/github.com/go-openapi/jsonpointer/pointer.go +++ b/vendor/github.com/go-openapi/jsonpointer/pointer.go @@ -1,28 +1,7 @@ -// Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) -// -// 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. - -// author sigu-399 -// author-github https://github.com/sigu-399 -// author-mail sigu.399@gmail.com -// -// repository-name jsonpointer -// repository-desc An implementation of JSON Pointer - Go language -// -// description Main and unique file. -// -// created 25-02-2013 +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 +// Package jsonpointer provides a golang implementation for json pointers. package jsonpointer import ( @@ -32,8 +11,6 @@ import ( "reflect" "strconv" "strings" - - "github.com/go-openapi/swag" ) const ( @@ -41,70 +18,429 @@ const ( pointerSeparator = `/` ) -var jsonPointableType = reflect.TypeOf(new(JSONPointable)).Elem() -var jsonSetableType = reflect.TypeOf(new(JSONSetable)).Elem() - -// JSONPointable is an interface for structs to implement when they need to customize the -// json pointer process -type JSONPointable interface { - JSONLookup(string) (any, error) -} - -// JSONSetable is an interface for structs to implement when they need to customize the -// json pointer process -type JSONSetable interface { - JSONSet(string, any) error +// Pointer is a representation of a json pointer. +// +// Use [Pointer.Get] to retrieve a value or [Pointer.Set] to set a value. +// +// It works with any go type interpreted as a JSON document, which means: +// +// - if a type implements [JSONPointable], its [JSONPointable.JSONLookup] method is used to resolve [Pointer.Get] +// - if a type implements [JSONSetable], its [JSONSetable.JSONSet] method is used to resolve [Pointer.Set] +// - a go map[K]V is interpreted as an object, with type K assignable to a string +// - a go slice []T is interpreted as an array +// - a go struct is interpreted as an object, with exported fields interpreted as keys +// - promoted fields from an embedded struct are traversed +// - scalars (e.g. int, float64 ...), channels, functions and go arrays cannot be traversed +// +// For struct s resolved by reflection, key mappings honor the conventional struct tag `json`. +// +// Fields that do not specify a `json` tag, or specify an empty one, or are tagged as `json:"-"` are ignored. +// +// # Limitations +// +// - Unlike go standard marshaling, untagged fields do not default to the go field name and are ignored. +// - anonymous fields are not traversed if untagged +type Pointer struct { + referenceTokens []string } -// New creates a new json pointer for the given string +// New creates a new json pointer from its string representation. func New(jsonPointerString string) (Pointer, error) { - var p Pointer err := p.parse(jsonPointerString) + return p, err +} +// Get uses the pointer to retrieve a value from a JSON document. +// +// It returns the value with its type as a [reflect.Kind] or an error. +func (p *Pointer) Get(document any, opts ...Option) (any, reflect.Kind, error) { + o := optionsWithDefaults(opts) + + return p.get(document, o.provider) } -// Pointer the json pointer reprsentation -type Pointer struct { - referenceTokens []string +// Set uses the pointer to set a value from a data type +// that represent a JSON document. +// +// # Mutation contract +// +// Set mutates the provided document in place whenever Go's type system allows +// it: when document is a map, a pointer, or when the targeted value is reached +// through an addressable ancestor (e.g. a struct field traversed via a pointer, +// a slice element). Callers that rely on this in-place behavior may continue +// to ignore the returned document. +// +// The returned document is only load-bearing when Set cannot mutate in place. +// This happens in one specific case: appending to a top-level slice passed by +// value (e.g. document of type []T rather than *[]T) via the RFC 6901 "-" +// terminal token. reflect.Append produces a new slice header that the library +// cannot rebind into the caller's variable; the updated document is returned +// instead. Pass *[]T if you want in-place rebind for that case as well. +// +// See [ErrDashToken] for the semantics of the "-" token. +func (p *Pointer) Set(document any, value any, opts ...Option) (any, error) { + o := optionsWithDefaults(opts) + + return p.set(document, value, o.provider) } -// "Constructor", parses the given string JSON pointer +// DecodedTokens returns the decoded (unescaped) tokens of this JSON pointer. +func (p *Pointer) DecodedTokens() []string { + result := make([]string, 0, len(p.referenceTokens)) + for _, token := range p.referenceTokens { + result = append(result, Unescape(token)) + } + + return result +} + +// IsEmpty returns true if this is an empty json pointer. +// +// This indicates that it points to the root document. +func (p *Pointer) IsEmpty() bool { + return len(p.referenceTokens) == 0 +} + +// String representation of a pointer. +func (p *Pointer) String() string { + if len(p.referenceTokens) == 0 { + return emptyPointer + } + + return pointerSeparator + strings.Join(p.referenceTokens, pointerSeparator) +} + +// Offset returns the byte offset, in the raw JSON text of document, of the +// location referenced by this pointer's terminal token. +// +// Unlike [Pointer.Get] and [Pointer.Set], which operate on a decoded Go value, +// Offset operates directly on the textual JSON source. It drives an +// [encoding/json.Decoder] over the string and stops at the terminal token, +// returning the position at which the decoder was about to read that token. +// +// It is primarily intended for tooling that needs to map a pointer back to a +// region of the original source: reporting line/column for validation or +// parse diagnostics, extracting a sub-document by slicing the raw bytes, or +// highlighting the referenced span in an editor. +// +// # Offset semantics +// +// The meaning of the returned offset depends on whether the terminal token +// addresses an object property or an array element: +// +// - Object property: the offset points to the first byte of the key (its +// opening quote character), not to the associated value. For example, +// pointer "/foo/bar" against {"foo": {"bar": 21}} returns 9, the index of +// the opening quote of "bar". +// - Array element: the offset points to the first byte of the value at that +// index. For example, pointer "/0/1" against [[1,2], [3,4]] returns 4, +// the index of the digit 2. +// +// # Errors +// +// Offset returns an error in any of these cases: +// +// - document is not syntactically valid JSON; +// - the structure of document does not match the pointer (e.g. traversing +// into a scalar, or a token that is neither a valid key nor a valid +// numeric index); +// - a referenced key or index does not exist in document; +// - the pointer's terminal token is the RFC 6901 "-" array token, which +// designates a nonexistent element and therefore has no offset in the +// source. The returned error wraps [ErrDashToken]. +// +// All errors wrap [ErrPointer]. +func (p *Pointer) Offset(document string) (int64, error) { + dec := json.NewDecoder(strings.NewReader(document)) + var offset int64 + for _, ttk := range p.DecodedTokens() { + tk, err := dec.Token() + if err != nil { + return 0, err + } + switch tk := tk.(type) { + case json.Delim: + switch tk { + case '{': + offset, err = offsetSingleObject(dec, ttk) + if err != nil { + return 0, err + } + case '[': + offset, err = offsetSingleArray(dec, ttk) + if err != nil { + return 0, err + } + default: + return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer) + } + default: + return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer) + } + } + return skipJSONSeparator(document, offset), nil +} + +// skipJSONSeparator advances offset past trailing JSON whitespace and at most +// one value separator (comma) in document, so the result points at the first +// byte of the next JSON token. +// +// The streaming decoder's InputOffset sits right after the most recently +// consumed token, which between values is the comma (or whitespace) — not +// the following token. Normalizing here keeps Offset's contract uniform: +// for both object keys and array elements, and regardless of position within +// the parent container, the returned offset always points at the first byte +// of the addressed token. +func skipJSONSeparator(document string, offset int64) int64 { + n := int64(len(document)) + for offset < n && isJSONWhitespace(document[offset]) { + offset++ + } + if offset < n && document[offset] == ',' { + offset++ + } + for offset < n && isJSONWhitespace(document[offset]) { + offset++ + } + return offset +} + +func isJSONWhitespace(c byte) bool { + return c == ' ' || c == '\t' || c == '\n' || c == '\r' +} + +// "Constructor", parses the given string JSON pointer. func (p *Pointer) parse(jsonPointerString string) error { + if jsonPointerString == emptyPointer { + return nil + } + + if !strings.HasPrefix(jsonPointerString, pointerSeparator) { + // non empty pointer must start with "/" + return errors.Join(ErrInvalidStart, ErrPointer) + } - var err error + referenceTokens := strings.Split(jsonPointerString, pointerSeparator) + p.referenceTokens = append(p.referenceTokens, referenceTokens[1:]...) - if jsonPointerString != emptyPointer { - if !strings.HasPrefix(jsonPointerString, pointerSeparator) { - err = errors.Join(ErrInvalidStart, ErrPointer) - } else { - referenceTokens := strings.Split(jsonPointerString, pointerSeparator) - p.referenceTokens = append(p.referenceTokens, referenceTokens[1:]...) + return nil +} + +func (p *Pointer) get(node any, nameProvider NameProvider) (any, reflect.Kind, error) { + if nameProvider == nil { + nameProvider = defaultOptions.provider + } + + kind := reflect.Invalid + + // full document when empty + if len(p.referenceTokens) == 0 { + return node, kind, nil + } + + for _, token := range p.referenceTokens { + decodedToken := Unescape(token) + + r, knd, err := getSingleImpl(node, decodedToken, nameProvider) + if err != nil { + return nil, knd, err } + node = r } - return err + rValue := reflect.ValueOf(node) + kind = rValue.Kind() + + return node, kind, nil } -// Get uses the pointer to retrieve a value from a JSON document -func (p *Pointer) Get(document any) (any, reflect.Kind, error) { - return p.get(document, swag.DefaultJSONNameProvider) +func (p *Pointer) set(node, data any, nameProvider NameProvider) (any, error) { + knd := reflect.ValueOf(node).Kind() + + if knd != reflect.Pointer && knd != reflect.Struct && knd != reflect.Map && knd != reflect.Slice && knd != reflect.Array { + return node, errors.Join( + fmt.Errorf("unexpected type: %T", node), //nolint:err113 // err wrapping is carried out by errors.Join, not fmt.Errorf. + ErrUnsupportedValueType, + ErrPointer, + ) + } + + // full document when empty + if len(p.referenceTokens) == 0 { + return node, nil + } + + if nameProvider == nil { + nameProvider = defaultOptions.provider + } + + return p.setAt(node, p.referenceTokens, data, nameProvider) } -// Set uses the pointer to set a value from a JSON document -func (p *Pointer) Set(document any, value any) (any, error) { - return document, p.set(document, value, swag.DefaultJSONNameProvider) +// setAt recursively walks the token list, setting the data at the terminal +// token and rebinding any new child reference (e.g. a slice header returned +// by an "-" append) into its parent on the way back up. +// +// Returning the (possibly new) node at each level is what makes append work +// at any depth without requiring the caller to pass a pointer to the +// containing slice: the new slice header propagates up and each parent +// rebinds it via the appropriate kind-specific setter. +func (p *Pointer) setAt(node any, tokens []string, data any, nameProvider NameProvider) (any, error) { + decodedToken := Unescape(tokens[0]) + + if len(tokens) == 1 { + return setSingleImpl(node, data, decodedToken, nameProvider) + } + + child, err := p.resolveNodeForToken(node, decodedToken, nameProvider) + if err != nil { + return node, err + } + + newChild, err := p.setAt(child, tokens[1:], data, nameProvider) + if err != nil { + return node, err + } + + return rebindChild(node, decodedToken, newChild, nameProvider) } -// GetForToken gets a value for a json pointer token 1 level deep -func GetForToken(document any, decodedToken string) (any, reflect.Kind, error) { - return getSingleImpl(document, decodedToken, swag.DefaultJSONNameProvider) +// rebindChild writes newChild back into node at decodedToken. +// +// For cases where the child was already mutated in place (pointer aliasing, +// addressable slice elements) the rebind is a safe no-op. For cases where +// the child was returned by value (map entries holding a slice, slices +// reached through a non-addressable ancestor), the rebind propagates the +// new value into the parent. +// +// Parents implementing [JSONPointable] are left alone: they took ownership +// of the child via JSONLookup and did not opt into a JSONSet-based rebind +// on intermediate tokens. +func rebindChild(node any, decodedToken string, newChild any, nameProvider NameProvider) (any, error) { + if _, ok := node.(JSONPointable); ok { + return node, nil + } + + rValue := reflect.Indirect(reflect.ValueOf(node)) + + switch rValue.Kind() { + case reflect.Struct: + nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) + if !ok { + return node, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) + } + fld := rValue.FieldByName(nm) + if !fld.CanSet() { + return node, nil + } + assignReflectValue(fld, newChild) + return node, nil + + case reflect.Map: + rValue.SetMapIndex(reflect.ValueOf(decodedToken), reflect.ValueOf(newChild)) + return node, nil + + case reflect.Slice: + if decodedToken == dashToken { + return node, errDashIntermediate() + } + idx, err := strconv.Atoi(decodedToken) + if err != nil { + return node, errors.Join(err, ErrPointer) + } + elem := rValue.Index(idx) + if !elem.CanSet() { + return node, nil + } + assignReflectValue(elem, newChild) + return node, nil + + default: + return node, errInvalidReference(decodedToken) + } } -// SetForToken gets a value for a json pointer token 1 level deep -func SetForToken(document any, decodedToken string, value any) (any, error) { - return document, setSingleImpl(document, value, decodedToken, swag.DefaultJSONNameProvider) +// assignReflectValue assigns src into dst, unwrapping a pointer when dst +// expects the pointee type. This tolerates the pointer-wrapping performed +// by [typeFromValue] for addressable fields. +func assignReflectValue(dst reflect.Value, src any) { + nv := reflect.ValueOf(src) + if !nv.IsValid() { + return + } + if nv.Type().AssignableTo(dst.Type()) { + dst.Set(nv) + return + } + if nv.Kind() == reflect.Pointer && nv.Elem().Type().AssignableTo(dst.Type()) { + dst.Set(nv.Elem()) + } +} + +func (p *Pointer) resolveNodeForToken(node any, decodedToken string, nameProvider NameProvider) (next any, err error) { + // check for nil during traversal + if isNil(node) { + return nil, fmt.Errorf("cannot traverse through nil value at %q: %w", decodedToken, ErrPointer) + } + + pointable, ok := node.(JSONPointable) + if ok { + r, err := pointable.JSONLookup(decodedToken) + if err != nil { + return nil, err + } + + fld := reflect.ValueOf(r) + if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Pointer { + return fld.Addr().Interface(), nil + } + + return r, nil + } + + rValue := reflect.Indirect(reflect.ValueOf(node)) + kind := rValue.Kind() + + switch kind { + case reflect.Struct: + nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) + if !ok { + return nil, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) + } + + return typeFromValue(rValue.FieldByName(nm)), nil + + case reflect.Map: + kv := reflect.ValueOf(decodedToken) + mv := rValue.MapIndex(kv) + + if !mv.IsValid() { + return nil, errNoKey(decodedToken) + } + + return typeFromValue(mv), nil + + case reflect.Slice: + if decodedToken == dashToken { + return nil, errDashIntermediate() + } + tokenIndex, err := strconv.Atoi(decodedToken) + if err != nil { + return nil, errors.Join(err, ErrPointer) + } + + sLength := rValue.Len() + if tokenIndex < 0 || tokenIndex >= sLength { + return nil, errOutOfBounds(sLength, tokenIndex) + } + + return typeFromValue(rValue.Index(tokenIndex)), nil + + default: + return nil, errInvalidReference(decodedToken) + } } func isNil(input any) bool { @@ -113,15 +449,40 @@ func isNil(input any) bool { } kind := reflect.TypeOf(input).Kind() - switch kind { //nolint:exhaustive - case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Chan: + switch kind { + case reflect.Pointer, reflect.Map, reflect.Slice, reflect.Chan: return reflect.ValueOf(input).IsNil() default: return false } } -func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvider) (any, reflect.Kind, error) { +func typeFromValue(v reflect.Value) any { + if v.CanAddr() && v.Kind() != reflect.Interface && v.Kind() != reflect.Map && v.Kind() != reflect.Slice && v.Kind() != reflect.Pointer { + return v.Addr().Interface() + } + + return v.Interface() +} + +// GetForToken gets a value for a json pointer token 1 level deep. +func GetForToken(document any, decodedToken string, opts ...Option) (any, reflect.Kind, error) { + o := optionsWithDefaults(opts) + + return getSingleImpl(document, decodedToken, o.provider) +} + +// SetForToken sets a value for a json pointer token 1 level deep. +// +// See [Pointer.Set] for the mutation contract, in particular the handling of +// the RFC 6901 "-" token on slices. +func SetForToken(document any, decodedToken string, value any, opts ...Option) (any, error) { + o := optionsWithDefaults(opts) + + return setSingleImpl(document, value, decodedToken, o.provider) +} + +func getSingleImpl(node any, decodedToken string, nameProvider NameProvider) (any, reflect.Kind, error) { rValue := reflect.Indirect(reflect.ValueOf(node)) kind := rValue.Kind() if isNil(node) { @@ -139,13 +500,15 @@ func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvide return getSingleImpl(*typed, decodedToken, nameProvider) } - switch kind { //nolint:exhaustive + switch kind { case reflect.Struct: nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) if !ok { return nil, kind, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) } + fld := rValue.FieldByName(nm) + return fld.Interface(), kind, nil case reflect.Map: @@ -155,297 +518,164 @@ func getSingleImpl(node any, decodedToken string, nameProvider *swag.NameProvide if mv.IsValid() { return mv.Interface(), kind, nil } - return nil, kind, fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer) + + return nil, kind, errNoKey(decodedToken) case reflect.Slice: + if decodedToken == dashToken { + return nil, kind, errDashOnGet() + } tokenIndex, err := strconv.Atoi(decodedToken) if err != nil { - return nil, kind, err + return nil, kind, errors.Join(err, ErrPointer) } sLength := rValue.Len() if tokenIndex < 0 || tokenIndex >= sLength { - return nil, kind, fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength-1, tokenIndex, ErrPointer) + return nil, kind, errOutOfBounds(sLength, tokenIndex) } elem := rValue.Index(tokenIndex) return elem.Interface(), kind, nil default: - return nil, kind, fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer) + return nil, kind, errInvalidReference(decodedToken) } - } -func setSingleImpl(node, data any, decodedToken string, nameProvider *swag.NameProvider) error { - rValue := reflect.Indirect(reflect.ValueOf(node)) - - if ns, ok := node.(JSONSetable); ok { // pointer impl - return ns.JSONSet(decodedToken, data) +func setSingleImpl(node, data any, decodedToken string, nameProvider NameProvider) (any, error) { + // check for nil to prevent panic when calling rValue.Type() + if isNil(node) { + return node, fmt.Errorf("cannot set field %q on nil value: %w", decodedToken, ErrPointer) } - if rValue.Type().Implements(jsonSetableType) { - return node.(JSONSetable).JSONSet(decodedToken, data) + if ns, ok := node.(JSONSetable); ok { + return node, ns.JSONSet(decodedToken, data) } - switch rValue.Kind() { //nolint:exhaustive + rValue := reflect.Indirect(reflect.ValueOf(node)) + + switch rValue.Kind() { case reflect.Struct: nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) if !ok { - return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) + return node, fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) } + fld := rValue.FieldByName(nm) - if fld.IsValid() { - fld.Set(reflect.ValueOf(data)) + if !fld.CanSet() { + return node, fmt.Errorf("can't set struct field %s to %v: %w", nm, data, ErrPointer) + } + + value := reflect.ValueOf(data) + valueType := value.Type() + assignedType := fld.Type() + + if !valueType.AssignableTo(assignedType) { + return node, fmt.Errorf("can't set value with type %T to field %s with type %v: %w", data, nm, assignedType, ErrPointer) } - return nil + + fld.Set(value) + + return node, nil case reflect.Map: kv := reflect.ValueOf(decodedToken) rValue.SetMapIndex(kv, reflect.ValueOf(data)) - return nil + + return node, nil case reflect.Slice: + if decodedToken == dashToken { + // RFC 6901 §4 / RFC 6902 append semantics: terminal "-" appends + // the value to the slice. We rebind in place when the slice is + // reachable via an addressable ancestor; otherwise we return the + // new slice header for the parent (or the public Set) to rebind. + value := reflect.ValueOf(data) + elemType := rValue.Type().Elem() + if !value.Type().AssignableTo(elemType) { + return node, fmt.Errorf("can't append value of type %T to slice of %v: %w", data, elemType, ErrPointer) + } + newSlice := reflect.Append(rValue, value) + if rValue.CanSet() { + rValue.Set(newSlice) + return node, nil + } + return newSlice.Interface(), nil + } + tokenIndex, err := strconv.Atoi(decodedToken) if err != nil { - return err + return node, errors.Join(err, ErrPointer) } + sLength := rValue.Len() if tokenIndex < 0 || tokenIndex >= sLength { - return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer) + return node, errOutOfBounds(sLength, tokenIndex) } elem := rValue.Index(tokenIndex) if !elem.CanSet() { - return fmt.Errorf("can't set slice index %s to %v: %w", decodedToken, data, ErrPointer) - } - elem.Set(reflect.ValueOf(data)) - return nil - - default: - return fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer) - } - -} - -func (p *Pointer) get(node any, nameProvider *swag.NameProvider) (any, reflect.Kind, error) { - - if nameProvider == nil { - nameProvider = swag.DefaultJSONNameProvider - } - - kind := reflect.Invalid - - // Full document when empty - if len(p.referenceTokens) == 0 { - return node, kind, nil - } - - for _, token := range p.referenceTokens { - decodedToken := Unescape(token) - - r, knd, err := getSingleImpl(node, decodedToken, nameProvider) - if err != nil { - return nil, knd, err - } - node = r - } - - rValue := reflect.ValueOf(node) - kind = rValue.Kind() - - return node, kind, nil -} - -func (p *Pointer) set(node, data any, nameProvider *swag.NameProvider) error { - knd := reflect.ValueOf(node).Kind() - - if knd != reflect.Ptr && knd != reflect.Struct && knd != reflect.Map && knd != reflect.Slice && knd != reflect.Array { - return errors.Join( - ErrUnsupportedValueType, - ErrPointer, - ) - } - - if nameProvider == nil { - nameProvider = swag.DefaultJSONNameProvider - } - - // Full document when empty - if len(p.referenceTokens) == 0 { - return nil - } - - lastI := len(p.referenceTokens) - 1 - for i, token := range p.referenceTokens { - isLastToken := i == lastI - decodedToken := Unescape(token) - - if isLastToken { - - return setSingleImpl(node, data, decodedToken, nameProvider) + return node, fmt.Errorf("can't set slice index %s to %v: %w", decodedToken, data, ErrPointer) } - rValue := reflect.Indirect(reflect.ValueOf(node)) - kind := rValue.Kind() + value := reflect.ValueOf(data) + valueType := value.Type() + assignedType := elem.Type() - if rValue.Type().Implements(jsonPointableType) { - r, err := node.(JSONPointable).JSONLookup(decodedToken) - if err != nil { - return err - } - fld := reflect.ValueOf(r) - if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Ptr { - node = fld.Addr().Interface() - continue - } - node = r - continue + if !valueType.AssignableTo(assignedType) { + return node, fmt.Errorf("can't set value with type %T to slice element %d with type %v: %w", data, tokenIndex, assignedType, ErrPointer) } - switch kind { //nolint:exhaustive - case reflect.Struct: - nm, ok := nameProvider.GetGoNameForType(rValue.Type(), decodedToken) - if !ok { - return fmt.Errorf("object has no field %q: %w", decodedToken, ErrPointer) - } - fld := rValue.FieldByName(nm) - if fld.CanAddr() && fld.Kind() != reflect.Interface && fld.Kind() != reflect.Map && fld.Kind() != reflect.Slice && fld.Kind() != reflect.Ptr { - node = fld.Addr().Interface() - continue - } - node = fld.Interface() - - case reflect.Map: - kv := reflect.ValueOf(decodedToken) - mv := rValue.MapIndex(kv) - - if !mv.IsValid() { - return fmt.Errorf("object has no key %q: %w", decodedToken, ErrPointer) - } - if mv.CanAddr() && mv.Kind() != reflect.Interface && mv.Kind() != reflect.Map && mv.Kind() != reflect.Slice && mv.Kind() != reflect.Ptr { - node = mv.Addr().Interface() - continue - } - node = mv.Interface() - - case reflect.Slice: - tokenIndex, err := strconv.Atoi(decodedToken) - if err != nil { - return err - } - sLength := rValue.Len() - if tokenIndex < 0 || tokenIndex >= sLength { - return fmt.Errorf("index out of bounds array[0,%d] index '%d': %w", sLength, tokenIndex, ErrPointer) - } - - elem := rValue.Index(tokenIndex) - if elem.CanAddr() && elem.Kind() != reflect.Interface && elem.Kind() != reflect.Map && elem.Kind() != reflect.Slice && elem.Kind() != reflect.Ptr { - node = elem.Addr().Interface() - continue - } - node = elem.Interface() - - default: - return fmt.Errorf("invalid token reference %q: %w", decodedToken, ErrPointer) - } - - } - - return nil -} + elem.Set(value) -// DecodedTokens returns the decoded tokens -func (p *Pointer) DecodedTokens() []string { - result := make([]string, 0, len(p.referenceTokens)) - for _, t := range p.referenceTokens { - result = append(result, Unescape(t)) - } - return result -} - -// IsEmpty returns true if this is an empty json pointer -// this indicates that it points to the root document -func (p *Pointer) IsEmpty() bool { - return len(p.referenceTokens) == 0 -} - -// Pointer to string representation function -func (p *Pointer) String() string { + return node, nil - if len(p.referenceTokens) == 0 { - return emptyPointer + default: + return node, errInvalidReference(decodedToken) } - - pointerString := pointerSeparator + strings.Join(p.referenceTokens, pointerSeparator) - - return pointerString } -func (p *Pointer) Offset(document string) (int64, error) { - dec := json.NewDecoder(strings.NewReader(document)) - var offset int64 - for _, ttk := range p.DecodedTokens() { +func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) { + for dec.More() { + offset := dec.InputOffset() tk, err := dec.Token() if err != nil { return 0, err } - switch tk := tk.(type) { - case json.Delim: - switch tk { - case '{': - offset, err = offsetSingleObject(dec, ttk) - if err != nil { - return 0, err - } - case '[': - offset, err = offsetSingleArray(dec, ttk) - if err != nil { - return 0, err - } - default: - return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer) - } - default: - return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer) + key, ok := tk.(string) + if !ok { + return 0, fmt.Errorf("invalid key token %#v: %w", tk, ErrPointer) + } + if key == decodedToken { + return offset, nil } - } - return offset, nil -} -func offsetSingleObject(dec *json.Decoder, decodedToken string) (int64, error) { - for dec.More() { - offset := dec.InputOffset() - tk, err := dec.Token() + // Consume the associated value. Scalars are fully read by a single + // Token() call; composite values must be drained. + tk, err = dec.Token() if err != nil { return 0, err } - switch tk := tk.(type) { - case json.Delim: - switch tk { - case '{': - if err = drainSingle(dec); err != nil { - return 0, err - } - case '[': + if delim, isDelim := tk.(json.Delim); isDelim { + switch delim { + case '{', '[': if err = drainSingle(dec); err != nil { return 0, err } } - case string: - if tk == decodedToken { - return offset, nil - } - default: - return 0, fmt.Errorf("invalid token %#v: %w", tk, ErrPointer) } } + return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer) } func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) { + if decodedToken == dashToken { + return 0, errDashOnOffset() + } idx, err := strconv.Atoi(decodedToken) if err != nil { - return 0, fmt.Errorf("token reference %q is not a number: %v: %w", decodedToken, err, ErrPointer) + return 0, fmt.Errorf("token reference %q is not a number: %w: %w", decodedToken, err, ErrPointer) } var i int for i = 0; i < idx && dec.More(); i++ { @@ -471,10 +701,12 @@ func offsetSingleArray(dec *json.Decoder, decodedToken string) (int64, error) { if !dec.More() { return 0, fmt.Errorf("token reference %q not found: %w", decodedToken, ErrPointer) } + return dec.InputOffset(), nil } // drainSingle drains a single level of object or array. +// // The decoder has to guarantee the beginning delim (i.e. '{' or '[') has been consumed. func drainSingle(dec *json.Decoder) error { for dec.More() { @@ -496,14 +728,15 @@ func drainSingle(dec *json.Decoder) error { } } - // Consumes the ending delim + // consumes the ending delim if _, err := dec.Token(); err != nil { return err } + return nil } -// Specific JSON pointer encoding here +// JSON pointer encoding: // ~0 => ~ // ~1 => / // ... and vice versa @@ -515,16 +748,24 @@ const ( decRefTok1 = `/` ) -// Unescape unescapes a json pointer reference token string to the original representation +var ( + encRefTokReplacer = strings.NewReplacer(encRefTok1, decRefTok1, encRefTok0, decRefTok0) //nolint:gochecknoglobals // it's okay to declare a replacer as a private global + decRefTokReplacer = strings.NewReplacer(decRefTok1, encRefTok1, decRefTok0, encRefTok0) //nolint:gochecknoglobals // it's okay to declare a replacer as a private global +) + +// Unescape unescapes a json pointer reference token string to the original representation. func Unescape(token string) string { - step1 := strings.ReplaceAll(token, encRefTok1, decRefTok1) - step2 := strings.ReplaceAll(step1, encRefTok0, decRefTok0) - return step2 + return encRefTokReplacer.Replace(token) } -// Escape escapes a pointer reference token string +// Escape escapes a pointer reference token string. +// +// The JSONPointer specification defines "/" as a separator and "~" as an escape prefix. +// +// Keys containing such characters are escaped with the following rules: +// +// - "~" is escaped as "~0" +// - "/" is escaped as "~1" func Escape(token string) string { - step1 := strings.ReplaceAll(token, decRefTok0, encRefTok0) - step2 := strings.ReplaceAll(step1, decRefTok1, encRefTok1) - return step2 + return decRefTokReplacer.Replace(token) } diff --git a/vendor/github.com/go-openapi/jsonreference/.editorconfig b/vendor/github.com/go-openapi/jsonreference/.editorconfig new file mode 100644 index 000000000..3152da69a --- /dev/null +++ b/vendor/github.com/go-openapi/jsonreference/.editorconfig @@ -0,0 +1,26 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +# Set default charset +[*.{js,py,go,scala,rb,java,html,css,less,sass,md}] +charset = utf-8 + +# Tab indentation (no size specified) +[*.go] +indent_style = tab + +[*.md] +trim_trailing_whitespace = false + +# Matches the exact files either package.json or .travis.yml +[{package.json,.travis.yml}] +indent_style = space +indent_size = 2 diff --git a/vendor/github.com/go-openapi/jsonreference/.gitignore b/vendor/github.com/go-openapi/jsonreference/.gitignore index 769c24400..885dc27ab 100644 --- a/vendor/github.com/go-openapi/jsonreference/.gitignore +++ b/vendor/github.com/go-openapi/jsonreference/.gitignore @@ -1 +1,6 @@ -secrets.yml +*.out +*.cov +.idea +.env +.mcp.json +.claude/ diff --git a/vendor/github.com/go-openapi/jsonreference/.golangci.yml b/vendor/github.com/go-openapi/jsonreference/.golangci.yml index 22f8d21cc..dc7c96053 100644 --- a/vendor/github.com/go-openapi/jsonreference/.golangci.yml +++ b/vendor/github.com/go-openapi/jsonreference/.golangci.yml @@ -1,61 +1,67 @@ -linters-settings: - govet: - check-shadowing: true - golint: - min-confidence: 0 - gocyclo: - min-complexity: 45 - maligned: - suggest-new: true - dupl: - threshold: 200 - goconst: - min-len: 2 - min-occurrences: 3 - +version: "2" linters: - enable-all: true + default: all disable: - - maligned - - unparam - - lll - - gochecknoinits - - gochecknoglobals + - depguard - funlen - godox - - gocognit - - whitespace - - wsl - - wrapcheck - - testpackage + - exhaustruct - nlreturn - - gomnd - - exhaustivestruct - - goerr113 - - errorlint - - nestif - - godot - - gofumpt + - nonamedreturns + - noinlineerr - paralleltest - - tparallel + - recvcheck + - testpackage - thelper - - ifshort - - exhaustruct + - tparallel - varnamelen - - gci - - depguard - - errchkjson - - inamedparam - - nonamedreturns - - musttag - - ireturn - - forcetypeassert - - cyclop - # deprecated linters - - deadcode - - interfacer - - scopelint - - varcheck - - structcheck - - golint - - nosnakecase + - whitespace + - wrapcheck + - wsl + - wsl_v5 + settings: + dupl: + threshold: 200 + goconst: + min-len: 2 + min-occurrences: 3 + cyclop: + max-complexity: 20 + gocyclo: + min-complexity: 20 + exhaustive: + default-signifies-exhaustive: true + default-case-required: true + lll: + line-length: 180 + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + - gofumpt + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ +issues: + # Maximum issues count per one linter. + # Set to 0 to disable. + # Default: 50 + max-issues-per-linter: 0 + # Maximum count of issues with the same text. + # Set to 0 to disable. + # Default: 3 + max-same-issues: 0 diff --git a/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md index 9322b065e..bac878f21 100644 --- a/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md +++ b/vendor/github.com/go-openapi/jsonreference/CODE_OF_CONDUCT.md @@ -23,7 +23,9 @@ include: Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or + advances + * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic @@ -55,7 +57,7 @@ further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at ivan+abuse@flanders.co.nz. All +reported by contacting the project team at . All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. @@ -68,7 +70,7 @@ members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] +available at [][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md b/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md new file mode 100644 index 000000000..7faeb83a7 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonreference/CONTRIBUTORS.md @@ -0,0 +1,21 @@ +# Contributors + +- Repository: ['go-openapi/jsonreference'] + +| Total Contributors | Total Contributions | +| --- | --- | +| 9 | 73 | + +| Username | All Time Contribution Count | All Commits | +| --- | --- | --- | +| @fredbi | 36 | https://github.com/go-openapi/jsonreference/commits?author=fredbi | +| @casualjim | 25 | https://github.com/go-openapi/jsonreference/commits?author=casualjim | +| @youyuanwu | 5 | https://github.com/go-openapi/jsonreference/commits?author=youyuanwu | +| @olivierlemasle | 2 | https://github.com/go-openapi/jsonreference/commits?author=olivierlemasle | +| @apelisse | 1 | https://github.com/go-openapi/jsonreference/commits?author=apelisse | +| @gbjk | 1 | https://github.com/go-openapi/jsonreference/commits?author=gbjk | +| @honza | 1 | https://github.com/go-openapi/jsonreference/commits?author=honza | +| @Neo2308 | 1 | https://github.com/go-openapi/jsonreference/commits?author=Neo2308 | +| @erraggy | 1 | https://github.com/go-openapi/jsonreference/commits?author=erraggy | + + _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_ diff --git a/vendor/github.com/go-openapi/jsonreference/NOTICE b/vendor/github.com/go-openapi/jsonreference/NOTICE new file mode 100644 index 000000000..814e87ef8 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonreference/NOTICE @@ -0,0 +1,39 @@ +Copyright 2015-2025 go-swagger maintainers + +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +This software library, github.com/go-openapi/jsonreference, includes software developed +by the go-swagger and go-openapi maintainers ("go-swagger maintainers"). + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this software except in compliance with the License. + +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0. + +This software is copied from, derived from, and inspired by other original software products. +It ships with copies of other software which license terms are recalled below. + +The original software was authored on 25-02-2013 by sigu-399 (https://github.com/sigu-399, sigu.399@gmail.com). + +github.com/sigh-399/jsonreference +=========================== + +// SPDX-FileCopyrightText: Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) +// SPDX-License-Identifier: Apache-2.0 + +Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) + +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/vendor/github.com/go-openapi/jsonreference/README.md b/vendor/github.com/go-openapi/jsonreference/README.md index c7fc2049c..adea16061 100644 --- a/vendor/github.com/go-openapi/jsonreference/README.md +++ b/vendor/github.com/go-openapi/jsonreference/README.md @@ -1,19 +1,127 @@ -# gojsonreference [![Build Status](https://github.com/go-openapi/jsonreference/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/jsonreference/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/jsonreference/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/jsonreference) +# jsonreference -[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) -[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/jsonreference/master/LICENSE) -[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/jsonreference.svg)](https://pkg.go.dev/github.com/go-openapi/jsonreference) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/jsonreference)](https://goreportcard.com/report/github.com/go-openapi/jsonreference) + +[![Tests][test-badge]][test-url] [![Coverage][cov-badge]][cov-url] [![CI vuln scan][vuln-scan-badge]][vuln-scan-url] [![CodeQL][codeql-badge]][codeql-url] + + + +[![Release][release-badge]][release-url] [![Go Report Card][gocard-badge]][gocard-url] [![CodeFactor Grade][codefactor-badge]][codefactor-url] [![License][license-badge]][license-url] + + +[![GoDoc][godoc-badge]][godoc-url] [![Discord Channel][discord-badge]][discord-url] [![go version][goversion-badge]][goversion-url] ![Top language][top-badge] ![Commits since latest release][commits-badge] -An implementation of JSON Reference - Go language +--- + +An implementation of JSON Reference for golang. + +## Announcements + +* **2025-12-19** : new community chat on discord + * a new discord community channel is available to be notified of changes and support users + * our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31** + +You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] + +Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url] ## Status -Feature complete. Stable API + +API is stable. + +## Import this library in your project + +```cmd +go get github.com/go-openapi/jsonreference +``` ## Dependencies -* https://github.com/go-openapi/jsonpointer + +* + +## Basic usage + +```go +// Creating a new reference +ref, err := jsonreference.New("http://example.com/doc.json#/definitions/Pet") + +// Fragment-only reference +fragRef := jsonreference.MustCreateRef("#/definitions/Pet") + +// Resolving references +parent, _ := jsonreference.New("http://example.com/base.json") +child, _ := jsonreference.New("#/definitions/Pet") +resolved, _ := parent.Inherits(child) +// Result: "http://example.com/base.json#/definitions/Pet" +``` + + +## Change log + +See ## References -* http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07 -* http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03 +* +* + +## Licensing + +This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). + +See the license [NOTICE](./NOTICE), which recalls the licensing terms of all the pieces of software +on top of which it has been built. + +## Other documentation + +* [All-time contributors](./CONTRIBUTORS.md) +* [Contributing guidelines](.github/CONTRIBUTING.md) +* [Maintainers documentation](docs/MAINTAINERS.md) +* [Code style](docs/STYLE.md) + +## Cutting a new release + +Maintainers can cut a new release by either: + +* running [this workflow](https://github.com/go-openapi/jsonreference/actions/workflows/bump-release.yml) +* or pushing a semver tag + * signed tags are preferred + * The tag message is prepended to release notes + + +[test-badge]: https://github.com/go-openapi/jsonreference/actions/workflows/go-test.yml/badge.svg +[test-url]: https://github.com/go-openapi/jsonreference/actions/workflows/go-test.yml +[cov-badge]: https://codecov.io/gh/go-openapi/jsonreference/branch/master/graph/badge.svg +[cov-url]: https://codecov.io/gh/go-openapi/jsonreference +[vuln-scan-badge]: https://github.com/go-openapi/jsonreference/actions/workflows/scanner.yml/badge.svg +[vuln-scan-url]: https://github.com/go-openapi/jsonreference/actions/workflows/scanner.yml +[codeql-badge]: https://github.com/go-openapi/jsonreference/actions/workflows/codeql.yml/badge.svg +[codeql-url]: https://github.com/go-openapi/jsonreference/actions/workflows/codeql.yml + +[release-badge]: https://badge.fury.io/gh/go-openapi%2Fjsonreference.svg +[release-url]: https://badge.fury.io/gh/go-openapi%2Fjsonreference +[gomod-badge]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fjsonreference.svg +[gomod-url]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fjsonreference + +[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/jsonreference +[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/jsonreference +[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/jsonreference +[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/jsonreference + +[doc-badge]: https://img.shields.io/badge/doc-site-blue?link=https%3A%2F%2Fgoswagger.io%2Fgo-openapi%2F +[doc-url]: https://goswagger.io/go-openapi +[godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/jsonreference +[godoc-url]: http://pkg.go.dev/github.com/go-openapi/jsonreference +[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png +[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM +[slack-url]: https://goswagger.slack.com/archives/C04R30YMU +[discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue +[discord-url]: https://discord.gg/twZ9BwT3 + + +[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg +[license-url]: https://github.com/go-openapi/jsonreference/?tab=Apache-2.0-1-ov-file#readme + +[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/jsonreference +[goversion-url]: https://github.com/go-openapi/jsonreference/blob/master/go.mod +[top-badge]: https://img.shields.io/github/languages/top/go-openapi/jsonreference +[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/jsonreference/latest diff --git a/vendor/github.com/go-openapi/jsonreference/SECURITY.md b/vendor/github.com/go-openapi/jsonreference/SECURITY.md new file mode 100644 index 000000000..1fea2c573 --- /dev/null +++ b/vendor/github.com/go-openapi/jsonreference/SECURITY.md @@ -0,0 +1,37 @@ +# Security Policy + +This policy outlines the commitment and practices of the go-openapi maintainers regarding security. + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| O.x | :white_check_mark: | + +## Vulnerability checks in place + +This repository uses automated vulnerability scans, at every merged commit and at least once a week. + +We use: + +* [`GitHub CodeQL`][codeql-url] +* [`trivy`][trivy-url] +* [`govulncheck`][govulncheck-url] + +Reports are centralized in github security reports and visible only to the maintainers. + +## Reporting a vulnerability + +If you become aware of a security vulnerability that affects the current repository, +**please report it privately to the maintainers** +rather than opening a publicly visible GitHub issue. + +Please follow the instructions provided by github to [Privately report a security vulnerability][github-guidance-url]. + +> [!NOTE] +> On Github, navigate to the project's "Security" tab then click on "Report a vulnerability". + +[codeql-url]: https://github.com/github/codeql +[trivy-url]: https://trivy.dev/docs/latest/getting-started +[govulncheck-url]: https://go.dev/blog/govulncheck +[github-guidance-url]: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability diff --git a/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go index f0610cf1e..a08b47320 100644 --- a/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go +++ b/vendor/github.com/go-openapi/jsonreference/internal/normalize_url.go @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + package internal import ( @@ -11,9 +14,11 @@ const ( defaultHTTPSPort = ":443" ) -// Regular expressions used by the normalizations -var rxPort = regexp.MustCompile(`(:\d+)/?$`) -var rxDupSlashes = regexp.MustCompile(`/{2,}`) +// Regular expressions used by the normalizations. +var ( + rxPort = regexp.MustCompile(`(:\d+)/?$`) + rxDupSlashes = regexp.MustCompile(`/{2,}`) +) // NormalizeURL will normalize the specified URL // This was added to replace a previous call to the no longer maintained purell library: diff --git a/vendor/github.com/go-openapi/jsonreference/reference.go b/vendor/github.com/go-openapi/jsonreference/reference.go index cfdef03e5..003ba7a83 100644 --- a/vendor/github.com/go-openapi/jsonreference/reference.go +++ b/vendor/github.com/go-openapi/jsonreference/reference.go @@ -1,27 +1,5 @@ -// Copyright 2013 sigu-399 ( https://github.com/sigu-399 ) -// -// 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. - -// author sigu-399 -// author-github https://github.com/sigu-399 -// author-mail sigu.399@gmail.com -// -// repository-name jsonreference -// repository-desc An implementation of JSON Reference - Go language -// -// description Main and unique file. -// -// created 26-02-2013 +// SPDX-FileCopyrightText: Copyright (c) 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 package jsonreference @@ -38,50 +16,51 @@ const ( fragmentRune = `#` ) -// New creates a new reference for the given string -func New(jsonReferenceString string) (Ref, error) { +// ErrChildURL is raised when there is no child. +var ErrChildURL = errors.New("child url is nil") + +// Ref represents a json reference object. +type Ref struct { + referenceURL *url.URL + referencePointer jsonpointer.Pointer + + HasFullURL bool + HasURLPathOnly bool + HasFragmentOnly bool + HasFileScheme bool + HasFullFilePath bool +} +// New creates a new reference for the given string. +func New(jsonReferenceString string) (Ref, error) { var r Ref err := r.parse(jsonReferenceString) return r, err - } // MustCreateRef parses the ref string and panics when it's invalid. -// Use the New method for a version that returns an error +// Use the New method for a version that returns an error. func MustCreateRef(ref string) Ref { r, err := New(ref) if err != nil { panic(err) } - return r -} -// Ref represents a json reference object -type Ref struct { - referenceURL *url.URL - referencePointer jsonpointer.Pointer - - HasFullURL bool - HasURLPathOnly bool - HasFragmentOnly bool - HasFileScheme bool - HasFullFilePath bool + return r } -// GetURL gets the URL for this reference +// GetURL gets the URL for this reference. func (r *Ref) GetURL() *url.URL { return r.referenceURL } -// GetPointer gets the json pointer for this reference +// GetPointer gets the json pointer for this reference. func (r *Ref) GetPointer() *jsonpointer.Pointer { return &r.referencePointer } -// String returns the best version of the url for this reference +// String returns the best version of the url for this reference. func (r *Ref) String() string { - if r.referenceURL != nil { return r.referenceURL.String() } @@ -93,7 +72,7 @@ func (r *Ref) String() string { return r.referencePointer.String() } -// IsRoot returns true if this reference is a root document +// IsRoot returns true if this reference is a root document. func (r *Ref) IsRoot() bool { return r.referenceURL != nil && !r.IsCanonical() && @@ -101,14 +80,32 @@ func (r *Ref) IsRoot() bool { r.referenceURL.Fragment == "" } -// IsCanonical returns true when this pointer starts with http(s):// or file:// +// IsCanonical returns true when this pointer starts with http(s):// or file://. func (r *Ref) IsCanonical() bool { return (r.HasFileScheme && r.HasFullFilePath) || (!r.HasFileScheme && r.HasFullURL) } -// "Constructor", parses the given string JSON reference -func (r *Ref) parse(jsonReferenceString string) error { +// Inherits creates a new reference from a parent and a child +// If the child cannot inherit from the parent, an error is returned. +func (r *Ref) Inherits(child Ref) (*Ref, error) { + childURL := child.GetURL() + parentURL := r.GetURL() + if childURL == nil { + return nil, ErrChildURL + } + if parentURL == nil { + return &child, nil + } + + ref, err := New(parentURL.ResolveReference(childURL).String()) + if err != nil { + return nil, err + } + return &ref, nil +} +// "Constructor", parses the given string JSON reference. +func (r *Ref) parse(jsonReferenceString string) error { parsed, err := url.Parse(jsonReferenceString) if err != nil { return err @@ -137,22 +134,3 @@ func (r *Ref) parse(jsonReferenceString string) error { return nil } - -// Inherits creates a new reference from a parent and a child -// If the child cannot inherit from the parent, an error is returned -func (r *Ref) Inherits(child Ref) (*Ref, error) { - childURL := child.GetURL() - parentURL := r.GetURL() - if childURL == nil { - return nil, errors.New("child url is nil") - } - if parentURL == nil { - return &child, nil - } - - ref, err := New(parentURL.ResolveReference(childURL).String()) - if err != nil { - return nil, err - } - return &ref, nil -} diff --git a/vendor/github.com/go-openapi/swag/.codecov.yml b/vendor/github.com/go-openapi/swag/.codecov.yml new file mode 100644 index 000000000..3354f44b2 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/.codecov.yml @@ -0,0 +1,4 @@ +ignore: + - jsonutils/fixtures_test + - jsonutils/adapters/ifaces/mocks + - jsonutils/adapters/testintegration/benchmarks diff --git a/vendor/github.com/go-openapi/swag/.gitignore b/vendor/github.com/go-openapi/swag/.gitignore index c4b1b64f0..1680db44c 100644 --- a/vendor/github.com/go-openapi/swag/.gitignore +++ b/vendor/github.com/go-openapi/swag/.gitignore @@ -3,3 +3,4 @@ vendor Godeps .idea *.out +.mcp.json diff --git a/vendor/github.com/go-openapi/swag/.golangci.yml b/vendor/github.com/go-openapi/swag/.golangci.yml index d2fafb8a2..126264a6b 100644 --- a/vendor/github.com/go-openapi/swag/.golangci.yml +++ b/vendor/github.com/go-openapi/swag/.golangci.yml @@ -1,56 +1,78 @@ -linters-settings: - gocyclo: - min-complexity: 45 - dupl: - threshold: 200 - goconst: - min-len: 2 - min-occurrences: 3 - +version: "2" linters: - enable-all: true + default: all disable: - - recvcheck - - unparam - - lll - - gochecknoinits - - gochecknoglobals + - cyclop + - depguard + - errchkjson + - errorlint + - exhaustruct + - forcetypeassert - funlen - - godox + - gochecknoglobals + - gochecknoinits - gocognit - - whitespace - - wsl - - wrapcheck - - testpackage - - nlreturn - - errorlint - - nestif - godot - - gofumpt + - godox + - gomoddirectives + - gosmopolitan + - inamedparam + - intrange + - ireturn + - lll + - musttag + - modernize + - nestif + - nlreturn + - nonamedreturns + - noinlineerr - paralleltest - - tparallel + - recvcheck + - testpackage - thelper - - exhaustruct + - tagliatelle + - tparallel + - unparam - varnamelen - - gci - - depguard - - errchkjson - - inamedparam - - nonamedreturns - - musttag - - ireturn - - forcetypeassert - - cyclop - # deprecated linters - #- deadcode - #- interfacer - #- scopelint - #- varcheck - #- structcheck - #- golint - #- nosnakecase - #- maligned - #- goerr113 - #- ifshort - #- gomnd - #- exhaustivestruct + - whitespace + - wrapcheck + - wsl + - wsl_v5 + settings: + dupl: + threshold: 200 + goconst: + min-len: 2 + min-occurrences: 3 + gocyclo: + min-complexity: 45 + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ +issues: + # Maximum issues count per one linter. + # Set to 0 to disable. + # Default: 50 + max-issues-per-linter: 0 + # Maximum count of issues with the same text. + # Set to 0 to disable. + # Default: 3 + max-same-issues: 0 diff --git a/vendor/github.com/go-openapi/swag/.mockery.yml b/vendor/github.com/go-openapi/swag/.mockery.yml new file mode 100644 index 000000000..8557cb58d --- /dev/null +++ b/vendor/github.com/go-openapi/swag/.mockery.yml @@ -0,0 +1,30 @@ +all: false +dir: '{{.InterfaceDir}}' +filename: mocks_test.go +force-file-write: true +formatter: goimports +include-auto-generated: false +log-level: info +structname: '{{.Mock}}{{.InterfaceName}}' +pkgname: '{{.SrcPackageName}}' +recursive: false +require-template-schema-exists: true +template: matryer +template-schema: '{{.Template}}.schema.json' +packages: + github.com/go-openapi/swag/jsonutils/adapters/ifaces: + config: + dir: jsonutils/adapters/ifaces/mocks + filename: mocks.go + pkgname: 'mocks' + force-file-write: true + all: true + github.com/go-openapi/swag/jsonutils/adapters/testintegration: + config: + inpackage: true + dir: jsonutils/adapters/testintegration + force-file-write: true + all: true + interfaces: + EJMarshaler: + EJUnmarshaler: diff --git a/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md b/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md index 9322b065e..bac878f21 100644 --- a/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md +++ b/vendor/github.com/go-openapi/swag/CODE_OF_CONDUCT.md @@ -23,7 +23,9 @@ include: Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or + advances + * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic @@ -55,7 +57,7 @@ further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at ivan+abuse@flanders.co.nz. All +reported by contacting the project team at . All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. @@ -68,7 +70,7 @@ members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] +available at [][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ diff --git a/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md b/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md new file mode 100644 index 000000000..286878acf --- /dev/null +++ b/vendor/github.com/go-openapi/swag/CONTRIBUTORS.md @@ -0,0 +1,36 @@ +# Contributors + +- Repository: ['go-openapi/swag'] + +| Total Contributors | Total Contributions | +| --- | --- | +| 24 | 242 | + +| Username | All Time Contribution Count | All Commits | +| --- | --- | --- | +| @fredbi | 112 | | +| @casualjim | 98 | | +| @alexandear | 4 | | +| @orisano | 3 | | +| @reinerRubin | 2 | | +| @n-inja | 2 | | +| @nitinmohan87 | 2 | | +| @Neo2308 | 2 | | +| @michaelbowler-form3 | 2 | | +| @ujjwalsh | 1 | | +| @griffin-stewie | 1 | | +| @POD666 | 1 | | +| @pytlesk4 | 1 | | +| @shirou | 1 | | +| @seanprince | 1 | | +| @petrkotas | 1 | | +| @mszczygiel | 1 | | +| @sosiska | 1 | | +| @kzys | 1 | | +| @faguirre1 | 1 | | +| @posener | 1 | | +| @diego-fu-hs | 1 | | +| @davidalpert | 1 | | +| @Xe | 1 | | + + _this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_ diff --git a/vendor/github.com/go-openapi/swag/README.md b/vendor/github.com/go-openapi/swag/README.md index a72922299..64f667103 100644 --- a/vendor/github.com/go-openapi/swag/README.md +++ b/vendor/github.com/go-openapi/swag/README.md @@ -1,23 +1,224 @@ -# Swag [![Build Status](https://github.com/go-openapi/swag/actions/workflows/go-test.yml/badge.svg)](https://github.com/go-openapi/swag/actions?query=workflow%3A"go+test") [![codecov](https://codecov.io/gh/go-openapi/swag/branch/master/graph/badge.svg)](https://codecov.io/gh/go-openapi/swag) +# Swag -[![Slack Status](https://slackin.goswagger.io/badge.svg)](https://slackin.goswagger.io) -[![license](http://img.shields.io/badge/license-Apache%20v2-orange.svg)](https://raw.githubusercontent.com/go-openapi/swag/master/LICENSE) -[![Go Reference](https://pkg.go.dev/badge/github.com/go-openapi/swag.svg)](https://pkg.go.dev/github.com/go-openapi/swag) -[![Go Report Card](https://goreportcard.com/badge/github.com/go-openapi/swag)](https://goreportcard.com/report/github.com/go-openapi/swag) + +[![Tests][test-badge]][test-url] [![Coverage][cov-badge]][cov-url] [![CI vuln scan][vuln-scan-badge]][vuln-scan-url] [![CodeQL][codeql-badge]][codeql-url] + + + +[![Release][release-badge]][release-url] [![Go Report Card][gocard-badge]][gocard-url] [![CodeFactor Grade][codefactor-badge]][codefactor-url] [![License][license-badge]][license-url] + + +[![GoDoc][godoc-badge]][godoc-url] [![Discord Channel][discord-badge]][discord-url] [![go version][goversion-badge]][goversion-url] ![Top language][top-badge] ![Commits since latest release][commits-badge] -Contains a bunch of helper functions for go-openapi and go-swagger projects. +--- + +A bunch of helper functions for go-openapi and go-swagger projects. You may also use it standalone for your projects. -* convert between value and pointers for builtin types -* convert from string to builtin types (wraps strconv) -* fast json concatenation -* search in path -* load from file or http -* name mangling +> **NOTE** +> `swag` is one of the foundational building blocks of the go-openapi initiative. +> +> Most repositories in `github.com/go-openapi/...` depend on it in some way. +> And so does our CLI tool `github.com/go-swagger/go-swagger`, +> as well as the code generated by this tool. + +* [Contents](#contents) +* [Dependencies](#dependencies) +* [Change log](#change-log) +* [Licensing](#licensing) +* [Note to contributors](#note-to-contributors) +* [Roadmap](#roadmap) + +## Announcements + +* **2025-12-19** : new community chat on discord + * a new discord community channel is available to be notified of changes and support users + * our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31** + +You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url] + +Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url] + +## Status + +API is stable. + +## Import this library in your project + +```cmd +go get github.com/go-openapi/swag/{module} +``` + +Or for backward compatibility: + +```cmd +go get github.com/go-openapi/swag +``` + +## Contents + +`go-openapi/swag` exposes a collection of relatively independent modules. + +Moving forward, no additional feature will be added to the `swag` API directly at the root package level, +which remains there for backward-compatibility purposes. All exported top-level features are now deprecated. + +Child modules will continue to evolve and some new ones may be added in the future. + +| Module | Content | Main features | +|---------------|---------|---------------| +| `cmdutils` | utilities to work with CLIs || +| `conv` | type conversion utilities | convert between values and pointers for any types
convert from string to builtin types (wraps `strconv`)
require `./typeutils` (test dependency)
| +| `fileutils` | file utilities | | +| `jsonname` | JSON utilities | infer JSON names from `go` properties
| +| `jsonutils` | JSON utilities | fast json concatenation
read and write JSON from and to dynamic `go` data structures
~require `github.com/mailru/easyjson`~
| +| `loading` | file loading | load from file or http
require `./yamlutils`
| +| `mangling` | safe name generation | name mangling for `go`
| +| `netutils` | networking utilities | host, port from address
| +| `stringutils` | `string` utilities | search in slice (with case-insensitive)
split/join query parameters as arrays
| +| `typeutils` | `go` types utilities | check the zero value for any type
safe check for a nil value
| +| `yamlutils` | YAML utilities | converting YAML to JSON
loading YAML into a dynamic YAML document
maintaining the original order of keys in YAML objects
require `./jsonutils`
~require `github.com/mailru/easyjson`~
require `go.yaml.in/yaml/v3`
| + +--- + +## Dependencies + +The root module `github.com/go-openapi/swag` at the repo level maintains a few +dependencies outside of the standard library. + +* YAML utilities depend on `go.yaml.in/yaml/v3` +* JSON utilities depend on their registered adapter module: + * by default, only the standard library is used + * `github.com/mailru/easyjson` is now only a dependency for module + `github.com/go-openapi/swag/jsonutils/adapters/easyjson/json`, + for users willing to import that module. + * integration tests and benchmarks use all the dependencies are published as their own module +* other dependencies are test dependencies drawn from `github.com/stretchr/testify` + +## Usage + +**How to explicitly register a dependency at runtime**? + +The following would maintain how JSON utilities proposed by `swag` used work, up to `v0.24.1`. + + ```go + import ( + "github.com/go-openapi/swag/jsonutils/adapters" + easyjson "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json" + ) + + func init() { + easyjson.Register(adapters.Registry) + } + ``` + +Subsequent calls to `jsonutils.ReadJSON()` or `jsonutils.WriteJSON()` will switch to `easyjson` +whenever the passed data structures implement the `easyjson.Unmarshaler` or `easyjson.Marshaler` respectively, +or fallback to the standard library. + +For more details, you may also look at our +[integration tests](jsonutils/adapters/testintegration/integration_suite_test.go#29). + +--- + +## Note to contributors + +All kinds of contributions are welcome. + +This repo is a go mono-repo. See [docs](docs/MAINTAINERS.md). + +More general guidelines are available [here](.github/CONTRIBUTING.md). + +## Roadmap + +See the current [TODO list](docs/TODOS.md) + +## Change log + +See + +For pre-v0.26.0 releases, see [release notes](./docs/NOTES.md). + +**What coming next?** + +Moving forward, we want to : + +* provide an implementation of the JSON adapter based on `encoding/json/v2`, for `go1.25` builds. +* provide similar implementations for `goccy/go-json` and `jsoniterator/go`, and perhaps some other + similar libraries may be interesting too. + + + +## Licensing + +This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE). + + + + + +## Other documentation + +* [All-time contributors](./CONTRIBUTORS.md) +* [Contributing guidelines](.github/CONTRIBUTING.md) +* [Maintainers documentation](docs/MAINTAINERS.md) +* [Code style](docs/STYLE.md) + +## Cutting a new release + +Maintainers can cut a new release by either: +* running [this workflow](https://github.com/go-openapi/swag/actions/workflows/bump-release.yml) +* or pushing a semver tag + * signed tags are preferred + * The tag message is prepended to release notes -This repo has only few dependencies outside of the standard library: + +[test-badge]: https://github.com/go-openapi/swag/actions/workflows/go-test.yml/badge.svg +[test-url]: https://github.com/go-openapi/swag/actions/workflows/go-test.yml +[cov-badge]: https://codecov.io/gh/go-openapi/swag/branch/master/graph/badge.svg +[cov-url]: https://codecov.io/gh/go-openapi/swag +[vuln-scan-badge]: https://github.com/go-openapi/swag/actions/workflows/scanner.yml/badge.svg +[vuln-scan-url]: https://github.com/go-openapi/swag/actions/workflows/scanner.yml +[codeql-badge]: https://github.com/go-openapi/swag/actions/workflows/codeql.yml/badge.svg +[codeql-url]: https://github.com/go-openapi/swag/actions/workflows/codeql.yml + +[release-badge]: https://badge.fury.io/gh/go-openapi%2Fswag.svg +[release-url]: https://badge.fury.io/gh/go-openapi%2Fswag +[gomod-badge]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fswag.svg +[gomod-url]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fswag + +[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/swag +[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/swag +[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/swag +[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/swag + +[doc-badge]: https://img.shields.io/badge/doc-site-blue?link=https%3A%2F%2Fgoswagger.io%2Fgo-openapi%2F +[doc-url]: https://goswagger.io/go-openapi +[godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/swag +[godoc-url]: http://pkg.go.dev/github.com/go-openapi/swag +[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png +[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM +[slack-url]: https://goswagger.slack.com/archives/C04R30YMU +[discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue +[discord-url]: https://discord.gg/FfnFYaC3k5 -* YAML utilities depend on `gopkg.in/yaml.v3` -* `github.com/mailru/easyjson v0.7.7` + +[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg +[license-url]: https://github.com/go-openapi/swag/?tab=Apache-2.0-1-ov-file#readme + +[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/swag +[goversion-url]: https://github.com/go-openapi/swag/blob/master/go.mod +[top-badge]: https://img.shields.io/github/languages/top/go-openapi/swag +[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/swag/latest diff --git a/vendor/github.com/go-openapi/swag/SECURITY.md b/vendor/github.com/go-openapi/swag/SECURITY.md new file mode 100644 index 000000000..1fea2c573 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/SECURITY.md @@ -0,0 +1,37 @@ +# Security Policy + +This policy outlines the commitment and practices of the go-openapi maintainers regarding security. + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| O.x | :white_check_mark: | + +## Vulnerability checks in place + +This repository uses automated vulnerability scans, at every merged commit and at least once a week. + +We use: + +* [`GitHub CodeQL`][codeql-url] +* [`trivy`][trivy-url] +* [`govulncheck`][govulncheck-url] + +Reports are centralized in github security reports and visible only to the maintainers. + +## Reporting a vulnerability + +If you become aware of a security vulnerability that affects the current repository, +**please report it privately to the maintainers** +rather than opening a publicly visible GitHub issue. + +Please follow the instructions provided by github to [Privately report a security vulnerability][github-guidance-url]. + +> [!NOTE] +> On Github, navigate to the project's "Security" tab then click on "Report a vulnerability". + +[codeql-url]: https://github.com/github/codeql +[trivy-url]: https://trivy.dev/docs/latest/getting-started +[govulncheck-url]: https://go.dev/blog/govulncheck +[github-guidance-url]: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability diff --git a/vendor/github.com/openshift/custom-resource-status/LICENSE b/vendor/github.com/go-openapi/swag/cmdutils/LICENSE similarity index 99% rename from vendor/github.com/openshift/custom-resource-status/LICENSE rename to vendor/github.com/go-openapi/swag/cmdutils/LICENSE index 261eeb9e9..d64569567 100644 --- a/vendor/github.com/openshift/custom-resource-status/LICENSE +++ b/vendor/github.com/go-openapi/swag/cmdutils/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ diff --git a/vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go b/vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go new file mode 100644 index 000000000..6c7bbb26f --- /dev/null +++ b/vendor/github.com/go-openapi/swag/cmdutils/cmd_utils.go @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package cmdutils + +// CommandLineOptionsGroup represents a group of user-defined command line options. +// +// This is for instance used to configure command line arguments in API servers generated by go-swagger. +type CommandLineOptionsGroup struct { + ShortDescription string + LongDescription string + Options any +} diff --git a/vendor/github.com/go-openapi/swag/cmdutils/doc.go b/vendor/github.com/go-openapi/swag/cmdutils/doc.go new file mode 100644 index 000000000..31f2c3753 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/cmdutils/doc.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package cmdutils brings helpers for CLIs produced by go-openapi +package cmdutils diff --git a/vendor/github.com/go-openapi/swag/cmdutils_iface.go b/vendor/github.com/go-openapi/swag/cmdutils_iface.go new file mode 100644 index 000000000..bd0c1fc12 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/cmdutils_iface.go @@ -0,0 +1,11 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import "github.com/go-openapi/swag/cmdutils" + +// CommandLineOptionsGroup represents a group of user-defined command line options. +// +// Deprecated: use [cmdutils.CommandLineOptionsGroup] instead. +type CommandLineOptionsGroup = cmdutils.CommandLineOptionsGroup diff --git a/vendor/github.com/go-openapi/swag/conv/LICENSE b/vendor/github.com/go-openapi/swag/conv/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/conv/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/conv/convert.go b/vendor/github.com/go-openapi/swag/conv/convert.go new file mode 100644 index 000000000..f205c3913 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/conv/convert.go @@ -0,0 +1,161 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package conv + +import ( + "math" + "strconv" + "strings" +) + +// same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER +const ( + maxJSONFloat = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1 + minJSONFloat = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1 + epsilon float64 = 1e-9 +) + +// IsFloat64AJSONInteger allows for integers [-2^53, 2^53-1] inclusive. +func IsFloat64AJSONInteger(f float64) bool { + if math.IsNaN(f) || math.IsInf(f, 0) || f < minJSONFloat || f > maxJSONFloat { + return false + } + rounded := math.Round(f) + if f == rounded { + return true + } + if rounded == 0 { // f = 0.0 exited above + return false + } + + diff := math.Abs(f - rounded) + if diff == 0 { + return true + } + + // relative error Abs{f - Round(f)) / Round(f)} < ε ; Round(f) + return diff < epsilon*math.Abs(rounded) +} + +// ConvertFloat turns a string into a float numerical value. +func ConvertFloat[T Float](str string) (T, error) { + var v T + f, err := strconv.ParseFloat(str, bitsize(v)) + if err != nil { + return 0, err + } + + return T(f), nil +} + +// ConvertInteger turns a string into a signed integer. +func ConvertInteger[T Signed](str string) (T, error) { + var v T + f, err := strconv.ParseInt(str, 10, bitsize(v)) + if err != nil { + return 0, err + } + + return T(f), nil +} + +// ConvertUinteger turns a string into an unsigned integer. +func ConvertUinteger[T Unsigned](str string) (T, error) { + var v T + f, err := strconv.ParseUint(str, 10, bitsize(v)) + if err != nil { + return 0, err + } + + return T(f), nil +} + +// ConvertBool turns a string into a boolean. +// +// It supports a few more "true" strings than [strconv.ParseBool]: +// +// - it is not case sensitive ("trUe" or "FalsE" work) +// - "ok", "yes", "y", "on", "selected", "checked", "enabled" are all true +// - everything that is not true is false: there is never an actual error returned +func ConvertBool(str string) (bool, error) { + switch strings.ToLower(str) { + case "true", + "1", + "yes", + "ok", + "y", + "on", + "selected", + "checked", + "t", + "enabled": + return true, nil + default: + return false, nil + } +} + +// ConvertFloat32 turns a string into a float32. +func ConvertFloat32(str string) (float32, error) { return ConvertFloat[float32](str) } + +// ConvertFloat64 turns a string into a float64 +func ConvertFloat64(str string) (float64, error) { return ConvertFloat[float64](str) } + +// ConvertInt8 turns a string into an int8 +func ConvertInt8(str string) (int8, error) { return ConvertInteger[int8](str) } + +// ConvertInt16 turns a string into an int16 +func ConvertInt16(str string) (int16, error) { + i, err := strconv.ParseInt(str, 10, 16) + if err != nil { + return 0, err + } + return int16(i), nil +} + +// ConvertInt32 turns a string into an int32 +func ConvertInt32(str string) (int32, error) { + i, err := strconv.ParseInt(str, 10, 32) + if err != nil { + return 0, err + } + return int32(i), nil +} + +// ConvertInt64 turns a string into an int64 +func ConvertInt64(str string) (int64, error) { + return strconv.ParseInt(str, 10, 64) +} + +// ConvertUint8 turns a string into an uint8 +func ConvertUint8(str string) (uint8, error) { + i, err := strconv.ParseUint(str, 10, 8) + if err != nil { + return 0, err + } + return uint8(i), nil +} + +// ConvertUint16 turns a string into an uint16 +func ConvertUint16(str string) (uint16, error) { + i, err := strconv.ParseUint(str, 10, 16) + if err != nil { + return 0, err + } + return uint16(i), nil +} + +// ConvertUint32 turns a string into an uint32 +func ConvertUint32(str string) (uint32, error) { + i, err := strconv.ParseUint(str, 10, 32) + if err != nil { + return 0, err + } + return uint32(i), nil +} + +// ConvertUint64 turns a string into an uint64 +func ConvertUint64(str string) (uint64, error) { + return strconv.ParseUint(str, 10, 64) +} diff --git a/vendor/github.com/go-openapi/swag/conv/convert_types.go b/vendor/github.com/go-openapi/swag/conv/convert_types.go new file mode 100644 index 000000000..cf4c6495e --- /dev/null +++ b/vendor/github.com/go-openapi/swag/conv/convert_types.go @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package conv + +// Unlicensed credits (idea, concept) +// +// The idea to convert values to pointers and the other way around, was inspired, eons ago, by the aws go sdk. +// +// Nowadays, all sensible API sdk's expose a similar functionality. + +// Pointer returns a pointer to the value passed in. +func Pointer[T any](v T) *T { + return &v +} + +// Value returns a shallow copy of the value of the pointer passed in. +// +// If the pointer is nil, the returned value is the zero value. +func Value[T any](v *T) T { + if v != nil { + return *v + } + + var zero T + return zero +} + +// PointerSlice converts a slice of values into a slice of pointers. +func PointerSlice[T any](src []T) []*T { + dst := make([]*T, len(src)) + for i := 0; i < len(src); i++ { + dst[i] = &(src[i]) + } + return dst +} + +// ValueSlice converts a slice of pointers into a slice of values. +// +// nil elements are zero values. +func ValueSlice[T any](src []*T) []T { + dst := make([]T, len(src)) + for i := 0; i < len(src); i++ { + if src[i] != nil { + dst[i] = *(src[i]) + } + } + return dst +} + +// PointerMap converts a map of values into a map of pointers. +func PointerMap[K comparable, T any](src map[K]T) map[K]*T { + dst := make(map[K]*T) + for k, val := range src { + v := val + dst[k] = &v + } + return dst +} + +// ValueMap converts a map of pointers into a map of values. +// +// nil elements are skipped. +func ValueMap[K comparable, T any](src map[K]*T) map[K]T { + dst := make(map[K]T) + for k, val := range src { + if val != nil { + dst[k] = *val + } + } + return dst +} diff --git a/vendor/github.com/go-openapi/swag/conv/doc.go b/vendor/github.com/go-openapi/swag/conv/doc.go new file mode 100644 index 000000000..1bd6ead6e --- /dev/null +++ b/vendor/github.com/go-openapi/swag/conv/doc.go @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package conv exposes utilities to convert types. +// +// The Convert and Format families of functions are essentially a shorthand to [strconv] functions, +// using the decimal representation of numbers. +// +// Features: +// +// - from string representation to value ("Convert*") and reciprocally ("Format*") +// - from pointer to value ([Value]) and reciprocally ([Pointer]) +// - from slice of values to slice of pointers ([PointerSlice]) and reciprocally ([ValueSlice]) +// - from map of values to map of pointers ([PointerMap]) and reciprocally ([ValueMap]) +package conv diff --git a/vendor/github.com/go-openapi/swag/conv/format.go b/vendor/github.com/go-openapi/swag/conv/format.go new file mode 100644 index 000000000..5b87b8e14 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/conv/format.go @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package conv + +import ( + "strconv" +) + +// FormatInteger turns an integer type into a string. +func FormatInteger[T Signed](value T) string { + return strconv.FormatInt(int64(value), 10) +} + +// FormatUinteger turns an unsigned integer type into a string. +func FormatUinteger[T Unsigned](value T) string { + return strconv.FormatUint(uint64(value), 10) +} + +// FormatFloat turns a floating point numerical value into a string. +func FormatFloat[T Float](value T) string { + return strconv.FormatFloat(float64(value), 'f', -1, bitsize(value)) +} + +// FormatBool turns a boolean into a string. +func FormatBool(value bool) string { + return strconv.FormatBool(value) +} diff --git a/vendor/github.com/go-openapi/swag/conv/sizeof.go b/vendor/github.com/go-openapi/swag/conv/sizeof.go new file mode 100644 index 000000000..494346557 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/conv/sizeof.go @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package conv + +import "unsafe" + +// bitsize returns the size in bits of a type. +// +// NOTE: [unsafe.SizeOf] simply returns the size in bytes of the value. +// For primitive types T, the generic stencil is precompiled and this value +// is resolved at compile time, resulting in an immediate call to [strconv.ParseFloat]. +// +// We may leave up to the go compiler to simplify this function into a +// constant value, which happens in practice at least for primitive types +// (e.g. numerical types). +func bitsize[T Numerical](value T) int { + const bitsPerByte = 8 + return int(unsafe.Sizeof(value)) * bitsPerByte +} diff --git a/vendor/github.com/go-openapi/swag/conv/type_constraints.go b/vendor/github.com/go-openapi/swag/conv/type_constraints.go new file mode 100644 index 000000000..81135e827 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/conv/type_constraints.go @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package conv + +type ( + // these type constraints are redefined after golang.org/x/exp/constraints, + // because importing that package causes an undesired go upgrade. + + // Signed integer types, cf. [golang.org/x/exp/constraints.Signed] + Signed interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 + } + + // Unsigned integer types, cf. [golang.org/x/exp/constraints.Unsigned] + Unsigned interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr + } + + // Float numerical types, cf. [golang.org/x/exp/constraints.Float] + Float interface { + ~float32 | ~float64 + } + + // Numerical types + Numerical interface { + Signed | Unsigned | Float + } +) diff --git a/vendor/github.com/go-openapi/swag/conv_iface.go b/vendor/github.com/go-openapi/swag/conv_iface.go new file mode 100644 index 000000000..eea7b2e56 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/conv_iface.go @@ -0,0 +1,486 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import ( + "time" + + "github.com/go-openapi/swag/conv" +) + +// IsFloat64AJSONInteger allows for integers [-2^53, 2^53-1] inclusive. +// +// Deprecated: use [conv.IsFloat64AJSONInteger] instead. +func IsFloat64AJSONInteger(f float64) bool { return conv.IsFloat64AJSONInteger(f) } + +// ConvertBool turns a string into a boolean. +// +// Deprecated: use [conv.ConvertBool] instead. +func ConvertBool(str string) (bool, error) { return conv.ConvertBool(str) } + +// ConvertFloat32 turns a string into a float32. +// +// Deprecated: use [conv.ConvertFloat32] instead. Alternatively, you may use the generic version [conv.ConvertFloat]. +func ConvertFloat32(str string) (float32, error) { return conv.ConvertFloat[float32](str) } + +// ConvertFloat64 turns a string into a float64. +// +// Deprecated: use [conv.ConvertFloat64] instead. Alternatively, you may use the generic version [conv.ConvertFloat]. +func ConvertFloat64(str string) (float64, error) { return conv.ConvertFloat[float64](str) } + +// ConvertInt8 turns a string into an int8. +// +// Deprecated: use [conv.ConvertInt8] instead. Alternatively, you may use the generic version [conv.ConvertInteger]. +func ConvertInt8(str string) (int8, error) { return conv.ConvertInteger[int8](str) } + +// ConvertInt16 turns a string into an int16. +// +// Deprecated: use [conv.ConvertInt16] instead. Alternatively, you may use the generic version [conv.ConvertInteger]. +func ConvertInt16(str string) (int16, error) { return conv.ConvertInteger[int16](str) } + +// ConvertInt32 turns a string into an int32. +// +// Deprecated: use [conv.ConvertInt32] instead. Alternatively, you may use the generic version [conv.ConvertInteger]. +func ConvertInt32(str string) (int32, error) { return conv.ConvertInteger[int32](str) } + +// ConvertInt64 turns a string into an int64. +// +// Deprecated: use [conv.ConvertInt64] instead. Alternatively, you may use the generic version [conv.ConvertInteger]. +func ConvertInt64(str string) (int64, error) { return conv.ConvertInteger[int64](str) } + +// ConvertUint8 turns a string into an uint8. +// +// Deprecated: use [conv.ConvertUint8] instead. Alternatively, you may use the generic version [conv.ConvertUinteger]. +func ConvertUint8(str string) (uint8, error) { return conv.ConvertUinteger[uint8](str) } + +// ConvertUint16 turns a string into an uint16. +// +// Deprecated: use [conv.ConvertUint16] instead. Alternatively, you may use the generic version [conv.ConvertUinteger]. +func ConvertUint16(str string) (uint16, error) { return conv.ConvertUinteger[uint16](str) } + +// ConvertUint32 turns a string into an uint32. +// +// Deprecated: use [conv.ConvertUint32] instead. Alternatively, you may use the generic version [conv.ConvertUinteger]. +func ConvertUint32(str string) (uint32, error) { return conv.ConvertUinteger[uint32](str) } + +// ConvertUint64 turns a string into an uint64. +// +// Deprecated: use [conv.ConvertUint64] instead. Alternatively, you may use the generic version [conv.ConvertUinteger]. +func ConvertUint64(str string) (uint64, error) { return conv.ConvertUinteger[uint64](str) } + +// FormatBool turns a boolean into a string. +// +// Deprecated: use [conv.FormatBool] instead. +func FormatBool(value bool) string { return conv.FormatBool(value) } + +// FormatFloat32 turns a float32 into a string. +// +// Deprecated: use [conv.FormatFloat] instead. +func FormatFloat32(value float32) string { return conv.FormatFloat(value) } + +// FormatFloat64 turns a float64 into a string. +// +// Deprecated: use [conv.FormatFloat] instead. +func FormatFloat64(value float64) string { return conv.FormatFloat(value) } + +// FormatInt8 turns an int8 into a string. +// +// Deprecated: use [conv.FormatInteger] instead. +func FormatInt8(value int8) string { return conv.FormatInteger(value) } + +// FormatInt16 turns an int16 into a string. +// +// Deprecated: use [conv.FormatInteger] instead. +func FormatInt16(value int16) string { return conv.FormatInteger(value) } + +// FormatInt32 turns an int32 into a string +// +// Deprecated: use [conv.FormatInteger] instead. +func FormatInt32(value int32) string { return conv.FormatInteger(value) } + +// FormatInt64 turns an int64 into a string. +// +// Deprecated: use [conv.FormatInteger] instead. +func FormatInt64(value int64) string { return conv.FormatInteger(value) } + +// FormatUint8 turns an uint8 into a string. +// +// Deprecated: use [conv.FormatUinteger] instead. +func FormatUint8(value uint8) string { return conv.FormatUinteger(value) } + +// FormatUint16 turns an uint16 into a string. +// +// Deprecated: use [conv.FormatUinteger] instead. +func FormatUint16(value uint16) string { return conv.FormatUinteger(value) } + +// FormatUint32 turns an uint32 into a string. +// +// Deprecated: use [conv.FormatUinteger] instead. +func FormatUint32(value uint32) string { return conv.FormatUinteger(value) } + +// FormatUint64 turns an uint64 into a string. +// +// Deprecated: use [conv.FormatUinteger] instead. +func FormatUint64(value uint64) string { return conv.FormatUinteger(value) } + +// String turn a pointer to of the string value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func String(v string) *string { return conv.Pointer(v) } + +// StringValue turn the value of the string pointer passed in or +// "" if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func StringValue(v *string) string { return conv.Value(v) } + +// StringSlice converts a slice of string values into a slice of string pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func StringSlice(src []string) []*string { return conv.PointerSlice(src) } + +// StringValueSlice converts a slice of string pointers into a slice of string values. +// +// Deprecated: use [conv.ValueSlice] instead. +func StringValueSlice(src []*string) []string { return conv.ValueSlice(src) } + +// StringMap converts a string map of string values into a string map of string pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func StringMap(src map[string]string) map[string]*string { return conv.PointerMap(src) } + +// StringValueMap converts a string map of string pointers into a string map of string values. +// +// Deprecated: use [conv.ValueMap] instead. +func StringValueMap(src map[string]*string) map[string]string { return conv.ValueMap(src) } + +// Bool turn a pointer to of the bool value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Bool(v bool) *bool { return conv.Pointer(v) } + +// BoolValue turn the value of the bool pointer passed in or false if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func BoolValue(v *bool) bool { return conv.Value(v) } + +// BoolSlice converts a slice of bool values into a slice of bool pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func BoolSlice(src []bool) []*bool { return conv.PointerSlice(src) } + +// BoolValueSlice converts a slice of bool pointers into a slice of bool values. +// +// Deprecated: use [conv.ValueSlice] instead. +func BoolValueSlice(src []*bool) []bool { return conv.ValueSlice(src) } + +// BoolMap converts a string map of bool values into a string map of bool pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func BoolMap(src map[string]bool) map[string]*bool { return conv.PointerMap(src) } + +// BoolValueMap converts a string map of bool pointers into a string map of bool values. +// +// Deprecated: use [conv.ValueMap] instead. +func BoolValueMap(src map[string]*bool) map[string]bool { return conv.ValueMap(src) } + +// Int turn a pointer to of the int value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Int(v int) *int { return conv.Pointer(v) } + +// IntValue turn the value of the int pointer passed in or 0 if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func IntValue(v *int) int { return conv.Value(v) } + +// IntSlice converts a slice of int values into a slice of int pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func IntSlice(src []int) []*int { return conv.PointerSlice(src) } + +// IntValueSlice converts a slice of int pointers into a slice of int values. +// +// Deprecated: use [conv.ValueSlice] instead. +func IntValueSlice(src []*int) []int { return conv.ValueSlice(src) } + +// IntMap converts a string map of int values into a string map of int pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func IntMap(src map[string]int) map[string]*int { return conv.PointerMap(src) } + +// IntValueMap converts a string map of int pointers into a string map of int values. +// +// Deprecated: use [conv.ValueMap] instead. +func IntValueMap(src map[string]*int) map[string]int { return conv.ValueMap(src) } + +// Int32 turn a pointer to of the int32 value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Int32(v int32) *int32 { return conv.Pointer(v) } + +// Int32Value turn the value of the int32 pointer passed in or 0 if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func Int32Value(v *int32) int32 { return conv.Value(v) } + +// Int32Slice converts a slice of int32 values into a slice of int32 pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func Int32Slice(src []int32) []*int32 { return conv.PointerSlice(src) } + +// Int32ValueSlice converts a slice of int32 pointers into a slice of int32 values. +// +// Deprecated: use [conv.ValueSlice] instead. +func Int32ValueSlice(src []*int32) []int32 { return conv.ValueSlice(src) } + +// Int32Map converts a string map of int32 values into a string map of int32 pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func Int32Map(src map[string]int32) map[string]*int32 { return conv.PointerMap(src) } + +// Int32ValueMap converts a string map of int32 pointers into a string map of int32 values. +// +// Deprecated: use [conv.ValueMap] instead. +func Int32ValueMap(src map[string]*int32) map[string]int32 { return conv.ValueMap(src) } + +// Int64 turn a pointer to of the int64 value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Int64(v int64) *int64 { return conv.Pointer(v) } + +// Int64Value turn the value of the int64 pointer passed in or 0 if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func Int64Value(v *int64) int64 { return conv.Value(v) } + +// Int64Slice converts a slice of int64 values into a slice of int64 pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func Int64Slice(src []int64) []*int64 { return conv.PointerSlice(src) } + +// Int64ValueSlice converts a slice of int64 pointers into a slice of int64 values. +// +// Deprecated: use [conv.ValueSlice] instead. +func Int64ValueSlice(src []*int64) []int64 { return conv.ValueSlice(src) } + +// Int64Map converts a string map of int64 values into a string map of int64 pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func Int64Map(src map[string]int64) map[string]*int64 { return conv.PointerMap(src) } + +// Int64ValueMap converts a string map of int64 pointers into a string map of int64 values. +// +// Deprecated: use [conv.ValueMap] instead. +func Int64ValueMap(src map[string]*int64) map[string]int64 { return conv.ValueMap(src) } + +// Uint16 turn a pointer to of the uint16 value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Uint16(v uint16) *uint16 { return conv.Pointer(v) } + +// Uint16Value turn the value of the uint16 pointer passed in or 0 if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func Uint16Value(v *uint16) uint16 { return conv.Value(v) } + +// Uint16Slice converts a slice of uint16 values into a slice of uint16 pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func Uint16Slice(src []uint16) []*uint16 { return conv.PointerSlice(src) } + +// Uint16ValueSlice converts a slice of uint16 pointers into a slice of uint16 values. +// +// Deprecated: use [conv.ValueSlice] instead. +func Uint16ValueSlice(src []*uint16) []uint16 { return conv.ValueSlice(src) } + +// Uint16Map converts a string map of uint16 values into a string map of uint16 pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func Uint16Map(src map[string]uint16) map[string]*uint16 { return conv.PointerMap(src) } + +// Uint16ValueMap converts a string map of uint16 pointers into a string map of uint16 values. +// +// Deprecated: use [conv.ValueMap] instead. +func Uint16ValueMap(src map[string]*uint16) map[string]uint16 { return conv.ValueMap(src) } + +// Uint turn a pointer to of the uint value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Uint(v uint) *uint { return conv.Pointer(v) } + +// UintValue turn the value of the uint pointer passed in or 0 if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func UintValue(v *uint) uint { return conv.Value(v) } + +// UintSlice converts a slice of uint values into a slice of uint pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func UintSlice(src []uint) []*uint { return conv.PointerSlice(src) } + +// UintValueSlice converts a slice of uint pointers into a slice of uint values. +// +// Deprecated: use [conv.ValueSlice] instead. +func UintValueSlice(src []*uint) []uint { return conv.ValueSlice(src) } + +// UintMap converts a string map of uint values into a string map of uint pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func UintMap(src map[string]uint) map[string]*uint { return conv.PointerMap(src) } + +// UintValueMap converts a string map of uint pointers into a string map of uint values. +// +// Deprecated: use [conv.ValueMap] instead. +func UintValueMap(src map[string]*uint) map[string]uint { return conv.ValueMap(src) } + +// Uint32 turn a pointer to of the uint32 value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Uint32(v uint32) *uint32 { return conv.Pointer(v) } + +// Uint32Value turn the value of the uint32 pointer passed in or 0 if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func Uint32Value(v *uint32) uint32 { return conv.Value(v) } + +// Uint32Slice converts a slice of uint32 values into a slice of uint32 pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func Uint32Slice(src []uint32) []*uint32 { return conv.PointerSlice(src) } + +// Uint32ValueSlice converts a slice of uint32 pointers into a slice of uint32 values. +// +// Deprecated: use [conv.ValueSlice] instead. +func Uint32ValueSlice(src []*uint32) []uint32 { return conv.ValueSlice(src) } + +// Uint32Map converts a string map of uint32 values into a string map of uint32 pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func Uint32Map(src map[string]uint32) map[string]*uint32 { return conv.PointerMap(src) } + +// Uint32ValueMap converts a string map of uint32 pointers into a string map of uint32 values. +// +// Deprecated: use [conv.ValueMap] instead. +func Uint32ValueMap(src map[string]*uint32) map[string]uint32 { return conv.ValueMap(src) } + +// Uint64 turn a pointer to of the uint64 value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Uint64(v uint64) *uint64 { return conv.Pointer(v) } + +// Uint64Value turn the value of the uint64 pointer passed in or 0 if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func Uint64Value(v *uint64) uint64 { return conv.Value(v) } + +// Uint64Slice converts a slice of uint64 values into a slice of uint64 pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func Uint64Slice(src []uint64) []*uint64 { return conv.PointerSlice(src) } + +// Uint64ValueSlice converts a slice of uint64 pointers into a slice of uint64 values. +// +// Deprecated: use [conv.ValueSlice] instead. +func Uint64ValueSlice(src []*uint64) []uint64 { return conv.ValueSlice(src) } + +// Uint64Map converts a string map of uint64 values into a string map of uint64 pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func Uint64Map(src map[string]uint64) map[string]*uint64 { return conv.PointerMap(src) } + +// Uint64ValueMap converts a string map of uint64 pointers into a string map of uint64 values. +// +// Deprecated: use [conv.ValueMap] instead. +func Uint64ValueMap(src map[string]*uint64) map[string]uint64 { return conv.ValueMap(src) } + +// Float32 turn a pointer to of the float32 value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Float32(v float32) *float32 { return conv.Pointer(v) } + +// Float32Value turn the value of the float32 pointer passed in or 0 if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func Float32Value(v *float32) float32 { return conv.Value(v) } + +// Float32Slice converts a slice of float32 values into a slice of float32 pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func Float32Slice(src []float32) []*float32 { return conv.PointerSlice(src) } + +// Float32ValueSlice converts a slice of float32 pointers into a slice of float32 values. +// +// Deprecated: use [conv.ValueSlice] instead. +func Float32ValueSlice(src []*float32) []float32 { return conv.ValueSlice(src) } + +// Float32Map converts a string map of float32 values into a string map of float32 pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func Float32Map(src map[string]float32) map[string]*float32 { return conv.PointerMap(src) } + +// Float32ValueMap converts a string map of float32 pointers into a string map of float32 values. +// +// Deprecated: use [conv.ValueMap] instead. +func Float32ValueMap(src map[string]*float32) map[string]float32 { return conv.ValueMap(src) } + +// Float64 turn a pointer to of the float64 value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Float64(v float64) *float64 { return conv.Pointer(v) } + +// Float64Value turn the value of the float64 pointer passed in or 0 if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func Float64Value(v *float64) float64 { return conv.Value(v) } + +// Float64Slice converts a slice of float64 values into a slice of float64 pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func Float64Slice(src []float64) []*float64 { return conv.PointerSlice(src) } + +// Float64ValueSlice converts a slice of float64 pointers into a slice of float64 values. +// +// Deprecated: use [conv.ValueSlice] instead. +func Float64ValueSlice(src []*float64) []float64 { return conv.ValueSlice(src) } + +// Float64Map converts a string map of float64 values into a string map of float64 pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func Float64Map(src map[string]float64) map[string]*float64 { return conv.PointerMap(src) } + +// Float64ValueMap converts a string map of float64 pointers into a string map of float64 values. +// +// Deprecated: use [conv.ValueMap] instead. +func Float64ValueMap(src map[string]*float64) map[string]float64 { return conv.ValueMap(src) } + +// Time turn a pointer to of the time.Time value passed in. +// +// Deprecated: use [conv.Pointer] instead. +func Time(v time.Time) *time.Time { return conv.Pointer(v) } + +// TimeValue turn the value of the time.Time pointer passed in or time.Time{} if the pointer is nil. +// +// Deprecated: use [conv.Value] instead. +func TimeValue(v *time.Time) time.Time { return conv.Value(v) } + +// TimeSlice converts a slice of time.Time values into a slice of time.Time pointers. +// +// Deprecated: use [conv.PointerSlice] instead. +func TimeSlice(src []time.Time) []*time.Time { return conv.PointerSlice(src) } + +// TimeValueSlice converts a slice of time.Time pointers into a slice of time.Time values +// +// Deprecated: use [conv.ValueSlice] instead. +func TimeValueSlice(src []*time.Time) []time.Time { return conv.ValueSlice(src) } + +// TimeMap converts a string map of time.Time values into a string map of time.Time pointers. +// +// Deprecated: use [conv.PointerMap] instead. +func TimeMap(src map[string]time.Time) map[string]*time.Time { return conv.PointerMap(src) } + +// TimeValueMap converts a string map of time.Time pointers into a string map of time.Time values. +// +// Deprecated: use [conv.ValueMap] instead. +func TimeValueMap(src map[string]*time.Time) map[string]time.Time { return conv.ValueMap(src) } diff --git a/vendor/github.com/go-openapi/swag/convert.go b/vendor/github.com/go-openapi/swag/convert.go deleted file mode 100644 index fc085aeb8..000000000 --- a/vendor/github.com/go-openapi/swag/convert.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// 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 swag - -import ( - "math" - "strconv" - "strings" -) - -// same as ECMA Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER -const ( - maxJSONFloat = float64(1<<53 - 1) // 9007199254740991.0 2^53 - 1 - minJSONFloat = -float64(1<<53 - 1) //-9007199254740991.0 -2^53 - 1 - epsilon float64 = 1e-9 -) - -// IsFloat64AJSONInteger allow for integers [-2^53, 2^53-1] inclusive -func IsFloat64AJSONInteger(f float64) bool { - if math.IsNaN(f) || math.IsInf(f, 0) || f < minJSONFloat || f > maxJSONFloat { - return false - } - fa := math.Abs(f) - g := float64(uint64(f)) - ga := math.Abs(g) - - diff := math.Abs(f - g) - - // more info: https://floating-point-gui.de/errors/comparison/#look-out-for-edge-cases - switch { - case f == g: // best case - return true - case f == float64(int64(f)) || f == float64(uint64(f)): // optimistic case - return true - case f == 0 || g == 0 || diff < math.SmallestNonzeroFloat64: // very close to 0 values - return diff < (epsilon * math.SmallestNonzeroFloat64) - } - // check the relative error - return diff/math.Min(fa+ga, math.MaxFloat64) < epsilon -} - -var evaluatesAsTrue map[string]struct{} - -func init() { - evaluatesAsTrue = map[string]struct{}{ - "true": {}, - "1": {}, - "yes": {}, - "ok": {}, - "y": {}, - "on": {}, - "selected": {}, - "checked": {}, - "t": {}, - "enabled": {}, - } -} - -// ConvertBool turn a string into a boolean -func ConvertBool(str string) (bool, error) { - _, ok := evaluatesAsTrue[strings.ToLower(str)] - return ok, nil -} - -// ConvertFloat32 turn a string into a float32 -func ConvertFloat32(str string) (float32, error) { - f, err := strconv.ParseFloat(str, 32) - if err != nil { - return 0, err - } - return float32(f), nil -} - -// ConvertFloat64 turn a string into a float64 -func ConvertFloat64(str string) (float64, error) { - return strconv.ParseFloat(str, 64) -} - -// ConvertInt8 turn a string into an int8 -func ConvertInt8(str string) (int8, error) { - i, err := strconv.ParseInt(str, 10, 8) - if err != nil { - return 0, err - } - return int8(i), nil -} - -// ConvertInt16 turn a string into an int16 -func ConvertInt16(str string) (int16, error) { - i, err := strconv.ParseInt(str, 10, 16) - if err != nil { - return 0, err - } - return int16(i), nil -} - -// ConvertInt32 turn a string into an int32 -func ConvertInt32(str string) (int32, error) { - i, err := strconv.ParseInt(str, 10, 32) - if err != nil { - return 0, err - } - return int32(i), nil -} - -// ConvertInt64 turn a string into an int64 -func ConvertInt64(str string) (int64, error) { - return strconv.ParseInt(str, 10, 64) -} - -// ConvertUint8 turn a string into an uint8 -func ConvertUint8(str string) (uint8, error) { - i, err := strconv.ParseUint(str, 10, 8) - if err != nil { - return 0, err - } - return uint8(i), nil -} - -// ConvertUint16 turn a string into an uint16 -func ConvertUint16(str string) (uint16, error) { - i, err := strconv.ParseUint(str, 10, 16) - if err != nil { - return 0, err - } - return uint16(i), nil -} - -// ConvertUint32 turn a string into an uint32 -func ConvertUint32(str string) (uint32, error) { - i, err := strconv.ParseUint(str, 10, 32) - if err != nil { - return 0, err - } - return uint32(i), nil -} - -// ConvertUint64 turn a string into an uint64 -func ConvertUint64(str string) (uint64, error) { - return strconv.ParseUint(str, 10, 64) -} - -// FormatBool turns a boolean into a string -func FormatBool(value bool) string { - return strconv.FormatBool(value) -} - -// FormatFloat32 turns a float32 into a string -func FormatFloat32(value float32) string { - return strconv.FormatFloat(float64(value), 'f', -1, 32) -} - -// FormatFloat64 turns a float64 into a string -func FormatFloat64(value float64) string { - return strconv.FormatFloat(value, 'f', -1, 64) -} - -// FormatInt8 turns an int8 into a string -func FormatInt8(value int8) string { - return strconv.FormatInt(int64(value), 10) -} - -// FormatInt16 turns an int16 into a string -func FormatInt16(value int16) string { - return strconv.FormatInt(int64(value), 10) -} - -// FormatInt32 turns an int32 into a string -func FormatInt32(value int32) string { - return strconv.Itoa(int(value)) -} - -// FormatInt64 turns an int64 into a string -func FormatInt64(value int64) string { - return strconv.FormatInt(value, 10) -} - -// FormatUint8 turns an uint8 into a string -func FormatUint8(value uint8) string { - return strconv.FormatUint(uint64(value), 10) -} - -// FormatUint16 turns an uint16 into a string -func FormatUint16(value uint16) string { - return strconv.FormatUint(uint64(value), 10) -} - -// FormatUint32 turns an uint32 into a string -func FormatUint32(value uint32) string { - return strconv.FormatUint(uint64(value), 10) -} - -// FormatUint64 turns an uint64 into a string -func FormatUint64(value uint64) string { - return strconv.FormatUint(value, 10) -} diff --git a/vendor/github.com/go-openapi/swag/convert_types.go b/vendor/github.com/go-openapi/swag/convert_types.go deleted file mode 100644 index c49cc473a..000000000 --- a/vendor/github.com/go-openapi/swag/convert_types.go +++ /dev/null @@ -1,730 +0,0 @@ -package swag - -import "time" - -// This file was taken from the aws go sdk - -// String returns a pointer to of the string value passed in. -func String(v string) *string { - return &v -} - -// StringValue returns the value of the string pointer passed in or -// "" if the pointer is nil. -func StringValue(v *string) string { - if v != nil { - return *v - } - return "" -} - -// StringSlice converts a slice of string values into a slice of -// string pointers -func StringSlice(src []string) []*string { - dst := make([]*string, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// StringValueSlice converts a slice of string pointers into a slice of -// string values -func StringValueSlice(src []*string) []string { - dst := make([]string, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// StringMap converts a string map of string values into a string -// map of string pointers -func StringMap(src map[string]string) map[string]*string { - dst := make(map[string]*string) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// StringValueMap converts a string map of string pointers into a string -// map of string values -func StringValueMap(src map[string]*string) map[string]string { - dst := make(map[string]string) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} - -// Bool returns a pointer to of the bool value passed in. -func Bool(v bool) *bool { - return &v -} - -// BoolValue returns the value of the bool pointer passed in or -// false if the pointer is nil. -func BoolValue(v *bool) bool { - if v != nil { - return *v - } - return false -} - -// BoolSlice converts a slice of bool values into a slice of -// bool pointers -func BoolSlice(src []bool) []*bool { - dst := make([]*bool, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// BoolValueSlice converts a slice of bool pointers into a slice of -// bool values -func BoolValueSlice(src []*bool) []bool { - dst := make([]bool, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// BoolMap converts a string map of bool values into a string -// map of bool pointers -func BoolMap(src map[string]bool) map[string]*bool { - dst := make(map[string]*bool) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// BoolValueMap converts a string map of bool pointers into a string -// map of bool values -func BoolValueMap(src map[string]*bool) map[string]bool { - dst := make(map[string]bool) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} - -// Int returns a pointer to of the int value passed in. -func Int(v int) *int { - return &v -} - -// IntValue returns the value of the int pointer passed in or -// 0 if the pointer is nil. -func IntValue(v *int) int { - if v != nil { - return *v - } - return 0 -} - -// IntSlice converts a slice of int values into a slice of -// int pointers -func IntSlice(src []int) []*int { - dst := make([]*int, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// IntValueSlice converts a slice of int pointers into a slice of -// int values -func IntValueSlice(src []*int) []int { - dst := make([]int, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// IntMap converts a string map of int values into a string -// map of int pointers -func IntMap(src map[string]int) map[string]*int { - dst := make(map[string]*int) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// IntValueMap converts a string map of int pointers into a string -// map of int values -func IntValueMap(src map[string]*int) map[string]int { - dst := make(map[string]int) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} - -// Int32 returns a pointer to of the int32 value passed in. -func Int32(v int32) *int32 { - return &v -} - -// Int32Value returns the value of the int32 pointer passed in or -// 0 if the pointer is nil. -func Int32Value(v *int32) int32 { - if v != nil { - return *v - } - return 0 -} - -// Int32Slice converts a slice of int32 values into a slice of -// int32 pointers -func Int32Slice(src []int32) []*int32 { - dst := make([]*int32, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// Int32ValueSlice converts a slice of int32 pointers into a slice of -// int32 values -func Int32ValueSlice(src []*int32) []int32 { - dst := make([]int32, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// Int32Map converts a string map of int32 values into a string -// map of int32 pointers -func Int32Map(src map[string]int32) map[string]*int32 { - dst := make(map[string]*int32) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// Int32ValueMap converts a string map of int32 pointers into a string -// map of int32 values -func Int32ValueMap(src map[string]*int32) map[string]int32 { - dst := make(map[string]int32) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} - -// Int64 returns a pointer to of the int64 value passed in. -func Int64(v int64) *int64 { - return &v -} - -// Int64Value returns the value of the int64 pointer passed in or -// 0 if the pointer is nil. -func Int64Value(v *int64) int64 { - if v != nil { - return *v - } - return 0 -} - -// Int64Slice converts a slice of int64 values into a slice of -// int64 pointers -func Int64Slice(src []int64) []*int64 { - dst := make([]*int64, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// Int64ValueSlice converts a slice of int64 pointers into a slice of -// int64 values -func Int64ValueSlice(src []*int64) []int64 { - dst := make([]int64, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// Int64Map converts a string map of int64 values into a string -// map of int64 pointers -func Int64Map(src map[string]int64) map[string]*int64 { - dst := make(map[string]*int64) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// Int64ValueMap converts a string map of int64 pointers into a string -// map of int64 values -func Int64ValueMap(src map[string]*int64) map[string]int64 { - dst := make(map[string]int64) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} - -// Uint16 returns a pointer to of the uint16 value passed in. -func Uint16(v uint16) *uint16 { - return &v -} - -// Uint16Value returns the value of the uint16 pointer passed in or -// 0 if the pointer is nil. -func Uint16Value(v *uint16) uint16 { - if v != nil { - return *v - } - - return 0 -} - -// Uint16Slice converts a slice of uint16 values into a slice of -// uint16 pointers -func Uint16Slice(src []uint16) []*uint16 { - dst := make([]*uint16, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - - return dst -} - -// Uint16ValueSlice converts a slice of uint16 pointers into a slice of -// uint16 values -func Uint16ValueSlice(src []*uint16) []uint16 { - dst := make([]uint16, len(src)) - - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - - return dst -} - -// Uint16Map converts a string map of uint16 values into a string -// map of uint16 pointers -func Uint16Map(src map[string]uint16) map[string]*uint16 { - dst := make(map[string]*uint16) - - for k, val := range src { - v := val - dst[k] = &v - } - - return dst -} - -// Uint16ValueMap converts a string map of uint16 pointers into a string -// map of uint16 values -func Uint16ValueMap(src map[string]*uint16) map[string]uint16 { - dst := make(map[string]uint16) - - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - - return dst -} - -// Uint returns a pointer to of the uint value passed in. -func Uint(v uint) *uint { - return &v -} - -// UintValue returns the value of the uint pointer passed in or -// 0 if the pointer is nil. -func UintValue(v *uint) uint { - if v != nil { - return *v - } - return 0 -} - -// UintSlice converts a slice of uint values into a slice of -// uint pointers -func UintSlice(src []uint) []*uint { - dst := make([]*uint, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// UintValueSlice converts a slice of uint pointers into a slice of -// uint values -func UintValueSlice(src []*uint) []uint { - dst := make([]uint, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// UintMap converts a string map of uint values into a string -// map of uint pointers -func UintMap(src map[string]uint) map[string]*uint { - dst := make(map[string]*uint) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// UintValueMap converts a string map of uint pointers into a string -// map of uint values -func UintValueMap(src map[string]*uint) map[string]uint { - dst := make(map[string]uint) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} - -// Uint32 returns a pointer to of the uint32 value passed in. -func Uint32(v uint32) *uint32 { - return &v -} - -// Uint32Value returns the value of the uint32 pointer passed in or -// 0 if the pointer is nil. -func Uint32Value(v *uint32) uint32 { - if v != nil { - return *v - } - return 0 -} - -// Uint32Slice converts a slice of uint32 values into a slice of -// uint32 pointers -func Uint32Slice(src []uint32) []*uint32 { - dst := make([]*uint32, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// Uint32ValueSlice converts a slice of uint32 pointers into a slice of -// uint32 values -func Uint32ValueSlice(src []*uint32) []uint32 { - dst := make([]uint32, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// Uint32Map converts a string map of uint32 values into a string -// map of uint32 pointers -func Uint32Map(src map[string]uint32) map[string]*uint32 { - dst := make(map[string]*uint32) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// Uint32ValueMap converts a string map of uint32 pointers into a string -// map of uint32 values -func Uint32ValueMap(src map[string]*uint32) map[string]uint32 { - dst := make(map[string]uint32) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} - -// Uint64 returns a pointer to of the uint64 value passed in. -func Uint64(v uint64) *uint64 { - return &v -} - -// Uint64Value returns the value of the uint64 pointer passed in or -// 0 if the pointer is nil. -func Uint64Value(v *uint64) uint64 { - if v != nil { - return *v - } - return 0 -} - -// Uint64Slice converts a slice of uint64 values into a slice of -// uint64 pointers -func Uint64Slice(src []uint64) []*uint64 { - dst := make([]*uint64, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// Uint64ValueSlice converts a slice of uint64 pointers into a slice of -// uint64 values -func Uint64ValueSlice(src []*uint64) []uint64 { - dst := make([]uint64, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// Uint64Map converts a string map of uint64 values into a string -// map of uint64 pointers -func Uint64Map(src map[string]uint64) map[string]*uint64 { - dst := make(map[string]*uint64) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// Uint64ValueMap converts a string map of uint64 pointers into a string -// map of uint64 values -func Uint64ValueMap(src map[string]*uint64) map[string]uint64 { - dst := make(map[string]uint64) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} - -// Float32 returns a pointer to of the float32 value passed in. -func Float32(v float32) *float32 { - return &v -} - -// Float32Value returns the value of the float32 pointer passed in or -// 0 if the pointer is nil. -func Float32Value(v *float32) float32 { - if v != nil { - return *v - } - - return 0 -} - -// Float32Slice converts a slice of float32 values into a slice of -// float32 pointers -func Float32Slice(src []float32) []*float32 { - dst := make([]*float32, len(src)) - - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - - return dst -} - -// Float32ValueSlice converts a slice of float32 pointers into a slice of -// float32 values -func Float32ValueSlice(src []*float32) []float32 { - dst := make([]float32, len(src)) - - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - - return dst -} - -// Float32Map converts a string map of float32 values into a string -// map of float32 pointers -func Float32Map(src map[string]float32) map[string]*float32 { - dst := make(map[string]*float32) - - for k, val := range src { - v := val - dst[k] = &v - } - - return dst -} - -// Float32ValueMap converts a string map of float32 pointers into a string -// map of float32 values -func Float32ValueMap(src map[string]*float32) map[string]float32 { - dst := make(map[string]float32) - - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - - return dst -} - -// Float64 returns a pointer to of the float64 value passed in. -func Float64(v float64) *float64 { - return &v -} - -// Float64Value returns the value of the float64 pointer passed in or -// 0 if the pointer is nil. -func Float64Value(v *float64) float64 { - if v != nil { - return *v - } - return 0 -} - -// Float64Slice converts a slice of float64 values into a slice of -// float64 pointers -func Float64Slice(src []float64) []*float64 { - dst := make([]*float64, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// Float64ValueSlice converts a slice of float64 pointers into a slice of -// float64 values -func Float64ValueSlice(src []*float64) []float64 { - dst := make([]float64, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// Float64Map converts a string map of float64 values into a string -// map of float64 pointers -func Float64Map(src map[string]float64) map[string]*float64 { - dst := make(map[string]*float64) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// Float64ValueMap converts a string map of float64 pointers into a string -// map of float64 values -func Float64ValueMap(src map[string]*float64) map[string]float64 { - dst := make(map[string]float64) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} - -// Time returns a pointer to of the time.Time value passed in. -func Time(v time.Time) *time.Time { - return &v -} - -// TimeValue returns the value of the time.Time pointer passed in or -// time.Time{} if the pointer is nil. -func TimeValue(v *time.Time) time.Time { - if v != nil { - return *v - } - return time.Time{} -} - -// TimeSlice converts a slice of time.Time values into a slice of -// time.Time pointers -func TimeSlice(src []time.Time) []*time.Time { - dst := make([]*time.Time, len(src)) - for i := 0; i < len(src); i++ { - dst[i] = &(src[i]) - } - return dst -} - -// TimeValueSlice converts a slice of time.Time pointers into a slice of -// time.Time values -func TimeValueSlice(src []*time.Time) []time.Time { - dst := make([]time.Time, len(src)) - for i := 0; i < len(src); i++ { - if src[i] != nil { - dst[i] = *(src[i]) - } - } - return dst -} - -// TimeMap converts a string map of time.Time values into a string -// map of time.Time pointers -func TimeMap(src map[string]time.Time) map[string]*time.Time { - dst := make(map[string]*time.Time) - for k, val := range src { - v := val - dst[k] = &v - } - return dst -} - -// TimeValueMap converts a string map of time.Time pointers into a string -// map of time.Time values -func TimeValueMap(src map[string]*time.Time) map[string]time.Time { - dst := make(map[string]time.Time) - for k, val := range src { - if val != nil { - dst[k] = *val - } - } - return dst -} diff --git a/vendor/github.com/go-openapi/swag/doc.go b/vendor/github.com/go-openapi/swag/doc.go index 55094cb74..b54b57478 100644 --- a/vendor/github.com/go-openapi/swag/doc.go +++ b/vendor/github.com/go-openapi/swag/doc.go @@ -1,31 +1,47 @@ -// Copyright 2015 go-swagger maintainers +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package swag contains a bunch of helper functions for go-openapi and go-swagger projects. // -// 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 +// You may also use it standalone for your projects. // -// http://www.apache.org/licenses/LICENSE-2.0 +// NOTE: all features that used to be exposed as package-level members (constants, variables, +// functions and types) are now deprecated and are superseded by equivalent features in +// more specialized sub-packages. +// Moving forward, no additional feature will be added to the [swag] API directly at the root package level, +// which remains there for backward-compatibility purposes. // -// 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 swag contains a bunch of helper functions for go-openapi and go-swagger projects. - -You may also use it standalone for your projects. - - - convert between value and pointers for builtin types - - convert from string to builtin types (wraps strconv) - - fast json concatenation - - search in path - - load from file or http - - name mangling - -This repo has only few dependencies outside of the standard library: - - - YAML utilities depend on gopkg.in/yaml.v2 -*/ +// Child modules will continue to evolve or some new ones may be added in the future. +// +// # Modules +// +// - [cmdutils] utilities to work with CLIs +// +// - [conv] type conversion utilities +// +// - [fileutils] file utilities +// +// - [jsonname] JSON utilities +// +// - [jsonutils] JSON utilities +// +// - [loading] file loading +// +// - [mangling] safe name generation +// +// - [netutils] networking utilities +// +// - [stringutils] `string` utilities +// +// - [typeutils] `go` types utilities +// +// - [yamlutils] YAML utilities +// +// # Dependencies +// +// This repo has a few dependencies outside of the standard library: +// +// - YAML utilities depend on [go.yaml.in/yaml/v3] package swag + +//go:generate mockery diff --git a/vendor/github.com/go-openapi/swag/errors.go b/vendor/github.com/go-openapi/swag/errors.go deleted file mode 100644 index 6c67fbf92..000000000 --- a/vendor/github.com/go-openapi/swag/errors.go +++ /dev/null @@ -1,15 +0,0 @@ -package swag - -type swagError string - -const ( - // ErrYAML is an error raised by YAML utilities - ErrYAML swagError = "yaml error" - - // ErrLoader is an error raised by the file loader utility - ErrLoader swagError = "loader error" -) - -func (e swagError) Error() string { - return string(e) -} diff --git a/vendor/github.com/go-openapi/swag/file.go b/vendor/github.com/go-openapi/swag/file.go deleted file mode 100644 index 16accc55f..000000000 --- a/vendor/github.com/go-openapi/swag/file.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// 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 swag - -import "mime/multipart" - -// File represents an uploaded file. -type File struct { - Data multipart.File - Header *multipart.FileHeader -} - -// Read bytes from the file -func (f *File) Read(p []byte) (n int, err error) { - return f.Data.Read(p) -} - -// Close the file -func (f *File) Close() error { - return f.Data.Close() -} diff --git a/vendor/github.com/go-openapi/swag/fileutils/LICENSE b/vendor/github.com/go-openapi/swag/fileutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/fileutils/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/fileutils/doc.go b/vendor/github.com/go-openapi/swag/fileutils/doc.go new file mode 100644 index 000000000..859a200d8 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/fileutils/doc.go @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package fileutils exposes utilities to deal with files and paths. +// +// Currently, there is: +// - [File] to represent an abstraction of an uploaded file. +// For instance, this is used by [github.com/go-openapi/runtime.File]. +// - path search utilities (e.g. finding packages in the GO search path) +package fileutils diff --git a/vendor/github.com/go-openapi/swag/fileutils/file.go b/vendor/github.com/go-openapi/swag/fileutils/file.go new file mode 100644 index 000000000..5ad4cfaea --- /dev/null +++ b/vendor/github.com/go-openapi/swag/fileutils/file.go @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package fileutils + +import "mime/multipart" + +// File represents an uploaded file. +type File struct { + Data multipart.File + Header *multipart.FileHeader +} + +// Read bytes from the file +func (f *File) Read(p []byte) (n int, err error) { + return f.Data.Read(p) +} + +// Close the file +func (f *File) Close() error { + return f.Data.Close() +} diff --git a/vendor/github.com/go-openapi/swag/path.go b/vendor/github.com/go-openapi/swag/fileutils/path.go similarity index 58% rename from vendor/github.com/go-openapi/swag/path.go rename to vendor/github.com/go-openapi/swag/fileutils/path.go index 941bd0176..dd09f690b 100644 --- a/vendor/github.com/go-openapi/swag/path.go +++ b/vendor/github.com/go-openapi/swag/fileutils/path.go @@ -1,18 +1,7 @@ -// Copyright 2015 go-swagger maintainers -// -// 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. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 -package swag +package fileutils import ( "os" @@ -21,10 +10,8 @@ import ( "strings" ) -const ( - // GOPATHKey represents the env key for gopath - GOPATHKey = "GOPATH" -) +// GOPATHKey represents the env key for gopath +const GOPATHKey = "GOPATH" // FindInSearchPath finds a package in a provided lists of paths func FindInSearchPath(searchPath, pkg string) string { @@ -40,11 +27,17 @@ func FindInSearchPath(searchPath, pkg string) string { } // FindInGoSearchPath finds a package in the $GOPATH:$GOROOT +// +// Deprecated: this function is no longer relevant with modern go. +// It uses [runtime.GOROOT] under the hood, which is deprecated as of go1.24. func FindInGoSearchPath(pkg string) string { return FindInSearchPath(FullGoSearchPath(), pkg) } // FullGoSearchPath gets the search paths for finding packages +// +// Deprecated: this function is no longer relevant with modern go. +// It uses [runtime.GOROOT] under the hood, which is deprecated as of go1.24. func FullGoSearchPath() string { allPaths := os.Getenv(GOPATHKey) if allPaths == "" { diff --git a/vendor/github.com/go-openapi/swag/fileutils_iface.go b/vendor/github.com/go-openapi/swag/fileutils_iface.go new file mode 100644 index 000000000..f3e79a0e4 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/fileutils_iface.go @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import "github.com/go-openapi/swag/fileutils" + +// GOPATHKey represents the env key for gopath +// +// Deprecated: use [fileutils.GOPATHKey] instead. +const GOPATHKey = fileutils.GOPATHKey + +// File represents an uploaded file. +// +// Deprecated: use [fileutils.File] instead. +type File = fileutils.File + +// FindInSearchPath finds a package in a provided lists of paths. +// +// Deprecated: use [fileutils.FindInSearchPath] instead. +func FindInSearchPath(searchPath, pkg string) string { + return fileutils.FindInSearchPath(searchPath, pkg) +} + +// FindInGoSearchPath finds a package in the $GOPATH:$GOROOT +// +// Deprecated: use [fileutils.FindInGoSearchPath] instead. +func FindInGoSearchPath(pkg string) string { return fileutils.FindInGoSearchPath(pkg) } + +// FullGoSearchPath gets the search paths for finding packages +// +// Deprecated: use [fileutils.FullGoSearchPath] instead. +func FullGoSearchPath() string { return fileutils.FullGoSearchPath() } diff --git a/vendor/github.com/go-openapi/swag/initialism_index.go b/vendor/github.com/go-openapi/swag/initialism_index.go deleted file mode 100644 index 20a359bb6..000000000 --- a/vendor/github.com/go-openapi/swag/initialism_index.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// 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 swag - -import ( - "sort" - "strings" - "sync" -) - -var ( - // commonInitialisms are common acronyms that are kept as whole uppercased words. - commonInitialisms *indexOfInitialisms - - // initialisms is a slice of sorted initialisms - initialisms []string - - // a copy of initialisms pre-baked as []rune - initialismsRunes [][]rune - initialismsUpperCased [][]rune - - isInitialism func(string) bool - - maxAllocMatches int -) - -func init() { - // Taken from https://github.com/golang/lint/blob/3390df4df2787994aea98de825b964ac7944b817/lint.go#L732-L769 - configuredInitialisms := map[string]bool{ - "ACL": true, - "API": true, - "ASCII": true, - "CPU": true, - "CSS": true, - "DNS": true, - "EOF": true, - "GUID": true, - "HTML": true, - "HTTPS": true, - "HTTP": true, - "ID": true, - "IP": true, - "IPv4": true, - "IPv6": true, - "JSON": true, - "LHS": true, - "OAI": true, - "QPS": true, - "RAM": true, - "RHS": true, - "RPC": true, - "SLA": true, - "SMTP": true, - "SQL": true, - "SSH": true, - "TCP": true, - "TLS": true, - "TTL": true, - "UDP": true, - "UI": true, - "UID": true, - "UUID": true, - "URI": true, - "URL": true, - "UTF8": true, - "VM": true, - "XML": true, - "XMPP": true, - "XSRF": true, - "XSS": true, - } - - // a thread-safe index of initialisms - commonInitialisms = newIndexOfInitialisms().load(configuredInitialisms) - initialisms = commonInitialisms.sorted() - initialismsRunes = asRunes(initialisms) - initialismsUpperCased = asUpperCased(initialisms) - maxAllocMatches = maxAllocHeuristic(initialismsRunes) - - // a test function - isInitialism = commonInitialisms.isInitialism -} - -func asRunes(in []string) [][]rune { - out := make([][]rune, len(in)) - for i, initialism := range in { - out[i] = []rune(initialism) - } - - return out -} - -func asUpperCased(in []string) [][]rune { - out := make([][]rune, len(in)) - - for i, initialism := range in { - out[i] = []rune(upper(trim(initialism))) - } - - return out -} - -func maxAllocHeuristic(in [][]rune) int { - heuristic := make(map[rune]int) - for _, initialism := range in { - heuristic[initialism[0]]++ - } - - var maxAlloc int - for _, val := range heuristic { - if val > maxAlloc { - maxAlloc = val - } - } - - return maxAlloc -} - -// AddInitialisms add additional initialisms -func AddInitialisms(words ...string) { - for _, word := range words { - // commonInitialisms[upper(word)] = true - commonInitialisms.add(upper(word)) - } - // sort again - initialisms = commonInitialisms.sorted() - initialismsRunes = asRunes(initialisms) - initialismsUpperCased = asUpperCased(initialisms) -} - -// indexOfInitialisms is a thread-safe implementation of the sorted index of initialisms. -// Since go1.9, this may be implemented with sync.Map. -type indexOfInitialisms struct { - sortMutex *sync.Mutex - index *sync.Map -} - -func newIndexOfInitialisms() *indexOfInitialisms { - return &indexOfInitialisms{ - sortMutex: new(sync.Mutex), - index: new(sync.Map), - } -} - -func (m *indexOfInitialisms) load(initial map[string]bool) *indexOfInitialisms { - m.sortMutex.Lock() - defer m.sortMutex.Unlock() - for k, v := range initial { - m.index.Store(k, v) - } - return m -} - -func (m *indexOfInitialisms) isInitialism(key string) bool { - _, ok := m.index.Load(key) - return ok -} - -func (m *indexOfInitialisms) add(key string) *indexOfInitialisms { - m.index.Store(key, true) - return m -} - -func (m *indexOfInitialisms) sorted() (result []string) { - m.sortMutex.Lock() - defer m.sortMutex.Unlock() - m.index.Range(func(key, _ interface{}) bool { - k := key.(string) - result = append(result, k) - return true - }) - sort.Sort(sort.Reverse(byInitialism(result))) - return -} - -type byInitialism []string - -func (s byInitialism) Len() int { - return len(s) -} -func (s byInitialism) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} -func (s byInitialism) Less(i, j int) bool { - if len(s[i]) != len(s[j]) { - return len(s[i]) < len(s[j]) - } - - return strings.Compare(s[i], s[j]) > 0 -} diff --git a/vendor/github.com/go-openapi/swag/json.go b/vendor/github.com/go-openapi/swag/json.go deleted file mode 100644 index c7caa9908..000000000 --- a/vendor/github.com/go-openapi/swag/json.go +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// 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 swag - -import ( - "bytes" - "encoding/json" - "log" - "reflect" - "strings" - "sync" - - "github.com/mailru/easyjson/jlexer" - "github.com/mailru/easyjson/jwriter" -) - -// nullJSON represents a JSON object with null type -var nullJSON = []byte("null") - -// DefaultJSONNameProvider the default cache for types -var DefaultJSONNameProvider = NewNameProvider() - -const comma = byte(',') - -var closers map[byte]byte - -func init() { - closers = map[byte]byte{ - '{': '}', - '[': ']', - } -} - -type ejMarshaler interface { - MarshalEasyJSON(w *jwriter.Writer) -} - -type ejUnmarshaler interface { - UnmarshalEasyJSON(w *jlexer.Lexer) -} - -// WriteJSON writes json data, prefers finding an appropriate interface to short-circuit the marshaler -// so it takes the fastest option available. -func WriteJSON(data interface{}) ([]byte, error) { - if d, ok := data.(ejMarshaler); ok { - jw := new(jwriter.Writer) - d.MarshalEasyJSON(jw) - return jw.BuildBytes() - } - if d, ok := data.(json.Marshaler); ok { - return d.MarshalJSON() - } - return json.Marshal(data) -} - -// ReadJSON reads json data, prefers finding an appropriate interface to short-circuit the unmarshaler -// so it takes the fastest option available -func ReadJSON(data []byte, value interface{}) error { - trimmedData := bytes.Trim(data, "\x00") - if d, ok := value.(ejUnmarshaler); ok { - jl := &jlexer.Lexer{Data: trimmedData} - d.UnmarshalEasyJSON(jl) - return jl.Error() - } - if d, ok := value.(json.Unmarshaler); ok { - return d.UnmarshalJSON(trimmedData) - } - return json.Unmarshal(trimmedData, value) -} - -// DynamicJSONToStruct converts an untyped json structure into a struct -func DynamicJSONToStruct(data interface{}, target interface{}) error { - // TODO: convert straight to a json typed map (mergo + iterate?) - b, err := WriteJSON(data) - if err != nil { - return err - } - return ReadJSON(b, target) -} - -// ConcatJSON concatenates multiple json objects efficiently -func ConcatJSON(blobs ...[]byte) []byte { - if len(blobs) == 0 { - return nil - } - - last := len(blobs) - 1 - for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) { - // strips trailing null objects - last-- - if last < 0 { - // there was nothing but "null"s or nil... - return nil - } - } - if last == 0 { - return blobs[0] - } - - var opening, closing byte - var idx, a int - buf := bytes.NewBuffer(nil) - - for i, b := range blobs[:last+1] { - if b == nil || bytes.Equal(b, nullJSON) { - // a null object is in the list: skip it - continue - } - if len(b) > 0 && opening == 0 { // is this an array or an object? - opening, closing = b[0], closers[b[0]] - } - - if opening != '{' && opening != '[' { - continue // don't know how to concatenate non container objects - } - - const minLengthIfNotEmpty = 3 - if len(b) < minLengthIfNotEmpty { // yep empty but also the last one, so closing this thing - if i == last && a > 0 { - if err := buf.WriteByte(closing); err != nil { - log.Println(err) - } - } - continue - } - - idx = 0 - if a > 0 { // we need to join with a comma for everything beyond the first non-empty item - if err := buf.WriteByte(comma); err != nil { - log.Println(err) - } - idx = 1 // this is not the first or the last so we want to drop the leading bracket - } - - if i != last { // not the last one, strip brackets - if _, err := buf.Write(b[idx : len(b)-1]); err != nil { - log.Println(err) - } - } else { // last one, strip only the leading bracket - if _, err := buf.Write(b[idx:]); err != nil { - log.Println(err) - } - } - a++ - } - // somehow it ended up being empty, so provide a default value - if buf.Len() == 0 { - if err := buf.WriteByte(opening); err != nil { - log.Println(err) - } - if err := buf.WriteByte(closing); err != nil { - log.Println(err) - } - } - return buf.Bytes() -} - -// ToDynamicJSON turns an object into a properly JSON typed structure -func ToDynamicJSON(data interface{}) interface{} { - // TODO: convert straight to a json typed map (mergo + iterate?) - b, err := json.Marshal(data) - if err != nil { - log.Println(err) - } - var res interface{} - if err := json.Unmarshal(b, &res); err != nil { - log.Println(err) - } - return res -} - -// FromDynamicJSON turns an object into a properly JSON typed structure -func FromDynamicJSON(data, target interface{}) error { - b, err := json.Marshal(data) - if err != nil { - log.Println(err) - } - return json.Unmarshal(b, target) -} - -// NameProvider represents an object capable of translating from go property names -// to json property names -// This type is thread-safe. -type NameProvider struct { - lock *sync.Mutex - index map[reflect.Type]nameIndex -} - -type nameIndex struct { - jsonNames map[string]string - goNames map[string]string -} - -// NewNameProvider creates a new name provider -func NewNameProvider() *NameProvider { - return &NameProvider{ - lock: &sync.Mutex{}, - index: make(map[reflect.Type]nameIndex), - } -} - -func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) { - for i := 0; i < tpe.NumField(); i++ { - targetDes := tpe.Field(i) - - if targetDes.PkgPath != "" { // unexported - continue - } - - if targetDes.Anonymous { // walk embedded structures tree down first - buildnameIndex(targetDes.Type, idx, reverseIdx) - continue - } - - if tag := targetDes.Tag.Get("json"); tag != "" { - - parts := strings.Split(tag, ",") - if len(parts) == 0 { - continue - } - - nm := parts[0] - if nm == "-" { - continue - } - if nm == "" { // empty string means we want to use the Go name - nm = targetDes.Name - } - - idx[nm] = targetDes.Name - reverseIdx[targetDes.Name] = nm - } - } -} - -func newNameIndex(tpe reflect.Type) nameIndex { - var idx = make(map[string]string, tpe.NumField()) - var reverseIdx = make(map[string]string, tpe.NumField()) - - buildnameIndex(tpe, idx, reverseIdx) - return nameIndex{jsonNames: idx, goNames: reverseIdx} -} - -// GetJSONNames gets all the json property names for a type -func (n *NameProvider) GetJSONNames(subject interface{}) []string { - n.lock.Lock() - defer n.lock.Unlock() - tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() - names, ok := n.index[tpe] - if !ok { - names = n.makeNameIndex(tpe) - } - - res := make([]string, 0, len(names.jsonNames)) - for k := range names.jsonNames { - res = append(res, k) - } - return res -} - -// GetJSONName gets the json name for a go property name -func (n *NameProvider) GetJSONName(subject interface{}, name string) (string, bool) { - tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() - return n.GetJSONNameForType(tpe, name) -} - -// GetJSONNameForType gets the json name for a go property name on a given type -func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) { - n.lock.Lock() - defer n.lock.Unlock() - names, ok := n.index[tpe] - if !ok { - names = n.makeNameIndex(tpe) - } - nme, ok := names.goNames[name] - return nme, ok -} - -func (n *NameProvider) makeNameIndex(tpe reflect.Type) nameIndex { - names := newNameIndex(tpe) - n.index[tpe] = names - return names -} - -// GetGoName gets the go name for a json property name -func (n *NameProvider) GetGoName(subject interface{}, name string) (string, bool) { - tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() - return n.GetGoNameForType(tpe, name) -} - -// GetGoNameForType gets the go name for a given type for a json property name -func (n *NameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) { - n.lock.Lock() - defer n.lock.Unlock() - names, ok := n.index[tpe] - if !ok { - names = n.makeNameIndex(tpe) - } - nme, ok := names.jsonNames[name] - return nme, ok -} diff --git a/vendor/github.com/go-openapi/swag/jsonname/LICENSE b/vendor/github.com/go-openapi/swag/jsonname/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonname/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/jsonname/doc.go b/vendor/github.com/go-openapi/swag/jsonname/doc.go new file mode 100644 index 000000000..79232eaca --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonname/doc.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package jsonname is a provider of json property names from go properties. +package jsonname diff --git a/vendor/github.com/go-openapi/swag/jsonname/go_name_provider.go b/vendor/github.com/go-openapi/swag/jsonname/go_name_provider.go new file mode 100644 index 000000000..adc442687 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonname/go_name_provider.go @@ -0,0 +1,286 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonname + +import ( + "reflect" + "strings" + "sync" +) + +var _ providerIface = (*GoNameProvider)(nil) + +// GoNameProvider resolves json property names to go struct field names following +// the same rules as the standard library's [encoding/json] package. +// +// Contrary to [NameProvider], it considers exported fields without a json tag, +// and promotes fields from anonymous embedded struct types. +// +// Rules (aligned with encoding/json): +// +// - unexported fields are ignored; +// - a field tagged `json:"-"` is ignored; +// - a field tagged `json:"-,"` is kept under the json name "-" (stdlib quirk); +// - a field tagged `json:""` or with no json tag at all keeps its Go name as json name; +// - anonymous struct fields without an explicit json tag have their fields +// promoted into the parent, following breadth-first depth rules: +// a shallower field wins over a deeper one; at equal depth, a conflict +// discards all conflicting fields unless exactly one has an explicit json tag. +// +// This type is safe for concurrent use. +type GoNameProvider struct { + lock sync.Mutex + index map[reflect.Type]nameIndex +} + +// NewGoNameProvider creates a new [GoNameProvider]. +func NewGoNameProvider() *GoNameProvider { + return &GoNameProvider{ + index: make(map[reflect.Type]nameIndex), + } +} + +// GetJSONNames gets all the json property names for a type. +func (n *GoNameProvider) GetJSONNames(subject any) []string { + n.lock.Lock() + defer n.lock.Unlock() + + tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() + names := n.nameIndexFor(tpe) + + res := make([]string, 0, len(names.jsonNames)) + for k := range names.jsonNames { + res = append(res, k) + } + + return res +} + +// GetJSONName gets the json name for a go property name. +func (n *GoNameProvider) GetJSONName(subject any, name string) (string, bool) { + tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() + + return n.GetJSONNameForType(tpe, name) +} + +// GetJSONNameForType gets the json name for a go property name on a given type. +func (n *GoNameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) { + n.lock.Lock() + defer n.lock.Unlock() + + names := n.nameIndexFor(tpe) + nme, ok := names.goNames[name] + + return nme, ok +} + +// GetGoName gets the go name for a json property name. +func (n *GoNameProvider) GetGoName(subject any, name string) (string, bool) { + tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() + + return n.GetGoNameForType(tpe, name) +} + +// GetGoNameForType gets the go name for a given type for a json property name. +func (n *GoNameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) { + n.lock.Lock() + defer n.lock.Unlock() + + names := n.nameIndexFor(tpe) + nme, ok := names.jsonNames[name] + + return nme, ok +} + +func (n *GoNameProvider) nameIndexFor(tpe reflect.Type) nameIndex { + if names, ok := n.index[tpe]; ok { + return names + } + + names := buildGoNameIndex(tpe) + n.index[tpe] = names + + return names +} + +// fieldEntry captures a candidate field discovered while walking a struct +// along with the indirection path from the root type (used to resolve conflicts +// by depth in the same way encoding/json does). +type fieldEntry struct { + goName string + jsonName string + index []int + tagged bool +} + +func buildGoNameIndex(tpe reflect.Type) nameIndex { + fields := collectGoFields(tpe) + + idx := make(map[string]string, len(fields)) + reverseIdx := make(map[string]string, len(fields)) + for _, f := range fields { + idx[f.jsonName] = f.goName + reverseIdx[f.goName] = f.jsonName + } + + return nameIndex{jsonNames: idx, goNames: reverseIdx} +} + +// collectGoFields walks tpe breadth-first along anonymous struct fields, +// reproducing the field selection performed by encoding/json.typeFields. +func collectGoFields(tpe reflect.Type) []fieldEntry { + if tpe.Kind() != reflect.Struct { + return nil + } + + type queued struct { + typ reflect.Type + index []int + } + + current := []queued{} + next := []queued{{typ: tpe}} + visited := map[reflect.Type]bool{tpe: true} + + var ( + candidates []fieldEntry + count = map[string]int{} + nextCount = map[string]int{} + ) + + for len(next) > 0 { + current, next = next, current[:0] + count, nextCount = nextCount, count + for k := range nextCount { + delete(nextCount, k) + } + + for _, q := range current { + for i := 0; i < q.typ.NumField(); i++ { + sf := q.typ.Field(i) + + if sf.Anonymous { + ft := sf.Type + if ft.Kind() == reflect.Ptr { + ft = ft.Elem() + } + if !sf.IsExported() && ft.Kind() != reflect.Struct { + continue + } + } else if !sf.IsExported() { + continue + } + + tag := sf.Tag.Get("json") + if tag == "-" { + continue + } + jsonName, _ := parseJSONTag(tag) + tagged := jsonName != "" + + ft := sf.Type + if ft.Kind() == reflect.Ptr { + ft = ft.Elem() + } + + if sf.Anonymous && ft.Kind() == reflect.Struct && !tagged { + if visited[ft] { + continue + } + visited[ft] = true + + index := make([]int, len(q.index)+1) + copy(index, q.index) + index[len(q.index)] = i + next = append(next, queued{typ: ft, index: index}) + + continue + } + + name := jsonName + if name == "" { + name = sf.Name + } + + index := make([]int, len(q.index)+1) + copy(index, q.index) + index[len(q.index)] = i + + candidates = append(candidates, fieldEntry{ + goName: sf.Name, + jsonName: name, + index: index, + tagged: tagged, + }) + nextCount[name]++ + } + } + } + + return dominantFields(candidates) +} + +// dominantFields applies the Go encoding/json conflict resolution rules: +// at each JSON name, the shallowest field wins; at equal depth, a uniquely +// tagged candidate wins; otherwise all candidates for that name are dropped. +func dominantFields(candidates []fieldEntry) []fieldEntry { + byName := make(map[string][]fieldEntry, len(candidates)) + for _, c := range candidates { + byName[c.jsonName] = append(byName[c.jsonName], c) + } + + out := make([]fieldEntry, 0, len(byName)) + for _, group := range byName { + if len(group) == 1 { + out = append(out, group[0]) + + continue + } + + minDepth := len(group[0].index) + for _, c := range group[1:] { + if len(c.index) < minDepth { + minDepth = len(c.index) + } + } + + var shallow []fieldEntry + for _, c := range group { + if len(c.index) == minDepth { + shallow = append(shallow, c) + } + } + + if len(shallow) == 1 { + out = append(out, shallow[0]) + + continue + } + + var tagged []fieldEntry + for _, c := range shallow { + if c.tagged { + tagged = append(tagged, c) + } + } + if len(tagged) == 1 { + out = append(out, tagged[0]) + } + } + + return out +} + +// parseJSONTag returns the name component of a json struct tag and whether +// it carried any non-name option (kept for future-proofing, e.g. "omitempty"). +func parseJSONTag(tag string) (string, string) { + if tag == "" { + return "", "" + } + if idx := strings.IndexByte(tag, ','); idx >= 0 { + return tag[:idx], tag[idx+1:] + } + + return tag, "" +} diff --git a/vendor/github.com/go-openapi/swag/jsonname/ifaces.go b/vendor/github.com/go-openapi/swag/jsonname/ifaces.go new file mode 100644 index 000000000..812ace563 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonname/ifaces.go @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonname + +import "reflect" + +// providerIface is an unexported compile-time contract that every name provider +// in this package is expected to satisfy. +// It mirrors the interface declared by the main consumer of this module: [github.com/go-openapi/jsonpointer.NameProvider]. +type providerIface interface { + GetGoName(subject any, name string) (string, bool) + GetGoNameForType(tpe reflect.Type, name string) (string, bool) +} diff --git a/vendor/github.com/go-openapi/swag/jsonname/name_provider.go b/vendor/github.com/go-openapi/swag/jsonname/name_provider.go new file mode 100644 index 000000000..9f5da7a01 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonname/name_provider.go @@ -0,0 +1,140 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonname + +import ( + "reflect" + "strings" + "sync" +) + +// DefaultJSONNameProvider is the default cache for types. +var DefaultJSONNameProvider = NewNameProvider() + +var _ providerIface = (*NameProvider)(nil) + +// NameProvider represents an object capable of translating from go property names +// to json property names. +// +// This type is thread-safe. +// +// See [github.com/go-openapi/jsonpointer.Pointer] for an example. +type NameProvider struct { + lock *sync.Mutex + index map[reflect.Type]nameIndex +} + +type nameIndex struct { + jsonNames map[string]string + goNames map[string]string +} + +// NewNameProvider creates a new name provider +func NewNameProvider() *NameProvider { + return &NameProvider{ + lock: &sync.Mutex{}, + index: make(map[reflect.Type]nameIndex), + } +} + +func buildnameIndex(tpe reflect.Type, idx, reverseIdx map[string]string) { + for i := 0; i < tpe.NumField(); i++ { + targetDes := tpe.Field(i) + + if targetDes.PkgPath != "" { // unexported + continue + } + + if targetDes.Anonymous { // walk embedded structures tree down first + buildnameIndex(targetDes.Type, idx, reverseIdx) + continue + } + + if tag := targetDes.Tag.Get("json"); tag != "" { + + parts := strings.Split(tag, ",") + if len(parts) == 0 { + continue + } + + nm := parts[0] + if nm == "-" { + continue + } + if nm == "" { // empty string means we want to use the Go name + nm = targetDes.Name + } + + idx[nm] = targetDes.Name + reverseIdx[targetDes.Name] = nm + } + } +} + +func newNameIndex(tpe reflect.Type) nameIndex { + var idx = make(map[string]string, tpe.NumField()) + var reverseIdx = make(map[string]string, tpe.NumField()) + + buildnameIndex(tpe, idx, reverseIdx) + return nameIndex{jsonNames: idx, goNames: reverseIdx} +} + +// GetJSONNames gets all the json property names for a type +func (n *NameProvider) GetJSONNames(subject any) []string { + n.lock.Lock() + defer n.lock.Unlock() + tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() + names, ok := n.index[tpe] + if !ok { + names = n.makeNameIndex(tpe) + } + + res := make([]string, 0, len(names.jsonNames)) + for k := range names.jsonNames { + res = append(res, k) + } + return res +} + +// GetJSONName gets the json name for a go property name +func (n *NameProvider) GetJSONName(subject any, name string) (string, bool) { + tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() + return n.GetJSONNameForType(tpe, name) +} + +// GetJSONNameForType gets the json name for a go property name on a given type +func (n *NameProvider) GetJSONNameForType(tpe reflect.Type, name string) (string, bool) { + n.lock.Lock() + defer n.lock.Unlock() + names, ok := n.index[tpe] + if !ok { + names = n.makeNameIndex(tpe) + } + nme, ok := names.goNames[name] + return nme, ok +} + +// GetGoName gets the go name for a json property name +func (n *NameProvider) GetGoName(subject any, name string) (string, bool) { + tpe := reflect.Indirect(reflect.ValueOf(subject)).Type() + return n.GetGoNameForType(tpe, name) +} + +// GetGoNameForType gets the go name for a given type for a json property name +func (n *NameProvider) GetGoNameForType(tpe reflect.Type, name string) (string, bool) { + n.lock.Lock() + defer n.lock.Unlock() + names, ok := n.index[tpe] + if !ok { + names = n.makeNameIndex(tpe) + } + nme, ok := names.jsonNames[name] + return nme, ok +} + +func (n *NameProvider) makeNameIndex(tpe reflect.Type) nameIndex { + names := newNameIndex(tpe) + n.index[tpe] = names + return names +} diff --git a/vendor/github.com/go-openapi/swag/jsonname_iface.go b/vendor/github.com/go-openapi/swag/jsonname_iface.go new file mode 100644 index 000000000..303a007f6 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonname_iface.go @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import ( + "github.com/go-openapi/swag/jsonname" +) + +// DefaultJSONNameProvider is the default cache for types +// +// Deprecated: use [jsonname.DefaultJSONNameProvider] instead. +var DefaultJSONNameProvider = jsonname.DefaultJSONNameProvider + +// NameProvider represents an object capable of translating from go property names +// to json property names. +// +// Deprecated: use [jsonname.NameProvider] instead. +type NameProvider = jsonname.NameProvider + +// NewNameProvider creates a new name provider +// +// Deprecated: use [jsonname.NewNameProvider] instead. +func NewNameProvider() *NameProvider { return jsonname.NewNameProvider() } diff --git a/vendor/github.com/go-openapi/swag/jsonutils/LICENSE b/vendor/github.com/go-openapi/swag/jsonutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/jsonutils/README.md b/vendor/github.com/go-openapi/swag/jsonutils/README.md new file mode 100644 index 000000000..07a2ca1d7 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/README.md @@ -0,0 +1,109 @@ +# jsonutils + +`jsonutils` exposes a few tools to work with JSON: + +- a fast, simple `Concat` to concatenate (not merge) JSON objects and arrays +- `FromDynamicJSON` to convert a data structure into a "dynamic JSON" data structure +- `ReadJSON` and `WriteJSON` behave like `json.Unmarshal` and `json.Marshal`, + with the ability to use another underlying serialization library through an `Adapter` + configured at runtime +- a `JSONMapSlice` structure that may be used to store JSON objects with the order of keys maintained + +## Dynamic JSON + +We call "dynamic JSON" the go data structure that results from unmarshaling JSON like this: + +```go + var value any + jsonBytes := `{"a": 1, ... }` + _ = json.Unmarshal(jsonBytes, &value) +``` + +In this configuration, the standard library mappings are as follows: + +| JSON | go | +|-----------|------------------| +| `number` | `float64` | +| `string` | `string` | +| `boolean` | `bool` | +| `null` | `nil` | +| `object` | `map[string]any` | +| `array` | `[]any` | + +## Map slices + +When using `JSONMapSlice`, the ordering of keys is ensured by replacing +mappings to `map[string]any` by a `JSONMapSlice` which is an (ordered) +slice of `JSONMapItem`s. + +Notice that a similar feature is available for YAML (see [`yamlutils`](../yamlutils)), +with a `YAMLMapSlice` type based on the `JSONMapSlice`. + +`JSONMapSlice` is similar to an ordered map, but the keys are not retrieved +in constant time. + +Another difference with the the above standard mappings is that numbers don't always map +to a `float64`: if the value is a JSON integer, it unmarshals to `int64`. + +See also [some examples](https://pkg.go.dev/github.com/go-openapi/swag/jsonutils#pkg-examples) + +## Adapters + +`ReadJSON`, `WriteJSON` and `FromDynamicJSON` (which is a combination of the latter two) +are wrappers on top of `json.Unmarshal` and `json.Marshal`. + +By default, the adapter merely wraps the standard library. + +The adapter may be used to register other JSON serialization libraries, +possibly several ones at the same time. + +If the value passed is identified as an "ordered map" (i.e. implements `ifaces.Ordered` +or `ifaces.SetOrdered`, the adapter favors the "ordered" JSON behavior and tries to +find a registered implementation that support ordered keys in objects. + +Our standard library implementation supports this. + +As of `v0.25.0`, we support through such an adapter the popular `mailru/easyjson` +library, which kicks in when the passed values support the `easyjson.Unmarshaler` +or `easyjson.Marshaler` interfaces. + +In the future, we plan to add more similar libraries that compete on the go JSON +serializers scene. + +## Registering an adapter + +In package `github.com/go-openapi/swag/easyjson/adapters`, several adapters are available. + +Each adapter is an independent go module. Hence you'll pick its dependencies only if you import it. + +At this moment we provide: + +- `stdlib`: JSON adapter based on the standard library +- `easyjson`: JSON adapter based on the `github.com/mailru/easyjson` + +The adapters provide the basic `Marshal` and `Unmarshal` capabilities, plus an implementation +of the `MapSlice` pattern. + +You may also build your own adapter based on your specific use-case. An adapter is not required to implement +all capabilities. + +Every adapter comes with a `Register` function, possibly with some options, to register the adapter +to a global registry. + +For example, to enable `easyjson` to be used in `ReadJSON` and `WriteJSON`, you would write something like: + +```go + import ( + "github.com/go-openapi/swag/jsonutils/adapters" + easyjson "github.com/go-openapi/swag/jsonutils/adapters/easyjson/json" + ) + + func init() { + easyjson.Register(adapters.Registry) + } +``` + +You may register several adapters. In this case, capability matching is evaluated from the last registered +adapters (LIFO). + +## [Benchmarks](./adapters/testintegration/benchmarks/README.md) diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go new file mode 100644 index 000000000..76d3898fc --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/doc.go @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package adapters exposes a registry of adapters to multiple +// JSON serialization libraries. +// +// All interfaces are defined in package [ifaces.Adapter]. +package adapters diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go new file mode 100644 index 000000000..1fd43a1fa --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/doc.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package ifaces exposes all interfaces to work with adapters. +package ifaces diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go new file mode 100644 index 000000000..7805e5e5e --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/ifaces.go @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package ifaces + +import ( + _ "encoding/json" // for documentation purpose + "iter" +) + +// Ordered knows how to iterate over the (key,value) pairs of a JSON object. +type Ordered interface { + OrderedItems() iter.Seq2[string, any] +} + +// SetOrdered knows how to append or update the keys of a JSON object, +// given an iterator over (key,value) pairs. +// +// If the provided iterator is nil then the receiver should be set to nil. +type SetOrdered interface { + SetOrderedItems(iter.Seq2[string, any]) +} + +// OrderedMap represent a JSON object (i.e. like a map[string,any]), +// and knows how to serialize and deserialize JSON with the order of keys maintained. +type OrderedMap interface { + Ordered + SetOrdered + + OrderedMarshalJSON() ([]byte, error) + OrderedUnmarshalJSON([]byte) error +} + +// MarshalAdapter behaves likes the standard library [json.Marshal]. +type MarshalAdapter interface { + Poolable + + Marshal(any) ([]byte, error) +} + +// OrderedMarshalAdapter behaves likes the standard library [json.Marshal], preserving the order of keys in objects. +type OrderedMarshalAdapter interface { + Poolable + + OrderedMarshal(Ordered) ([]byte, error) +} + +// UnmarshalAdapter behaves likes the standard library [json.Unmarshal]. +type UnmarshalAdapter interface { + Poolable + + Unmarshal([]byte, any) error +} + +// OrderedUnmarshalAdapter behaves likes the standard library [json.Unmarshal], preserving the order of keys in objects. +type OrderedUnmarshalAdapter interface { + Poolable + + OrderedUnmarshal([]byte, SetOrdered) error +} + +// Adapter exposes an interface like the standard [json] library. +type Adapter interface { + MarshalAdapter + UnmarshalAdapter + + OrderedAdapter +} + +// OrderedAdapter exposes interfaces to process JSON and keep the order of object keys. +type OrderedAdapter interface { + OrderedMarshalAdapter + OrderedUnmarshalAdapter + NewOrderedMap(capacity int) OrderedMap +} + +type Poolable interface { + // Self-redeem: for [Adapter] s that are allocated from a pool. + // The [Adapter] must not be used after calling [Redeem]. + Redeem() + + // Reset the state of the [Adapter], if any. + Reset() +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go new file mode 100644 index 000000000..2d6c69f4e --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/ifaces/registry_iface.go @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package ifaces + +import ( + "strings" +) + +// Capability indicates what a JSON adapter is capable of. +type Capability uint8 + +const ( + CapabilityMarshalJSON Capability = 1 << iota + CapabilityUnmarshalJSON + CapabilityOrderedMarshalJSON + CapabilityOrderedUnmarshalJSON + CapabilityOrderedMap +) + +func (c Capability) String() string { + switch c { + case CapabilityMarshalJSON: + return "MarshalJSON" + case CapabilityUnmarshalJSON: + return "UnmarshalJSON" + case CapabilityOrderedMarshalJSON: + return "OrderedMarshalJSON" + case CapabilityOrderedUnmarshalJSON: + return "OrderedUnmarshalJSON" + case CapabilityOrderedMap: + return "OrderedMap" + default: + return "" + } +} + +// Capabilities holds several unitary capability flags +type Capabilities uint8 + +// Has some capability flag enabled. +func (c Capabilities) Has(capability Capability) bool { + return Capability(c)&capability > 0 +} + +func (c Capabilities) String() string { + var w strings.Builder + + first := true + for _, capability := range []Capability{ + CapabilityMarshalJSON, + CapabilityUnmarshalJSON, + CapabilityOrderedMarshalJSON, + CapabilityOrderedUnmarshalJSON, + CapabilityOrderedMap, + } { + if c.Has(capability) { + if !first { + w.WriteByte('|') + } else { + first = false + } + w.WriteString(capability.String()) + } + } + + return w.String() +} + +const ( + AllCapabilities Capabilities = Capabilities(uint8(CapabilityMarshalJSON) | + uint8(CapabilityUnmarshalJSON) | + uint8(CapabilityOrderedMarshalJSON) | + uint8(CapabilityOrderedUnmarshalJSON) | + uint8(CapabilityOrderedMap)) + + AllUnorderedCapabilities Capabilities = Capabilities(uint8(CapabilityMarshalJSON) | uint8(CapabilityUnmarshalJSON)) +) + +// RegistryEntry describes how any given adapter registers its capabilities to the [Registrar]. +type RegistryEntry struct { + Who string + What Capabilities + Constructor func() Adapter + Support func(what Capability, value any) bool +} + +// Registrar is a type that knows how to keep registration calls from adapters. +type Registrar interface { + RegisterFor(RegistryEntry) +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go new file mode 100644 index 000000000..3062acaff --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/registry.go @@ -0,0 +1,229 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package adapters + +import ( + "fmt" + "reflect" + "slices" + "sync" + + "github.com/go-openapi/swag/jsonutils/adapters/ifaces" + stdlib "github.com/go-openapi/swag/jsonutils/adapters/stdlib/json" +) + +// Registry holds the global registry for registered adapters. +var Registry = NewRegistrar() + +var ( + defaultRegistered = stdlib.Register + + _ ifaces.Registrar = &Registrar{} +) + +type registryError string + +func (e registryError) Error() string { + return string(e) +} + +// ErrRegistry indicates an error returned by the [Registrar]. +var ErrRegistry registryError = "JSON adapters registry error" + +type registry []*ifaces.RegistryEntry + +// Registrar holds registered [ifaces.Adapters] for different serialization capabilities. +// +// Internally, it maintains a cache for data types that favor a given adapter. +type Registrar struct { + marshalerRegistry registry + unmarshalerRegistry registry + orderedMarshalerRegistry registry + orderedUnmarshalerRegistry registry + orderedMapRegistry registry + + gmx sync.RWMutex + + // cache indexed by value type, so we don't have to lookup + marshalerCache map[reflect.Type]*ifaces.RegistryEntry + unmarshalerCache map[reflect.Type]*ifaces.RegistryEntry + orderedMarshalerCache map[reflect.Type]*ifaces.RegistryEntry + orderedUnmarshalerCache map[reflect.Type]*ifaces.RegistryEntry + orderedMapCache map[reflect.Type]*ifaces.RegistryEntry +} + +func NewRegistrar() *Registrar { + r := &Registrar{} + + r.marshalerRegistry = make(registry, 0, 1) + r.unmarshalerRegistry = make(registry, 0, 1) + r.orderedMarshalerRegistry = make(registry, 0, 1) + r.orderedUnmarshalerRegistry = make(registry, 0, 1) + r.orderedMapRegistry = make(registry, 0, 1) + + r.marshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry) + r.unmarshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry) + r.orderedMarshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry) + r.orderedUnmarshalerCache = make(map[reflect.Type]*ifaces.RegistryEntry) + r.orderedMapCache = make(map[reflect.Type]*ifaces.RegistryEntry) + + defaultRegistered(r) + + return r +} + +// ClearCache resets the internal type cache. +func (r *Registrar) ClearCache() { + r.gmx.Lock() + r.clearCache() + r.gmx.Unlock() +} + +// Reset the [Registrar] to its defaults. +func (r *Registrar) Reset() { + r.gmx.Lock() + r.clearCache() + r.marshalerRegistry = r.marshalerRegistry[:0] + r.unmarshalerRegistry = r.unmarshalerRegistry[:0] + r.orderedMarshalerRegistry = r.orderedMarshalerRegistry[:0] + r.orderedUnmarshalerRegistry = r.orderedUnmarshalerRegistry[:0] + r.orderedMapRegistry = r.orderedMapRegistry[:0] + r.gmx.Unlock() + + defaultRegistered(r) +} + +// RegisterFor registers an adapter for some JSON capabilities. +func (r *Registrar) RegisterFor(entry ifaces.RegistryEntry) { + r.gmx.Lock() + if entry.What.Has(ifaces.CapabilityMarshalJSON) { + e := entry + e.What &= ifaces.Capabilities(ifaces.CapabilityMarshalJSON) + r.marshalerRegistry = slices.Insert(r.marshalerRegistry, 0, &e) + } + if entry.What.Has(ifaces.CapabilityUnmarshalJSON) { + e := entry + e.What &= ifaces.Capabilities(ifaces.CapabilityUnmarshalJSON) + r.unmarshalerRegistry = slices.Insert(r.unmarshalerRegistry, 0, &e) + } + if entry.What.Has(ifaces.CapabilityOrderedMarshalJSON) { + e := entry + e.What &= ifaces.Capabilities(ifaces.CapabilityOrderedMarshalJSON) + r.orderedMarshalerRegistry = slices.Insert(r.orderedMarshalerRegistry, 0, &e) + } + if entry.What.Has(ifaces.CapabilityOrderedUnmarshalJSON) { + e := entry + e.What &= ifaces.Capabilities(ifaces.CapabilityOrderedUnmarshalJSON) + r.orderedUnmarshalerRegistry = slices.Insert(r.orderedUnmarshalerRegistry, 0, &e) + } + if entry.What.Has(ifaces.CapabilityOrderedMap) { + e := entry + e.What &= ifaces.Capabilities(ifaces.CapabilityOrderedMap) + r.orderedMapRegistry = slices.Insert(r.orderedMapRegistry, 0, &e) + } + r.gmx.Unlock() +} + +// AdapterFor returns an [ifaces.Adapter] that supports this capability for this type of value. +// +// The [ifaces.Adapter] may be redeemed to its pool using its Redeem() method, for adapters that support global +// pooling. When this is not the case, the redeem function is just a no-operation. +func (r *Registrar) AdapterFor(capability ifaces.Capability, value any) ifaces.Adapter { + entry := r.findFirstFor(capability, value) + if entry == nil { + return nil + } + + return entry.Constructor() +} + +func (r *Registrar) clearCache() { + clear(r.marshalerCache) + clear(r.unmarshalerCache) + clear(r.orderedMarshalerCache) + clear(r.orderedUnmarshalerCache) + clear(r.orderedMapCache) +} + +func (r *Registrar) findFirstFor(capability ifaces.Capability, value any) *ifaces.RegistryEntry { + switch capability { + case ifaces.CapabilityMarshalJSON: + return r.findFirstInRegistryFor(r.marshalerRegistry, r.marshalerCache, capability, value) + case ifaces.CapabilityUnmarshalJSON: + return r.findFirstInRegistryFor(r.unmarshalerRegistry, r.unmarshalerCache, capability, value) + case ifaces.CapabilityOrderedMarshalJSON: + return r.findFirstInRegistryFor(r.orderedMarshalerRegistry, r.orderedMarshalerCache, capability, value) + case ifaces.CapabilityOrderedUnmarshalJSON: + return r.findFirstInRegistryFor(r.orderedUnmarshalerRegistry, r.orderedUnmarshalerCache, capability, value) + case ifaces.CapabilityOrderedMap: + return r.findFirstInRegistryFor(r.orderedMapRegistry, r.orderedMapCache, capability, value) + default: + panic(fmt.Errorf("unsupported capability %d: %w", capability, ErrRegistry)) + } +} + +func (r *Registrar) findFirstInRegistryFor(reg registry, cache map[reflect.Type]*ifaces.RegistryEntry, capability ifaces.Capability, value any) *ifaces.RegistryEntry { + r.gmx.RLock() + if len(reg) > 1 { + if entry, ok := cache[reflect.TypeOf(value)]; ok { + // cache hit + r.gmx.RUnlock() + return entry + } + } + + for _, entry := range reg { + if !entry.Support(capability, value) { + continue + } + + r.gmx.RUnlock() + + // update the internal cache + r.gmx.Lock() + cache[reflect.TypeOf(value)] = entry + r.gmx.Unlock() + + return entry + } + + // no adapter found + r.gmx.RUnlock() + + return nil +} + +// MarshalAdapterFor returns the first adapter that knows how to Marshal this type of value. +func MarshalAdapterFor(value any) ifaces.MarshalAdapter { + return Registry.AdapterFor(ifaces.CapabilityMarshalJSON, value) +} + +// OrderedMarshalAdapterFor returns the first adapter that knows how to OrderedMarshal this type of value. +func OrderedMarshalAdapterFor(value ifaces.Ordered) ifaces.OrderedMarshalAdapter { + return Registry.AdapterFor(ifaces.CapabilityOrderedMarshalJSON, value) +} + +// UnmarshalAdapterFor returns the first adapter that knows how to Unmarshal this type of value. +func UnmarshalAdapterFor(value any) ifaces.UnmarshalAdapter { + return Registry.AdapterFor(ifaces.CapabilityUnmarshalJSON, value) +} + +// OrderedUnmarshalAdapterFor provides the first adapter that knows how to OrderedUnmarshal this type of value. +func OrderedUnmarshalAdapterFor(value ifaces.SetOrdered) ifaces.OrderedUnmarshalAdapter { + return Registry.AdapterFor(ifaces.CapabilityOrderedUnmarshalJSON, value) +} + +// NewOrderedMap provides the "ordered map" implementation provided by the registry. +func NewOrderedMap(capacity int) ifaces.OrderedMap { + var v any + adapter := Registry.AdapterFor(ifaces.CapabilityOrderedUnmarshalJSON, v) + if adapter == nil { + return nil + } + + defer adapter.Redeem() + return adapter.NewOrderedMap(capacity) +} + +func noopRedeemer() {} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go new file mode 100644 index 000000000..0213ff5c2 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/adapter.go @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + stdjson "encoding/json" + + "github.com/go-openapi/swag/jsonutils/adapters/ifaces" + "github.com/go-openapi/swag/typeutils" +) + +const sensibleBufferSize = 8192 + +type jsonError string + +func (e jsonError) Error() string { + return string(e) +} + +// ErrStdlib indicates that an error comes from the stdlib JSON adapter +var ErrStdlib jsonError = "error from the JSON adapter stdlib" + +var _ ifaces.Adapter = &Adapter{} + +type Adapter struct { +} + +// NewAdapter yields an [ifaces.Adapter] using the standard library. +func NewAdapter() *Adapter { + return &Adapter{} +} + +func (a *Adapter) Marshal(value any) ([]byte, error) { + return stdjson.Marshal(value) +} + +func (a *Adapter) Unmarshal(data []byte, value any) error { + return stdjson.Unmarshal(data, value) +} + +func (a *Adapter) OrderedMarshal(value ifaces.Ordered) ([]byte, error) { + w := poolOfWriters.Borrow() + defer func() { + poolOfWriters.Redeem(w) + }() + + if typeutils.IsNil(value) { + w.RawString("null") + + return w.BuildBytes() + } + + w.RawByte('{') + first := true + for k, v := range value.OrderedItems() { + if first { + first = false + } else { + w.RawByte(',') + } + + w.String(k) + w.RawByte(':') + + switch val := v.(type) { + case ifaces.Ordered: + w.Raw(a.OrderedMarshal(val)) + default: + w.Raw(stdjson.Marshal(v)) + } + } + + w.RawByte('}') + + return w.BuildBytes() +} + +func (a *Adapter) OrderedUnmarshal(data []byte, value ifaces.SetOrdered) error { + var m MapSlice + if err := m.OrderedUnmarshalJSON(data); err != nil { + return err + } + + if typeutils.IsNil(m) { + // force input value to nil + value.SetOrderedItems(nil) + + return nil + } + + value.SetOrderedItems(m.OrderedItems()) + + return nil +} + +func (a *Adapter) NewOrderedMap(capacity int) ifaces.OrderedMap { + m := make(MapSlice, 0, capacity) + + return &m +} + +// Redeem the [Adapter] when it comes from a pool. +// +// The adapter becomes immediately unusable once redeemed. +func (a *Adapter) Redeem() { + if a == nil { + return + } + + RedeemAdapter(a) +} + +func (a *Adapter) Reset() { +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go new file mode 100644 index 000000000..5ea1b4404 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/doc.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package json implements an [ifaces.Adapter] using the standard library. +package json diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go new file mode 100644 index 000000000..b5aa1c797 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/lexer.go @@ -0,0 +1,320 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + stdjson "encoding/json" + "errors" + "fmt" + "io" + "math" + "strconv" + + "github.com/go-openapi/swag/conv" +) + +type token struct { + stdjson.Token +} + +func (t token) String() string { + if t == invalidToken { + return "invalid token" + } + if t == eofToken { + return "EOF" + } + + return fmt.Sprintf("%v", t.Token) +} + +func (t token) Kind() tokenKind { + switch t.Token.(type) { + case nil: + return tokenNull + case stdjson.Delim: + return tokenDelim + case bool: + return tokenBool + case float64: + return tokenFloat + case stdjson.Number: + return tokenNumber + case string: + return tokenString + default: + return tokenUndef + } +} + +func (t token) Delim() byte { + r, ok := t.Token.(stdjson.Delim) + if !ok { + return 0 + } + + return byte(r) +} + +type tokenKind uint8 + +const ( + tokenUndef tokenKind = iota + tokenString + tokenNumber + tokenFloat + tokenBool + tokenNull + tokenDelim +) + +var ( + invalidToken = token{ + Token: stdjson.Token(struct{}{}), + } + + eofToken = token{ + Token: stdjson.Token(&struct{}{}), + } + + undefToken = token{ + Token: stdjson.Token(uint8(0)), + } +) + +// jlexer apes easyjson's jlexer, but uses the standard library decoder under the hood. +type jlexer struct { + buf *bytesReader + dec *stdjson.Decoder + err error + // current token + next token + // started bool +} + +type bytesReader struct { + buf []byte + offset int +} + +func (b *bytesReader) Reset() { + b.buf = nil + b.offset = 0 +} + +func (b *bytesReader) Read(p []byte) (int, error) { + if b.offset >= len(b.buf) { + return 0, io.EOF + } + + n := len(p) + buf := b.buf[b.offset:] + m := len(buf) + + if n >= m { + copy(p, buf) + b.offset += m + + return m, nil + } + + copy(p, buf[:n]) + b.offset += n + + return n, nil +} + +var _ io.Reader = &bytesReader{} + +func newLexer(data []byte) *jlexer { + l := &jlexer{ + // current: undefToken, + next: undefToken, + } + l.buf = &bytesReader{ + buf: data, + } + l.dec = stdjson.NewDecoder(l.buf) // unfortunately, cannot pool this + + return l +} + +func (l *jlexer) Reset() { + l.err = nil + l.next = undefToken + // leave l.dec and l.buf alone, since they are replaced at every Borrow +} + +func (l *jlexer) Error() error { + return l.err +} + +func (l *jlexer) SetErr(err error) { + l.err = err +} + +func (l *jlexer) Ok() bool { + return l.err == nil +} + +// NextToken consumes a token +func (l *jlexer) NextToken() token { + if !l.Ok() { + return invalidToken + } + + if l.next != undefToken { + next := l.next + l.next = undefToken + + return next + } + + return l.fetchToken() +} + +// PeekToken returns the next token without consuming it +func (l *jlexer) PeekToken() token { + if l.next == undefToken { + l.next = l.fetchToken() + } + + return l.next +} + +func (l *jlexer) Skip() { + _ = l.NextToken() +} + +func (l *jlexer) IsDelim(c byte) bool { + if !l.Ok() { + return false + } + + next := l.PeekToken() + if next.Kind() != tokenDelim { + return false + } + + if next.Delim() != c { + return false + } + + return true +} + +func (l *jlexer) IsNull() bool { + if !l.Ok() { + return false + } + + next := l.PeekToken() + + return next.Kind() == tokenNull +} + +func (l *jlexer) Delim(c byte) { + if !l.Ok() { + return + } + + tok := l.NextToken() + if tok.Kind() != tokenDelim { + l.err = fmt.Errorf("expected a delimiter token but got '%v': %w", tok, ErrStdlib) + + return + } + + if tok.Delim() != c { + l.err = fmt.Errorf("expected delimiter '%q' but got '%q': %w", c, tok.Delim(), ErrStdlib) + } +} + +func (l *jlexer) Null() { + if !l.Ok() { + return + } + + tok := l.NextToken() + if tok.Kind() != tokenNull { + l.err = fmt.Errorf("expected a null token but got '%v': %w", tok, ErrStdlib) + } +} + +func (l *jlexer) Number() any { + if !l.Ok() { + return 0 + } + + tok := l.NextToken() + + switch tok.Kind() { //nolint:exhaustive + case tokenNumber: + n := tok.Token.(stdjson.Number).String() + f, _ := strconv.ParseFloat(n, 64) + if conv.IsFloat64AJSONInteger(f) { + return int64(math.Trunc(f)) + } + + return f + + case tokenFloat: + f := tok.Token.(float64) + if conv.IsFloat64AJSONInteger(f) { + return int64(math.Trunc(f)) + } + + return f + + default: + l.err = fmt.Errorf("expected a number token but got '%v': %w", tok, ErrStdlib) + + return 0 + } +} + +func (l *jlexer) Bool() bool { + if !l.Ok() { + return false + } + + tok := l.NextToken() + if tok.Kind() != tokenBool { + l.err = fmt.Errorf("expected a bool token but got '%v': %w", tok, ErrStdlib) + + return false + } + + return tok.Token.(bool) +} + +func (l *jlexer) String() string { + if !l.Ok() { + return "" + } + + tok := l.NextToken() + if tok.Kind() != tokenString { + l.err = fmt.Errorf("expected a string token but got '%v': %w", tok, ErrStdlib) + + return "" + } + + return tok.Token.(string) +} + +// Commas and colons are elided. +func (l *jlexer) fetchToken() token { + jtok, err := l.dec.Token() + if err != nil { + if errors.Is(err, io.EOF) { + return eofToken + } + + l.err = errors.Join(err, ErrStdlib) + return invalidToken + } + + return token{Token: jtok} +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go new file mode 100644 index 000000000..54deef406 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/ordered_map.go @@ -0,0 +1,266 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + stdjson "encoding/json" + "fmt" + "iter" + + "github.com/go-openapi/swag/jsonutils/adapters/ifaces" +) + +var _ ifaces.OrderedMap = &MapSlice{} + +// MapSlice represents a JSON object, with the order of keys maintained. +type MapSlice []MapItem + +func (s MapSlice) OrderedItems() iter.Seq2[string, any] { + return func(yield func(string, any) bool) { + for _, item := range s { + if !yield(item.Key, item.Value) { + return + } + } + } +} + +func (s *MapSlice) SetOrderedItems(items iter.Seq2[string, any]) { + if items == nil { + *s = nil + + return + } + + m := *s + if len(m) > 0 { + // update mode + idx := make(map[string]int, len(m)) + + for i, item := range m { + idx[item.Key] = i + } + + for k, v := range items { + idx, ok := idx[k] + if ok { + m[idx].Value = v + + continue + } + m = append(m, MapItem{Key: k, Value: v}) + } + + *s = m + + return + } + + for k, v := range items { + m = append(m, MapItem{Key: k, Value: v}) + } + + *s = m +} + +// MarshalJSON renders a [MapSlice] as JSON bytes, preserving the order of keys. +func (s MapSlice) MarshalJSON() ([]byte, error) { + return s.OrderedMarshalJSON() +} + +func (s MapSlice) OrderedMarshalJSON() ([]byte, error) { + w := poolOfWriters.Borrow() + defer func() { + poolOfWriters.Redeem(w) + }() + + s.marshalObject(w) + + return w.BuildBytes() // this clones data, so it's okay to redeem the writer and its buffer +} + +// UnmarshalJSON builds a [MapSlice] from JSON bytes, preserving the order of keys. +// +// Inner objects are unmarshaled as [MapSlice] slices and not map[string]any. +func (s *MapSlice) UnmarshalJSON(data []byte) error { + return s.OrderedUnmarshalJSON(data) +} + +func (s *MapSlice) OrderedUnmarshalJSON(data []byte) error { + l := poolOfLexers.Borrow(data) + defer func() { + poolOfLexers.Redeem(l) + }() + + s.unmarshalObject(l) + + return l.Error() +} + +func (s MapSlice) marshalObject(w *jwriter) { + if s == nil { + w.RawString("null") + + return + } + + w.RawByte('{') + + if len(s) == 0 { + w.RawByte('}') + + return + } + + s[0].marshalJSON(w) + + for i := 1; i < len(s); i++ { + w.RawByte(',') + s[i].marshalJSON(w) + } + + w.RawByte('}') +} + +func (s *MapSlice) unmarshalObject(in *jlexer) { + if in.IsNull() { + in.Skip() + + return + } + + in.Delim('{') // consume token + if !in.Ok() { + return + } + + result := make(MapSlice, 0) + + for in.Ok() && !in.IsDelim('}') { + var mi MapItem + + mi.unmarshalKeyValue(in) + result = append(result, mi) + } + + in.Delim('}') + + if !in.Ok() { + return + } + + *s = result +} + +// MapItem represents the value of a key in a JSON object held by [MapSlice]. +// +// Notice that [MapItem] should not be marshaled to or unmarshaled from JSON directly, +// use this type as part of a [MapSlice] when dealing with JSON bytes. +type MapItem struct { + Key string + Value any +} + +func (s MapItem) marshalJSON(w *jwriter) { + w.String(s.Key) + w.RawByte(':') + w.Raw(stdjson.Marshal(s.Value)) +} + +func (s *MapItem) unmarshalKeyValue(in *jlexer) { + key := in.String() // consume string + value := s.asInterface(in) // consume any value, including termination tokens '}' or ']' + + if !in.Ok() { + return + } + + s.Key = key + s.Value = value +} + +func (s *MapItem) unmarshalArray(in *jlexer) []any { + if in.IsNull() { + in.Skip() + + return nil + } + + in.Delim('[') // consume token + if !in.Ok() { + return nil + } + + ret := make([]any, 0) + + for in.Ok() && !in.IsDelim(']') { + ret = append(ret, s.asInterface(in)) + } + + in.Delim(']') + if !in.Ok() { + return nil + } + + return ret +} + +// asInterface is very much like [jlexer.Lexer.Interface], but unmarshals an object +// into a [MapSlice], not a map[string]any. +// +// We have to force parsing errors somehow, since [jlexer.Lexer] doesn't let us +// set a parsing error directly. +func (s *MapItem) asInterface(in *jlexer) any { + if !in.Ok() { + return nil + } + + tok := in.PeekToken() // look-ahead what the next token looks like + kind := tok.Kind() + + switch kind { + case tokenString: + return in.String() // consume string + + case tokenNumber, tokenFloat: + return in.Number() + + case tokenBool: + return in.Bool() + + case tokenNull: + in.Null() + + return nil + + case tokenDelim: + switch tok.Delim() { + case '{': // not consumed yet + ret := make(MapSlice, 0) + ret.unmarshalObject(in) // consumes the terminating '}' + + if in.Ok() { + return ret + } + + // lexer is in an error state: will exhaust + return nil + + case '[': // not consumed yet + return s.unmarshalArray(in) // consumes the terminating ']' + default: + in.SetErr(fmt.Errorf("unexpected delimiter: %v: %w", tok, ErrStdlib)) // force error + return nil + } + + case tokenUndef: + fallthrough + default: + if in.Ok() { + in.SetErr(fmt.Errorf("unexpected token: %v: %w", tok, ErrStdlib)) // force error + } + + return nil + } +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go new file mode 100644 index 000000000..709b97c30 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/pool.go @@ -0,0 +1,143 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + "encoding/json" + "sync" + + "github.com/go-openapi/swag/jsonutils/adapters/ifaces" +) + +type adaptersPool struct { + sync.Pool +} + +func (p *adaptersPool) Borrow() *Adapter { + return p.Get().(*Adapter) +} + +func (p *adaptersPool) BorrowIface() ifaces.Adapter { + return p.Get().(*Adapter) +} + +func (p *adaptersPool) Redeem(a *Adapter) { + p.Put(a) +} + +type writersPool struct { + sync.Pool +} + +func (p *writersPool) Borrow() *jwriter { + ptr := p.Get() + + jw := ptr.(*jwriter) + jw.Reset() + + return jw +} + +func (p *writersPool) Redeem(w *jwriter) { + p.Put(w) +} + +type lexersPool struct { + sync.Pool +} + +func (p *lexersPool) Borrow(data []byte) *jlexer { + ptr := p.Get() + + l := ptr.(*jlexer) + l.buf = poolOfReaders.Borrow(data) + l.dec = json.NewDecoder(l.buf) // cannot pool, not exposed by the encoding/json API + l.Reset() + + return l +} + +func (p *lexersPool) Redeem(l *jlexer) { + l.dec = nil + discard := l.buf + l.buf = nil + poolOfReaders.Redeem(discard) + p.Put(l) +} + +type readersPool struct { + sync.Pool +} + +func (p *readersPool) Borrow(data []byte) *bytesReader { + ptr := p.Get() + + b := ptr.(*bytesReader) + b.Reset() + b.buf = data + + return b +} + +func (p *readersPool) Redeem(b *bytesReader) { + p.Put(b) +} + +var ( + poolOfAdapters = &adaptersPool{ + Pool: sync.Pool{ + New: func() any { + return NewAdapter() + }, + }, + } + + poolOfWriters = &writersPool{ + Pool: sync.Pool{ + New: func() any { + return newJWriter() + }, + }, + } + + poolOfLexers = &lexersPool{ + Pool: sync.Pool{ + New: func() any { + return newLexer(nil) + }, + }, + } + + poolOfReaders = &readersPool{ + Pool: sync.Pool{ + New: func() any { + return &bytesReader{} + }, + }, + } +) + +// BorrowAdapter borrows an [Adapter] from the pool, recycling already allocated instances. +func BorrowAdapter() *Adapter { + return poolOfAdapters.Borrow() +} + +// BorrowAdapterIface borrows a stdlib [Adapter] and converts it directly +// to [ifaces.Adapter]. This is useful to avoid further allocations when +// translating the concrete type into an interface. +func BorrowAdapterIface() ifaces.Adapter { + return poolOfAdapters.BorrowIface() +} + +// RedeemAdapter redeems an [Adapter] to the pool, so it may be recycled. +func RedeemAdapter(a *Adapter) { + poolOfAdapters.Redeem(a) +} + +func RedeemAdapterIface(a ifaces.Adapter) { + concrete, ok := a.(*Adapter) + if ok { + poolOfAdapters.Redeem(concrete) + } +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go new file mode 100644 index 000000000..fc8818694 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/register.go @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + "fmt" + "reflect" + + "github.com/go-openapi/swag/jsonutils/adapters/ifaces" +) + +func Register(dispatcher ifaces.Registrar) { + t := reflect.TypeOf(Adapter{}) + dispatcher.RegisterFor( + ifaces.RegistryEntry{ + Who: fmt.Sprintf("%s.%s", t.PkgPath(), t.Name()), + What: ifaces.AllCapabilities, + Constructor: BorrowAdapterIface, + Support: support, + }) +} + +func support(_ ifaces.Capability, _ any) bool { + return true +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go new file mode 100644 index 000000000..dc2325c1a --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/adapters/stdlib/json/writer.go @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package json + +import ( + "bytes" + "encoding/json" + "strings" +) + +type jwriter struct { + buf *bytes.Buffer + err error +} + +func newJWriter() *jwriter { + buf := make([]byte, 0, sensibleBufferSize) + + return &jwriter{buf: bytes.NewBuffer(buf)} +} + +func (w *jwriter) Reset() { + w.buf.Reset() + w.err = nil +} + +func (w *jwriter) RawString(s string) { + if w.err != nil { + return + } + w.buf.WriteString(s) +} + +func (w *jwriter) Raw(b []byte, err error) { + if w.err != nil { + return + } + if err != nil { + w.err = err + return + } + + _, _ = w.buf.Write(b) +} + +func (w *jwriter) RawByte(c byte) { + if w.err != nil { + return + } + w.buf.WriteByte(c) +} + +var quoteReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`) + +func (w *jwriter) String(s string) { + if w.err != nil { + return + } + // escape quotes and \ + s = quoteReplacer.Replace(s) + + _ = w.buf.WriteByte('"') + json.HTMLEscape(w.buf, []byte(s)) + _ = w.buf.WriteByte('"') +} + +// BuildBytes returns a clone of the internal buffer. +func (w *jwriter) BuildBytes() ([]byte, error) { + if w.err != nil { + return nil, w.err + } + + return bytes.Clone(w.buf.Bytes()), nil +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/concat.go b/vendor/github.com/go-openapi/swag/jsonutils/concat.go new file mode 100644 index 000000000..2068503af --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/concat.go @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonutils + +import ( + "bytes" +) + +// nullJSON represents a JSON object with null type +var nullJSON = []byte("null") + +const comma = byte(',') + +var closers map[byte]byte + +func init() { + closers = map[byte]byte{ + '{': '}', + '[': ']', + } +} + +// ConcatJSON concatenates multiple json objects or arrays efficiently. +// +// Note that [ConcatJSON] performs a very simple (and fast) concatenation +// operation: it does not attempt to merge objects. +func ConcatJSON(blobs ...[]byte) []byte { + if len(blobs) == 0 { + return nil + } + + last := len(blobs) - 1 + for blobs[last] == nil || bytes.Equal(blobs[last], nullJSON) { + // strips trailing null objects + last-- + if last < 0 { + // there was nothing but "null"s or nil... + return nil + } + } + if last == 0 { + return blobs[0] + } + + var opening, closing byte + var idx, a int + buf := bytes.NewBuffer(nil) + + for i, b := range blobs[:last+1] { + if b == nil || bytes.Equal(b, nullJSON) { + // a null object is in the list: skip it + continue + } + if len(b) > 0 && opening == 0 { // is this an array or an object? + opening, closing = b[0], closers[b[0]] + } + + if opening != '{' && opening != '[' { + continue // don't know how to concatenate non container objects + } + + const minLengthIfNotEmpty = 3 + if len(b) < minLengthIfNotEmpty { // yep empty but also the last one, so closing this thing + if i == last && a > 0 { + _ = buf.WriteByte(closing) // never returns err != nil + } + continue + } + + idx = 0 + if a > 0 { // we need to join with a comma for everything beyond the first non-empty item + _ = buf.WriteByte(comma) // never returns err != nil + idx = 1 // this is not the first or the last so we want to drop the leading bracket + } + + if i != last { // not the last one, strip brackets + _, _ = buf.Write(b[idx : len(b)-1]) // never returns err != nil + } else { // last one, strip only the leading bracket + _, _ = buf.Write(b[idx:]) + } + a++ + } + + // somehow it ended up being empty, so provide a default value + if buf.Len() == 0 && (opening == '{' || opening == '[') { + _ = buf.WriteByte(opening) // never returns err != nil + _ = buf.WriteByte(closing) + } + + return buf.Bytes() +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/doc.go b/vendor/github.com/go-openapi/swag/jsonutils/doc.go new file mode 100644 index 000000000..3926cc58d --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/doc.go @@ -0,0 +1,7 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package jsonutils provides helpers to work with JSON. +// +// These utilities work with dynamic go structures to and from JSON. +package jsonutils diff --git a/vendor/github.com/go-openapi/swag/jsonutils/json.go b/vendor/github.com/go-openapi/swag/jsonutils/json.go new file mode 100644 index 000000000..40753ce03 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/json.go @@ -0,0 +1,116 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonutils + +import ( + "bytes" + "encoding/json" + + "github.com/go-openapi/swag/jsonutils/adapters" + "github.com/go-openapi/swag/jsonutils/adapters/ifaces" +) + +// WriteJSON marshals a data structure as JSON. +// +// The difference with [json.Marshal] is that it may check among several alternatives +// to do so. +// +// See [adapters.Registrar] for more details about how to configure +// multiple serialization alternatives. +// +// NOTE: to allow types that are [easyjson.Marshaler] s to use that route to process JSON, +// you now need to register the adapter for easyjson at runtime. +func WriteJSON(value any) ([]byte, error) { + if orderedMap, isOrdered := value.(ifaces.Ordered); isOrdered { + orderedMarshaler := adapters.OrderedMarshalAdapterFor(orderedMap) + + if orderedMarshaler != nil { + defer orderedMarshaler.Redeem() + + return orderedMarshaler.OrderedMarshal(orderedMap) + } + + // no support found in registered adapters, fallback to the default (unordered) case + } + + marshaler := adapters.MarshalAdapterFor(value) + if marshaler != nil { + defer marshaler.Redeem() + + return marshaler.Marshal(value) + } + + // no support found in registered adapters, fallback to the default standard library. + // + // This only happens when tinkering with the global registry of adapters, since the default handles all the above cases. + return json.Marshal(value) // Codecov ignore // this is a safeguard not easily simulated in tests +} + +// ReadJSON unmarshals JSON data into a data structure. +// +// The difference with [json.Unmarshal] is that it may check among several alternatives +// to do so. +// +// See [adapters.Registrar] for more details about how to configure +// multiple serialization alternatives. +// +// NOTE: value must be a pointer. +// +// If the provided value implements [ifaces.SetOrdered], it is a considered an "ordered map" and [ReadJSON] +// will favor an adapter that supports the [ifaces.OrderedUnmarshal] feature, or fallback to +// an unordered behavior if none is found. +// +// NOTE: to allow types that are [easyjson.Unmarshaler] s to use that route to process JSON, +// you now need to register the adapter for easyjson at runtime. +func ReadJSON(data []byte, value any) error { + trimmedData := bytes.Trim(data, "\x00") + + if orderedMap, isOrdered := value.(ifaces.SetOrdered); isOrdered { + // if the value is an ordered map, favors support for OrderedUnmarshal. + + orderedUnmarshaler := adapters.OrderedUnmarshalAdapterFor(orderedMap) + + if orderedUnmarshaler != nil { + defer orderedUnmarshaler.Redeem() + + return orderedUnmarshaler.OrderedUnmarshal(trimmedData, orderedMap) + } + + // no support found in registered adapters, fallback to the default (unordered) case + } + + unmarshaler := adapters.UnmarshalAdapterFor(value) + if unmarshaler != nil { + defer unmarshaler.Redeem() + + return unmarshaler.Unmarshal(trimmedData, value) + } + + // no support found in registered adapters, fallback to the default standard library. + // + // This only happens when tinkering with the global registry of adapters, since the default handles all the above cases. + return json.Unmarshal(trimmedData, value) // Codecov ignore // this is a safeguard not easily simulated in tests +} + +// FromDynamicJSON turns a go value into a properly JSON typed structure. +// +// "Dynamic JSON" refers to what you get when unmarshaling JSON into an untyped any, +// i.e. objects are represented by map[string]any, arrays by []any, and +// all numbers are represented as float64. +// +// NOTE: target must be a pointer. +// +// # Maintaining the order of keys in objects +// +// If source and target implement [ifaces.Ordered] and [ifaces.SetOrdered] respectively, +// they are considered "ordered maps" and the order of keys is maintained in the +// "jsonification" process. In that case, map[string]any values are replaced by (ordered) [JSONMapSlice] ones. +func FromDynamicJSON(source, target any) error { + b, err := WriteJSON(source) + if err != nil { + return err + } + + return ReadJSON(b, target) +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go b/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go new file mode 100644 index 000000000..38dd3e244 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils/ordered_map.go @@ -0,0 +1,114 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package jsonutils + +import ( + "iter" + + "github.com/go-openapi/swag/jsonutils/adapters" + "github.com/go-openapi/swag/typeutils" +) + +// JSONMapSlice represents a JSON object, with the order of keys maintained. +// +// It behaves like an ordered map, but keys can't be accessed in constant time. +type JSONMapSlice []JSONMapItem + +// OrderedItems iterates over all (key,value) pairs with the order of keys maintained. +// +// This implements the [ifaces.Ordered] interface, so that [ifaces.Adapter] s know how to marshal +// keys in the desired order. +func (s JSONMapSlice) OrderedItems() iter.Seq2[string, any] { + return func(yield func(string, any) bool) { + for _, item := range s { + if !yield(item.Key, item.Value) { + return + } + } + } +} + +// SetOrderedItems sets keys in the [JSONMapSlice] objects, as presented by +// the provided iterator. +// +// As a special case, if items is nil, this sets to receiver to a nil slice. +// +// This implements the [ifaces.SetOrdered] interface, so that [ifaces.Adapter] s know how to unmarshal +// keys in the desired order. +func (s *JSONMapSlice) SetOrderedItems(items iter.Seq2[string, any]) { + if items == nil { + // force receiver to be a nil slice + *s = nil + + return + } + + m := *s + if len(m) > 0 { + // update mode: short-circuited when unmarshaling fresh data structures + idx := make(map[string]int, len(m)) + + for i, item := range m { + idx[item.Key] = i + } + + for k, v := range items { + idx, ok := idx[k] + if ok { + m[idx].Value = v + + continue + } + + m = append(m, JSONMapItem{Key: k, Value: v}) + } + + *s = m + + return + } + + for k, v := range items { + m = append(m, JSONMapItem{Key: k, Value: v}) + } + + *s = m +} + +// MarshalJSON renders a [JSONMapSlice] as JSON bytes, preserving the order of keys. +// +// It will pick the JSON library currently configured by the [adapters.Registry] (defaults to the standard library). +func (s JSONMapSlice) MarshalJSON() ([]byte, error) { + orderedMarshaler := adapters.OrderedMarshalAdapterFor(s) + defer orderedMarshaler.Redeem() + + return orderedMarshaler.OrderedMarshal(s) +} + +// UnmarshalJSON builds a [JSONMapSlice] from JSON bytes, preserving the order of keys. +// +// Inner objects are unmarshaled as ordered [JSONMapSlice] slices and not map[string]any. +// +// It will pick the JSON library currently configured by the [adapters.Registry] (defaults to the standard library). +func (s *JSONMapSlice) UnmarshalJSON(data []byte) error { + if typeutils.IsNil(*s) { + // allow to unmarshal with a simple var declaration (nil slice) + *s = JSONMapSlice{} + } + + orderedUnmarshaler := adapters.OrderedUnmarshalAdapterFor(s) + defer orderedUnmarshaler.Redeem() + + return orderedUnmarshaler.OrderedUnmarshal(data, s) +} + +// JSONMapItem represents the value of a key in a JSON object held by [JSONMapSlice]. +// +// Notice that JSONMapItem should not be marshaled to or unmarshaled from JSON directly. +// +// Use this type as part of a [JSONMapSlice] when dealing with JSON bytes. +type JSONMapItem struct { + Key string + Value any +} diff --git a/vendor/github.com/go-openapi/swag/jsonutils_iface.go b/vendor/github.com/go-openapi/swag/jsonutils_iface.go new file mode 100644 index 000000000..7bd4105fa --- /dev/null +++ b/vendor/github.com/go-openapi/swag/jsonutils_iface.go @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import ( + "log" + + "github.com/go-openapi/swag/jsonutils" +) + +// JSONMapSlice represents a JSON object, with the order of keys maintained +// +// Deprecated: use [jsonutils.JSONMapSlice] instead, or [yamlutils.YAMLMapSlice] if you marshal YAML. +type JSONMapSlice = jsonutils.JSONMapSlice + +// JSONMapItem represents a JSON object, with the order of keys maintained +// +// Deprecated: use [jsonutils.JSONMapItem] instead. +type JSONMapItem = jsonutils.JSONMapItem + +// WriteJSON writes json data. +// +// Deprecated: use [jsonutils.WriteJSON] instead. +func WriteJSON(data any) ([]byte, error) { return jsonutils.WriteJSON(data) } + +// ReadJSON reads json data. +// +// Deprecated: use [jsonutils.ReadJSON] instead. +func ReadJSON(data []byte, value any) error { return jsonutils.ReadJSON(data, value) } + +// DynamicJSONToStruct converts an untyped JSON structure into a target data type. +// +// Deprecated: use [jsonutils.FromDynamicJSON] instead. +func DynamicJSONToStruct(data any, target any) error { + return jsonutils.FromDynamicJSON(data, target) +} + +// ConcatJSON concatenates multiple JSON objects efficiently. +// +// Deprecated: use [jsonutils.ConcatJSON] instead. +func ConcatJSON(blobs ...[]byte) []byte { return jsonutils.ConcatJSON(blobs...) } + +// ToDynamicJSON turns a go value into a properly JSON untyped structure. +// +// It is the same as [FromDynamicJSON], but doesn't check for errors. +// +// Deprecated: this function is a misnomer and is unsafe. Use [jsonutils.FromDynamicJSON] instead. +func ToDynamicJSON(value any) any { + var res any + if err := FromDynamicJSON(value, &res); err != nil { + log.Println(err) + } + + return res +} + +// FromDynamicJSON turns a go value into a properly JSON typed structure. +// +// "Dynamic JSON" refers to what you get when unmarshaling JSON into an untyped any, +// i.e. objects are represented by map[string]any, arrays by []any, and all +// scalar values are any. +// +// Deprecated: use [jsonutils.FromDynamicJSON] instead. +func FromDynamicJSON(data, target any) error { return jsonutils.FromDynamicJSON(data, target) } diff --git a/vendor/github.com/go-openapi/swag/loading/LICENSE b/vendor/github.com/go-openapi/swag/loading/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/loading/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/loading/doc.go b/vendor/github.com/go-openapi/swag/loading/doc.go new file mode 100644 index 000000000..8cf7bcb8b --- /dev/null +++ b/vendor/github.com/go-openapi/swag/loading/doc.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package loading provides tools to load a file from http or from a local file system. +package loading diff --git a/vendor/github.com/go-openapi/swag/loading/errors.go b/vendor/github.com/go-openapi/swag/loading/errors.go new file mode 100644 index 000000000..b3964289c --- /dev/null +++ b/vendor/github.com/go-openapi/swag/loading/errors.go @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package loading + +type loadingError string + +const ( + // ErrLoader is an error raised by the file loader utility + ErrLoader loadingError = "loader error" +) + +func (e loadingError) Error() string { + return string(e) +} diff --git a/vendor/github.com/go-openapi/swag/loading/json.go b/vendor/github.com/go-openapi/swag/loading/json.go new file mode 100644 index 000000000..59db12f5c --- /dev/null +++ b/vendor/github.com/go-openapi/swag/loading/json.go @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package loading + +import ( + "encoding/json" + "errors" + "path/filepath" +) + +// JSONMatcher matches json for a file loader. +func JSONMatcher(path string) bool { + ext := filepath.Ext(path) + return ext == ".json" || ext == ".jsn" || ext == ".jso" +} + +// JSONDoc loads a json document from either a file or a remote url. +func JSONDoc(path string, opts ...Option) (json.RawMessage, error) { + data, err := LoadFromFileOrHTTP(path, opts...) + if err != nil { + return nil, errors.Join(err, ErrLoader) + } + return json.RawMessage(data), nil +} diff --git a/vendor/github.com/go-openapi/swag/loading.go b/vendor/github.com/go-openapi/swag/loading/loading.go similarity index 61% rename from vendor/github.com/go-openapi/swag/loading.go rename to vendor/github.com/go-openapi/swag/loading/loading.go index 658a24b78..269fb74d1 100644 --- a/vendor/github.com/go-openapi/swag/loading.go +++ b/vendor/github.com/go-openapi/swag/loading/loading.go @@ -1,54 +1,26 @@ -// Copyright 2015 go-swagger maintainers -// -// 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. +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 -package swag +package loading import ( + "context" + "embed" "fmt" "io" "log" "net/http" "net/url" - "os" "path" "path/filepath" "runtime" "strings" - "time" ) -// LoadHTTPTimeout the default timeout for load requests -var LoadHTTPTimeout = 30 * time.Second - -// LoadHTTPBasicAuthUsername the username to use when load requests require basic auth -var LoadHTTPBasicAuthUsername = "" - -// LoadHTTPBasicAuthPassword the password to use when load requests require basic auth -var LoadHTTPBasicAuthPassword = "" - -// LoadHTTPCustomHeaders an optional collection of custom HTTP headers for load requests -var LoadHTTPCustomHeaders = map[string]string{} - // LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in -func LoadFromFileOrHTTP(pth string) ([]byte, error) { - return LoadStrategy(pth, os.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(pth) -} - -// LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in -// timeout arg allows for per request overriding of the request timeout -func LoadFromFileOrHTTPWithTimeout(pth string, timeout time.Duration) ([]byte, error) { - return LoadStrategy(pth, os.ReadFile, loadHTTPBytes(timeout))(pth) +func LoadFromFileOrHTTP(pth string, opts ...Option) ([]byte, error) { + o := optionsWithDefaults(opts) + return LoadStrategy(pth, o.ReadFileFunc(), loadHTTPBytes(opts...), opts...)(pth) } // LoadStrategy returns a loader function for a given path or URI. @@ -81,10 +53,12 @@ func LoadFromFileOrHTTPWithTimeout(pth string, timeout time.Duration) ([]byte, e // - `file://host/folder/file` becomes an UNC path like `\\host\folder\file` (no port specification is supported) // - `file:///c:/folder/file` becomes `C:\folder\file` // - `file://c:/folder/file` is tolerated (without leading `/`) and becomes `c:\folder\file` -func LoadStrategy(pth string, local, remote func(string) ([]byte, error)) func(string) ([]byte, error) { +func LoadStrategy(pth string, local, remote func(string) ([]byte, error), opts ...Option) func(string) ([]byte, error) { if strings.HasPrefix(pth, "http") { return remote } + o := optionsWithDefaults(opts) + _, isEmbedFS := o.fs.(embed.FS) return func(p string) ([]byte, error) { upth, err := url.PathUnescape(p) @@ -92,19 +66,19 @@ func LoadStrategy(pth string, local, remote func(string) ([]byte, error)) func(s return nil, err } - if !strings.HasPrefix(p, `file://`) { + cpth, hasPrefix := strings.CutPrefix(upth, "file://") + if !hasPrefix || isEmbedFS || runtime.GOOS != "windows" { + // crude processing: trim the file:// prefix. This leaves full URIs with a host with a (mostly) unexpected result // regular file path provided: just normalize slashes - return local(filepath.FromSlash(upth)) - } - - if runtime.GOOS != "windows" { - // crude processing: this leaves full URIs with a host with a (mostly) unexpected result - upth = strings.TrimPrefix(upth, `file://`) + if isEmbedFS { + // on windows, we need to slash the path if FS is an embed FS. + return local(strings.TrimLeft(filepath.ToSlash(cpth), "./")) // remove invalid leading characters for embed FS + } - return local(filepath.FromSlash(upth)) + return local(filepath.FromSlash(cpth)) } - // windows-only pre-processing of file://... URIs + // windows-only pre-processing of file://... URIs, excluding embed.FS // support for canonical file URIs on windows. u, err := url.Parse(filepath.ToSlash(upth)) @@ -139,19 +113,29 @@ func LoadStrategy(pth string, local, remote func(string) ([]byte, error)) func(s } } -func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) { +func loadHTTPBytes(opts ...Option) func(path string) ([]byte, error) { + o := optionsWithDefaults(opts) + return func(path string) ([]byte, error) { - client := &http.Client{Timeout: timeout} - req, err := http.NewRequest(http.MethodGet, path, nil) //nolint:noctx + client := o.client + timeoutCtx := context.Background() + var cancel func() + + if o.httpTimeout > 0 { + timeoutCtx, cancel = context.WithTimeout(timeoutCtx, o.httpTimeout) + defer cancel() + } + + req, err := http.NewRequestWithContext(timeoutCtx, http.MethodGet, path, nil) if err != nil { return nil, err } - if LoadHTTPBasicAuthUsername != "" && LoadHTTPBasicAuthPassword != "" { - req.SetBasicAuth(LoadHTTPBasicAuthUsername, LoadHTTPBasicAuthPassword) + if o.basicAuthUsername != "" && o.basicAuthPassword != "" { + req.SetBasicAuth(o.basicAuthUsername, o.basicAuthPassword) } - for key, val := range LoadHTTPCustomHeaders { + for key, val := range o.customHeaders { req.Header.Set(key, val) } diff --git a/vendor/github.com/go-openapi/swag/loading/options.go b/vendor/github.com/go-openapi/swag/loading/options.go new file mode 100644 index 000000000..6674ac69e --- /dev/null +++ b/vendor/github.com/go-openapi/swag/loading/options.go @@ -0,0 +1,125 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package loading + +import ( + "io/fs" + "net/http" + "os" + "time" +) + +type ( + // Option provides options for loading a file over HTTP or from a file. + Option func(*options) + + httpOptions struct { + httpTimeout time.Duration + basicAuthUsername string + basicAuthPassword string + customHeaders map[string]string + client *http.Client + } + + fileOptions struct { + fs fs.ReadFileFS + } + + options struct { + httpOptions + fileOptions + } +) + +func (fo fileOptions) ReadFileFunc() func(string) ([]byte, error) { + if fo.fs == nil { + return os.ReadFile + } + + return fo.fs.ReadFile +} + +// WithTimeout sets a timeout for the remote file loader. +// +// The default timeout is 30s. +func WithTimeout(timeout time.Duration) Option { + return func(o *options) { + o.httpTimeout = timeout + } +} + +// WithBasicAuth sets a basic authentication scheme for the remote file loader. +func WithBasicAuth(username, password string) Option { + return func(o *options) { + o.basicAuthUsername = username + o.basicAuthPassword = password + } +} + +// WithCustomHeaders sets custom headers for the remote file loader. +func WithCustomHeaders(headers map[string]string) Option { + return func(o *options) { + if o.customHeaders == nil { + o.customHeaders = make(map[string]string, len(headers)) + } + + for header, value := range headers { + o.customHeaders[header] = value + } + } +} + +// WithHTTPClient overrides the default HTTP client used to fetch a remote file. +// +// By default, [http.DefaultClient] is used. +func WithHTTPClient(client *http.Client) Option { + return func(o *options) { + o.client = client + } +} + +// WithFS sets a file system for the local file loader. +// +// If the provided file system is a [fs.ReadFileFS], the ReadFile function is used. +// Otherwise, ReadFile is wrapped using [fs.ReadFile]. +// +// By default, the file system is the one provided by the os package. +// +// For example, this may be set to consume from an embedded file system, or a rooted FS. +func WithFS(filesystem fs.FS) Option { + return func(o *options) { + if rfs, ok := filesystem.(fs.ReadFileFS); ok { + o.fs = rfs + + return + } + o.fs = readFileFS{FS: filesystem} + } +} + +type readFileFS struct { + fs.FS +} + +func (r readFileFS) ReadFile(name string) ([]byte, error) { + return fs.ReadFile(r.FS, name) +} + +func optionsWithDefaults(opts []Option) options { + const defaultTimeout = 30 * time.Second + + o := options{ + // package level defaults + httpOptions: httpOptions{ + httpTimeout: defaultTimeout, + client: http.DefaultClient, + }, + } + + for _, apply := range opts { + apply(&o) + } + + return o +} diff --git a/vendor/github.com/go-openapi/swag/loading/yaml.go b/vendor/github.com/go-openapi/swag/loading/yaml.go new file mode 100644 index 000000000..3ebb53668 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/loading/yaml.go @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package loading + +import ( + "encoding/json" + "path/filepath" + + "github.com/go-openapi/swag/yamlutils" +) + +// YAMLMatcher matches yaml for a file loader. +func YAMLMatcher(path string) bool { + ext := filepath.Ext(path) + return ext == ".yaml" || ext == ".yml" +} + +// YAMLDoc loads a yaml document from either http or a file and converts it to json. +func YAMLDoc(path string, opts ...Option) (json.RawMessage, error) { + yamlDoc, err := YAMLData(path, opts...) + if err != nil { + return nil, err + } + + return yamlutils.YAMLToJSON(yamlDoc) +} + +// YAMLData loads a yaml document from either http or a file. +func YAMLData(path string, opts ...Option) (any, error) { + data, err := LoadFromFileOrHTTP(path, opts...) + if err != nil { + return nil, err + } + + return yamlutils.BytesToYAMLDoc(data) +} diff --git a/vendor/github.com/go-openapi/swag/loading_iface.go b/vendor/github.com/go-openapi/swag/loading_iface.go new file mode 100644 index 000000000..27ec3fb8c --- /dev/null +++ b/vendor/github.com/go-openapi/swag/loading_iface.go @@ -0,0 +1,91 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import ( + "encoding/json" + "time" + + "github.com/go-openapi/swag/loading" +) + +var ( + // Package-level defaults for the file loading utilities (deprecated). + + // LoadHTTPTimeout the default timeout for load requests. + // + // Deprecated: use [loading.WithTimeout] instead. + LoadHTTPTimeout = 30 * time.Second + + // LoadHTTPBasicAuthUsername the username to use when load requests require basic auth. + // + // Deprecated: use [loading.WithBasicAuth] instead. + LoadHTTPBasicAuthUsername = "" + + // LoadHTTPBasicAuthPassword the password to use when load requests require basic auth. + // + // Deprecated: use [loading.WithBasicAuth] instead. + LoadHTTPBasicAuthPassword = "" + + // LoadHTTPCustomHeaders an optional collection of custom HTTP headers for load requests. + // + // Deprecated: use [loading.WithCustomHeaders] instead. + LoadHTTPCustomHeaders = map[string]string{} +) + +// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the provided path. +// +// Deprecated: use [loading.LoadFromFileOrHTTP] instead. +func LoadFromFileOrHTTP(pth string, opts ...loading.Option) ([]byte, error) { + return loading.LoadFromFileOrHTTP(pth, loadingOptionsWithDefaults(opts)...) +} + +// LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in +// timeout arg allows for per request overriding of the request timeout. +// +// Deprecated: use [loading.LoadFileOrHTTP] with the [loading.WithTimeout] option instead. +func LoadFromFileOrHTTPWithTimeout(pth string, timeout time.Duration, opts ...loading.Option) ([]byte, error) { + opts = append(opts, loading.WithTimeout(timeout)) + + return LoadFromFileOrHTTP(pth, opts...) +} + +// LoadStrategy returns a loader function for a given path or URL. +// +// Deprecated: use [loading.LoadStrategy] instead. +func LoadStrategy(pth string, local, remote func(string) ([]byte, error), opts ...loading.Option) func(string) ([]byte, error) { + return loading.LoadStrategy(pth, local, remote, loadingOptionsWithDefaults(opts)...) +} + +// YAMLMatcher matches yaml for a file loader. +// +// Deprecated: use [loading.YAMLMatcher] instead. +func YAMLMatcher(path string) bool { return loading.YAMLMatcher(path) } + +// YAMLDoc loads a yaml document from either http or a file and converts it to json. +// +// Deprecated: use [loading.YAMLDoc] instead. +func YAMLDoc(path string) (json.RawMessage, error) { + return loading.YAMLDoc(path) +} + +// YAMLData loads a yaml document from either http or a file. +// +// Deprecated: use [loading.YAMLData] instead. +func YAMLData(path string) (any, error) { + return loading.YAMLData(path) +} + +// loadingOptionsWithDefaults bridges deprecated default settings that use package-level variables, +// with the recommended use of loading.Option. +func loadingOptionsWithDefaults(opts []loading.Option) []loading.Option { + o := []loading.Option{ + loading.WithTimeout(LoadHTTPTimeout), + loading.WithBasicAuth(LoadHTTPBasicAuthUsername, LoadHTTPBasicAuthPassword), + loading.WithCustomHeaders(LoadHTTPCustomHeaders), + } + o = append(o, opts...) + + return o +} diff --git a/vendor/github.com/go-openapi/swag/BENCHMARK.md b/vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md similarity index 53% rename from vendor/github.com/go-openapi/swag/BENCHMARK.md rename to vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md index e7f28ed6b..abe6e9533 100644 --- a/vendor/github.com/go-openapi/swag/BENCHMARK.md +++ b/vendor/github.com/go-openapi/swag/mangling/BENCHMARK.md @@ -1,12 +1,10 @@ -# Benchmarks - -## Name mangling utilities +# Benchmarking name mangling utilities ```bash go test -bench XXX -run XXX -benchtime 30s ``` -### Benchmarks at b3e7a5386f996177e4808f11acb2aa93a0f660df +## Benchmarks at `b3e7a5386f996177e4808f11acb2aa93a0f660df` ``` goos: linux @@ -21,7 +19,7 @@ BenchmarkToXXXName/ToHumanNameLower-4 895334 40354 ns/op 10472 B/op BenchmarkToXXXName/ToHumanNameTitle-4 882441 40678 ns/op 10566 B/op 749 allocs/op ``` -### Benchmarks after PR #79 +## Benchmarks after PR #79 ~ x10 performance improvement and ~ /100 memory allocations. @@ -50,3 +48,43 @@ BenchmarkToXXXName/ToCommandName-16 32256634 1137 ns/op 147 B/op BenchmarkToXXXName/ToHumanNameLower-16 18599661 1946 ns/op 92 B/op 6 allocs/op BenchmarkToXXXName/ToHumanNameTitle-16 17581353 2054 ns/op 105 B/op 6 allocs/op ``` + +## Benchmarks at `d7d2d1b895f5b6747afaff312dd2a402e69e818b` + +go1.24 + +``` +goos: linux +goarch: amd64 +pkg: github.com/go-openapi/swag +cpu: AMD Ryzen 7 5800X 8-Core Processor +BenchmarkToXXXName/ToGoName-16 19757858 1881 ns/op 42 B/op 5 allocs/op +BenchmarkToXXXName/ToVarName-16 17494111 2094 ns/op 74 B/op 7 allocs/op +BenchmarkToXXXName/ToFileName-16 28161226 1492 ns/op 158 B/op 7 allocs/op +BenchmarkToXXXName/ToCommandName-16 23787333 1489 ns/op 158 B/op 7 allocs/op +BenchmarkToXXXName/ToHumanNameLower-16 17537257 2030 ns/op 103 B/op 6 allocs/op +BenchmarkToXXXName/ToHumanNameTitle-16 16977453 2156 ns/op 105 B/op 6 allocs/op +``` + +## Benchmarks after PR #106 + +Moving the scope of everything down to a struct allowed to reduce a bit garbage and pooling. + +On top of that, ToGoName (and thus ToVarName) have been subject to a minor optimization, removing a few allocations. + +Overall timings improve by ~ -10%. + +go1.24 + +``` +goos: linux +goarch: amd64 +pkg: github.com/go-openapi/swag/mangling +cpu: AMD Ryzen 7 5800X 8-Core Processor +BenchmarkToXXXName/ToGoName-16 22496130 1618 ns/op 31 B/op 3 allocs/op +BenchmarkToXXXName/ToVarName-16 22538068 1618 ns/op 33 B/op 3 allocs/op +BenchmarkToXXXName/ToFileName-16 27722977 1236 ns/op 105 B/op 6 allocs/op +BenchmarkToXXXName/ToCommandName-16 27967395 1258 ns/op 105 B/op 6 allocs/op +BenchmarkToXXXName/ToHumanNameLower-16 18587901 1917 ns/op 103 B/op 6 allocs/op +BenchmarkToXXXName/ToHumanNameTitle-16 17193208 2019 ns/op 108 B/op 7 allocs/op +``` diff --git a/vendor/github.com/go-openapi/swag/mangling/LICENSE b/vendor/github.com/go-openapi/swag/mangling/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/mangling/doc.go b/vendor/github.com/go-openapi/swag/mangling/doc.go new file mode 100644 index 000000000..ce0d89048 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling/doc.go @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package mangling provides name mangling capabilities. +// +// Name mangling is an important stage when generating code: +// it helps construct safe program identifiers that abide by the language rules +// and play along with linters. +// +// Examples: +// +// Suppose we get an object name taken from an API spec: "json_object", +// +// We may generate a legit go type name using [NameMangler.ToGoName]: "JsonObject". +// +// We may then locate this type in a source file named using [NameMangler.ToFileName]: "json_object.go". +// +// The methods exposed by the NameMangler are used to generate code in many different contexts, such as: +// +// - generating exported or unexported go identifiers from a JSON schema or an API spec +// - generating file names +// - generating human-readable comments for types and variables +// - generating JSON-like API identifiers from go code +// - ... +package mangling diff --git a/vendor/github.com/go-openapi/swag/mangling/initialism_index.go b/vendor/github.com/go-openapi/swag/mangling/initialism_index.go new file mode 100644 index 000000000..e5b70c149 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling/initialism_index.go @@ -0,0 +1,270 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mangling + +import ( + "sort" + "strings" + "unicode" + "unicode/utf8" +) + +// DefaultInitialisms returns all the initialisms configured by default for this package. +// +// # Motivation +// +// Common initialisms are acronyms for which the ordinary camel-casing rules are altered and +// for which we retain the original case. +// +// This is largely specific to the go naming conventions enforced by golint (now revive). +// +// # Example +// +// In go, "id" is a good-looking identifier, but "Id" is not and "ID" is preferred +// (notice that this stems only from conventions: the go compiler accepts all of these). +// +// Similarly, we may use "http", but not "Http". In this case, "HTTP" is preferred. +// +// # Reference and customization +// +// The default list of these casing-style exceptions is taken from the [github.com/mgechev/revive] linter for go: +// https://github.com/mgechev/revive/blob/master/lint/name.go#L93 +// +// There are a few additions to the original list, such as IPv4, IPv6 and OAI ("OpenAPI"). +// +// For these additions, "IPv4" would be preferred to "Ipv4" or "IPV4", and "OAI" to "Oai" +// +// You may redefine this list entirely using the mangler option [WithInitialisms], or simply add extra definitions +// using [WithAdditionalInitialisms]. +// +// # Mixed-case and plurals +// +// Notice that initialisms are not necessarily fully upper-cased: a mixed-case initialism indicates the preferred casing. +// +// Obviously, lower-case only initialisms do not make a lot of sense: if lower-case only initialisms are added, +// they will be considered fully capitalized. +// +// Plural forms use mixed case like "IDs". And so do values like "IPv4" or "IPv6". +// +// The [NameMangler] automatically detects simple plurals for words such as "IDs" or "APIs", +// so you don't need to configure these variants. +// +// At this moment, it doesn't support pluralization of terms that ends with an 's' (or 'S'), since there is +// no clear consensus on whether a word like DNS should be pluralized as DNSes or remain invariant. +// The [NameMangler] consider those invariant. Therefore DNSs or DNSes are not recognized as plurals for DNS. +// +// Besids, we don't want to support pluralization of terms which would otherwise conflict with another one, +// like "HTTPs" vs "HTTPS". All these should be considered invariant. Hence: "Https" matches "HTTPS" and +// "HTTPSS" is "HTTPS" followed by "S". +func DefaultInitialisms() []string { + return []string{ + "ACL", + "API", + "ASCII", + "CPU", + "CSS", + "DNS", + "EOF", + "GUID", + "HTML", + "HTTPS", + "HTTP", + "ID", + "IP", + "IPv4", // prefer the mixed case outcome IPv4 over the capitalized IPV4 + "IPv6", // prefer the mixed case outcome IPv6 over the capitalized IPV6 + "JSON", + "LHS", + "OAI", + "QPS", + "RAM", + "RHS", + "RPC", + "SLA", + "SMTP", + "SQL", + "SSH", + "TCP", + "TLS", + "TTL", + "UDP", + "UI", + "UID", + "UUID", + "URI", + "URL", + "UTF8", + "VM", + "XML", + "XMPP", + "XSRF", + "XSS", + } +} + +type indexOfInitialisms struct { + initialismsCache + + index map[string]struct{} +} + +func newIndexOfInitialisms() *indexOfInitialisms { + return &indexOfInitialisms{ + index: make(map[string]struct{}), + } +} + +func (m *indexOfInitialisms) add(words ...string) *indexOfInitialisms { + for _, word := range words { + // sanitization of injected words: trimmed from blanks, and must start with a letter + trimmed := strings.TrimSpace(word) + + firstRune, _ := utf8.DecodeRuneInString(trimmed) + if !unicode.IsLetter(firstRune) { + continue + } + + // Initialisms are case-sensitive. This means that we support mixed-case words. + // However, if specified as a lower-case string, the initialism should be fully capitalized. + if trimmed == strings.ToLower(trimmed) { + m.index[strings.ToUpper(trimmed)] = struct{}{} + + continue + } + + m.index[trimmed] = struct{}{} + } + return m +} + +func (m *indexOfInitialisms) sorted() []string { + result := make([]string, 0, len(m.index)) + for k := range m.index { + result = append(result, k) + } + sort.Sort(sort.Reverse(byInitialism(result))) + return result +} + +func (m *indexOfInitialisms) buildCache() { + m.build(m.sorted(), m.pluralForm) +} + +// initialismsCache caches all needed pre-computed and converted initialism entries, +// in the desired resolution order. +type initialismsCache struct { + initialisms []string + initialismsRunes [][]rune + initialismsUpperCased [][]rune // initialisms cached in their trimmed, upper-cased version + initialismsPluralForm []pluralForm +} + +func (c *initialismsCache) build(in []string, pluralfunc func(string) pluralForm) { + c.initialisms = in + c.initialismsRunes = asRunes(c.initialisms) + c.initialismsUpperCased = asUpperCased(c.initialisms) + c.initialismsPluralForm = asPluralForms(c.initialisms, pluralfunc) +} + +// pluralForm denotes the kind of pluralization to be used for initialisms. +// +// At this moment, initialisms are either invariant or follow a simple plural form with an +// extra (lower case) "s". +type pluralForm uint8 + +const ( + notPlural pluralForm = iota + invariantPlural + simplePlural +) + +func (f pluralForm) String() string { + switch f { + case notPlural: + return "notPlural" + case invariantPlural: + return "invariantPlural" + case simplePlural: + return "simplePlural" + default: + return "" + } +} + +// pluralForm indicates how we want to pluralize a given initialism. +// +// Besides configured invariant forms (like HTTP and HTTPS), +// an initialism is normally pluralized by adding a single 's', like in IDs. +// +// Initialisms ending with an 'S' or an 's' are configured as invariant (we don't +// support plural forms like CSSes or DNSes, however the mechanism could be extended to +// do just that). +func (m *indexOfInitialisms) pluralForm(key string) pluralForm { + if _, ok := m.index[key]; !ok { + return notPlural + } + + if strings.HasSuffix(strings.ToUpper(key), "S") { + return invariantPlural + } + + if _, ok := m.index[key+"s"]; ok { + return invariantPlural + } + + if _, ok := m.index[key+"S"]; ok { + return invariantPlural + } + + return simplePlural +} + +type byInitialism []string + +func (s byInitialism) Len() int { + return len(s) +} +func (s byInitialism) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// Less specifies the order in which initialisms are prioritized: +// 1. match longest first +// 2. when equal length, match in reverse lexicographical order, lower case match comes first +func (s byInitialism) Less(i, j int) bool { + if len(s[i]) != len(s[j]) { + return len(s[i]) < len(s[j]) + } + + return s[i] < s[j] +} + +func asRunes(in []string) [][]rune { + out := make([][]rune, len(in)) + for i, initialism := range in { + out[i] = []rune(initialism) + } + + return out +} + +func asUpperCased(in []string) [][]rune { + out := make([][]rune, len(in)) + + for i, initialism := range in { + out[i] = []rune(upper(trim(initialism))) + } + + return out +} + +// asPluralForms bakes an index of pluralization support. +func asPluralForms(in []string, pluralFunc func(string) pluralForm) []pluralForm { + out := make([]pluralForm, len(in)) + for i, initialism := range in { + out[i] = pluralFunc(initialism) + } + + return out +} diff --git a/vendor/github.com/go-openapi/swag/mangling/name_lexem.go b/vendor/github.com/go-openapi/swag/mangling/name_lexem.go new file mode 100644 index 000000000..bc837e3b9 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling/name_lexem.go @@ -0,0 +1,186 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mangling + +import ( + "bytes" + "strings" + "unicode" + "unicode/utf8" +) + +type ( + lexemKind uint8 + + nameLexem struct { + original string + matchedInitialism string + kind lexemKind + } +) + +const ( + lexemKindCasualName lexemKind = iota + lexemKindInitialismName +) + +func newInitialismNameLexem(original, matchedInitialism string) nameLexem { + return nameLexem{ + kind: lexemKindInitialismName, + original: original, + matchedInitialism: matchedInitialism, + } +} + +func newCasualNameLexem(original string) nameLexem { + return nameLexem{ + kind: lexemKindCasualName, + original: trim(original), // TODO: save on calls to trim + } +} + +// WriteTitleized writes the titleized lexeme to a bytes.Buffer. +// +// If the first letter cannot be capitalized, it doesn't write anything and return false, +// so the caller may attempt some workaround strategy. +func (l nameLexem) WriteTitleized(w *bytes.Buffer, alwaysUpper bool) bool { + if l.kind == lexemKindInitialismName { + w.WriteString(l.matchedInitialism) + + return true + } + + if len(l.original) == 0 { + return true + } + + if len(l.original) == 1 { + // identifier is too short: casing will depend on the context + firstByte := l.original[0] + switch { + case 'A' <= firstByte && firstByte <= 'Z': + // safe + w.WriteByte(firstByte) + + return true + case alwaysUpper && 'a' <= firstByte && firstByte <= 'z': + w.WriteByte(firstByte - 'a' + 'A') + + return true + default: + + // not a letter: skip and let the caller decide + return false + } + } + + if firstByte := l.original[0]; firstByte < utf8.RuneSelf { + // ASCII + switch { + case 'A' <= firstByte && firstByte <= 'Z': + // already an upper case letter + w.WriteString(l.original) + + return true + case 'a' <= firstByte && firstByte <= 'z': + w.WriteByte(firstByte - 'a' + 'A') + w.WriteString(l.original[1:]) + + return true + default: + // not a good candidate: doesn't start with a letter + return false + } + } + + // unicode + firstRune, idx := utf8.DecodeRuneInString(l.original) + if !unicode.IsLetter(firstRune) || !unicode.IsUpper(unicode.ToUpper(firstRune)) { + // not a good candidate: doesn't start with a letter + // or a rune for which case doesn't make sense (e.g. East-Asian runes etc) + return false + } + + rest := l.original[idx:] + w.WriteRune(unicode.ToUpper(firstRune)) + w.WriteString(strings.ToLower(rest)) + + return true +} + +// WriteLower is like write titleized but it writes a lower-case version of the lexeme. +// +// Similarly, there is no writing if the casing of the first rune doesn't make sense. +func (l nameLexem) WriteLower(w *bytes.Buffer, alwaysLower bool) bool { + if l.kind == lexemKindInitialismName { + w.WriteString(lower(l.matchedInitialism)) + + return true + } + + if len(l.original) == 0 { + return true + } + + if len(l.original) == 1 { + // identifier is too short: casing will depend on the context + firstByte := l.original[0] + switch { + case 'a' <= firstByte && firstByte <= 'z': + // safe + w.WriteByte(firstByte) + + return true + case alwaysLower && 'A' <= firstByte && firstByte <= 'Z': + w.WriteByte(firstByte - 'A' + 'a') + + return true + default: + + // not a letter: skip and let the caller decide + return false + } + } + + if firstByte := l.original[0]; firstByte < utf8.RuneSelf { + // ASCII + switch { + case 'a' <= firstByte && firstByte <= 'z': + // already a lower case letter + w.WriteString(l.original) + + return true + case 'A' <= firstByte && firstByte <= 'Z': + w.WriteByte(firstByte - 'A' + 'a') + w.WriteString(l.original[1:]) + + return true + default: + // not a good candidate: doesn't start with a letter + return false + } + } + + // unicode + firstRune, idx := utf8.DecodeRuneInString(l.original) + if !unicode.IsLetter(firstRune) || !unicode.IsLower(unicode.ToLower(firstRune)) { + // not a good candidate: doesn't start with a letter + // or a rune for which case doesn't make sense (e.g. East-Asian runes etc) + return false + } + + rest := l.original[idx:] + w.WriteRune(unicode.ToLower(firstRune)) + w.WriteString(rest) + + return true +} + +func (l nameLexem) GetOriginal() string { + return l.original +} + +func (l nameLexem) IsInitialism() bool { + return l.kind == lexemKindInitialismName +} diff --git a/vendor/github.com/go-openapi/swag/mangling/name_mangler.go b/vendor/github.com/go-openapi/swag/mangling/name_mangler.go new file mode 100644 index 000000000..da685681d --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling/name_mangler.go @@ -0,0 +1,370 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mangling + +import ( + "strings" + "unicode" +) + +// NameMangler knows how to transform sentences or words into +// identifiers that are a better fit in contexts such as: +// +// - unexported or exported go variable identifiers +// - file names +// - camel cased identifiers +// - ... +// +// The [NameMangler] is safe for concurrent use, save for its [NameMangler.AddInitialisms] method, +// which is not. +// +// # Known limitations +// +// At this moment, the [NameMangler] doesn't play well with "all caps" text: +// +// unless every single upper-cased word is declared as an initialism, capitalized words would generally +// not be transformed with the expected result, e.g. +// +// ToFileName("THIS_IS_ALL_CAPS") +// +// yields the weird outcome +// +// "t_h_i_s_i_s_a_l_l_c_a_p_s" +type NameMangler struct { + options + + index *indexOfInitialisms + + splitter splitter + splitterWithPostSplit splitter + + _ struct{} +} + +// NewNameMangler builds a name mangler ready to convert strings. +// +// The default name mangler is configured with default common initialisms and all default options. +func NewNameMangler(opts ...Option) NameMangler { + m := NameMangler{ + options: optionsWithDefaults(opts), + index: newIndexOfInitialisms(), + } + m.addInitialisms(m.commonInitialisms...) + + // a splitter that returns matches lexemes as ready-to-assemble strings: + // details of the lexemes are redeemed. + m.splitter = newSplitter( + withInitialismsCache(&m.index.initialismsCache), + withReplaceFunc(m.replaceFunc), + ) + + // a splitter that returns matches lexemes ready for post-processing + m.splitterWithPostSplit = newSplitter( + withInitialismsCache(&m.index.initialismsCache), + withReplaceFunc(m.replaceFunc), + withPostSplitInitialismCheck, + ) + + return m +} + +// AddInitialisms declares extra initialisms to the mangler. +// +// It declares extra words as "initialisms" (i.e. words that won't be camel cased or titled cased), +// on top of the existing list of common initialisms (such as ID, HTTP...). +// +// Added words must start with a (unicode) letter. If some don't, they are ignored. +// Added words are either fully capitalized or mixed-cased. Lower-case only words are considered capitalized. +// +// It is typically used just after initializing the [NameMangler]. +// +// When all initialisms are known at the time the mangler is initialized, it is preferable to +// use [NewNameMangler] with the option [WithAdditionalInitialisms]. +// +// Adding initialisms mutates the mangler and should not be carried out concurrently with other calls to the mangler. +func (m *NameMangler) AddInitialisms(words ...string) { + m.addInitialisms(words...) +} + +// Initialisms renders the list of initialisms supported by this mangler. +func (m *NameMangler) Initialisms() []string { + return m.index.initialisms +} + +// Camelize a single word. +// +// Example: +// +// - "HELLO" and "hello" become "Hello". +func (m NameMangler) Camelize(word string) string { + ru := []rune(word) + + switch len(ru) { + case 0: + return "" + case 1: + return string(unicode.ToUpper(ru[0])) + default: + camelized := poolOfBuffers.BorrowBuffer(len(word)) + camelized.Grow(len(word)) + defer func() { + poolOfBuffers.RedeemBuffer(camelized) + }() + + camelized.WriteRune(unicode.ToUpper(ru[0])) + for _, ru := range ru[1:] { + camelized.WriteRune(unicode.ToLower(ru)) + } + + return camelized.String() + } +} + +// ToFileName generates a suitable snake-case file name from a sentence. +// +// It lower-cases everything with underscore (_) as a word separator. +// +// Examples: +// +// - "Hello, Swagger" becomes "hello_swagger" +// - "HelloSwagger" becomes "hello_swagger" +func (m NameMangler) ToFileName(name string) string { + inptr := m.split(name) + in := *inptr + out := make([]string, 0, len(in)) + + for _, w := range in { + out = append(out, lower(w)) + } + poolOfStrings.RedeemStrings(inptr) + + return strings.Join(out, "_") +} + +// ToCommandName generates a suitable CLI command name from a sentence. +// +// It lower-cases everything with dash (-) as a word separator. +// +// Examples: +// +// - "Hello, Swagger" becomes "hello-swagger" +// - "HelloSwagger" becomes "hello-swagger" +func (m NameMangler) ToCommandName(name string) string { + inptr := m.split(name) + in := *inptr + out := make([]string, 0, len(in)) + + for _, w := range in { + out = append(out, lower(w)) + } + poolOfStrings.RedeemStrings(inptr) + + return strings.Join(out, "-") +} + +// ToHumanNameLower represents a code name as a human-readable series of words. +// +// It lower-cases everything with blank space as a word separator. +// +// NOTE: parts recognized as initialisms just keep their original casing. +// +// Examples: +// +// - "Hello, Swagger" becomes "hello swagger" +// - "HelloSwagger" or "Hello-Swagger" become "hello swagger" +func (m NameMangler) ToHumanNameLower(name string) string { + s := m.splitterWithPostSplit + in := s.split(name) + out := make([]string, 0, len(*in)) + + for _, w := range *in { + if !w.IsInitialism() { + out = append(out, lower(w.GetOriginal())) + } else { + out = append(out, trim(w.GetOriginal())) + } + } + + poolOfLexems.RedeemLexems(in) + + return strings.Join(out, " ") +} + +// ToHumanNameTitle represents a code name as a human-readable series of titleized words. +// +// It titleizes every word with blank space as a word separator. +// +// Examples: +// +// - "hello, Swagger" becomes "Hello Swagger" +// - "helloSwagger" becomes "Hello Swagger" +func (m NameMangler) ToHumanNameTitle(name string) string { + s := m.splitterWithPostSplit + in := s.split(name) + + out := make([]string, 0, len(*in)) + for _, w := range *in { + original := trim(w.GetOriginal()) + if !w.IsInitialism() { + out = append(out, m.Camelize(original)) + } else { + out = append(out, original) + } + } + poolOfLexems.RedeemLexems(in) + + return strings.Join(out, " ") +} + +// ToJSONName generates a camelized single-word version of a sentence. +// +// The output assembles every camelized word, but for the first word, which +// is lower-cased. +// +// Example: +// +// - "Hello_swagger" becomes "helloSwagger" +func (m NameMangler) ToJSONName(name string) string { + inptr := m.split(name) + in := *inptr + out := make([]string, 0, len(in)) + + for i, w := range in { + if i == 0 { + out = append(out, lower(w)) + continue + } + out = append(out, m.Camelize(trim(w))) + } + + poolOfStrings.RedeemStrings(inptr) + + return strings.Join(out, "") +} + +// ToVarName generates a legit unexported go variable name from a sentence. +// +// The generated name plays well with linters (see also [NameMangler.ToGoName]). +// +// Examples: +// +// - "Hello_swagger" becomes "helloSwagger" +// - "Http_server" becomes "httpServer" +// +// This name applies the same rules as [NameMangler.ToGoName] (legit exported variable), save the +// capitalization of the initial rune. +// +// Special case: when the initial part is a recognized as an initialism (like in the example above), +// the full part is lower-cased. +func (m NameMangler) ToVarName(name string) string { + return m.goIdentifier(name, false) +} + +// ToGoName generates a legit exported go variable name from a sentence. +// +// The generated name plays well with most linters. +// +// ToGoName abides by the go "exported" symbol rule starting with an upper-case letter. +// +// Examples: +// +// - "hello_swagger" becomes "HelloSwagger" +// - "Http_server" becomes "HTTPServer" +// +// # Edge cases +// +// Whenever the first rune is not eligible to upper case, a special prefix is prepended to the resulting name. +// By default this is simply "X" and you may customize this behavior using the [WithGoNamePrefixFunc] option. +// +// This happens when the first rune is not a letter, e.g. a digit, or a symbol that has no word transliteration +// (see also [WithReplaceFunc] about symbol transliterations), +// as well as for most East Asian or Devanagari runes, for which there is no such concept as upper-case. +// +// # Linting +// +// [revive], the successor of golint is the reference linter. +// +// This means that [NameMangler.ToGoName] supports the initialisms that revive checks (see also [DefaultInitialisms]). +// +// At this moment, there is no attempt to transliterate unicode into ascii, meaning that some linters +// (e.g. asciicheck, gosmopolitan) may croak on go identifiers generated from unicode input. +// +// [revive]: https://github.com/mgechev/revive +func (m NameMangler) ToGoName(name string) string { + return m.goIdentifier(name, true) +} + +func (m NameMangler) goIdentifier(name string, exported bool) string { + s := m.splitterWithPostSplit + lexems := s.split(name) + defer func() { + poolOfLexems.RedeemLexems(lexems) + }() + lexemes := *lexems + + if len(lexemes) == 0 { + return "" + } + + result := poolOfBuffers.BorrowBuffer(len(name)) + defer func() { + poolOfBuffers.RedeemBuffer(result) + }() + + firstPart := lexemes[0] + if !exported { + if ok := firstPart.WriteLower(result, true); !ok { + // NOTE: an initialism as the first part is lower-cased: no longer generates stuff like hTTPxyz. + // + // same prefixing rule applied to unexported variable as to an exported one, so that we have consistent + // names, whether the generated identifier is exported or not. + result.WriteString(strings.ToLower(m.prefixFunc()(name))) + result.WriteString(lexemes[0].GetOriginal()) + } + } else { + if ok := firstPart.WriteTitleized(result, true); !ok { + // "repairs" a lexeme that doesn't start with a letter to become + // the start a legit go name. The current strategy is very crude and simply adds a fixed prefix, + // e.g. "X". + // For instance "1_sesame_street" would be split into lexemes ["1", "sesame", "street"] and + // the first one ("1") would result in something like "X1" (with the default prefix function). + // + // NOTE: no longer forcing the first part to be fully upper-cased + result.WriteString(m.prefixFunc()(name)) + result.WriteString(lexemes[0].GetOriginal()) + } + } + + for _, lexem := range lexemes[1:] { + // NOTE: no longer forcing initialism parts to be fully upper-cased: + // * pluralized initialism preserve their trailing "s" + // * mixed-cased initialisms, such as IPv4, are preserved + if ok := lexem.WriteTitleized(result, false); !ok { + // it's not titleized: perhaps it's too short, perhaps the first rune is not a letter. + // write anyway + result.WriteString(lexem.GetOriginal()) + } + } + + return result.String() +} + +func (m *NameMangler) addInitialisms(words ...string) { + m.index.add(words...) + m.index.buildCache() +} + +// split calls the inner splitter. +func (m NameMangler) split(str string) *[]string { + s := m.splitter + lexems := s.split(str) + result := poolOfStrings.BorrowStrings() + + for _, lexem := range *lexems { + *result = append(*result, lexem.GetOriginal()) + } + poolOfLexems.RedeemLexems(lexems) + + return result +} diff --git a/vendor/github.com/go-openapi/swag/mangling/options.go b/vendor/github.com/go-openapi/swag/mangling/options.go new file mode 100644 index 000000000..3c92b2f18 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling/options.go @@ -0,0 +1,150 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mangling + +type ( + // PrefixFunc defines a safeguard rule (that may depend on the input string), to prefix + // a generated go name (in [NameMangler.ToGoName] and [NameMangler.ToVarName]). + // + // See [NameMangler.ToGoName] for more about which edge cases the prefix function covers. + PrefixFunc func(string) string + + // ReplaceFunc is a transliteration function to replace special runes by a word. + ReplaceFunc func(r rune) (string, bool) + + // Option to configure a [NameMangler]. + Option func(*options) + + options struct { + commonInitialisms []string + + goNamePrefixFunc PrefixFunc + goNamePrefixFuncPtr *PrefixFunc + replaceFunc func(r rune) (string, bool) + } +) + +func (o *options) prefixFunc() PrefixFunc { + if o.goNamePrefixFuncPtr != nil && *o.goNamePrefixFuncPtr != nil { + return *o.goNamePrefixFuncPtr + } + + return o.goNamePrefixFunc +} + +// WithGoNamePrefixFunc overrides the default prefix rule to safeguard generated go names. +// +// Example: +// +// This helps convert "123" into "{prefix}123" (a very crude strategy indeed, but it works). +// +// See [github.com/go-swagger/go-swagger/generator.DefaultFuncMap] for an example. +// +// The prefix function is assumed to return a string that starts with an upper case letter. +// +// The default is to prefix with "X". +// +// See [NameMangler.ToGoName] for more about which edge cases the prefix function covers. +func WithGoNamePrefixFunc(fn PrefixFunc) Option { + return func(o *options) { + o.goNamePrefixFunc = fn + } +} + +// WithGoNamePrefixFuncPtr is like [WithGoNamePrefixFunc] but it specifies a pointer to a function. +// +// [WithGoNamePrefixFunc] should be preferred in most situations. This option should only serve the +// purpose of handling special situations where the prefix function is not an internal variable +// (e.g. an exported package global). +// +// [WithGoNamePrefixFuncPtr] supersedes [WithGoNamePrefixFunc] if it also specified. +// +// If the provided pointer is nil or points to a nil value, this option has no effect. +// +// The caller should ensure that no undesirable concurrent changes are applied to the function pointed to. +func WithGoNamePrefixFuncPtr(ptr *PrefixFunc) Option { + return func(o *options) { + o.goNamePrefixFuncPtr = ptr + } +} + +// WithInitialisms declares the initialisms this mangler supports. +// +// This supersedes any pre-loaded defaults (see [DefaultInitialisms] for more about what initialisms are). +// +// It declares words to be recognized as "initialisms" (i.e. words that won't be camel cased or titled cased). +// +// Words must start with a (unicode) letter. If some don't, they are ignored. +// Words are either fully capitalized or mixed-cased. Lower-case only words are considered capitalized. +func WithInitialisms(words ...string) Option { + return func(o *options) { + o.commonInitialisms = words + } +} + +// WithAdditionalInitialisms adds new initialisms to the currently supported list (see [DefaultInitialisms]). +// +// The same sanitization rules apply as those described for [WithInitialisms]. +func WithAdditionalInitialisms(words ...string) Option { + return func(o *options) { + o.commonInitialisms = append(o.commonInitialisms, words...) + } +} + +// WithReplaceFunc specifies a custom transliteration function instead of the default. +// +// The default translates the following characters into words as follows: +// +// - '@' -> 'At' +// - '&' -> 'And' +// - '|' -> 'Pipe' +// - '$' -> 'Dollar' +// - '!' -> 'Bang' +// +// Notice that the outcome of a transliteration should always be titleized. +func WithReplaceFunc(fn ReplaceFunc) Option { + return func(o *options) { + o.replaceFunc = fn + } +} + +func defaultPrefixFunc(_ string) string { + return "X" +} + +// defaultReplaceTable finds a word representation for special characters. +func defaultReplaceTable(r rune) (string, bool) { + switch r { + case '@': + return "At ", true + case '&': + return "And ", true + case '|': + return "Pipe ", true + case '$': + return "Dollar ", true + case '!': + return "Bang ", true + case '-': + return "", true + case '_': + return "", true + default: + return "", false + } +} + +func optionsWithDefaults(opts []Option) options { + o := options{ + commonInitialisms: DefaultInitialisms(), + goNamePrefixFunc: defaultPrefixFunc, + replaceFunc: defaultReplaceTable, + } + + for _, apply := range opts { + apply(&o) + } + + return o +} diff --git a/vendor/github.com/go-openapi/swag/mangling/pools.go b/vendor/github.com/go-openapi/swag/mangling/pools.go new file mode 100644 index 000000000..f81043514 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling/pools.go @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mangling + +import ( + "bytes" + "sync" +) + +const maxAllocMatches = 8 + +type ( + // memory pools of temporary objects. + // + // These are used to recycle temporarily allocated objects + // and relieve the GC from undue pressure. + + matchesPool struct { + *sync.Pool + } + + buffersPool struct { + *sync.Pool + } + + lexemsPool struct { + *sync.Pool + } + + stringsPool struct { + *sync.Pool + } +) + +var ( + // poolOfMatches holds temporary slices for recycling during the initialism match process + poolOfMatches = matchesPool{ + Pool: &sync.Pool{ + New: func() any { + s := make(initialismMatches, 0, maxAllocMatches) + + return &s + }, + }, + } + + poolOfBuffers = buffersPool{ + Pool: &sync.Pool{ + New: func() any { + return new(bytes.Buffer) + }, + }, + } + + poolOfLexems = lexemsPool{ + Pool: &sync.Pool{ + New: func() any { + s := make([]nameLexem, 0, maxAllocMatches) + + return &s + }, + }, + } + + poolOfStrings = stringsPool{ + Pool: &sync.Pool{ + New: func() any { + s := make([]string, 0, maxAllocMatches) + + return &s + }, + }, + } +) + +func (p matchesPool) BorrowMatches() *initialismMatches { + s := p.Get().(*initialismMatches) + *s = (*s)[:0] // reset slice, keep allocated capacity + + return s +} + +func (p buffersPool) BorrowBuffer(size int) *bytes.Buffer { + s := p.Get().(*bytes.Buffer) + s.Reset() + + if s.Cap() < size { + s.Grow(size) + } + + return s +} + +func (p lexemsPool) BorrowLexems() *[]nameLexem { + s := p.Get().(*[]nameLexem) + *s = (*s)[:0] // reset slice, keep allocated capacity + + return s +} + +func (p stringsPool) BorrowStrings() *[]string { + s := p.Get().(*[]string) + *s = (*s)[:0] // reset slice, keep allocated capacity + + return s +} + +func (p matchesPool) RedeemMatches(s *initialismMatches) { + p.Put(s) +} + +func (p buffersPool) RedeemBuffer(s *bytes.Buffer) { + p.Put(s) +} + +func (p lexemsPool) RedeemLexems(s *[]nameLexem) { + p.Put(s) +} + +func (p stringsPool) RedeemStrings(s *[]string) { + p.Put(s) +} diff --git a/vendor/github.com/go-openapi/swag/mangling/split.go b/vendor/github.com/go-openapi/swag/mangling/split.go new file mode 100644 index 000000000..ed12ea256 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling/split.go @@ -0,0 +1,341 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mangling + +import ( + "fmt" + "unicode" +) + +type splitterOption func(*splitter) + +// withPostSplitInitialismCheck allows to catch initialisms after main split process +func withPostSplitInitialismCheck(s *splitter) { + s.postSplitInitialismCheck = true +} + +func withReplaceFunc(fn ReplaceFunc) func(*splitter) { + return func(s *splitter) { + s.replaceFunc = fn + } +} + +func withInitialismsCache(c *initialismsCache) splitterOption { + return func(s *splitter) { + s.initialismsCache = c + } +} + +type ( + initialismMatch struct { + body []rune + start, end int + complete bool + hasPlural pluralForm + } + initialismMatches []initialismMatch +) + +// String representation of a match, e.g. for debugging. +func (m initialismMatch) String() string { + return fmt.Sprintf("{body: %s (%d), start: %d, end; %d, complete: %t, hasPlural: %v}", + string(m.body), len(m.body), m.start, m.end, m.complete, m.hasPlural, + ) +} + +func (m initialismMatch) isZero() bool { + return m.start == 0 && m.end == 0 +} + +type splitter struct { + *initialismsCache + + postSplitInitialismCheck bool + replaceFunc ReplaceFunc +} + +func newSplitter(options ...splitterOption) splitter { + var s splitter + + for _, option := range options { + option(&s) + } + + if s.replaceFunc == nil { + s.replaceFunc = defaultReplaceTable + } + + return s +} + +func (s splitter) split(name string) *[]nameLexem { + nameRunes := []rune(name) + matches := s.gatherInitialismMatches(nameRunes) + if matches == nil { + return poolOfLexems.BorrowLexems() + } + + return s.mapMatchesToNameLexems(nameRunes, matches) +} + +func (s splitter) gatherInitialismMatches(nameRunes []rune) *initialismMatches { + matches := poolOfMatches.BorrowMatches() + const minLenInitialism = 1 + if len(nameRunes) < minLenInitialism+1 { + // can't match initialism with 0 or 1 rune + return matches + } + + // first iteration + s.findMatches(matches, nameRunes, nameRunes[0], 0) + + for i, currentRune := range nameRunes[1:] { + currentRunePosition := i + 1 + // recycle allocations as we loop over runes + // with such recycling, only 2 slices should be allocated per call + // instead of o(n). + // + // BorrowMatches always yields slices with zero length (with some capacity) + newMatches := poolOfMatches.BorrowMatches() + + // check current initialism matches + for _, match := range *matches { + if keepCompleteMatch := match.complete; keepCompleteMatch { + // the match is already complete: keep it then move on to the next match + *newMatches = append(*newMatches, match) + continue + } + + if currentRunePosition-match.start == len(match.body) { + // unmatched: skip + continue + } + + // 1. by construction of the matches, we can't have currentRunePosition - match.start < 0 + // because matches have been computed with their start <= currentRunePosition in the previous + // iterations. + // 2. by construction of the matches, we can't have currentRunePosition - match.start >= len(match.body) + + currentMatchRune := match.body[currentRunePosition-match.start] + if currentMatchRune != currentRune { + // failed match, discard it then move on to the next match + continue + } + + // try to complete the current match + if currentRunePosition-match.start == len(match.body)-1 { + // we are close: the next step is to check the symbol ahead + // if it is a lowercase letter, then it is not the end of match + // but the beginning of the next word. + // + // NOTE(fredbi): this heuristic sometimes leads to counterintuitive splits and + // perhaps (not sure yet) we should check against case _alternance_. + // + // Example: + // + // In the current version, in the sentence "IDS initialism", "ID" is recognized as an initialism, + // leading to a split like "id_s_initialism" (or IDSInitialism), + // whereas in the sentence "IDx initialism", it is not and produces something like + // "i_d_x_initialism" (or IDxInitialism). The generated file name is not great. + // + // Both go identifiers are tolerated by linters. + // + // Notice that the slightly different input "IDs initialism" is correctly detected + // as a pluralized initialism and produces something like "ids_initialism" (or IDsInitialism). + + if currentRunePosition < len(nameRunes)-1 { // when before the last rune + nextRune := nameRunes[currentRunePosition+1] + + // recognize a plural form for this initialism (only simple english pluralization is supported). + if nextRune == 's' && match.hasPlural == simplePlural { + // detected a pluralized initialism + match.body = append(match.body, nextRune) + lookAhead := currentRunePosition + 1 + if lookAhead < len(nameRunes)-1 { + nextRune = nameRunes[lookAhead+1] + if newWord := unicode.IsLower(nextRune); newWord { + // it is the start of a new word. + // Match is only partial and the initialism is not recognized: + // move on to the next match, but do not advance the rune position + continue + } + } + + // this is a pluralized match: keep it + currentRunePosition++ + match.complete = true + match.hasPlural = simplePlural + match.end = currentRunePosition + *newMatches = append(*newMatches, match) + + // match is complete: keep it then move on to the next match + continue + } + + // other cases + // example: invariant plural such as "TLS" + if newWord := unicode.IsLower(nextRune); newWord { + // it is the start of a new word + // Match is only partial and the initialism is not recognized : move on + continue + } + } + + match.complete = true + match.end = currentRunePosition + } + + // append the ongoing matching attempt: it is not necessarily complete, but was successful so far. + // Let's see if it still matches on the next rune. + *newMatches = append(*newMatches, match) + } + + s.findMatches(newMatches, nameRunes, currentRune, currentRunePosition) + + poolOfMatches.RedeemMatches(matches) + matches = newMatches + } + + // it is up to the caller to redeem this last slice + return matches +} + +func (s splitter) findMatches(newMatches *initialismMatches, nameRunes []rune, currentRune rune, currentRunePosition int) { + // check for new initialism matches, based on the first character + for i, r := range s.initialismsRunes { + if r[0] != currentRune { + continue + } + + if currentRunePosition+len(r) > len(nameRunes) { + continue // not eligible: would spilll over the initial string + } + + // possible matches: all initialisms starting with the current rune and that can fit the given string (nameRunes) + *newMatches = append(*newMatches, initialismMatch{ + start: currentRunePosition, + body: r, + complete: false, + hasPlural: s.initialismsPluralForm[i], + }) + } +} + +func (s splitter) mapMatchesToNameLexems(nameRunes []rune, matches *initialismMatches) *[]nameLexem { + nameLexems := poolOfLexems.BorrowLexems() + + var lastAcceptedMatch initialismMatch + for _, match := range *matches { + if !match.complete { + continue + } + + if firstMatch := lastAcceptedMatch.isZero(); firstMatch { + s.appendBrokenDownCasualString(nameLexems, nameRunes[:match.start]) + *nameLexems = append(*nameLexems, s.breakInitialism(string(match.body))) + + lastAcceptedMatch = match + + continue + } + + if overlappedMatch := match.start <= lastAcceptedMatch.end; overlappedMatch { + continue + } + + middle := nameRunes[lastAcceptedMatch.end+1 : match.start] + s.appendBrokenDownCasualString(nameLexems, middle) + *nameLexems = append(*nameLexems, s.breakInitialism(string(match.body))) + + lastAcceptedMatch = match + } + + // we have not found any accepted matches + if lastAcceptedMatch.isZero() { + *nameLexems = (*nameLexems)[:0] + s.appendBrokenDownCasualString(nameLexems, nameRunes) + } else if lastAcceptedMatch.end+1 != len(nameRunes) { + rest := nameRunes[lastAcceptedMatch.end+1:] + s.appendBrokenDownCasualString(nameLexems, rest) + } + + poolOfMatches.RedeemMatches(matches) + + return nameLexems +} + +func (s splitter) breakInitialism(original string) nameLexem { + return newInitialismNameLexem(original, original) +} + +func (s splitter) appendBrokenDownCasualString(segments *[]nameLexem, str []rune) { + currentSegment := poolOfBuffers.BorrowBuffer(len(str)) // unlike strings.Builder, bytes.Buffer initial storage can reused + defer func() { + poolOfBuffers.RedeemBuffer(currentSegment) + }() + + addCasualNameLexem := func(original string) { + *segments = append(*segments, newCasualNameLexem(original)) + } + + addInitialismNameLexem := func(original, match string) { + *segments = append(*segments, newInitialismNameLexem(original, match)) + } + + var addNameLexem func(string) + if s.postSplitInitialismCheck { + addNameLexem = func(original string) { + for i := range s.initialisms { + if isEqualFoldIgnoreSpace(s.initialismsUpperCased[i], original) { + addInitialismNameLexem(original, s.initialisms[i]) + + return + } + } + + addCasualNameLexem(original) + } + } else { + addNameLexem = addCasualNameLexem + } + + // NOTE: (performance). The few remaining non-amortized allocations + // lay in the code below: using String() forces + for _, rn := range str { + if replace, found := s.replaceFunc(rn); found { + if currentSegment.Len() > 0 { + addNameLexem(currentSegment.String()) + currentSegment.Reset() + } + + if replace != "" { + addNameLexem(replace) + } + + continue + } + + if !unicode.In(rn, unicode.L, unicode.M, unicode.N, unicode.Pc) { + if currentSegment.Len() > 0 { + addNameLexem(currentSegment.String()) + currentSegment.Reset() + } + + continue + } + + if unicode.IsUpper(rn) { + if currentSegment.Len() > 0 { + addNameLexem(currentSegment.String()) + } + currentSegment.Reset() + } + + currentSegment.WriteRune(rn) + } + + if currentSegment.Len() > 0 { + addNameLexem(currentSegment.String()) + } +} diff --git a/vendor/github.com/go-openapi/swag/string_bytes.go b/vendor/github.com/go-openapi/swag/mangling/string_bytes.go similarity index 60% rename from vendor/github.com/go-openapi/swag/string_bytes.go rename to vendor/github.com/go-openapi/swag/mangling/string_bytes.go index 90745d5ca..28daaf72b 100644 --- a/vendor/github.com/go-openapi/swag/string_bytes.go +++ b/vendor/github.com/go-openapi/swag/mangling/string_bytes.go @@ -1,4 +1,7 @@ -package swag +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mangling import "unsafe" diff --git a/vendor/github.com/go-openapi/swag/mangling/util.go b/vendor/github.com/go-openapi/swag/mangling/util.go new file mode 100644 index 000000000..0636417e3 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling/util.go @@ -0,0 +1,118 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package mangling + +import ( + "strings" + "unicode" + "unicode/utf8" +) + +// Removes leading whitespaces +func trim(str string) string { return strings.TrimSpace(str) } + +// upper is strings.ToUpper() combined with trim +func upper(str string) string { + return strings.ToUpper(trim(str)) +} + +// lower is strings.ToLower() combined with trim +func lower(str string) string { + return strings.ToLower(trim(str)) +} + +// isEqualFoldIgnoreSpace is the same as strings.EqualFold, but +// it ignores leading and trailing blank spaces in the compared +// string. +// +// base is assumed to be composed of upper-cased runes, and be already +// trimmed. +// +// This code is heavily inspired from strings.EqualFold. +func isEqualFoldIgnoreSpace(base []rune, str string) bool { + var i, baseIndex int + // equivalent to b := []byte(str), but without data copy + b := hackStringBytes(str) + + for i < len(b) { + if c := b[i]; c < utf8.RuneSelf { + // fast path for ASCII + if c != ' ' && c != '\t' { + break + } + i++ + + continue + } + + // unicode case + r, size := utf8.DecodeRune(b[i:]) + if !unicode.IsSpace(r) { + break + } + i += size + } + + if i >= len(b) { + return len(base) == 0 + } + + for _, baseRune := range base { + if i >= len(b) { + break + } + + if c := b[i]; c < utf8.RuneSelf { + // single byte rune case (ASCII) + if baseRune >= utf8.RuneSelf { + return false + } + + baseChar := byte(baseRune) + if c != baseChar && ((c < 'a') || (c > 'z') || (c-'a'+'A' != baseChar)) { + return false + } + + baseIndex++ + i++ + + continue + } + + // unicode case + r, size := utf8.DecodeRune(b[i:]) + if unicode.ToUpper(r) != baseRune { + return false + } + baseIndex++ + i += size + } + + if baseIndex != len(base) { + return false + } + + // all passed: now we should only have blanks + for i < len(b) { + if c := b[i]; c < utf8.RuneSelf { + // fast path for ASCII + if c != ' ' && c != '\t' { + return false + } + i++ + + continue + } + + // unicode case + r, size := utf8.DecodeRune(b[i:]) + if !unicode.IsSpace(r) { + return false + } + + i += size + } + + return true +} diff --git a/vendor/github.com/go-openapi/swag/mangling_iface.go b/vendor/github.com/go-openapi/swag/mangling_iface.go new file mode 100644 index 000000000..98b9a9992 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/mangling_iface.go @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import "github.com/go-openapi/swag/mangling" + +// GoNamePrefixFunc sets an optional rule to prefix go names +// which do not start with a letter. +// +// GoNamePrefixFunc should not be written to while concurrently using the other mangling functions of this package. +// +// Deprecated: use [mangling.WithGoNamePrefixFunc] instead. +var GoNamePrefixFunc mangling.PrefixFunc + +// swagNameMangler is a global instance of the name mangler specifically alloted +// to support deprecated functions. +var swagNameMangler = mangling.NewNameMangler( + mangling.WithGoNamePrefixFuncPtr(&GoNamePrefixFunc), +) + +// AddInitialisms adds additional initialisms to the default list (see [mangling.DefaultInitialisms]). +// +// AddInitialisms is not safe to be called concurrently. +// +// Deprecated: use [mangling.WithAdditionalInitialisms] instead. +func AddInitialisms(words ...string) { + swagNameMangler.AddInitialisms(words...) +} + +// Camelize a single word. +// +// Deprecated: use [mangling.NameMangler.Camelize] instead. +func Camelize(word string) string { return swagNameMangler.Camelize(word) } + +// ToFileName lowercases and underscores a go type name. +// +// Deprecated: use [mangling.NameMangler.ToFileName] instead. +func ToFileName(name string) string { return swagNameMangler.ToFileName(name) } + +// ToCommandName lowercases and underscores a go type name. +// +// Deprecated: use [mangling.NameMangler.ToCommandName] instead. +func ToCommandName(name string) string { return swagNameMangler.ToCommandName(name) } + +// ToHumanNameLower represents a code name as a human series of words. +// +// Deprecated: use [mangling.NameMangler.ToHumanNameLower] instead. +func ToHumanNameLower(name string) string { return swagNameMangler.ToHumanNameLower(name) } + +// ToHumanNameTitle represents a code name as a human series of words with the first letters titleized. +// +// Deprecated: use [mangling.NameMangler.ToHumanNameTitle] instead. +func ToHumanNameTitle(name string) string { return swagNameMangler.ToHumanNameTitle(name) } + +// ToJSONName camel-cases a name which can be underscored or pascal-cased. +// +// Deprecated: use [mangling.NameMangler.ToJSONName] instead. +func ToJSONName(name string) string { return swagNameMangler.ToJSONName(name) } + +// ToVarName camel-cases a name which can be underscored or pascal-cased. +// +// Deprecated: use [mangling.NameMangler.ToVarName] instead. +func ToVarName(name string) string { return swagNameMangler.ToVarName(name) } + +// ToGoName translates a swagger name which can be underscored or camel cased to a name that golint likes. +// +// Deprecated: use [mangling.NameMangler.ToGoName] instead. +func ToGoName(name string) string { return swagNameMangler.ToGoName(name) } diff --git a/vendor/github.com/go-openapi/swag/name_lexem.go b/vendor/github.com/go-openapi/swag/name_lexem.go deleted file mode 100644 index 8bb64ac32..000000000 --- a/vendor/github.com/go-openapi/swag/name_lexem.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// 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 swag - -import ( - "unicode" - "unicode/utf8" -) - -type ( - lexemKind uint8 - - nameLexem struct { - original string - matchedInitialism string - kind lexemKind - } -) - -const ( - lexemKindCasualName lexemKind = iota - lexemKindInitialismName -) - -func newInitialismNameLexem(original, matchedInitialism string) nameLexem { - return nameLexem{ - kind: lexemKindInitialismName, - original: original, - matchedInitialism: matchedInitialism, - } -} - -func newCasualNameLexem(original string) nameLexem { - return nameLexem{ - kind: lexemKindCasualName, - original: original, - } -} - -func (l nameLexem) GetUnsafeGoName() string { - if l.kind == lexemKindInitialismName { - return l.matchedInitialism - } - - var ( - first rune - rest string - ) - - for i, orig := range l.original { - if i == 0 { - first = orig - continue - } - - if i > 0 { - rest = l.original[i:] - break - } - } - - if len(l.original) > 1 { - b := poolOfBuffers.BorrowBuffer(utf8.UTFMax + len(rest)) - defer func() { - poolOfBuffers.RedeemBuffer(b) - }() - b.WriteRune(unicode.ToUpper(first)) - b.WriteString(lower(rest)) - return b.String() - } - - return l.original -} - -func (l nameLexem) GetOriginal() string { - return l.original -} - -func (l nameLexem) IsInitialism() bool { - return l.kind == lexemKindInitialismName -} diff --git a/vendor/github.com/go-openapi/swag/net.go b/vendor/github.com/go-openapi/swag/net.go deleted file mode 100644 index 821235f84..000000000 --- a/vendor/github.com/go-openapi/swag/net.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// 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 swag - -import ( - "net" - "strconv" -) - -// SplitHostPort splits a network address into a host and a port. -// The port is -1 when there is no port to be found -func SplitHostPort(addr string) (host string, port int, err error) { - h, p, err := net.SplitHostPort(addr) - if err != nil { - return "", -1, err - } - if p == "" { - return "", -1, &net.AddrError{Err: "missing port in address", Addr: addr} - } - - pi, err := strconv.Atoi(p) - if err != nil { - return "", -1, err - } - return h, pi, nil -} diff --git a/vendor/github.com/go-openapi/swag/netutils/LICENSE b/vendor/github.com/go-openapi/swag/netutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/netutils/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/netutils/doc.go b/vendor/github.com/go-openapi/swag/netutils/doc.go new file mode 100644 index 000000000..74282f8e5 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/netutils/doc.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package netutils provides helpers for network-related tasks. +package netutils diff --git a/vendor/github.com/go-openapi/swag/netutils/net.go b/vendor/github.com/go-openapi/swag/netutils/net.go new file mode 100644 index 000000000..82a1544af --- /dev/null +++ b/vendor/github.com/go-openapi/swag/netutils/net.go @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package netutils + +import ( + "net" + "strconv" +) + +// SplitHostPort splits a network address into a host and a port. +// +// The difference with the standard net.SplitHostPort is that the port is converted to an int. +// +// The port is -1 when there is no port to be found. +func SplitHostPort(addr string) (host string, port int, err error) { + h, p, err := net.SplitHostPort(addr) + if err != nil { + return "", -1, err + } + if p == "" { + return "", -1, &net.AddrError{Err: "missing port in address", Addr: addr} + } + + pi, err := strconv.Atoi(p) + if err != nil { + return "", -1, err + } + + return h, pi, nil +} diff --git a/vendor/github.com/go-openapi/swag/netutils_iface.go b/vendor/github.com/go-openapi/swag/netutils_iface.go new file mode 100644 index 000000000..d658de25b --- /dev/null +++ b/vendor/github.com/go-openapi/swag/netutils_iface.go @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import "github.com/go-openapi/swag/netutils" + +// SplitHostPort splits a network address into a host and a port. +// +// Deprecated: use [netutils.SplitHostPort] instead. +func SplitHostPort(addr string) (host string, port int, err error) { + return netutils.SplitHostPort(addr) +} diff --git a/vendor/github.com/go-openapi/swag/split.go b/vendor/github.com/go-openapi/swag/split.go deleted file mode 100644 index 274727a86..000000000 --- a/vendor/github.com/go-openapi/swag/split.go +++ /dev/null @@ -1,508 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// 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 swag - -import ( - "bytes" - "sync" - "unicode" - "unicode/utf8" -) - -type ( - splitter struct { - initialisms []string - initialismsRunes [][]rune - initialismsUpperCased [][]rune // initialisms cached in their trimmed, upper-cased version - postSplitInitialismCheck bool - } - - splitterOption func(*splitter) - - initialismMatch struct { - body []rune - start, end int - complete bool - } - initialismMatches []initialismMatch -) - -type ( - // memory pools of temporary objects. - // - // These are used to recycle temporarily allocated objects - // and relieve the GC from undue pressure. - - matchesPool struct { - *sync.Pool - } - - buffersPool struct { - *sync.Pool - } - - lexemsPool struct { - *sync.Pool - } - - splittersPool struct { - *sync.Pool - } -) - -var ( - // poolOfMatches holds temporary slices for recycling during the initialism match process - poolOfMatches = matchesPool{ - Pool: &sync.Pool{ - New: func() any { - s := make(initialismMatches, 0, maxAllocMatches) - - return &s - }, - }, - } - - poolOfBuffers = buffersPool{ - Pool: &sync.Pool{ - New: func() any { - return new(bytes.Buffer) - }, - }, - } - - poolOfLexems = lexemsPool{ - Pool: &sync.Pool{ - New: func() any { - s := make([]nameLexem, 0, maxAllocMatches) - - return &s - }, - }, - } - - poolOfSplitters = splittersPool{ - Pool: &sync.Pool{ - New: func() any { - s := newSplitter() - - return &s - }, - }, - } -) - -// nameReplaceTable finds a word representation for special characters. -func nameReplaceTable(r rune) (string, bool) { - switch r { - case '@': - return "At ", true - case '&': - return "And ", true - case '|': - return "Pipe ", true - case '$': - return "Dollar ", true - case '!': - return "Bang ", true - case '-': - return "", true - case '_': - return "", true - default: - return "", false - } -} - -// split calls the splitter. -// -// Use newSplitter for more control and options -func split(str string) []string { - s := poolOfSplitters.BorrowSplitter() - lexems := s.split(str) - result := make([]string, 0, len(*lexems)) - - for _, lexem := range *lexems { - result = append(result, lexem.GetOriginal()) - } - poolOfLexems.RedeemLexems(lexems) - poolOfSplitters.RedeemSplitter(s) - - return result - -} - -func newSplitter(options ...splitterOption) splitter { - s := splitter{ - postSplitInitialismCheck: false, - initialisms: initialisms, - initialismsRunes: initialismsRunes, - initialismsUpperCased: initialismsUpperCased, - } - - for _, option := range options { - option(&s) - } - - return s -} - -// withPostSplitInitialismCheck allows to catch initialisms after main split process -func withPostSplitInitialismCheck(s *splitter) { - s.postSplitInitialismCheck = true -} - -func (p matchesPool) BorrowMatches() *initialismMatches { - s := p.Get().(*initialismMatches) - *s = (*s)[:0] // reset slice, keep allocated capacity - - return s -} - -func (p buffersPool) BorrowBuffer(size int) *bytes.Buffer { - s := p.Get().(*bytes.Buffer) - s.Reset() - - if s.Cap() < size { - s.Grow(size) - } - - return s -} - -func (p lexemsPool) BorrowLexems() *[]nameLexem { - s := p.Get().(*[]nameLexem) - *s = (*s)[:0] // reset slice, keep allocated capacity - - return s -} - -func (p splittersPool) BorrowSplitter(options ...splitterOption) *splitter { - s := p.Get().(*splitter) - s.postSplitInitialismCheck = false // reset options - for _, apply := range options { - apply(s) - } - - return s -} - -func (p matchesPool) RedeemMatches(s *initialismMatches) { - p.Put(s) -} - -func (p buffersPool) RedeemBuffer(s *bytes.Buffer) { - p.Put(s) -} - -func (p lexemsPool) RedeemLexems(s *[]nameLexem) { - p.Put(s) -} - -func (p splittersPool) RedeemSplitter(s *splitter) { - p.Put(s) -} - -func (m initialismMatch) isZero() bool { - return m.start == 0 && m.end == 0 -} - -func (s splitter) split(name string) *[]nameLexem { - nameRunes := []rune(name) - matches := s.gatherInitialismMatches(nameRunes) - if matches == nil { - return poolOfLexems.BorrowLexems() - } - - return s.mapMatchesToNameLexems(nameRunes, matches) -} - -func (s splitter) gatherInitialismMatches(nameRunes []rune) *initialismMatches { - var matches *initialismMatches - - for currentRunePosition, currentRune := range nameRunes { - // recycle these allocations as we loop over runes - // with such recycling, only 2 slices should be allocated per call - // instead of o(n). - newMatches := poolOfMatches.BorrowMatches() - - // check current initialism matches - if matches != nil { // skip first iteration - for _, match := range *matches { - if keepCompleteMatch := match.complete; keepCompleteMatch { - *newMatches = append(*newMatches, match) - continue - } - - // drop failed match - currentMatchRune := match.body[currentRunePosition-match.start] - if currentMatchRune != currentRune { - continue - } - - // try to complete ongoing match - if currentRunePosition-match.start == len(match.body)-1 { - // we are close; the next step is to check the symbol ahead - // if it is a small letter, then it is not the end of match - // but beginning of the next word - - if currentRunePosition < len(nameRunes)-1 { - nextRune := nameRunes[currentRunePosition+1] - if newWord := unicode.IsLower(nextRune); newWord { - // oh ok, it was the start of a new word - continue - } - } - - match.complete = true - match.end = currentRunePosition - } - - *newMatches = append(*newMatches, match) - } - } - - // check for new initialism matches - for i := range s.initialisms { - initialismRunes := s.initialismsRunes[i] - if initialismRunes[0] == currentRune { - *newMatches = append(*newMatches, initialismMatch{ - start: currentRunePosition, - body: initialismRunes, - complete: false, - }) - } - } - - if matches != nil { - poolOfMatches.RedeemMatches(matches) - } - matches = newMatches - } - - // up to the caller to redeem this last slice - return matches -} - -func (s splitter) mapMatchesToNameLexems(nameRunes []rune, matches *initialismMatches) *[]nameLexem { - nameLexems := poolOfLexems.BorrowLexems() - - var lastAcceptedMatch initialismMatch - for _, match := range *matches { - if !match.complete { - continue - } - - if firstMatch := lastAcceptedMatch.isZero(); firstMatch { - s.appendBrokenDownCasualString(nameLexems, nameRunes[:match.start]) - *nameLexems = append(*nameLexems, s.breakInitialism(string(match.body))) - - lastAcceptedMatch = match - - continue - } - - if overlappedMatch := match.start <= lastAcceptedMatch.end; overlappedMatch { - continue - } - - middle := nameRunes[lastAcceptedMatch.end+1 : match.start] - s.appendBrokenDownCasualString(nameLexems, middle) - *nameLexems = append(*nameLexems, s.breakInitialism(string(match.body))) - - lastAcceptedMatch = match - } - - // we have not found any accepted matches - if lastAcceptedMatch.isZero() { - *nameLexems = (*nameLexems)[:0] - s.appendBrokenDownCasualString(nameLexems, nameRunes) - } else if lastAcceptedMatch.end+1 != len(nameRunes) { - rest := nameRunes[lastAcceptedMatch.end+1:] - s.appendBrokenDownCasualString(nameLexems, rest) - } - - poolOfMatches.RedeemMatches(matches) - - return nameLexems -} - -func (s splitter) breakInitialism(original string) nameLexem { - return newInitialismNameLexem(original, original) -} - -func (s splitter) appendBrokenDownCasualString(segments *[]nameLexem, str []rune) { - currentSegment := poolOfBuffers.BorrowBuffer(len(str)) // unlike strings.Builder, bytes.Buffer initial storage can reused - defer func() { - poolOfBuffers.RedeemBuffer(currentSegment) - }() - - addCasualNameLexem := func(original string) { - *segments = append(*segments, newCasualNameLexem(original)) - } - - addInitialismNameLexem := func(original, match string) { - *segments = append(*segments, newInitialismNameLexem(original, match)) - } - - var addNameLexem func(string) - if s.postSplitInitialismCheck { - addNameLexem = func(original string) { - for i := range s.initialisms { - if isEqualFoldIgnoreSpace(s.initialismsUpperCased[i], original) { - addInitialismNameLexem(original, s.initialisms[i]) - - return - } - } - - addCasualNameLexem(original) - } - } else { - addNameLexem = addCasualNameLexem - } - - for _, rn := range str { - if replace, found := nameReplaceTable(rn); found { - if currentSegment.Len() > 0 { - addNameLexem(currentSegment.String()) - currentSegment.Reset() - } - - if replace != "" { - addNameLexem(replace) - } - - continue - } - - if !unicode.In(rn, unicode.L, unicode.M, unicode.N, unicode.Pc) { - if currentSegment.Len() > 0 { - addNameLexem(currentSegment.String()) - currentSegment.Reset() - } - - continue - } - - if unicode.IsUpper(rn) { - if currentSegment.Len() > 0 { - addNameLexem(currentSegment.String()) - } - currentSegment.Reset() - } - - currentSegment.WriteRune(rn) - } - - if currentSegment.Len() > 0 { - addNameLexem(currentSegment.String()) - } -} - -// isEqualFoldIgnoreSpace is the same as strings.EqualFold, but -// it ignores leading and trailing blank spaces in the compared -// string. -// -// base is assumed to be composed of upper-cased runes, and be already -// trimmed. -// -// This code is heavily inspired from strings.EqualFold. -func isEqualFoldIgnoreSpace(base []rune, str string) bool { - var i, baseIndex int - // equivalent to b := []byte(str), but without data copy - b := hackStringBytes(str) - - for i < len(b) { - if c := b[i]; c < utf8.RuneSelf { - // fast path for ASCII - if c != ' ' && c != '\t' { - break - } - i++ - - continue - } - - // unicode case - r, size := utf8.DecodeRune(b[i:]) - if !unicode.IsSpace(r) { - break - } - i += size - } - - if i >= len(b) { - return len(base) == 0 - } - - for _, baseRune := range base { - if i >= len(b) { - break - } - - if c := b[i]; c < utf8.RuneSelf { - // single byte rune case (ASCII) - if baseRune >= utf8.RuneSelf { - return false - } - - baseChar := byte(baseRune) - if c != baseChar && - !('a' <= c && c <= 'z' && c-'a'+'A' == baseChar) { - return false - } - - baseIndex++ - i++ - - continue - } - - // unicode case - r, size := utf8.DecodeRune(b[i:]) - if unicode.ToUpper(r) != baseRune { - return false - } - baseIndex++ - i += size - } - - if baseIndex != len(base) { - return false - } - - // all passed: now we should only have blanks - for i < len(b) { - if c := b[i]; c < utf8.RuneSelf { - // fast path for ASCII - if c != ' ' && c != '\t' { - return false - } - i++ - - continue - } - - // unicode case - r, size := utf8.DecodeRune(b[i:]) - if !unicode.IsSpace(r) { - return false - } - - i += size - } - - return true -} diff --git a/vendor/github.com/go-openapi/swag/stringutils/LICENSE b/vendor/github.com/go-openapi/swag/stringutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/stringutils/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/stringutils/collection_formats.go b/vendor/github.com/go-openapi/swag/stringutils/collection_formats.go new file mode 100644 index 000000000..28056ad25 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/stringutils/collection_formats.go @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package stringutils + +import "strings" + +const ( + // collectionFormatComma = "csv" + collectionFormatSpace = "ssv" + collectionFormatTab = "tsv" + collectionFormatPipe = "pipes" + collectionFormatMulti = "multi" + + collectionFormatDefaultSep = "," +) + +// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute): +// +// ssv: space separated value +// tsv: tab separated value +// pipes: pipe (|) separated value +// csv: comma separated value (default) +func JoinByFormat(data []string, format string) []string { + if len(data) == 0 { + return data + } + var sep string + switch format { + case collectionFormatSpace: + sep = " " + case collectionFormatTab: + sep = "\t" + case collectionFormatPipe: + sep = "|" + case collectionFormatMulti: + return data + default: + sep = collectionFormatDefaultSep + } + return []string{strings.Join(data, sep)} +} + +// SplitByFormat splits a string by a known format: +// +// ssv: space separated value +// tsv: tab separated value +// pipes: pipe (|) separated value +// csv: comma separated value (default) +func SplitByFormat(data, format string) []string { + if data == "" { + return nil + } + var sep string + switch format { + case collectionFormatSpace: + sep = " " + case collectionFormatTab: + sep = "\t" + case collectionFormatPipe: + sep = "|" + case collectionFormatMulti: + return nil + default: + sep = collectionFormatDefaultSep + } + var result []string + for _, s := range strings.Split(data, sep) { + if ts := strings.TrimSpace(s); ts != "" { + result = append(result, ts) + } + } + return result +} diff --git a/vendor/github.com/go-openapi/swag/stringutils/doc.go b/vendor/github.com/go-openapi/swag/stringutils/doc.go new file mode 100644 index 000000000..c6d17a116 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/stringutils/doc.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package stringutils exposes helpers to search and process strings. +package stringutils diff --git a/vendor/github.com/go-openapi/swag/stringutils/strings.go b/vendor/github.com/go-openapi/swag/stringutils/strings.go new file mode 100644 index 000000000..cd792b7d0 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/stringutils/strings.go @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package stringutils + +import ( + "slices" + "strings" +) + +// ContainsStrings searches a slice of strings for a case-sensitive match +// +// Now equivalent to the standard library [slice.Contains]. +func ContainsStrings(coll []string, item string) bool { + return slices.Contains(coll, item) +} + +// ContainsStringsCI searches a slice of strings for a case-insensitive match +func ContainsStringsCI(coll []string, item string) bool { + return slices.ContainsFunc(coll, func(e string) bool { + return strings.EqualFold(e, item) + }) +} diff --git a/vendor/github.com/go-openapi/swag/stringutils_iface.go b/vendor/github.com/go-openapi/swag/stringutils_iface.go new file mode 100644 index 000000000..dbfa48484 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/stringutils_iface.go @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import "github.com/go-openapi/swag/stringutils" + +// ContainsStrings searches a slice of strings for a case-sensitive match. +// +// Deprecated: use [slices.Contains] or [stringutils.ContainsStrings] instead. +func ContainsStrings(coll []string, item string) bool { + return stringutils.ContainsStrings(coll, item) +} + +// ContainsStringsCI searches a slice of strings for a case-insensitive match. +// +// Deprecated: use [stringutils.ContainsStringsCI] instead. +func ContainsStringsCI(coll []string, item string) bool { + return stringutils.ContainsStringsCI(coll, item) +} + +// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute). +// +// Deprecated: use [stringutils.JoinByFormat] instead. +func JoinByFormat(data []string, format string) []string { + return stringutils.JoinByFormat(data, format) +} + +// SplitByFormat splits a string by a known format. +// +// Deprecated: use [stringutils.SplitByFormat] instead. +func SplitByFormat(data, format string) []string { + return stringutils.SplitByFormat(data, format) +} diff --git a/vendor/github.com/go-openapi/swag/typeutils/LICENSE b/vendor/github.com/go-openapi/swag/typeutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/typeutils/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/typeutils/doc.go b/vendor/github.com/go-openapi/swag/typeutils/doc.go new file mode 100644 index 000000000..66bed20df --- /dev/null +++ b/vendor/github.com/go-openapi/swag/typeutils/doc.go @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package typeutils exposes utilities to inspect generic types. +package typeutils diff --git a/vendor/github.com/go-openapi/swag/typeutils/types.go b/vendor/github.com/go-openapi/swag/typeutils/types.go new file mode 100644 index 000000000..55487a673 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/typeutils/types.go @@ -0,0 +1,80 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package typeutils + +import "reflect" + +type zeroable interface { + IsZero() bool +} + +// IsZero returns true when the value passed into the function is a zero value. +// This allows for safer checking of interface values. +func IsZero(data any) bool { + v := reflect.ValueOf(data) + // check for nil data + switch v.Kind() { //nolint:exhaustive + case + reflect.Interface, + reflect.Func, + reflect.Chan, + reflect.Pointer, + reflect.UnsafePointer, + reflect.Map, + reflect.Slice: + if v.IsNil() { + return true + } + } + + // check for things that have an IsZero method instead + if vv, ok := data.(zeroable); ok { + return vv.IsZero() + } + + // continue with slightly more complex reflection + switch v.Kind() { //nolint:exhaustive + case reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Struct, reflect.Array: + return reflect.DeepEqual(data, reflect.Zero(v.Type()).Interface()) + case reflect.Invalid: + return true + default: + return false + } +} + +// IsNil checks if input is nil. +// +// For types chan, func, interface, map, pointer, or slice it returns true if its argument is nil. +// +// See [reflect.Value.IsNil]. +func IsNil(input any) bool { + if input == nil { + return true + } + + kind := reflect.TypeOf(input).Kind() + switch kind { //nolint:exhaustive + case reflect.Pointer, + reflect.UnsafePointer, + reflect.Map, + reflect.Slice, + reflect.Chan, + reflect.Interface, + reflect.Func: + return reflect.ValueOf(input).IsNil() + default: + return false + } +} diff --git a/vendor/github.com/go-openapi/swag/typeutils_iface.go b/vendor/github.com/go-openapi/swag/typeutils_iface.go new file mode 100644 index 000000000..b63813ea4 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/typeutils_iface.go @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import "github.com/go-openapi/swag/typeutils" + +// IsZero returns true when the value passed into the function is a zero value. +// This allows for safer checking of interface values. +// +// Deprecated: use [typeutils.IsZero] instead. +func IsZero(data any) bool { return typeutils.IsZero(data) } diff --git a/vendor/github.com/go-openapi/swag/util.go b/vendor/github.com/go-openapi/swag/util.go deleted file mode 100644 index 5051401c4..000000000 --- a/vendor/github.com/go-openapi/swag/util.go +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// 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 swag - -import ( - "reflect" - "strings" - "unicode" - "unicode/utf8" -) - -// GoNamePrefixFunc sets an optional rule to prefix go names -// which do not start with a letter. -// -// The prefix function is assumed to return a string that starts with an upper case letter. -// -// e.g. to help convert "123" into "{prefix}123" -// -// The default is to prefix with "X" -var GoNamePrefixFunc func(string) string - -func prefixFunc(name, in string) string { - if GoNamePrefixFunc == nil { - return "X" + in - } - - return GoNamePrefixFunc(name) + in -} - -const ( - // collectionFormatComma = "csv" - collectionFormatSpace = "ssv" - collectionFormatTab = "tsv" - collectionFormatPipe = "pipes" - collectionFormatMulti = "multi" -) - -// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute): -// -// ssv: space separated value -// tsv: tab separated value -// pipes: pipe (|) separated value -// csv: comma separated value (default) -func JoinByFormat(data []string, format string) []string { - if len(data) == 0 { - return data - } - var sep string - switch format { - case collectionFormatSpace: - sep = " " - case collectionFormatTab: - sep = "\t" - case collectionFormatPipe: - sep = "|" - case collectionFormatMulti: - return data - default: - sep = "," - } - return []string{strings.Join(data, sep)} -} - -// SplitByFormat splits a string by a known format: -// -// ssv: space separated value -// tsv: tab separated value -// pipes: pipe (|) separated value -// csv: comma separated value (default) -func SplitByFormat(data, format string) []string { - if data == "" { - return nil - } - var sep string - switch format { - case collectionFormatSpace: - sep = " " - case collectionFormatTab: - sep = "\t" - case collectionFormatPipe: - sep = "|" - case collectionFormatMulti: - return nil - default: - sep = "," - } - var result []string - for _, s := range strings.Split(data, sep) { - if ts := strings.TrimSpace(s); ts != "" { - result = append(result, ts) - } - } - return result -} - -// Removes leading whitespaces -func trim(str string) string { - return strings.TrimSpace(str) -} - -// Shortcut to strings.ToUpper() -func upper(str string) string { - return strings.ToUpper(trim(str)) -} - -// Shortcut to strings.ToLower() -func lower(str string) string { - return strings.ToLower(trim(str)) -} - -// Camelize an uppercased word -func Camelize(word string) string { - camelized := poolOfBuffers.BorrowBuffer(len(word)) - defer func() { - poolOfBuffers.RedeemBuffer(camelized) - }() - - for pos, ru := range []rune(word) { - if pos > 0 { - camelized.WriteRune(unicode.ToLower(ru)) - } else { - camelized.WriteRune(unicode.ToUpper(ru)) - } - } - return camelized.String() -} - -// ToFileName lowercases and underscores a go type name -func ToFileName(name string) string { - in := split(name) - out := make([]string, 0, len(in)) - - for _, w := range in { - out = append(out, lower(w)) - } - - return strings.Join(out, "_") -} - -// ToCommandName lowercases and underscores a go type name -func ToCommandName(name string) string { - in := split(name) - out := make([]string, 0, len(in)) - - for _, w := range in { - out = append(out, lower(w)) - } - return strings.Join(out, "-") -} - -// ToHumanNameLower represents a code name as a human series of words -func ToHumanNameLower(name string) string { - s := poolOfSplitters.BorrowSplitter(withPostSplitInitialismCheck) - in := s.split(name) - poolOfSplitters.RedeemSplitter(s) - out := make([]string, 0, len(*in)) - - for _, w := range *in { - if !w.IsInitialism() { - out = append(out, lower(w.GetOriginal())) - } else { - out = append(out, trim(w.GetOriginal())) - } - } - poolOfLexems.RedeemLexems(in) - - return strings.Join(out, " ") -} - -// ToHumanNameTitle represents a code name as a human series of words with the first letters titleized -func ToHumanNameTitle(name string) string { - s := poolOfSplitters.BorrowSplitter(withPostSplitInitialismCheck) - in := s.split(name) - poolOfSplitters.RedeemSplitter(s) - - out := make([]string, 0, len(*in)) - for _, w := range *in { - original := trim(w.GetOriginal()) - if !w.IsInitialism() { - out = append(out, Camelize(original)) - } else { - out = append(out, original) - } - } - poolOfLexems.RedeemLexems(in) - - return strings.Join(out, " ") -} - -// ToJSONName camelcases a name which can be underscored or pascal cased -func ToJSONName(name string) string { - in := split(name) - out := make([]string, 0, len(in)) - - for i, w := range in { - if i == 0 { - out = append(out, lower(w)) - continue - } - out = append(out, Camelize(trim(w))) - } - return strings.Join(out, "") -} - -// ToVarName camelcases a name which can be underscored or pascal cased -func ToVarName(name string) string { - res := ToGoName(name) - if isInitialism(res) { - return lower(res) - } - if len(res) <= 1 { - return lower(res) - } - return lower(res[:1]) + res[1:] -} - -// ToGoName translates a swagger name which can be underscored or camel cased to a name that golint likes -func ToGoName(name string) string { - s := poolOfSplitters.BorrowSplitter(withPostSplitInitialismCheck) - lexems := s.split(name) - poolOfSplitters.RedeemSplitter(s) - defer func() { - poolOfLexems.RedeemLexems(lexems) - }() - lexemes := *lexems - - if len(lexemes) == 0 { - return "" - } - - result := poolOfBuffers.BorrowBuffer(len(name)) - defer func() { - poolOfBuffers.RedeemBuffer(result) - }() - - // check if not starting with a letter, upper case - firstPart := lexemes[0].GetUnsafeGoName() - if lexemes[0].IsInitialism() { - firstPart = upper(firstPart) - } - - if c := firstPart[0]; c < utf8.RuneSelf { - // ASCII - switch { - case 'A' <= c && c <= 'Z': - result.WriteString(firstPart) - case 'a' <= c && c <= 'z': - result.WriteByte(c - 'a' + 'A') - result.WriteString(firstPart[1:]) - default: - result.WriteString(prefixFunc(name, firstPart)) - // NOTE: no longer check if prefixFunc returns a string that starts with uppercase: - // assume this is always the case - } - } else { - // unicode - firstRune, _ := utf8.DecodeRuneInString(firstPart) - switch { - case !unicode.IsLetter(firstRune): - result.WriteString(prefixFunc(name, firstPart)) - case !unicode.IsUpper(firstRune): - result.WriteString(prefixFunc(name, firstPart)) - /* - result.WriteRune(unicode.ToUpper(firstRune)) - result.WriteString(firstPart[offset:]) - */ - default: - result.WriteString(firstPart) - } - } - - for _, lexem := range lexemes[1:] { - goName := lexem.GetUnsafeGoName() - - // to support old behavior - if lexem.IsInitialism() { - goName = upper(goName) - } - result.WriteString(goName) - } - - return result.String() -} - -// ContainsStrings searches a slice of strings for a case-sensitive match -func ContainsStrings(coll []string, item string) bool { - for _, a := range coll { - if a == item { - return true - } - } - return false -} - -// ContainsStringsCI searches a slice of strings for a case-insensitive match -func ContainsStringsCI(coll []string, item string) bool { - for _, a := range coll { - if strings.EqualFold(a, item) { - return true - } - } - return false -} - -type zeroable interface { - IsZero() bool -} - -// IsZero returns true when the value passed into the function is a zero value. -// This allows for safer checking of interface values. -func IsZero(data interface{}) bool { - v := reflect.ValueOf(data) - // check for nil data - switch v.Kind() { //nolint:exhaustive - case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: - if v.IsNil() { - return true - } - } - - // check for things that have an IsZero method instead - if vv, ok := data.(zeroable); ok { - return vv.IsZero() - } - - // continue with slightly more complex reflection - switch v.Kind() { //nolint:exhaustive - case reflect.String: - return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Struct, reflect.Array: - return reflect.DeepEqual(data, reflect.Zero(v.Type()).Interface()) - case reflect.Invalid: - return true - default: - return false - } -} - -// CommandLineOptionsGroup represents a group of user-defined command line options -type CommandLineOptionsGroup struct { - ShortDescription string - LongDescription string - Options interface{} -} diff --git a/vendor/github.com/go-openapi/swag/yaml.go b/vendor/github.com/go-openapi/swag/yaml.go deleted file mode 100644 index 575346539..000000000 --- a/vendor/github.com/go-openapi/swag/yaml.go +++ /dev/null @@ -1,481 +0,0 @@ -// Copyright 2015 go-swagger maintainers -// -// 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 swag - -import ( - "encoding/json" - "fmt" - "path/filepath" - "reflect" - "sort" - "strconv" - - "github.com/mailru/easyjson/jlexer" - "github.com/mailru/easyjson/jwriter" - yaml "gopkg.in/yaml.v3" -) - -// YAMLMatcher matches yaml -func YAMLMatcher(path string) bool { - ext := filepath.Ext(path) - return ext == ".yaml" || ext == ".yml" -} - -// YAMLToJSON converts YAML unmarshaled data into json compatible data -func YAMLToJSON(data interface{}) (json.RawMessage, error) { - jm, err := transformData(data) - if err != nil { - return nil, err - } - b, err := WriteJSON(jm) - return json.RawMessage(b), err -} - -// BytesToYAMLDoc converts a byte slice into a YAML document -func BytesToYAMLDoc(data []byte) (interface{}, error) { - var document yaml.Node // preserve order that is present in the document - if err := yaml.Unmarshal(data, &document); err != nil { - return nil, err - } - if document.Kind != yaml.DocumentNode || len(document.Content) != 1 || document.Content[0].Kind != yaml.MappingNode { - return nil, fmt.Errorf("only YAML documents that are objects are supported: %w", ErrYAML) - } - return &document, nil -} - -func yamlNode(root *yaml.Node) (interface{}, error) { - switch root.Kind { - case yaml.DocumentNode: - return yamlDocument(root) - case yaml.SequenceNode: - return yamlSequence(root) - case yaml.MappingNode: - return yamlMapping(root) - case yaml.ScalarNode: - return yamlScalar(root) - case yaml.AliasNode: - return yamlNode(root.Alias) - default: - return nil, fmt.Errorf("unsupported YAML node type: %v: %w", root.Kind, ErrYAML) - } -} - -func yamlDocument(node *yaml.Node) (interface{}, error) { - if len(node.Content) != 1 { - return nil, fmt.Errorf("unexpected YAML Document node content length: %d: %w", len(node.Content), ErrYAML) - } - return yamlNode(node.Content[0]) -} - -func yamlMapping(node *yaml.Node) (interface{}, error) { - const sensibleAllocDivider = 2 - m := make(JSONMapSlice, len(node.Content)/sensibleAllocDivider) - - var j int - for i := 0; i < len(node.Content); i += 2 { - var nmi JSONMapItem - k, err := yamlStringScalarC(node.Content[i]) - if err != nil { - return nil, fmt.Errorf("unable to decode YAML map key: %w: %w", err, ErrYAML) - } - nmi.Key = k - v, err := yamlNode(node.Content[i+1]) - if err != nil { - return nil, fmt.Errorf("unable to process YAML map value for key %q: %w: %w", k, err, ErrYAML) - } - nmi.Value = v - m[j] = nmi - j++ - } - return m, nil -} - -func yamlSequence(node *yaml.Node) (interface{}, error) { - s := make([]interface{}, 0) - - for i := 0; i < len(node.Content); i++ { - - v, err := yamlNode(node.Content[i]) - if err != nil { - return nil, fmt.Errorf("unable to decode YAML sequence value: %w: %w", err, ErrYAML) - } - s = append(s, v) - } - return s, nil -} - -const ( // See https://yaml.org/type/ - yamlStringScalar = "tag:yaml.org,2002:str" - yamlIntScalar = "tag:yaml.org,2002:int" - yamlBoolScalar = "tag:yaml.org,2002:bool" - yamlFloatScalar = "tag:yaml.org,2002:float" - yamlTimestamp = "tag:yaml.org,2002:timestamp" - yamlNull = "tag:yaml.org,2002:null" -) - -func yamlScalar(node *yaml.Node) (interface{}, error) { - switch node.LongTag() { - case yamlStringScalar: - return node.Value, nil - case yamlBoolScalar: - b, err := strconv.ParseBool(node.Value) - if err != nil { - return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w: %w", node.Value, err, ErrYAML) - } - return b, nil - case yamlIntScalar: - i, err := strconv.ParseInt(node.Value, 10, 64) - if err != nil { - return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w: %w", node.Value, err, ErrYAML) - } - return i, nil - case yamlFloatScalar: - f, err := strconv.ParseFloat(node.Value, 64) - if err != nil { - return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w: %w", node.Value, err, ErrYAML) - } - return f, nil - case yamlTimestamp: - return node.Value, nil - case yamlNull: - return nil, nil //nolint:nilnil - default: - return nil, fmt.Errorf("YAML tag %q is not supported: %w", node.LongTag(), ErrYAML) - } -} - -func yamlStringScalarC(node *yaml.Node) (string, error) { - if node.Kind != yaml.ScalarNode { - return "", fmt.Errorf("expecting a string scalar but got %q: %w", node.Kind, ErrYAML) - } - switch node.LongTag() { - case yamlStringScalar, yamlIntScalar, yamlFloatScalar: - return node.Value, nil - default: - return "", fmt.Errorf("YAML tag %q is not supported as map key: %w", node.LongTag(), ErrYAML) - } -} - -// JSONMapSlice represent a JSON object, with the order of keys maintained -type JSONMapSlice []JSONMapItem - -// MarshalJSON renders a JSONMapSlice as JSON -func (s JSONMapSlice) MarshalJSON() ([]byte, error) { - w := &jwriter.Writer{Flags: jwriter.NilMapAsEmpty | jwriter.NilSliceAsEmpty} - s.MarshalEasyJSON(w) - return w.BuildBytes() -} - -// MarshalEasyJSON renders a JSONMapSlice as JSON, using easyJSON -func (s JSONMapSlice) MarshalEasyJSON(w *jwriter.Writer) { - w.RawByte('{') - - ln := len(s) - last := ln - 1 - for i := 0; i < ln; i++ { - s[i].MarshalEasyJSON(w) - if i != last { // last item - w.RawByte(',') - } - } - - w.RawByte('}') -} - -// UnmarshalJSON makes a JSONMapSlice from JSON -func (s *JSONMapSlice) UnmarshalJSON(data []byte) error { - l := jlexer.Lexer{Data: data} - s.UnmarshalEasyJSON(&l) - return l.Error() -} - -// UnmarshalEasyJSON makes a JSONMapSlice from JSON, using easyJSON -func (s *JSONMapSlice) UnmarshalEasyJSON(in *jlexer.Lexer) { - if in.IsNull() { - in.Skip() - return - } - - var result JSONMapSlice - in.Delim('{') - for !in.IsDelim('}') { - var mi JSONMapItem - mi.UnmarshalEasyJSON(in) - result = append(result, mi) - } - *s = result -} - -func (s JSONMapSlice) MarshalYAML() (interface{}, error) { - var n yaml.Node - n.Kind = yaml.DocumentNode - var nodes []*yaml.Node - for _, item := range s { - nn, err := json2yaml(item.Value) - if err != nil { - return nil, err - } - ns := []*yaml.Node{ - { - Kind: yaml.ScalarNode, - Tag: yamlStringScalar, - Value: item.Key, - }, - nn, - } - nodes = append(nodes, ns...) - } - - n.Content = []*yaml.Node{ - { - Kind: yaml.MappingNode, - Content: nodes, - }, - } - - return yaml.Marshal(&n) -} - -func isNil(input interface{}) bool { - if input == nil { - return true - } - kind := reflect.TypeOf(input).Kind() - switch kind { //nolint:exhaustive - case reflect.Ptr, reflect.Map, reflect.Slice, reflect.Chan: - return reflect.ValueOf(input).IsNil() - default: - return false - } -} - -func json2yaml(item interface{}) (*yaml.Node, error) { - if isNil(item) { - return &yaml.Node{ - Kind: yaml.ScalarNode, - Value: "null", - }, nil - } - - switch val := item.(type) { - case JSONMapSlice: - var n yaml.Node - n.Kind = yaml.MappingNode - for i := range val { - childNode, err := json2yaml(&val[i].Value) - if err != nil { - return nil, err - } - n.Content = append(n.Content, &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlStringScalar, - Value: val[i].Key, - }, childNode) - } - return &n, nil - case map[string]interface{}: - var n yaml.Node - n.Kind = yaml.MappingNode - keys := make([]string, 0, len(val)) - for k := range val { - keys = append(keys, k) - } - sort.Strings(keys) - - for _, k := range keys { - v := val[k] - childNode, err := json2yaml(v) - if err != nil { - return nil, err - } - n.Content = append(n.Content, &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlStringScalar, - Value: k, - }, childNode) - } - return &n, nil - case []interface{}: - var n yaml.Node - n.Kind = yaml.SequenceNode - for i := range val { - childNode, err := json2yaml(val[i]) - if err != nil { - return nil, err - } - n.Content = append(n.Content, childNode) - } - return &n, nil - case string: - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlStringScalar, - Value: val, - }, nil - case float64: - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlFloatScalar, - Value: strconv.FormatFloat(val, 'f', -1, 64), - }, nil - case int64: - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlIntScalar, - Value: strconv.FormatInt(val, 10), - }, nil - case uint64: - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlIntScalar, - Value: strconv.FormatUint(val, 10), - }, nil - case bool: - return &yaml.Node{ - Kind: yaml.ScalarNode, - Tag: yamlBoolScalar, - Value: strconv.FormatBool(val), - }, nil - default: - return nil, fmt.Errorf("unhandled type: %T: %w", val, ErrYAML) - } -} - -// JSONMapItem represents the value of a key in a JSON object held by JSONMapSlice -type JSONMapItem struct { - Key string - Value interface{} -} - -// MarshalJSON renders a JSONMapItem as JSON -func (s JSONMapItem) MarshalJSON() ([]byte, error) { - w := &jwriter.Writer{Flags: jwriter.NilMapAsEmpty | jwriter.NilSliceAsEmpty} - s.MarshalEasyJSON(w) - return w.BuildBytes() -} - -// MarshalEasyJSON renders a JSONMapItem as JSON, using easyJSON -func (s JSONMapItem) MarshalEasyJSON(w *jwriter.Writer) { - w.String(s.Key) - w.RawByte(':') - w.Raw(WriteJSON(s.Value)) -} - -// UnmarshalJSON makes a JSONMapItem from JSON -func (s *JSONMapItem) UnmarshalJSON(data []byte) error { - l := jlexer.Lexer{Data: data} - s.UnmarshalEasyJSON(&l) - return l.Error() -} - -// UnmarshalEasyJSON makes a JSONMapItem from JSON, using easyJSON -func (s *JSONMapItem) UnmarshalEasyJSON(in *jlexer.Lexer) { - key := in.UnsafeString() - in.WantColon() - value := in.Interface() - in.WantComma() - s.Key = key - s.Value = value -} - -func transformData(input interface{}) (out interface{}, err error) { - format := func(t interface{}) (string, error) { - switch k := t.(type) { - case string: - return k, nil - case uint: - return strconv.FormatUint(uint64(k), 10), nil - case uint8: - return strconv.FormatUint(uint64(k), 10), nil - case uint16: - return strconv.FormatUint(uint64(k), 10), nil - case uint32: - return strconv.FormatUint(uint64(k), 10), nil - case uint64: - return strconv.FormatUint(k, 10), nil - case int: - return strconv.Itoa(k), nil - case int8: - return strconv.FormatInt(int64(k), 10), nil - case int16: - return strconv.FormatInt(int64(k), 10), nil - case int32: - return strconv.FormatInt(int64(k), 10), nil - case int64: - return strconv.FormatInt(k, 10), nil - default: - return "", fmt.Errorf("unexpected map key type, got: %T: %w", k, ErrYAML) - } - } - - switch in := input.(type) { - case yaml.Node: - return yamlNode(&in) - case *yaml.Node: - return yamlNode(in) - case map[interface{}]interface{}: - o := make(JSONMapSlice, 0, len(in)) - for ke, va := range in { - var nmi JSONMapItem - if nmi.Key, err = format(ke); err != nil { - return nil, err - } - - v, ert := transformData(va) - if ert != nil { - return nil, ert - } - nmi.Value = v - o = append(o, nmi) - } - return o, nil - case []interface{}: - len1 := len(in) - o := make([]interface{}, len1) - for i := 0; i < len1; i++ { - o[i], err = transformData(in[i]) - if err != nil { - return nil, err - } - } - return o, nil - } - return input, nil -} - -// YAMLDoc loads a yaml document from either http or a file and converts it to json -func YAMLDoc(path string) (json.RawMessage, error) { - yamlDoc, err := YAMLData(path) - if err != nil { - return nil, err - } - - data, err := YAMLToJSON(yamlDoc) - if err != nil { - return nil, err - } - - return data, nil -} - -// YAMLData loads a yaml document from either http or a file -func YAMLData(path string) (interface{}, error) { - data, err := LoadFromFileOrHTTP(path) - if err != nil { - return nil, err - } - - return BytesToYAMLDoc(data) -} diff --git a/vendor/github.com/go-openapi/swag/yamlutils/LICENSE b/vendor/github.com/go-openapi/swag/yamlutils/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/yamlutils/LICENSE @@ -0,0 +1,202 @@ + + 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/vendor/github.com/go-openapi/swag/yamlutils/doc.go b/vendor/github.com/go-openapi/swag/yamlutils/doc.go new file mode 100644 index 000000000..7bb92a82f --- /dev/null +++ b/vendor/github.com/go-openapi/swag/yamlutils/doc.go @@ -0,0 +1,13 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +// Package yamlutils provides utilities to work with YAML documents. +// +// - [BytesToYAMLDoc] to construct a [yaml.Node] document +// - [YAMLToJSON] to convert a [yaml.Node] document to JSON bytes +// - [YAMLMapSlice] to serialize and deserialize YAML with the order of keys maintained +package yamlutils + +import ( + _ "go.yaml.in/yaml/v3" // for documentation purpose only +) diff --git a/vendor/github.com/go-openapi/swag/yamlutils/errors.go b/vendor/github.com/go-openapi/swag/yamlutils/errors.go new file mode 100644 index 000000000..e87bc5e8b --- /dev/null +++ b/vendor/github.com/go-openapi/swag/yamlutils/errors.go @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package yamlutils + +type yamlError string + +const ( + // ErrYAML is an error raised by YAML utilities + ErrYAML yamlError = "yaml error" +) + +func (e yamlError) Error() string { + return string(e) +} diff --git a/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go b/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go new file mode 100644 index 000000000..3daf68dbb --- /dev/null +++ b/vendor/github.com/go-openapi/swag/yamlutils/ordered_map.go @@ -0,0 +1,316 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package yamlutils + +import ( + "fmt" + "iter" + "slices" + "sort" + "strconv" + + "github.com/go-openapi/swag/conv" + "github.com/go-openapi/swag/jsonutils" + "github.com/go-openapi/swag/jsonutils/adapters/ifaces" + "github.com/go-openapi/swag/typeutils" + yaml "go.yaml.in/yaml/v3" +) + +var ( + _ yaml.Marshaler = YAMLMapSlice{} + _ yaml.Unmarshaler = &YAMLMapSlice{} +) + +// YAMLMapSlice represents a YAML object, with the order of keys maintained. +// +// It is similar to [jsonutils.JSONMapSlice] and also knows how to marshal and unmarshal YAML. +// +// It behaves like an ordered map, but keys can't be accessed in constant time. +type YAMLMapSlice []YAMLMapItem + +// YAMLMapItem represents the value of a key in a YAML object held by [YAMLMapSlice]. +// +// It is entirely equivalent to [jsonutils.JSONMapItem], with the same limitation that +// you should not Marshal or Unmarshal directly this type, outside of a [YAMLMapSlice]. +type YAMLMapItem = jsonutils.JSONMapItem + +func (s YAMLMapSlice) OrderedItems() iter.Seq2[string, any] { + return func(yield func(string, any) bool) { + for _, item := range s { + if !yield(item.Key, item.Value) { + return + } + } + } +} + +// SetOrderedItems implements [ifaces.SetOrdered]: it merges keys passed by the iterator argument +// into the [YAMLMapSlice]. +func (s *YAMLMapSlice) SetOrderedItems(items iter.Seq2[string, any]) { + if items == nil { + // force receiver to be a nil slice + *s = nil + + return + } + + m := *s + if len(m) > 0 { + // update mode: short-circuited when unmarshaling fresh data structures + idx := make(map[string]int, len(m)) + + for i, item := range m { + idx[item.Key] = i + } + + for k, v := range items { + idx, ok := idx[k] + if ok { + m[idx].Value = v + + continue + } + + m = append(m, YAMLMapItem{Key: k, Value: v}) + } + + *s = m + + return + } + + for k, v := range items { + m = append(m, YAMLMapItem{Key: k, Value: v}) + } + + *s = m +} + +// MarshalJSON renders this YAML object as JSON bytes. +// +// The difference with standard JSON marshaling is that the order of keys is maintained. +func (s YAMLMapSlice) MarshalJSON() ([]byte, error) { + return jsonutils.JSONMapSlice(s).MarshalJSON() +} + +// UnmarshalJSON builds this YAML object from JSON bytes. +// +// The difference with standard JSON marshaling is that the order of keys is maintained. +func (s *YAMLMapSlice) UnmarshalJSON(data []byte) error { + js := jsonutils.JSONMapSlice(*s) + + if err := js.UnmarshalJSON(data); err != nil { + return err + } + + *s = YAMLMapSlice(js) + + return nil +} + +// MarshalYAML produces a YAML document as bytes +// +// The difference with standard YAML marshaling is that the order of keys is maintained. +// +// It implements [yaml.Marshaler]. +func (s YAMLMapSlice) MarshalYAML() (any, error) { + if typeutils.IsNil(s) { + return []byte("null\n"), nil + } + var n yaml.Node + n.Kind = yaml.DocumentNode + var nodes []*yaml.Node + + for _, item := range s { + nn, err := json2yaml(item.Value) + if err != nil { + return nil, err + } + + ns := []*yaml.Node{ + { + Kind: yaml.ScalarNode, + Tag: yamlStringScalar, + Value: item.Key, + }, + nn, + } + nodes = append(nodes, ns...) + } + + n.Content = []*yaml.Node{ + { + Kind: yaml.MappingNode, + Content: nodes, + }, + } + + return yaml.Marshal(&n) +} + +// UnmarshalYAML builds a YAMLMapSlice object from a YAML document [yaml.Node]. +// +// It implements [yaml.Unmarshaler]. +func (s *YAMLMapSlice) UnmarshalYAML(node *yaml.Node) error { + if typeutils.IsNil(*s) { + // allow to unmarshal with a simple var declaration (nil slice) + *s = YAMLMapSlice{} + } + if node == nil { + *s = nil + return nil + } + + const sensibleAllocDivider = 2 + m := slices.Grow(*s, len(node.Content)/sensibleAllocDivider) + m = m[:0] + + for i := 0; i < len(node.Content); i += 2 { + var nmi YAMLMapItem + k, err := yamlStringScalarC(node.Content[i]) + if err != nil { + return fmt.Errorf("unable to decode YAML map key: %w: %w", err, ErrYAML) + } + nmi.Key = k + v, err := yamlNode(node.Content[i+1]) + if err != nil { + return fmt.Errorf("unable to process YAML map value for key %q: %w: %w", k, err, ErrYAML) + } + nmi.Value = v + m = append(m, nmi) + } + + *s = m + + return nil +} + +func json2yaml(item any) (*yaml.Node, error) { + if typeutils.IsNil(item) { + return &yaml.Node{ + Kind: yaml.ScalarNode, + Value: "null", + }, nil + } + + switch val := item.(type) { + case ifaces.Ordered: + return orderedYAML(val) + + case map[string]any: + var n yaml.Node + n.Kind = yaml.MappingNode + keys := make([]string, 0, len(val)) + for k := range val { + keys = append(keys, k) + } + sort.Strings(keys) + + for _, k := range keys { + v := val[k] + childNode, err := json2yaml(v) + if err != nil { + return nil, err + } + n.Content = append(n.Content, &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlStringScalar, + Value: k, + }, childNode) + } + return &n, nil + + case []any: + var n yaml.Node + n.Kind = yaml.SequenceNode + for i := range val { + childNode, err := json2yaml(val[i]) + if err != nil { + return nil, err + } + n.Content = append(n.Content, childNode) + } + return &n, nil + case string: + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlStringScalar, + Value: val, + }, nil + case float32: + return floatNode(val) + case float64: + return floatNode(val) + case int: + return integerNode(val) + case int8: + return integerNode(val) + case int16: + return integerNode(val) + case int32: + return integerNode(val) + case int64: + return integerNode(val) + case uint: + return uintegerNode(val) + case uint8: + return uintegerNode(val) + case uint16: + return uintegerNode(val) + case uint32: + return uintegerNode(val) + case uint64: + return uintegerNode(val) + case bool: + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlBoolScalar, + Value: strconv.FormatBool(val), + }, nil + default: + return nil, fmt.Errorf("unhandled type: %T: %w", val, ErrYAML) + } +} + +func floatNode[T conv.Float](val T) (*yaml.Node, error) { + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlFloatScalar, + Value: conv.FormatFloat(val), + }, nil +} + +func integerNode[T conv.Signed](val T) (*yaml.Node, error) { + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlIntScalar, + Value: conv.FormatInteger(val), + }, nil +} + +func uintegerNode[T conv.Unsigned](val T) (*yaml.Node, error) { + return &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlIntScalar, + Value: conv.FormatUinteger(val), + }, nil +} + +func orderedYAML[T ifaces.Ordered](val T) (*yaml.Node, error) { + var n yaml.Node + n.Kind = yaml.MappingNode + for key, value := range val.OrderedItems() { + childNode, err := json2yaml(value) + if err != nil { + return nil, err + } + + n.Content = append(n.Content, &yaml.Node{ + Kind: yaml.ScalarNode, + Tag: yamlStringScalar, + Value: key, + }, childNode) + } + return &n, nil +} diff --git a/vendor/github.com/go-openapi/swag/yamlutils/yaml.go b/vendor/github.com/go-openapi/swag/yamlutils/yaml.go new file mode 100644 index 000000000..e3aff3c2f --- /dev/null +++ b/vendor/github.com/go-openapi/swag/yamlutils/yaml.go @@ -0,0 +1,211 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package yamlutils + +import ( + json "encoding/json" + "fmt" + "strconv" + + "github.com/go-openapi/swag/jsonutils" + yaml "go.yaml.in/yaml/v3" +) + +// YAMLToJSON converts a YAML document into JSON bytes. +// +// Note: a YAML document is the output from a [yaml.Marshaler], e.g a pointer to a [yaml.Node]. +// +// [YAMLToJSON] is typically called after [BytesToYAMLDoc]. +func YAMLToJSON(value any) (json.RawMessage, error) { + jm, err := transformData(value) + if err != nil { + return nil, err + } + + b, err := jsonutils.WriteJSON(jm) + + return json.RawMessage(b), err +} + +// BytesToYAMLDoc converts a byte slice into a YAML document. +// +// This function only supports root documents that are objects. +// +// A YAML document is a pointer to a [yaml.Node]. +func BytesToYAMLDoc(data []byte) (any, error) { + var document yaml.Node // preserve order that is present in the document + if err := yaml.Unmarshal(data, &document); err != nil { + return nil, err + } + if document.Kind != yaml.DocumentNode || len(document.Content) != 1 || document.Content[0].Kind != yaml.MappingNode { + return nil, fmt.Errorf("only YAML documents that are objects are supported: %w", ErrYAML) + } + return &document, nil +} + +func yamlNode(root *yaml.Node) (any, error) { + switch root.Kind { + case yaml.DocumentNode: + return yamlDocument(root) + case yaml.SequenceNode: + return yamlSequence(root) + case yaml.MappingNode: + return yamlMapping(root) + case yaml.ScalarNode: + return yamlScalar(root) + case yaml.AliasNode: + return yamlNode(root.Alias) + default: + return nil, fmt.Errorf("unsupported YAML node type: %v: %w", root.Kind, ErrYAML) + } +} + +func yamlDocument(node *yaml.Node) (any, error) { + if len(node.Content) != 1 { + return nil, fmt.Errorf("unexpected YAML Document node content length: %d: %w", len(node.Content), ErrYAML) + } + return yamlNode(node.Content[0]) +} + +func yamlMapping(node *yaml.Node) (any, error) { + const sensibleAllocDivider = 2 // nodes concatenate (key,value) sequences + m := make(YAMLMapSlice, len(node.Content)/sensibleAllocDivider) + + if err := m.UnmarshalYAML(node); err != nil { + return nil, err + } + + return m, nil +} + +func yamlSequence(node *yaml.Node) (any, error) { + s := make([]any, 0) + + for i := range len(node.Content) { + v, err := yamlNode(node.Content[i]) + if err != nil { + return nil, fmt.Errorf("unable to decode YAML sequence value: %w: %w", err, ErrYAML) + } + s = append(s, v) + } + return s, nil +} + +const ( // See https://yaml.org/type/ + yamlStringScalar = "tag:yaml.org,2002:str" + yamlIntScalar = "tag:yaml.org,2002:int" + yamlBoolScalar = "tag:yaml.org,2002:bool" + yamlFloatScalar = "tag:yaml.org,2002:float" + yamlTimestamp = "tag:yaml.org,2002:timestamp" + yamlNull = "tag:yaml.org,2002:null" +) + +func yamlScalar(node *yaml.Node) (any, error) { + switch node.LongTag() { + case yamlStringScalar: + return node.Value, nil + case yamlBoolScalar: + b, err := strconv.ParseBool(node.Value) + if err != nil { + return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w: %w", node.Value, err, ErrYAML) + } + return b, nil + case yamlIntScalar: + i, err := strconv.ParseInt(node.Value, 10, 64) + if err != nil { + return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w: %w", node.Value, err, ErrYAML) + } + return i, nil + case yamlFloatScalar: + f, err := strconv.ParseFloat(node.Value, 64) + if err != nil { + return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w: %w", node.Value, err, ErrYAML) + } + return f, nil + case yamlTimestamp: + // YAML timestamp is marshaled as string, not time + return node.Value, nil + case yamlNull: + return nil, nil //nolint:nilnil + default: + return nil, fmt.Errorf("YAML tag %q is not supported: %w", node.LongTag(), ErrYAML) + } +} + +func yamlStringScalarC(node *yaml.Node) (string, error) { + if node.Kind != yaml.ScalarNode { + return "", fmt.Errorf("expecting a string scalar but got %q: %w", node.Kind, ErrYAML) + } + switch node.LongTag() { + case yamlStringScalar, yamlIntScalar, yamlFloatScalar: + return node.Value, nil + default: + return "", fmt.Errorf("YAML tag %q is not supported as map key: %w", node.LongTag(), ErrYAML) + } +} + +func format(t any) (string, error) { + switch k := t.(type) { + case string: + return k, nil + case uint: + return strconv.FormatUint(uint64(k), 10), nil + case uint8: + return strconv.FormatUint(uint64(k), 10), nil + case uint16: + return strconv.FormatUint(uint64(k), 10), nil + case uint32: + return strconv.FormatUint(uint64(k), 10), nil + case uint64: + return strconv.FormatUint(k, 10), nil + case int: + return strconv.Itoa(k), nil + case int8: + return strconv.FormatInt(int64(k), 10), nil + case int16: + return strconv.FormatInt(int64(k), 10), nil + case int32: + return strconv.FormatInt(int64(k), 10), nil + case int64: + return strconv.FormatInt(k, 10), nil + default: + return "", fmt.Errorf("unexpected map key type, got: %T: %w", k, ErrYAML) + } +} + +func transformData(input any) (out any, err error) { + switch in := input.(type) { + case yaml.Node: + return yamlNode(&in) + case *yaml.Node: + return yamlNode(in) + case map[any]any: + o := make(YAMLMapSlice, 0, len(in)) + for ke, va := range in { + var nmi YAMLMapItem + if nmi.Key, err = format(ke); err != nil { + return nil, err + } + + v, ert := transformData(va) + if ert != nil { + return nil, ert + } + nmi.Value = v + o = append(o, nmi) + } + return o, nil + case []any: + len1 := len(in) + o := make([]any, len1) + for i := range len1 { + o[i], err = transformData(in[i]) + if err != nil { + return nil, err + } + } + return o, nil + } + return input, nil +} diff --git a/vendor/github.com/go-openapi/swag/yamlutils_iface.go b/vendor/github.com/go-openapi/swag/yamlutils_iface.go new file mode 100644 index 000000000..57767efc5 --- /dev/null +++ b/vendor/github.com/go-openapi/swag/yamlutils_iface.go @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers +// SPDX-License-Identifier: Apache-2.0 + +package swag + +import ( + "encoding/json" + + "github.com/go-openapi/swag/yamlutils" +) + +// YAMLToJSON converts YAML unmarshaled data into json compatible data +// +// Deprecated: use [yamlutils.YAMLToJSON] instead. +func YAMLToJSON(data any) (json.RawMessage, error) { return yamlutils.YAMLToJSON(data) } + +// BytesToYAMLDoc converts a byte slice into a YAML document +// +// Deprecated: use [yamlutils.BytesToYAMLDoc] instead. +func BytesToYAMLDoc(data []byte) (any, error) { return yamlutils.BytesToYAMLDoc(data) } diff --git a/vendor/github.com/google/gnostic-models/extensions/extension.proto b/vendor/github.com/google/gnostic-models/extensions/extension.proto index 875137c1a..a60042989 100644 --- a/vendor/github.com/google/gnostic-models/extensions/extension.proto +++ b/vendor/github.com/google/gnostic-models/extensions/extension.proto @@ -42,7 +42,7 @@ option java_package = "org.gnostic.v1"; option objc_class_prefix = "GNX"; // The Go package name. -option go_package = "./extensions;gnostic_extension_v1"; +option go_package = "github.com/google/gnostic-models/extensions;gnostic_extension_v1"; // The version number of Gnostic. message Version { diff --git a/vendor/github.com/google/gnostic-models/openapiv2/OpenAPIv2.proto b/vendor/github.com/google/gnostic-models/openapiv2/OpenAPIv2.proto index 1c59b2f4a..49adafcc8 100644 --- a/vendor/github.com/google/gnostic-models/openapiv2/OpenAPIv2.proto +++ b/vendor/github.com/google/gnostic-models/openapiv2/OpenAPIv2.proto @@ -42,7 +42,7 @@ option java_package = "org.openapi_v2"; option objc_class_prefix = "OAS"; // The Go package name. -option go_package = "./openapiv2;openapi_v2"; +option go_package = "github.com/google/gnostic-models/openapiv2;openapi_v2"; message AdditionalPropertiesItem { oneof oneof { diff --git a/vendor/github.com/google/gnostic-models/openapiv3/OpenAPIv3.proto b/vendor/github.com/google/gnostic-models/openapiv3/OpenAPIv3.proto index 1be335b89..af4b6254b 100644 --- a/vendor/github.com/google/gnostic-models/openapiv3/OpenAPIv3.proto +++ b/vendor/github.com/google/gnostic-models/openapiv3/OpenAPIv3.proto @@ -42,7 +42,7 @@ option java_package = "org.openapi_v3"; option objc_class_prefix = "OAS"; // The Go package name. -option go_package = "./openapiv3;openapi_v3"; +option go_package = "github.com/google/gnostic-models/openapiv3;openapi_v3"; message AdditionalPropertiesItem { oneof oneof { diff --git a/vendor/github.com/google/gnostic-models/openapiv3/annotations.proto b/vendor/github.com/google/gnostic-models/openapiv3/annotations.proto index 09ee0aac5..895b4567c 100644 --- a/vendor/github.com/google/gnostic-models/openapiv3/annotations.proto +++ b/vendor/github.com/google/gnostic-models/openapiv3/annotations.proto @@ -20,7 +20,7 @@ import "google/protobuf/descriptor.proto"; import "openapiv3/OpenAPIv3.proto"; // The Go package name. -option go_package = "./openapiv3;openapi_v3"; +option go_package = "github.com/google/gnostic-models/openapiv3;openapi_v3"; // This option lets the proto compiler generate Java code inside the package // name (see below) instead of inside an outer class. It creates a simpler // developer experience by reducing one-level of name nesting and be diff --git a/vendor/github.com/hashicorp/go-hclog/LICENSE b/vendor/github.com/hashicorp/go-hclog/LICENSE index abaf1e45f..9938fb50e 100644 --- a/vendor/github.com/hashicorp/go-hclog/LICENSE +++ b/vendor/github.com/hashicorp/go-hclog/LICENSE @@ -1,6 +1,4 @@ -MIT License - -Copyright (c) 2017 HashiCorp +Copyright (c) 2017 HashiCorp, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/hashicorp/go-hclog/README.md b/vendor/github.com/hashicorp/go-hclog/README.md index 5d56f4b59..983d44c7d 100644 --- a/vendor/github.com/hashicorp/go-hclog/README.md +++ b/vendor/github.com/hashicorp/go-hclog/README.md @@ -17,11 +17,8 @@ JSON output mode for production. ## Stability Note -While this library is fully open source and HashiCorp will be maintaining it -(since we are and will be making extensive use of it), the API and output -format is subject to minor changes as we fully bake and vet it in our projects. -This notice will be removed once it's fully integrated into our major projects -and no further changes are anticipated. +This library has reached 1.0 stability. Its API can be considered solidified +and promised through future versions. ## Installation and Docs @@ -102,7 +99,7 @@ into all the callers. ### Using `hclog.Fmt()` ```go -var int totalBandwidth = 200 +totalBandwidth := 200 appLogger.Info("total bandwidth exceeded", "bandwidth", hclog.Fmt("%d GB/s", totalBandwidth)) ``` @@ -143,6 +140,10 @@ log.Printf("[DEBUG] %d", 42) ... [DEBUG] my-app: 42 ``` -Notice that if `appLogger` is initialized with the `INFO` log level _and_ you +Notice that if `appLogger` is initialized with the `INFO` log level, _and_ you specify `InferLevels: true`, you will not see any output here. You must change `appLogger` to `DEBUG` to see output. See the docs for more information. + +If the log lines start with a timestamp you can use the +`InferLevelsWithTimestamp` option to try and ignore them. Please note that in order +for `InferLevelsWithTimestamp` to be relevant, `InferLevels` must be set to `true`. diff --git a/vendor/github.com/hashicorp/go-hclog/colorize_unix.go b/vendor/github.com/hashicorp/go-hclog/colorize_unix.go index 44aa9bf2c..d00816b38 100644 --- a/vendor/github.com/hashicorp/go-hclog/colorize_unix.go +++ b/vendor/github.com/hashicorp/go-hclog/colorize_unix.go @@ -1,3 +1,7 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + +//go:build !windows // +build !windows package hclog @@ -6,22 +10,35 @@ import ( "github.com/mattn/go-isatty" ) +// hasFD is used to check if the writer has an Fd value to check +// if it's a terminal. +type hasFD interface { + Fd() uintptr +} + // setColorization will mutate the values of this logger -// to approperately configure colorization options. It provides +// to appropriately configure colorization options. It provides // a wrapper to the output stream on Windows systems. func (l *intLogger) setColorization(opts *LoggerOptions) { - switch opts.Color { - case ColorOff: - fallthrough - case ForceColor: + if opts.Color != AutoColor { return - case AutoColor: - fi := l.checkWriterIsFile() - isUnixTerm := isatty.IsTerminal(fi.Fd()) - isCygwinTerm := isatty.IsCygwinTerminal(fi.Fd()) - isTerm := isUnixTerm || isCygwinTerm - if !isTerm { + } + + if sc, ok := l.writer.w.(SupportsColor); ok { + if !sc.SupportsColor() { + l.headerColor = ColorOff l.writer.color = ColorOff } + return + } + + fi, ok := l.writer.w.(hasFD) + if !ok { + return + } + + if !isatty.IsTerminal(fi.Fd()) { + l.headerColor = ColorOff + l.writer.color = ColorOff } } diff --git a/vendor/github.com/hashicorp/go-hclog/colorize_windows.go b/vendor/github.com/hashicorp/go-hclog/colorize_windows.go index 23486b6d7..2c3fb9ea6 100644 --- a/vendor/github.com/hashicorp/go-hclog/colorize_windows.go +++ b/vendor/github.com/hashicorp/go-hclog/colorize_windows.go @@ -1,3 +1,7 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + +//go:build windows // +build windows package hclog @@ -6,28 +10,32 @@ import ( "os" colorable "github.com/mattn/go-colorable" - "github.com/mattn/go-isatty" ) // setColorization will mutate the values of this logger -// to approperately configure colorization options. It provides +// to appropriately configure colorization options. It provides // a wrapper to the output stream on Windows systems. func (l *intLogger) setColorization(opts *LoggerOptions) { - switch opts.Color { - case ColorOff: + if opts.Color == ColorOff { + return + } + + fi, ok := l.writer.w.(*os.File) + if !ok { + l.writer.color = ColorOff + l.headerColor = ColorOff return - case ForceColor: - fi := l.checkWriterIsFile() - l.writer.w = colorable.NewColorable(fi) - case AutoColor: - fi := l.checkWriterIsFile() - isUnixTerm := isatty.IsTerminal(os.Stdout.Fd()) - isCygwinTerm := isatty.IsCygwinTerminal(os.Stdout.Fd()) - isTerm := isUnixTerm || isCygwinTerm - if !isTerm { - l.writer.color = ColorOff - return - } - l.writer.w = colorable.NewColorable(fi) + } + + cfi := colorable.NewColorable(fi) + + // NewColorable detects if color is possible and if it's not, then it + // returns the original value. So we can test if we got the original + // value back to know if color is possible. + if cfi == fi { + l.writer.color = ColorOff + l.headerColor = ColorOff + } else { + l.writer.w = cfi } } diff --git a/vendor/github.com/hashicorp/go-hclog/context.go b/vendor/github.com/hashicorp/go-hclog/context.go index 7815f5019..eb5aba556 100644 --- a/vendor/github.com/hashicorp/go-hclog/context.go +++ b/vendor/github.com/hashicorp/go-hclog/context.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + package hclog import ( diff --git a/vendor/github.com/hashicorp/go-hclog/exclude.go b/vendor/github.com/hashicorp/go-hclog/exclude.go index cfd4307a8..4b73ba553 100644 --- a/vendor/github.com/hashicorp/go-hclog/exclude.go +++ b/vendor/github.com/hashicorp/go-hclog/exclude.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + package hclog import ( diff --git a/vendor/github.com/hashicorp/go-hclog/global.go b/vendor/github.com/hashicorp/go-hclog/global.go index 22ebc57d8..a7403f593 100644 --- a/vendor/github.com/hashicorp/go-hclog/global.go +++ b/vendor/github.com/hashicorp/go-hclog/global.go @@ -1,7 +1,11 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + package hclog import ( "sync" + "time" ) var ( @@ -14,17 +18,18 @@ var ( DefaultOptions = &LoggerOptions{ Level: DefaultLevel, Output: DefaultOutput, + TimeFn: time.Now, } ) // Default returns a globally held logger. This can be a good starting -// place, and then you can use .With() and .Name() to create sub-loggers +// place, and then you can use .With() and .Named() to create sub-loggers // to be used in more specific contexts. // The value of the Default logger can be set via SetDefault() or by // changing the options in DefaultOptions. // // This method is goroutine safe, returning a global from memory, but -// cause should be used if SetDefault() is called it random times +// care should be used if SetDefault() is called it random times // in the program as that may result in race conditions and an unexpected // Logger being returned. func Default() Logger { diff --git a/vendor/github.com/hashicorp/go-hclog/interceptlogger.go b/vendor/github.com/hashicorp/go-hclog/interceptlogger.go index 08a6677eb..e9b1c1885 100644 --- a/vendor/github.com/hashicorp/go-hclog/interceptlogger.go +++ b/vendor/github.com/hashicorp/go-hclog/interceptlogger.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + package hclog import ( @@ -18,8 +21,13 @@ type interceptLogger struct { } func NewInterceptLogger(opts *LoggerOptions) InterceptLogger { + l := newLogger(opts) + if l.callerOffset > 0 { + // extra frames for interceptLogger.{Warn,Info,Log,etc...}, and interceptLogger.log + l.callerOffset += 2 + } intercept := &interceptLogger{ - Logger: New(opts), + Logger: l, mu: new(sync.Mutex), sinkCount: new(int32), Sinks: make(map[SinkAdapter]struct{}), @@ -31,6 +39,14 @@ func NewInterceptLogger(opts *LoggerOptions) InterceptLogger { } func (i *interceptLogger) Log(level Level, msg string, args ...interface{}) { + i.log(level, msg, args...) +} + +// log is used to make the caller stack frame lookup consistent. If Warn,Info,etc +// all called Log then direct calls to Log would have a different stack frame +// depth. By having all the methods call the same helper we ensure the stack +// frame depth is the same. +func (i *interceptLogger) log(level Level, msg string, args ...interface{}) { i.Logger.Log(level, msg, args...) if atomic.LoadInt32(i.sinkCount) == 0 { return @@ -45,72 +61,27 @@ func (i *interceptLogger) Log(level Level, msg string, args ...interface{}) { // Emit the message and args at TRACE level to log and sinks func (i *interceptLogger) Trace(msg string, args ...interface{}) { - i.Logger.Trace(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Trace, msg, i.retrieveImplied(args...)...) - } + i.log(Trace, msg, args...) } // Emit the message and args at DEBUG level to log and sinks func (i *interceptLogger) Debug(msg string, args ...interface{}) { - i.Logger.Debug(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Debug, msg, i.retrieveImplied(args...)...) - } + i.log(Debug, msg, args...) } // Emit the message and args at INFO level to log and sinks func (i *interceptLogger) Info(msg string, args ...interface{}) { - i.Logger.Info(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Info, msg, i.retrieveImplied(args...)...) - } + i.log(Info, msg, args...) } // Emit the message and args at WARN level to log and sinks func (i *interceptLogger) Warn(msg string, args ...interface{}) { - i.Logger.Warn(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Warn, msg, i.retrieveImplied(args...)...) - } + i.log(Warn, msg, args...) } // Emit the message and args at ERROR level to log and sinks func (i *interceptLogger) Error(msg string, args ...interface{}) { - i.Logger.Error(msg, args...) - if atomic.LoadInt32(i.sinkCount) == 0 { - return - } - - i.mu.Lock() - defer i.mu.Unlock() - for s := range i.Sinks { - s.Accept(i.Name(), Error, msg, i.retrieveImplied(args...)...) - } + i.log(Error, msg, args...) } func (i *interceptLogger) retrieveImplied(args ...interface{}) []interface{} { @@ -123,17 +94,11 @@ func (i *interceptLogger) retrieveImplied(args ...interface{}) []interface{} { return cp } -// Create a new sub-Logger that a name decending from the current name. +// Create a new sub-Logger that a name descending from the current name. // This is used to create a subsystem specific Logger. // Registered sinks will subscribe to these messages as well. func (i *interceptLogger) Named(name string) Logger { - var sub interceptLogger - - sub = *i - - sub.Logger = i.Logger.Named(name) - - return &sub + return i.NamedIntercept(name) } // Create a new sub-Logger with an explicit name. This ignores the current @@ -141,13 +106,7 @@ func (i *interceptLogger) Named(name string) Logger { // within the normal hierarchy. Registered sinks will subscribe // to these messages as well. func (i *interceptLogger) ResetNamed(name string) Logger { - var sub interceptLogger - - sub = *i - - sub.Logger = i.Logger.ResetNamed(name) - - return &sub + return i.ResetNamedIntercept(name) } // Create a new sub-Logger that a name decending from the current name. @@ -157,9 +116,7 @@ func (i *interceptLogger) NamedIntercept(name string) InterceptLogger { var sub interceptLogger sub = *i - sub.Logger = i.Logger.Named(name) - return &sub } @@ -171,9 +128,7 @@ func (i *interceptLogger) ResetNamedIntercept(name string) InterceptLogger { var sub interceptLogger sub = *i - sub.Logger = i.Logger.ResetNamed(name) - return &sub } @@ -210,22 +165,28 @@ func (i *interceptLogger) DeregisterSink(sink SinkAdapter) { atomic.AddInt32(i.sinkCount, -1) } -// Create a *log.Logger that will send it's data through this Logger. This -// allows packages that expect to be using the standard library to log to -// actually use this logger, which will also send to any registered sinks. func (i *interceptLogger) StandardLoggerIntercept(opts *StandardLoggerOptions) *log.Logger { + return i.StandardLogger(opts) +} + +func (i *interceptLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger { if opts == nil { opts = &StandardLoggerOptions{} } - return log.New(i.StandardWriterIntercept(opts), "", 0) + return log.New(i.StandardWriter(opts), "", 0) } func (i *interceptLogger) StandardWriterIntercept(opts *StandardLoggerOptions) io.Writer { + return i.StandardWriter(opts) +} + +func (i *interceptLogger) StandardWriter(opts *StandardLoggerOptions) io.Writer { return &stdlogAdapter{ - log: i, - inferLevels: opts.InferLevels, - forceLevel: opts.ForceLevel, + log: i, + inferLevels: opts.InferLevels, + inferLevelsWithTimestamp: opts.InferLevelsWithTimestamp, + forceLevel: opts.ForceLevel, } } diff --git a/vendor/github.com/hashicorp/go-hclog/intlogger.go b/vendor/github.com/hashicorp/go-hclog/intlogger.go index 7158125de..272a710c0 100644 --- a/vendor/github.com/hashicorp/go-hclog/intlogger.go +++ b/vendor/github.com/hashicorp/go-hclog/intlogger.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + package hclog import ( @@ -8,9 +11,7 @@ import ( "fmt" "io" "log" - "os" "reflect" - "regexp" "runtime" "sort" "strconv" @@ -18,14 +19,20 @@ import ( "sync" "sync/atomic" "time" + "unicode" + "unicode/utf8" "github.com/fatih/color" ) -// TimeFormat to use for logging. This is a version of RFC3339 that contains -// contains millisecond precision +// TimeFormat is the time format to use for plain (non-JSON) output. +// This is a version of RFC3339 that contains millisecond precision. const TimeFormat = "2006-01-02T15:04:05.000Z0700" +// TimeFormatJSON is the time format to use for JSON output. +// This is a version of RFC3339 that contains microsecond precision. +const TimeFormatJSON = "2006-01-02T15:04:05.000000Z07:00" + // errJsonUnsupportedTypeMsg is included in log json entries, if an arg cannot be serialized to json const errJsonUnsupportedTypeMsg = "logging contained values that don't serialize to json" @@ -45,18 +52,41 @@ var ( Warn: color.New(color.FgHiYellow), Error: color.New(color.FgHiRed), } + + faintBoldColor = color.New(color.Faint, color.Bold) + faintColor = color.New(color.Faint) + faintMultiLinePrefix string + faintFieldSeparator string + faintFieldSeparatorWithNewLine string ) +func init() { + // Force all the colors to enabled because we do our own detection of color usage. + for _, c := range _levelToColor { + c.EnableColor() + } + + faintBoldColor.EnableColor() + faintColor.EnableColor() + + faintMultiLinePrefix = faintColor.Sprint(" | ") + faintFieldSeparator = faintColor.Sprint("=") + faintFieldSeparatorWithNewLine = faintColor.Sprint("=\n") +} + // Make sure that intLogger is a Logger var _ Logger = &intLogger{} // intLogger is an internal logger implementation. Internal in that it is // defined entirely by this package. type intLogger struct { - json bool - caller bool - name string - timeFormat string + json bool + jsonEscapeEnabled bool + callerOffset int + name string + timeFormat string + timeFn TimeFunction + disableTime bool // This is an interface so that it's shared by any derived loggers, since // those derived loggers share the bufio.Writer as well. @@ -64,9 +94,31 @@ type intLogger struct { writer *writer level *int32 + // The value of curEpoch when our level was set + setEpoch uint64 + + // The value of curEpoch the last time we performed the level sync process + ownEpoch uint64 + + // Shared amongst all the loggers created in this hierachy, used to determine + // if the level sync process should be run by comparing it with ownEpoch + curEpoch *uint64 + + // The logger this one was created from. Only set when syncParentLevel is set + parent *intLogger + + headerColor ColorOption + fieldColor ColorOption + implied []interface{} exclude func(level Level, msg string, args ...interface{}) bool + + // create subloggers with their own level setting + independentLevels bool + syncParentLevel bool + + subloggerHook func(sub Logger) Logger } // New returns a configured logger. @@ -77,7 +129,12 @@ func New(opts *LoggerOptions) Logger { // NewSinkAdapter returns a SinkAdapter with configured settings // defined by LoggerOptions func NewSinkAdapter(opts *LoggerOptions) SinkAdapter { - return newLogger(opts) + l := newLogger(opts) + if l.callerOffset > 0 { + // extra frames for interceptLogger.{Warn,Info,Log,etc...}, and SinkAdapter.Accept + l.callerOffset += 2 + } + return l } func newLogger(opts *LoggerOptions) *intLogger { @@ -100,38 +157,80 @@ func newLogger(opts *LoggerOptions) *intLogger { mutex = new(sync.Mutex) } - l := &intLogger{ - json: opts.JSONFormat, - caller: opts.IncludeLocation, - name: opts.Name, - timeFormat: TimeFormat, - mutex: mutex, - writer: newWriter(output, opts.Color), - level: new(int32), - exclude: opts.Exclude, + var ( + primaryColor = ColorOff + headerColor = ColorOff + fieldColor = ColorOff + ) + switch { + case opts.ColorHeaderOnly: + headerColor = opts.Color + case opts.ColorHeaderAndFields: + fieldColor = opts.Color + headerColor = opts.Color + default: + primaryColor = opts.Color } - l.setColorization(opts) + l := &intLogger{ + json: opts.JSONFormat, + jsonEscapeEnabled: !opts.JSONEscapeDisabled, + name: opts.Name, + timeFormat: TimeFormat, + timeFn: time.Now, + disableTime: opts.DisableTime, + mutex: mutex, + writer: newWriter(output, primaryColor), + level: new(int32), + curEpoch: new(uint64), + exclude: opts.Exclude, + independentLevels: opts.IndependentLevels, + syncParentLevel: opts.SyncParentLevel, + headerColor: headerColor, + fieldColor: fieldColor, + subloggerHook: opts.SubloggerHook, + } + if opts.IncludeLocation { + l.callerOffset = offsetIntLogger + opts.AdditionalLocationOffset + } - if opts.DisableTime { - l.timeFormat = "" - } else if opts.TimeFormat != "" { + if l.json { + l.timeFormat = TimeFormatJSON + } + if opts.TimeFn != nil { + l.timeFn = opts.TimeFn + } + if opts.TimeFormat != "" { l.timeFormat = opts.TimeFormat } + if l.subloggerHook == nil { + l.subloggerHook = identityHook + } + + l.setColorization(opts) + atomic.StoreInt32(l.level, int32(level)) return l } +func identityHook(logger Logger) Logger { + return logger +} + +// offsetIntLogger is the stack frame offset in the call stack for the caller to +// one of the Warn, Info, Log, etc methods. +const offsetIntLogger = 3 + // Log a message and a set of key/value pairs if the given level is at // or more severe that the threshold configured in the Logger. func (l *intLogger) log(name string, level Level, msg string, args ...interface{}) { - if level < Level(atomic.LoadInt32(l.level)) { + if level < l.GetLevel() { return } - t := time.Now() + t := l.timeFn() l.mutex.Lock() defer l.mutex.Unlock() @@ -178,34 +277,56 @@ func trimCallerPath(path string) string { return path[idx+1:] } -var logImplFile = regexp.MustCompile(`.+intlogger.go|.+interceptlogger.go$`) +// isNormal indicates if the rune is one allowed to exist as an unquoted +// string value. This is a subset of ASCII, `-` through `~`. +func isNormal(r rune) bool { + return 0x2D <= r && r <= 0x7E // - through ~ +} -// Non-JSON logging format function +// needsQuoting returns false if all the runes in string are normal, according +// to isNormal +func needsQuoting(str string) bool { + for _, r := range str { + if !isNormal(r) { + return true + } + } + + return false +} + +// logPlain is the non-JSON logging format function which writes directly +// to the underlying writer the logger was initialized with. +// +// If the logger was initialized with a color function, it also handles +// applying the color to the log message. +// +// Color Options +// 1. No color. +// 2. Color the whole log line, based on the level. +// 3. Color only the header (level) part of the log line. +// 4. Color both the header and fields of the log line. func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, args ...interface{}) { - if len(l.timeFormat) > 0 { + + if !l.disableTime { l.writer.WriteString(t.Format(l.timeFormat)) l.writer.WriteByte(' ') } s, ok := _levelToBracket[level] if ok { - l.writer.WriteString(s) + if l.headerColor != ColorOff { + color := _levelToColor[level] + color.Fprint(l.writer, s) + } else { + l.writer.WriteString(s) + } } else { l.writer.WriteString("[?????]") } - offset := 3 - if l.caller { - // Check if the caller is inside our package and inside - // a logger implementation file - if _, file, _, ok := runtime.Caller(3); ok { - match := logImplFile.MatchString(file) - if match { - offset = 4 - } - } - - if _, file, line, ok := runtime.Caller(offset); ok { + if l.callerOffset > 0 { + if _, file, line, ok := runtime.Caller(l.callerOffset); ok { l.writer.WriteByte(' ') l.writer.WriteString(trimCallerPath(file)) l.writer.WriteByte(':') @@ -218,16 +339,19 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, if name != "" { l.writer.WriteString(name) - l.writer.WriteString(": ") + if msg != "" { + l.writer.WriteString(": ") + l.writer.WriteString(msg) + } + } else if msg != "" { + l.writer.WriteString(msg) } - l.writer.WriteString(msg) - args = append(l.implied, args...) var stacktrace CapturedStacktrace - if args != nil && len(args) > 0 { + if len(args) > 0 { if len(args)%2 != 0 { cs, ok := args[len(args)-1].(CapturedStacktrace) if ok { @@ -241,16 +365,23 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, l.writer.WriteByte(':') + // Handle the field arguments, which come in pairs (key=val). FOR: for i := 0; i < len(args); i = i + 2 { var ( + key string val string raw bool ) + // Convert the field value to a string. switch st := args[i+1].(type) { case string: val = st + if st == "" { + val = `""` + raw = true + } case int: val = strconv.FormatInt(int64(st), 10) case int64: @@ -282,6 +413,9 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, continue FOR case Format: val = fmt.Sprintf(st[0].(string), st[1:]...) + case Quote: + raw = true + val = strconv.Quote(string(st)) default: v := reflect.ValueOf(st) if v.Kind() == reflect.Slice { @@ -292,20 +426,57 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, } } - l.writer.WriteByte(' ') + // Convert the field key to a string. switch st := args[i].(type) { case string: - l.writer.WriteString(st) + key = st default: - l.writer.WriteString(fmt.Sprintf("%s", st)) + key = fmt.Sprintf("%s", st) + } + + // Optionally apply the ANSI "faint" and "bold" + // SGR values to the key. + if l.fieldColor != ColorOff { + key = faintBoldColor.Sprint(key) } - l.writer.WriteByte('=') - if !raw && strings.ContainsAny(val, " \t\n\r") { + // Values may contain multiple lines, and that format + // is preserved, with each line prefixed with a " | " + // to show it's part of a collection of lines. + // + // Values may also need quoting, if not all the runes + // in the value string are "normal", like if they + // contain ANSI escape sequences. + if strings.Contains(val, "\n") { + l.writer.WriteString("\n ") + l.writer.WriteString(key) + if l.fieldColor != ColorOff { + l.writer.WriteString(faintFieldSeparatorWithNewLine) + writeIndent(l.writer, val, faintMultiLinePrefix) + } else { + l.writer.WriteString("=\n") + writeIndent(l.writer, val, " | ") + } + l.writer.WriteString(" ") + } else if !raw && needsQuoting(val) { + l.writer.WriteByte(' ') + l.writer.WriteString(key) + if l.fieldColor != ColorOff { + l.writer.WriteString(faintFieldSeparator) + } else { + l.writer.WriteByte('=') + } l.writer.WriteByte('"') - l.writer.WriteString(val) + writeEscapedForOutput(l.writer, val, true) l.writer.WriteByte('"') } else { + l.writer.WriteByte(' ') + l.writer.WriteString(key) + if l.fieldColor != ColorOff { + l.writer.WriteString(faintFieldSeparator) + } else { + l.writer.WriteByte('=') + } l.writer.WriteString(val) } } @@ -315,9 +486,108 @@ func (l *intLogger) logPlain(t time.Time, name string, level Level, msg string, if stacktrace != "" { l.writer.WriteString(string(stacktrace)) + l.writer.WriteString("\n") + } +} + +func writeIndent(w *writer, str string, indent string) { + for { + nl := strings.IndexByte(str, "\n"[0]) + if nl == -1 { + if str != "" { + w.WriteString(indent) + writeEscapedForOutput(w, str, false) + w.WriteString("\n") + } + return + } + + w.WriteString(indent) + writeEscapedForOutput(w, str[:nl], false) + w.WriteString("\n") + str = str[nl+1:] } } +func needsEscaping(str string) bool { + for _, b := range str { + if !unicode.IsPrint(b) || b == '"' { + return true + } + } + + return false +} + +const ( + lowerhex = "0123456789abcdef" +) + +var bufPool = sync.Pool{ + New: func() interface{} { + return new(bytes.Buffer) + }, +} + +func writeEscapedForOutput(w io.Writer, str string, escapeQuotes bool) { + if !needsEscaping(str) { + w.Write([]byte(str)) + return + } + + bb := bufPool.Get().(*bytes.Buffer) + bb.Reset() + + defer bufPool.Put(bb) + + for _, r := range str { + if escapeQuotes && r == '"' { + bb.WriteString(`\"`) + } else if unicode.IsPrint(r) { + bb.WriteRune(r) + } else { + switch r { + case '\a': + bb.WriteString(`\a`) + case '\b': + bb.WriteString(`\b`) + case '\f': + bb.WriteString(`\f`) + case '\n': + bb.WriteString(`\n`) + case '\r': + bb.WriteString(`\r`) + case '\t': + bb.WriteString(`\t`) + case '\v': + bb.WriteString(`\v`) + default: + switch { + case r < ' ': + bb.WriteString(`\x`) + bb.WriteByte(lowerhex[byte(r)>>4]) + bb.WriteByte(lowerhex[byte(r)&0xF]) + case !utf8.ValidRune(r): + r = 0xFFFD + fallthrough + case r < 0x10000: + bb.WriteString(`\u`) + for s := 12; s >= 0; s -= 4 { + bb.WriteByte(lowerhex[r>>uint(s)&0xF]) + } + default: + bb.WriteString(`\U`) + for s := 28; s >= 0; s -= 4 { + bb.WriteByte(lowerhex[r>>uint(s)&0xF]) + } + } + } + } + } + + w.Write(bb.Bytes()) +} + func (l *intLogger) renderSlice(v reflect.Value) string { var buf bytes.Buffer @@ -334,22 +604,19 @@ func (l *intLogger) renderSlice(v reflect.Value) string { switch sv.Kind() { case reflect.String: - val = sv.String() + val = strconv.Quote(sv.String()) case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: val = strconv.FormatInt(sv.Int(), 10) case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: val = strconv.FormatUint(sv.Uint(), 10) default: val = fmt.Sprintf("%v", sv.Interface()) + if strings.ContainsAny(val, " \t\n\r") { + val = strconv.Quote(val) + } } - if strings.ContainsAny(val, " \t\n\r") { - buf.WriteByte('"') - buf.WriteString(val) - buf.WriteByte('"') - } else { - buf.WriteString(val) - } + buf.WriteString(val) } buf.WriteRune(']') @@ -362,7 +629,7 @@ func (l *intLogger) logJSON(t time.Time, name string, level Level, msg string, a vals := l.jsonMapEntry(t, name, level, msg) args = append(l.implied, args...) - if args != nil && len(args) > 0 { + if len(args) > 0 { if len(args)%2 != 0 { cs, ok := args[len(args)-1].(CapturedStacktrace) if ok { @@ -402,21 +669,27 @@ func (l *intLogger) logJSON(t time.Time, name string, level Level, msg string, a } } - err := json.NewEncoder(l.writer).Encode(vals) + encoder := json.NewEncoder(l.writer) + encoder.SetEscapeHTML(l.jsonEscapeEnabled) + err := encoder.Encode(vals) if err != nil { if _, ok := err.(*json.UnsupportedTypeError); ok { plainVal := l.jsonMapEntry(t, name, level, msg) plainVal["@warn"] = errJsonUnsupportedTypeMsg - json.NewEncoder(l.writer).Encode(plainVal) + errEncoder := json.NewEncoder(l.writer) + errEncoder.SetEscapeHTML(l.jsonEscapeEnabled) + errEncoder.Encode(plainVal) } } } func (l intLogger) jsonMapEntry(t time.Time, name string, level Level, msg string) map[string]interface{} { vals := map[string]interface{}{ - "@message": msg, - "@timestamp": t.Format("2006-01-02T15:04:05.000000Z07:00"), + "@message": msg, + } + if !l.disableTime { + vals["@timestamp"] = t.Format(l.timeFormat) } var levelStr string @@ -441,8 +714,8 @@ func (l intLogger) jsonMapEntry(t time.Time, name string, level Level, msg strin vals["@module"] = name } - if l.caller { - if _, file, line, ok := runtime.Caller(4); ok { + if l.callerOffset > 0 { + if _, file, line, ok := runtime.Caller(l.callerOffset + 1); ok { vals["@caller"] = fmt.Sprintf("%s:%d", file, line) } } @@ -481,27 +754,27 @@ func (l *intLogger) Error(msg string, args ...interface{}) { // Indicate that the logger would emit TRACE level logs func (l *intLogger) IsTrace() bool { - return Level(atomic.LoadInt32(l.level)) == Trace + return l.GetLevel() == Trace } // Indicate that the logger would emit DEBUG level logs func (l *intLogger) IsDebug() bool { - return Level(atomic.LoadInt32(l.level)) <= Debug + return l.GetLevel() <= Debug } // Indicate that the logger would emit INFO level logs func (l *intLogger) IsInfo() bool { - return Level(atomic.LoadInt32(l.level)) <= Info + return l.GetLevel() <= Info } // Indicate that the logger would emit WARN level logs func (l *intLogger) IsWarn() bool { - return Level(atomic.LoadInt32(l.level)) <= Warn + return l.GetLevel() <= Warn } // Indicate that the logger would emit ERROR level logs func (l *intLogger) IsError() bool { - return Level(atomic.LoadInt32(l.level)) <= Error + return l.GetLevel() <= Error } const MissingKey = "EXTRA_VALUE_AT_END" @@ -517,7 +790,7 @@ func (l *intLogger) With(args ...interface{}) Logger { args = args[:len(args)-1] } - sl := *l + sl := l.copy() result := make(map[string]interface{}, len(l.implied)+len(args)) keys := make([]string, 0, len(l.implied)+len(args)) @@ -551,13 +824,13 @@ func (l *intLogger) With(args ...interface{}) Logger { sl.implied = append(sl.implied, MissingKey, extra) } - return &sl + return l.subloggerHook(sl) } // Create a new sub-Logger that a name decending from the current name. // This is used to create a subsystem specific Logger. func (l *intLogger) Named(name string) Logger { - sl := *l + sl := l.copy() if sl.name != "" { sl.name = sl.name + "." + name @@ -565,18 +838,18 @@ func (l *intLogger) Named(name string) Logger { sl.name = name } - return &sl + return l.subloggerHook(sl) } // Create a new sub-Logger with an explicit name. This ignores the current // name. This is used to create a standalone logger that doesn't fall // within the normal hierarchy. func (l *intLogger) ResetNamed(name string) Logger { - sl := *l + sl := l.copy() sl.name = name - return &sl + return l.subloggerHook(sl) } func (l *intLogger) ResetOutput(opts *LoggerOptions) error { @@ -617,7 +890,63 @@ func (l *intLogger) resetOutput(opts *LoggerOptions) error { // Update the logging level on-the-fly. This will affect all subloggers as // well. func (l *intLogger) SetLevel(level Level) { - atomic.StoreInt32(l.level, int32(level)) + if !l.syncParentLevel { + atomic.StoreInt32(l.level, int32(level)) + return + } + + nsl := new(int32) + *nsl = int32(level) + + l.level = nsl + + l.ownEpoch = atomic.AddUint64(l.curEpoch, 1) + l.setEpoch = l.ownEpoch +} + +func (l *intLogger) searchLevelPtr() *int32 { + p := l.parent + + ptr := l.level + + max := l.setEpoch + + for p != nil { + if p.setEpoch > max { + max = p.setEpoch + ptr = p.level + } + + p = p.parent + } + + return ptr +} + +// Returns the current level +func (l *intLogger) GetLevel() Level { + // We perform the loads immediately to keep the CPU pipeline busy, which + // effectively makes the second load cost nothing. Once loaded into registers + // the comparison returns the already loaded value. The comparison is almost + // always true, so the branch predictor should hit consistently with it. + var ( + curEpoch = atomic.LoadUint64(l.curEpoch) + level = Level(atomic.LoadInt32(l.level)) + own = l.ownEpoch + ) + + if curEpoch == own { + return level + } + + // Perform the level sync process. We'll avoid doing this next time by seeing the + // epoch as current. + + ptr := l.searchLevelPtr() + l.level = ptr + l.ownEpoch = curEpoch + + return Level(atomic.LoadInt32(ptr)) } // Create a *log.Logger that will send it's data through this Logger. This @@ -632,21 +961,19 @@ func (l *intLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger { } func (l *intLogger) StandardWriter(opts *StandardLoggerOptions) io.Writer { - return &stdlogAdapter{ - log: l, - inferLevels: opts.InferLevels, - forceLevel: opts.ForceLevel, + newLog := *l + if l.callerOffset > 0 { + // the stack is + // logger.printf() -> l.Output() ->l.out.writer(hclog:stdlogAdaptor.write) -> hclog:stdlogAdaptor.dispatch() + // So plus 4. + newLog.callerOffset = l.callerOffset + 4 } -} - -// checks if the underlying io.Writer is a file, and -// panics if not. For use by colorization. -func (l *intLogger) checkWriterIsFile() *os.File { - fi, ok := l.writer.w.(*os.File) - if !ok { - panic("Cannot enable coloring of non-file Writers") + return &stdlogAdapter{ + log: &newLog, + inferLevels: opts.InferLevels, + inferLevelsWithTimestamp: opts.InferLevelsWithTimestamp, + forceLevel: opts.ForceLevel, } - return fi } // Accept implements the SinkAdapter interface @@ -663,3 +990,18 @@ func (i *intLogger) ImpliedArgs() []interface{} { func (i *intLogger) Name() string { return i.name } + +// copy returns a shallow copy of the intLogger, replacing the level pointer +// when necessary +func (l *intLogger) copy() *intLogger { + sl := *l + + if l.independentLevels { + sl.level = new(int32) + *sl.level = *l.level + } else if l.syncParentLevel { + sl.parent = l + } + + return &sl +} diff --git a/vendor/github.com/hashicorp/go-hclog/logger.go b/vendor/github.com/hashicorp/go-hclog/logger.go index 8d5eed76e..ad17544f5 100644 --- a/vendor/github.com/hashicorp/go-hclog/logger.go +++ b/vendor/github.com/hashicorp/go-hclog/logger.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + package hclog import ( @@ -5,10 +8,11 @@ import ( "log" "os" "strings" + "time" ) var ( - //DefaultOutput is used as the default log output. + // DefaultOutput is used as the default log output. DefaultOutput io.Writer = os.Stderr // DefaultLevel is used as the default log level. @@ -27,7 +31,7 @@ const ( // of actions in code, such as function enters/exits, etc. Trace Level = 1 - // Debug information for programmer lowlevel analysis. + // Debug information for programmer low-level analysis. Debug Level = 2 // Info information about steady state operations. @@ -38,15 +42,18 @@ const ( // Error information about unrecoverable events. Error Level = 5 + + // Off disables all logging output. + Off Level = 6 ) -// Format is a simple convience type for when formatting is required. When +// Format is a simple convenience type for when formatting is required. When // processing a value of this type, the logger automatically treats the first // argument as a Printf formatting string and passes the rest as the values // to be formatted. For example: L.Info(Fmt{"%d beans/day", beans}). type Format []interface{} -// Fmt returns a Format type. This is a convience function for creating a Format +// Fmt returns a Format type. This is a convenience function for creating a Format // type. func Fmt(str string, args ...interface{}) Format { return append(Format{str}, args...) @@ -64,6 +71,12 @@ type Octal int // text output. For example: L.Info("bits", Binary(17)) type Binary int +// A simple shortcut to format strings with Go quoting. Control and +// non-printable characters will be escaped with their backslash equivalents in +// output. Intended for untrusted or multiline strings which should be logged +// as concisely as possible. +type Quote string + // ColorOption expresses how the output should be colored, if at all. type ColorOption uint8 @@ -79,6 +92,13 @@ const ( ForceColor ) +// SupportsColor is an optional interface that can be implemented by the output +// value. If implemented and SupportsColor() returns true, then AutoColor will +// enable colorization. +type SupportsColor interface { + SupportsColor() bool +} + // LevelFromString returns a Level type for the named log level, or "NoLevel" if // the level string is invalid. This facilitates setting the log level via // config or environment variable by name in a predictable way. @@ -96,6 +116,8 @@ func LevelFromString(levelStr string) Level { return Warn case "error": return Error + case "off": + return Off default: return NoLevel } @@ -115,12 +137,14 @@ func (l Level) String() string { return "error" case NoLevel: return "none" + case Off: + return "off" default: return "unknown" } } -// Logger describes the interface that must be implemeted by all loggers. +// Logger describes the interface that must be implemented by all loggers. type Logger interface { // Args are alternating key, val pairs // keys must be strings @@ -179,10 +203,14 @@ type Logger interface { // the current name as well. ResetNamed(name string) Logger - // Updates the level. This should affect all sub-loggers as well. If an + // Updates the level. This should affect all related loggers as well, + // unless they were created with IndependentLevels. If an // implementation cannot update the level on the fly, it should no-op. SetLevel(level Level) + // Returns the current level + GetLevel() Level + // Return a value that conforms to the stdlib log.Logger interface StandardLogger(opts *StandardLoggerOptions) *log.Logger @@ -198,6 +226,16 @@ type StandardLoggerOptions struct { // [DEBUG] and strip it off before reapplying it. InferLevels bool + // Indicate that some minimal parsing should be done on strings to try + // and detect their level and re-emit them while ignoring possible + // timestamp values in the beginning of the string. + // This supports the strings like [ERROR], [ERR] [TRACE], [WARN], [INFO], + // [DEBUG] and strip it off before reapplying it. + // The timestamp detection may result in false positives and incomplete + // string outputs. + // InferLevelsWithTimestamp is only relevant if InferLevels is true. + InferLevelsWithTimestamp bool + // ForceLevel is used to force all output from the standard logger to be at // the specified level. Similar to InferLevels, this will strip any level // prefix contained in the logged string before applying the forced level. @@ -205,12 +243,14 @@ type StandardLoggerOptions struct { ForceLevel Level } +type TimeFunction = func() time.Time + // LoggerOptions can be used to configure a new logger. type LoggerOptions struct { // Name of the subsystem to prefix logs with Name string - // The threshold for the logger. Anything less severe is supressed + // The threshold for the logger. Anything less severe is suppressed Level Level // Where to write the logs to. Defaults to os.Stderr if nil @@ -224,25 +264,73 @@ type LoggerOptions struct { // Control if the output should be in JSON. JSONFormat bool + // Control the escape switch of json.Encoder + JSONEscapeDisabled bool + // Include file and line information in each log line IncludeLocation bool + // AdditionalLocationOffset is the number of additional stack levels to skip + // when finding the file and line information for the log line + AdditionalLocationOffset int + // The time format to use instead of the default TimeFormat string + // A function which is called to get the time object that is formatted using `TimeFormat` + TimeFn TimeFunction + // Control whether or not to display the time at all. This is required // because setting TimeFormat to empty assumes the default format. DisableTime bool - // Color the output. On Windows, colored logs are only avaiable for io.Writers that + // Color the output. On Windows, colored logs are only available for io.Writers that // are concretely instances of *os.File. Color ColorOption + // Only color the header, not the body. This can help with readability of long messages. + ColorHeaderOnly bool + + // Color the header and message body fields. This can help with readability + // of long messages with multiple fields. + ColorHeaderAndFields bool + // A function which is called with the log information and if it returns true the value // should not be logged. // This is useful when interacting with a system that you wish to suppress the log // message for (because it's too noisy, etc) Exclude func(level Level, msg string, args ...interface{}) bool + + // IndependentLevels causes subloggers to be created with an independent + // copy of this logger's level. This means that using SetLevel on this + // logger will not affect any subloggers, and SetLevel on any subloggers + // will not affect the parent or sibling loggers. + IndependentLevels bool + + // When set, changing the level of a logger effects only it's direct sub-loggers + // rather than all sub-loggers. For example: + // a := logger.Named("a") + // a.SetLevel(Error) + // b := a.Named("b") + // c := a.Named("c") + // b.GetLevel() => Error + // c.GetLevel() => Error + // b.SetLevel(Info) + // a.GetLevel() => Error + // b.GetLevel() => Info + // c.GetLevel() => Error + // a.SetLevel(Warn) + // a.GetLevel() => Warn + // b.GetLevel() => Warn + // c.GetLevel() => Warn + SyncParentLevel bool + + // SubloggerHook registers a function that is called when a sublogger via + // Named, With, or ResetNamed is created. If defined, the function is passed + // the newly created Logger and the returned Logger is returned from the + // original function. This option allows customization via interception and + // wrapping of Logger instances. + SubloggerHook func(sub Logger) Logger } // InterceptLogger describes the interface for using a logger @@ -271,10 +359,10 @@ type InterceptLogger interface { // the current name as well. ResetNamedIntercept(name string) InterceptLogger - // Return a value that conforms to the stdlib log.Logger interface + // Deprecated: use StandardLogger StandardLoggerIntercept(opts *StandardLoggerOptions) *log.Logger - // Return a value that conforms to io.Writer, which can be passed into log.SetOutput() + // Deprecated: use StandardWriter StandardWriterIntercept(opts *StandardLoggerOptions) io.Writer } diff --git a/vendor/github.com/hashicorp/go-hclog/nulllogger.go b/vendor/github.com/hashicorp/go-hclog/nulllogger.go index bc14f7708..d43da809e 100644 --- a/vendor/github.com/hashicorp/go-hclog/nulllogger.go +++ b/vendor/github.com/hashicorp/go-hclog/nulllogger.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + package hclog import ( @@ -49,6 +52,8 @@ func (l *nullLogger) ResetNamed(name string) Logger { return l } func (l *nullLogger) SetLevel(level Level) {} +func (l *nullLogger) GetLevel() Level { return NoLevel } + func (l *nullLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger { return log.New(l.StandardWriter(opts), "", log.LstdFlags) } diff --git a/vendor/github.com/hashicorp/go-hclog/stdlog.go b/vendor/github.com/hashicorp/go-hclog/stdlog.go index f35d875d3..03739b61f 100644 --- a/vendor/github.com/hashicorp/go-hclog/stdlog.go +++ b/vendor/github.com/hashicorp/go-hclog/stdlog.go @@ -1,18 +1,27 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + package hclog import ( "bytes" "log" + "regexp" "strings" ) +// Regex to ignore characters commonly found in timestamp formats from the +// beginning of inputs. +var logTimestampRegexp = regexp.MustCompile(`^[\d\s\:\/\.\+-TZ]*`) + // Provides a io.Writer to shim the data out of *log.Logger // and back into our Logger. This is basically the only way to // build upon *log.Logger. type stdlogAdapter struct { - log Logger - inferLevels bool - forceLevel Level + log Logger + inferLevels bool + inferLevelsWithTimestamp bool + forceLevel Level } // Take the data, infer the levels if configured, and send it through @@ -28,6 +37,10 @@ func (s *stdlogAdapter) Write(data []byte) (int, error) { // Log at the forced level s.dispatch(str, s.forceLevel) } else if s.inferLevels { + if s.inferLevelsWithTimestamp { + str = s.trimTimestamp(str) + } + level, str := s.pickLevel(str) s.dispatch(str, level) } else { @@ -64,7 +77,7 @@ func (s *stdlogAdapter) pickLevel(str string) (Level, string) { case strings.HasPrefix(str, "[INFO]"): return Info, strings.TrimSpace(str[6:]) case strings.HasPrefix(str, "[WARN]"): - return Warn, strings.TrimSpace(str[7:]) + return Warn, strings.TrimSpace(str[6:]) case strings.HasPrefix(str, "[ERROR]"): return Error, strings.TrimSpace(str[7:]) case strings.HasPrefix(str, "[ERR]"): @@ -74,6 +87,11 @@ func (s *stdlogAdapter) pickLevel(str string) (Level, string) { } } +func (s *stdlogAdapter) trimTimestamp(str string) string { + idx := logTimestampRegexp.FindStringIndex(str) + return str[idx[1]:] +} + type logWriter struct { l *log.Logger } diff --git a/vendor/github.com/hashicorp/go-hclog/writer.go b/vendor/github.com/hashicorp/go-hclog/writer.go index 421a1f06c..4ee219bf0 100644 --- a/vendor/github.com/hashicorp/go-hclog/writer.go +++ b/vendor/github.com/hashicorp/go-hclog/writer.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MIT + package hclog import ( diff --git a/vendor/github.com/hashicorp/go-plugin/.go-version b/vendor/github.com/hashicorp/go-plugin/.go-version new file mode 100644 index 000000000..f9e8384bb --- /dev/null +++ b/vendor/github.com/hashicorp/go-plugin/.go-version @@ -0,0 +1 @@ +1.24.1 diff --git a/vendor/github.com/hashicorp/go-plugin/CHANGELOG.md b/vendor/github.com/hashicorp/go-plugin/CHANGELOG.md index 3d0379c50..14703c6e7 100644 --- a/vendor/github.com/hashicorp/go-plugin/CHANGELOG.md +++ b/vendor/github.com/hashicorp/go-plugin/CHANGELOG.md @@ -1,9 +1,39 @@ +## v1.7.0 + +CHANGES: + +* When go-plugin encounters a stack trace on the server stderr stream, it now raises output to a log-level of Error instead of Debug. [[GH-292](https://github.com/hashicorp/go-plugin/pull/292)] + +ENHANCEMENTS: + +* Don't spend resources parsing log lines when logging is disabled [[GH-352](https://github.com/hashicorp/go-plugin/pull/352)] + +## v1.6.2 + +ENHANCEMENTS: + +* Added support for gRPC dial options to the `Dial` API [[GH-257](https://github.com/hashicorp/go-plugin/pull/257)] + +BUGS: + +* Fixed a bug where reattaching to a plugin that exits could kill an unrelated process [[GH-320](https://github.com/hashicorp/go-plugin/pull/320)] + +## v1.6.1 + +BUGS: + +* Suppress spurious `os.ErrClosed` on plugin shutdown [[GH-299](https://github.com/hashicorp/go-plugin/pull/299)] + +ENHANCEMENTS: + +* deps: bump google.golang.org/grpc to v1.58.3 [[GH-296](https://github.com/hashicorp/go-plugin/pull/296)] + ## v1.6.0 CHANGES: * plugin: Plugins written in other languages can optionally start to advertise whether they support gRPC broker multiplexing. - If the environment variable `PLUGIN_MULTIPLEX_GRPC` is set, it is safe to include a seventh field containing a boolean + If the environment variable `PLUGIN_MULTIPLEX_GRPC` is set, it is safe to include a seventh field containing a boolean value in the `|`-separated protocol negotiation line. ENHANCEMENTS: diff --git a/vendor/github.com/hashicorp/go-plugin/client.go b/vendor/github.com/hashicorp/go-plugin/client.go index 73f6b3515..1f14db99f 100644 --- a/vendor/github.com/hashicorp/go-plugin/client.go +++ b/vendor/github.com/hashicorp/go-plugin/client.go @@ -14,7 +14,6 @@ import ( "fmt" "hash" "io" - "io/ioutil" "net" "os" "os/exec" @@ -82,7 +81,7 @@ const defaultPluginLogBufferSize = 64 * 1024 // // Plugin hosts should use one Client for each plugin executable. To // dispense a plugin type, use the `Client.Client` function, and then -// cal `Dispense`. This awkward API is mostly historical but is used to split +// call `Dispense`. This awkward API is mostly historical but is used to split // the client that deals with subprocess management and the client that // does RPC management. // @@ -104,9 +103,9 @@ type Client struct { // goroutines. clientWaitGroup sync.WaitGroup - // stderrWaitGroup is used to prevent the command's Wait() function from - // being called before we've finished reading from the stderr pipe. - stderrWaitGroup sync.WaitGroup + // pipesWaitGroup is used to prevent the command's Wait() function from + // being called before we've finished reading from the stdout and stderr pipe. + pipesWaitGroup sync.WaitGroup // processKilled is used for testing only, to flag when the process was // forcefully killed. @@ -202,7 +201,7 @@ type ClientConfig struct { // SyncStdout, SyncStderr can be set to override the // respective os.Std* values in the plugin. Care should be taken to // avoid races here. If these are nil, then this will be set to - // ioutil.Discard. + // io.Discard. SyncStdout io.Writer SyncStderr io.Writer @@ -345,7 +344,7 @@ func (s *SecureConfig) Check(filePath string) (bool, error) { if err != nil { return false, err } - defer file.Close() + defer func() { _ = file.Close() }() _, err = io.Copy(s.Hash, file) if err != nil { @@ -401,7 +400,7 @@ func NewClient(config *ClientConfig) (c *Client) { } if config.Stderr == nil { - config.Stderr = ioutil.Discard + config.Stderr = io.Discard } if config.SyncStdout == nil { @@ -514,7 +513,7 @@ func (c *Client) Kill() { c.clientWaitGroup.Wait() if hostSocketDir != "" { - os.RemoveAll(hostSocketDir) + _ = os.RemoveAll(hostSocketDir) } // Make sure there is no reference to the old process after it has been @@ -743,7 +742,7 @@ func (c *Client) Start() (addr net.Addr, err error) { rErr := recover() if err != nil || rErr != nil { - runner.Kill(context.Background()) + _ = runner.Kill(context.Background()) } if rErr != nil { @@ -756,8 +755,8 @@ func (c *Client) Start() (addr net.Addr, err error) { // Start goroutine that logs the stderr c.clientWaitGroup.Add(1) - c.stderrWaitGroup.Add(1) - // logStderr calls Done() + c.pipesWaitGroup.Add(1) + // logStderr calls c.pipesWaitGroup.Done() go c.logStderr(runner.Name(), runner.Stderr()) c.clientWaitGroup.Add(1) @@ -767,9 +766,9 @@ func (c *Client) Start() (addr net.Addr, err error) { defer c.clientWaitGroup.Done() - // wait to finish reading from stderr since the stderr pipe reader + // wait to finish reading from stdout/stderr since the stdout/stderr pipe readers // will be closed by the subsequent call to cmd.Wait(). - c.stderrWaitGroup.Wait() + c.pipesWaitGroup.Wait() // Wait for the command to end. err := runner.Wait(context.Background()) @@ -780,7 +779,7 @@ func (c *Client) Start() (addr net.Addr, err error) { c.logger.Info("plugin process exited", "plugin", runner.Name(), "id", runner.ID()) } - os.Stderr.Sync() + _ = os.Stderr.Sync() // Set that we exited, which takes a lock c.l.Lock() @@ -792,8 +791,10 @@ func (c *Client) Start() (addr net.Addr, err error) { // out of stdout linesCh := make(chan string) c.clientWaitGroup.Add(1) + c.pipesWaitGroup.Add(1) go func() { defer c.clientWaitGroup.Done() + defer c.pipesWaitGroup.Done() defer close(linesCh) scanner := bufio.NewScanner(runner.Stdout()) @@ -851,15 +852,15 @@ func (c *Client) Start() (addr net.Addr, err error) { var coreProtocol int coreProtocol, err = strconv.Atoi(parts[0]) if err != nil { - err = fmt.Errorf("Error parsing core protocol version: %s", err) + err = fmt.Errorf("error parsing core protocol version: %s", err) return } if coreProtocol != CoreProtocolVersion { - err = fmt.Errorf("Incompatible core API version with plugin. "+ + err = fmt.Errorf("incompatible core API version with plugin. "+ "Plugin version: %s, Core version: %d\n\n"+ "To fix this, the plugin usually only needs to be recompiled.\n"+ - "Please report this to the plugin author.", parts[0], CoreProtocolVersion) + "Please report this to the plugin author", parts[0], CoreProtocolVersion) return } } @@ -885,10 +886,16 @@ func (c *Client) Start() (addr net.Addr, err error) { switch network { case "tcp": addr, err = net.ResolveTCPAddr("tcp", address) + if err != nil { + return nil, err + } case "unix": addr, err = net.ResolveUnixAddr("unix", address) + if err != nil { + return nil, err + } default: - err = fmt.Errorf("Unknown address type: %s", address) + return nil, fmt.Errorf("unknown address type: %s", address) } // If we have a server type, then record that. We default to net/rpc @@ -906,7 +913,7 @@ func (c *Client) Start() (addr net.Addr, err error) { } } if !found { - err = fmt.Errorf("Unsupported plugin protocol %q. Supported: %v", + err = fmt.Errorf("unsupported plugin protocol %q. Supported: %v", c.protocol, c.config.AllowedProtocols) return addr, err } @@ -984,7 +991,7 @@ func (c *Client) reattach() (net.Addr, error) { defer c.ctxCancel() // Wait for the process to die - r.Wait(context.Background()) + _ = r.Wait(context.Background()) // Log so we can see it c.logger.Debug("reattached plugin process exited") @@ -1039,7 +1046,7 @@ func (c *Client) checkProtoVersion(protoVersion string) (int, PluginSet, error) return version, plugins, nil } - return 0, nil, fmt.Errorf("Incompatible API version with plugin. "+ + return 0, nil, fmt.Errorf("incompatible API version with plugin. "+ "Plugin version: %d, Client versions: %d", serverVersion, clientVersions) } @@ -1095,8 +1102,8 @@ func (c *Client) Protocol() Protocol { return c.protocol } -func netAddrDialer(addr net.Addr) func(string, time.Duration) (net.Conn, error) { - return func(_ string, _ time.Duration) (net.Conn, error) { +func netAddrDialer(addr net.Addr) func(context.Context, string) (net.Conn, error) { + return func(context.Context, string) (net.Conn, error) { // Connect to the client conn, err := net.Dial(addr.Network(), addr.String()) if err != nil { @@ -1104,7 +1111,7 @@ func netAddrDialer(addr net.Addr) func(string, time.Duration) (net.Conn, error) } if tcpConn, ok := conn.(*net.TCPConn); ok { // Make sure to set keep alive so that the connection doesn't die - tcpConn.SetKeepAlive(true) + _ = tcpConn.SetKeepAlive(true) } return conn, nil @@ -1113,7 +1120,7 @@ func netAddrDialer(addr net.Addr) func(string, time.Duration) (net.Conn, error) // dialer is compatible with grpc.WithDialer and creates the connection // to the plugin. -func (c *Client) dialer(_ string, timeout time.Duration) (net.Conn, error) { +func (c *Client) dialer(ctx context.Context, _ string) (net.Conn, error) { muxer, err := c.getGRPCMuxer(c.address) if err != nil { return nil, err @@ -1126,7 +1133,7 @@ func (c *Client) dialer(_ string, timeout time.Duration) (net.Conn, error) { return nil, err } } else { - conn, err = netAddrDialer(c.address)("", timeout) + conn, err = netAddrDialer(c.address)(ctx, "") if err != nil { return nil, err } @@ -1159,14 +1166,22 @@ func (c *Client) getGRPCMuxer(addr net.Addr) (*grpcmux.GRPCClientMuxer, error) { func (c *Client) logStderr(name string, r io.Reader) { defer c.clientWaitGroup.Done() - defer c.stderrWaitGroup.Done() + defer c.pipesWaitGroup.Done() + l := c.logger.Named(filepath.Base(name)) + loggerLevel := l.GetLevel() + loggerDisabled := loggerLevel == hclog.Off reader := bufio.NewReaderSize(r, c.config.PluginLogBufferSize) // continuation indicates the previous line was a prefix continuation := false + // inPanic indicates we saw the start of a stack trace and should divert all + // remaining untagged lines to stderr + var inPanic bool + for { + line, isPrefix, err := reader.ReadLine() switch { case err == io.EOF: @@ -1176,7 +1191,7 @@ func (c *Client) logStderr(name string, r io.Reader) { return } - c.config.Stderr.Write(line) + _, _ = c.config.Stderr.Write(line) // The line was longer than our max token size, so it's likely // incomplete and won't unmarshal. @@ -1185,14 +1200,26 @@ func (c *Client) logStderr(name string, r io.Reader) { // if we're finishing a continued line, add the newline back in if !isPrefix { - c.config.Stderr.Write([]byte{'\n'}) + _, _ = c.config.Stderr.Write([]byte{'\n'}) } continuation = isPrefix continue } - c.config.Stderr.Write([]byte{'\n'}) + _, _ = c.config.Stderr.Write([]byte{'\n'}) + + // + // Any side-effects other than writing to the hclog logger must be + // above this point! + // + + if loggerDisabled { + // If the logger we'd be writing to is completely disabled then + // we can skip all of the parsing work to decide what log level + // we'd use to write this line. + continue + } entry, err := parseJSON(line) // If output is not JSON format, print directly to Debug @@ -1210,14 +1237,25 @@ func (c *Client) logStderr(name string, r io.Reader) { l.Warn(line) case strings.HasPrefix(line, "[ERROR]"): l.Error(line) + case strings.HasPrefix(line, "panic: ") || strings.HasPrefix(line, "fatal error: "): + inPanic = true + fallthrough + case inPanic: + l.Error(line) default: l.Debug(line) } } else { - out := flattenKVPairs(entry.KVPairs) + logLevel := hclog.LevelFromString(entry.Level) + if logLevel != hclog.NoLevel && logLevel < loggerLevel { + // The logger will ignore this log entry anyway, so we + // won't spend any more time preparing it. + continue + } + out := flattenKVPairs(entry.KVPairs) out = append(out, "timestamp", entry.Timestamp.Format(hclog.TimeFormat)) - switch hclog.LevelFromString(entry.Level) { + switch logLevel { case hclog.Trace: l.Trace(entry.Message, out...) case hclog.Debug: diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_broker.go b/vendor/github.com/hashicorp/go-plugin/grpc_broker.go index 5b17e37fe..bb4cd3edb 100644 --- a/vendor/github.com/hashicorp/go-plugin/grpc_broker.go +++ b/vendor/github.com/hashicorp/go-plugin/grpc_broker.go @@ -100,8 +100,6 @@ func (s *gRPCBrokerServer) StartStream(stream plugin.GRPCBroker_StartStreamServe case s.recv <- i: } } - - return nil } // Send is used by the GRPCBroker to pass connection information into the stream @@ -210,8 +208,6 @@ func (s *gRPCBrokerClientImpl) StartStream() error { case s.recv <- i: } } - - return nil } // Send is used by the GRPCBroker to pass connection information into the stream @@ -382,7 +378,7 @@ func (b *GRPCBroker) AcceptAndServe(id uint32, newGRPCServer func([]grpc.ServerO log.Printf("[ERR] plugin: plugin acceptAndServe error: %s", err) return } - defer ln.Close() + defer func() { _ = ln.Close() }() var opts []grpc.ServerOption if b.tls != nil { @@ -418,7 +414,7 @@ func (b *GRPCBroker) AcceptAndServe(id uint32, newGRPCServer func([]grpc.ServerO } // Block until we are done - g.Run() + _ = g.Run() } // Close closes the stream and all servers. @@ -502,8 +498,8 @@ func (b *GRPCBroker) knock(id uint32) error { return nil } -func (b *GRPCBroker) muxDial(id uint32) func(string, time.Duration) (net.Conn, error) { - return func(string, time.Duration) (net.Conn, error) { +func (b *GRPCBroker) muxDial(id uint32) func(context.Context, string) (net.Conn, error) { + return func(context.Context, string) (net.Conn, error) { b.dialMutex.Lock() defer b.dialMutex.Unlock() @@ -523,9 +519,12 @@ func (b *GRPCBroker) muxDial(id uint32) func(string, time.Duration) (net.Conn, e } // Dial opens a connection by ID. -func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) { +func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) { return b.DialWithOptions(id) } + +// Dial opens a connection by ID with options. +func (b *GRPCBroker) DialWithOptions(id uint32, opts ...grpc.DialOption) (conn *grpc.ClientConn, err error) { if b.muxer.Enabled() { - return dialGRPCConn(b.tls, b.muxDial(id)) + return dialGRPCConn(b.tls, b.muxDial(id), opts...) } var c *plugin.ConnInfo @@ -554,13 +553,13 @@ func (b *GRPCBroker) Dial(id uint32) (conn *grpc.ClientConn, err error) { case "unix": addr, err = net.ResolveUnixAddr("unix", address) default: - err = fmt.Errorf("Unknown address type: %s", c.Address) + err = fmt.Errorf("unknown address type: %s", c.Address) } if err != nil { return nil, err } - return dialGRPCConn(b.tls, netAddrDialer(addr)) + return dialGRPCConn(b.tls, netAddrDialer(addr), opts...) } // NextId returns a unique ID to use next. diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_client.go b/vendor/github.com/hashicorp/go-plugin/grpc_client.go index 627649d83..579212a1a 100644 --- a/vendor/github.com/hashicorp/go-plugin/grpc_client.go +++ b/vendor/github.com/hashicorp/go-plugin/grpc_client.go @@ -9,20 +9,20 @@ import ( "fmt" "math" "net" - "time" "github.com/hashicorp/go-plugin/internal/plugin" "google.golang.org/grpc" "google.golang.org/grpc/credentials" + "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/health/grpc_health_v1" ) -func dialGRPCConn(tls *tls.Config, dialer func(string, time.Duration) (net.Conn, error), dialOpts ...grpc.DialOption) (*grpc.ClientConn, error) { +func dialGRPCConn(tls *tls.Config, dialer func(context.Context, string) (net.Conn, error), dialOpts ...grpc.DialOption) (*grpc.ClientConn, error) { // Build dialing options. opts := make([]grpc.DialOption, 0) // We use a custom dialer so that we can connect over unix domain sockets. - opts = append(opts, grpc.WithDialer(dialer)) + opts = append(opts, grpc.WithContextDialer(dialer)) // Fail right away opts = append(opts, grpc.FailOnNonTempDialError(true)) @@ -30,7 +30,7 @@ func dialGRPCConn(tls *tls.Config, dialer func(string, time.Duration) (net.Conn, // If we have no TLS configuration set, we need to explicitly tell grpc // that we're connecting with an insecure connection. if tls == nil { - opts = append(opts, grpc.WithInsecure()) + opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) } else { opts = append(opts, grpc.WithTransportCredentials( credentials.NewTLS(tls))) @@ -70,7 +70,7 @@ func newGRPCClient(doneCtx context.Context, c *Client) (*GRPCClient, error) { brokerGRPCClient := newGRPCBrokerClient(conn) broker := newGRPCBroker(brokerGRPCClient, c.config.TLSConfig, c.unixSocketCfg, c.runner, muxer) go broker.Run() - go brokerGRPCClient.StartStream() + go func() { _ = brokerGRPCClient.StartStream() }() // Start the stdio client stdioClient, err := newGRPCStdioClient(doneCtx, c.logger.Named("stdio"), conn) @@ -103,8 +103,8 @@ type GRPCClient struct { // ClientProtocol impl. func (c *GRPCClient) Close() error { - c.broker.Close() - c.controller.Shutdown(c.doneCtx, &plugin.Empty{}) + _ = c.broker.Close() + _, _ = c.controller.Shutdown(c.doneCtx, &plugin.Empty{}) return c.Conn.Close() } diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_server.go b/vendor/github.com/hashicorp/go-plugin/grpc_server.go index a5f40c7f0..48195953d 100644 --- a/vendor/github.com/hashicorp/go-plugin/grpc_server.go +++ b/vendor/github.com/hashicorp/go-plugin/grpc_server.go @@ -119,7 +119,7 @@ func (s *GRPCServer) Stop() { s.server.Stop() if s.broker != nil { - s.broker.Close() + _ = s.broker.Close() s.broker = nil } } @@ -130,7 +130,7 @@ func (s *GRPCServer) GracefulStop() { s.server.GracefulStop() if s.broker != nil { - s.broker.Close() + _ = s.broker.Close() s.broker = nil } } diff --git a/vendor/github.com/hashicorp/go-plugin/grpc_stdio.go b/vendor/github.com/hashicorp/go-plugin/grpc_stdio.go index ae06c1163..ce8eb9e1e 100644 --- a/vendor/github.com/hashicorp/go-plugin/grpc_stdio.go +++ b/vendor/github.com/hashicorp/go-plugin/grpc_stdio.go @@ -178,7 +178,7 @@ func copyChan(log hclog.Logger, dst chan<- []byte, src io.Reader) { for { // Make our data buffer. We allocate a new one per loop iteration // so that we can send it over the channel. - var data [1024]byte + var data [grpcStdioBuffer]byte // Read the data, this will block until data is available n, err := bufsrc.Read(data[:]) diff --git a/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_reattach.go b/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_reattach.go index dce1a86a8..5fbeee29d 100644 --- a/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_reattach.go +++ b/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_reattach.go @@ -28,10 +28,9 @@ func ReattachFunc(pid int, addr net.Addr) runner.ReattachFunc { // doesn't actually return an error if it can't find the process. conn, err := net.Dial(addr.Network(), addr.String()) if err != nil { - p.Kill() return nil, ErrProcessNotFound } - conn.Close() + _ = conn.Close() return &CmdAttachedRunner{ pid: pid, diff --git a/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_runner.go b/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_runner.go index b26fea928..bde63249e 100644 --- a/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_runner.go +++ b/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/cmd_runner.go @@ -20,7 +20,7 @@ var ( // ErrProcessNotFound is returned when a client is instantiated to // reattach to an existing process and it isn't found. - ErrProcessNotFound = errors.New("Reattachment process not found") + ErrProcessNotFound = errors.New("reattachment process not found") ) const unrecognizedRemotePluginMessage = `This usually means diff --git a/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/notes_unix.go b/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/notes_unix.go index ce04cfebc..03d73625e 100644 --- a/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/notes_unix.go +++ b/vendor/github.com/hashicorp/go-plugin/internal/cmdrunner/notes_unix.go @@ -53,13 +53,13 @@ func additionalNotesAboutCommand(path string) string { } if elfFile, err := elf.Open(path); err == nil { - defer elfFile.Close() + defer func() { _ = elfFile.Close() }() notes += fmt.Sprintf(" ELF architecture: %s (current architecture: %s)\n", elfFile.Machine, runtime.GOARCH) } else if machoFile, err := macho.Open(path); err == nil { - defer machoFile.Close() + defer func() { _ = machoFile.Close() }() notes += fmt.Sprintf(" MachO architecture: %s (current architecture: %s)\n", machoFile.Cpu, runtime.GOARCH) } else if peFile, err := pe.Open(path); err == nil { - defer peFile.Close() + defer func() { _ = peFile.Close() }() machine, ok := peTypes[peFile.Machine] if !ok { machine = "unknown" diff --git a/vendor/github.com/hashicorp/go-plugin/log_entry.go b/vendor/github.com/hashicorp/go-plugin/log_entry.go index ab963d56b..dc86eb09f 100644 --- a/vendor/github.com/hashicorp/go-plugin/log_entry.go +++ b/vendor/github.com/hashicorp/go-plugin/log_entry.go @@ -10,10 +10,10 @@ import ( // logEntry is the JSON payload that gets sent to Stderr from the plugin to the host type logEntry struct { - Message string `json:"@message"` - Level string `json:"@level"` - Timestamp time.Time `json:"timestamp"` - KVPairs []*logEntryKV `json:"kv_pairs"` + Message string `json:"@message"` + Level string `json:"@level"` + Timestamp time.Time `json:"timestamp"` + KVPairs []logEntryKV `json:"kv_pairs"` } // logEntryKV is a key value pair within the Output payload @@ -24,7 +24,7 @@ type logEntryKV struct { // flattenKVPairs is used to flatten KVPair slice into []interface{} // for hclog consumption. -func flattenKVPairs(kvs []*logEntryKV) []interface{} { +func flattenKVPairs(kvs []logEntryKV) []interface{} { var result []interface{} for _, kv := range kvs { result = append(result, kv.Key) @@ -66,7 +66,7 @@ func parseJSON(input []byte) (*logEntry, error) { // Parse dynamic KV args from the hclog payload. for k, v := range raw { - entry.KVPairs = append(entry.KVPairs, &logEntryKV{ + entry.KVPairs = append(entry.KVPairs, logEntryKV{ Key: k, Value: v, }) diff --git a/vendor/github.com/hashicorp/go-plugin/mux_broker.go b/vendor/github.com/hashicorp/go-plugin/mux_broker.go index 4eb1208fb..c331edaa4 100644 --- a/vendor/github.com/hashicorp/go-plugin/mux_broker.go +++ b/vendor/github.com/hashicorp/go-plugin/mux_broker.go @@ -68,7 +68,7 @@ func (m *MuxBroker) Accept(id uint32) (net.Conn, error) { // Ack our connection if err := binary.Write(c, binary.LittleEndian, id); err != nil { - c.Close() + _ = c.Close() return nil, err } @@ -105,18 +105,18 @@ func (m *MuxBroker) Dial(id uint32) (net.Conn, error) { // Write the stream ID onto the wire. if err := binary.Write(stream, binary.LittleEndian, id); err != nil { - stream.Close() + _ = stream.Close() return nil, err } // Read the ack that we connected. Then we're off! var ack uint32 if err := binary.Read(stream, binary.LittleEndian, &ack); err != nil { - stream.Close() + _ = stream.Close() return nil, err } if ack != id { - stream.Close() + _ = stream.Close() return nil, fmt.Errorf("bad ack: %d (expected %d)", ack, id) } @@ -148,7 +148,7 @@ func (m *MuxBroker) Run() { // Read the stream ID from the stream var id uint32 if err := binary.Read(stream, binary.LittleEndian, &id); err != nil { - stream.Close() + _ = stream.Close() continue } @@ -199,9 +199,7 @@ func (m *MuxBroker) timeoutWait(id uint32, p *muxBrokerPending) { // If we timed out, then check if we have a channel in the buffer, // and if so, close it. if timeout { - select { - case s := <-p.ch: - s.Close() - } + s := <-p.ch + _ = s.Close() } } diff --git a/vendor/github.com/hashicorp/go-plugin/rpc_client.go b/vendor/github.com/hashicorp/go-plugin/rpc_client.go index 142454df8..d5bc5926d 100644 --- a/vendor/github.com/hashicorp/go-plugin/rpc_client.go +++ b/vendor/github.com/hashicorp/go-plugin/rpc_client.go @@ -33,7 +33,7 @@ func newRPCClient(c *Client) (*RPCClient, error) { } if tcpConn, ok := conn.(*net.TCPConn); ok { // Make sure to set keep alive so that the connection doesn't die - tcpConn.SetKeepAlive(true) + _ = tcpConn.SetKeepAlive(true) } if c.config.TLSConfig != nil { @@ -43,7 +43,7 @@ func newRPCClient(c *Client) (*RPCClient, error) { // Create the actual RPC client result, err := NewRPCClient(conn, c.config.Plugins) if err != nil { - conn.Close() + _ = conn.Close() return nil, err } @@ -52,7 +52,7 @@ func newRPCClient(c *Client) (*RPCClient, error) { c.config.SyncStdout, c.config.SyncStderr) if err != nil { - result.Close() + _ = result.Close() return nil, err } @@ -65,23 +65,23 @@ func NewRPCClient(conn io.ReadWriteCloser, plugins map[string]Plugin) (*RPCClien // Create the yamux client so we can multiplex mux, err := yamux.Client(conn, nil) if err != nil { - conn.Close() + _ = conn.Close() return nil, err } // Connect to the control stream. control, err := mux.Open() if err != nil { - mux.Close() + _ = mux.Close() return nil, err } // Connect stdout, stderr streams stdstream := make([]net.Conn, 2) - for i, _ := range stdstream { + for i := range stdstream { stdstream[i], err = mux.Open() if err != nil { - mux.Close() + _ = mux.Close() return nil, err } } diff --git a/vendor/github.com/hashicorp/go-plugin/rpc_server.go b/vendor/github.com/hashicorp/go-plugin/rpc_server.go index cec0a3d93..a871663b3 100644 --- a/vendor/github.com/hashicorp/go-plugin/rpc_server.go +++ b/vendor/github.com/hashicorp/go-plugin/rpc_server.go @@ -69,7 +69,7 @@ func (s *RPCServer) ServeConn(conn io.ReadWriteCloser) { // First create the yamux server to wrap this connection mux, err := yamux.Server(conn, nil) if err != nil { - conn.Close() + _ = conn.Close() log.Printf("[ERR] plugin: error creating yamux server: %s", err) return } @@ -77,7 +77,7 @@ func (s *RPCServer) ServeConn(conn io.ReadWriteCloser) { // Accept the control connection control, err := mux.Accept() if err != nil { - mux.Close() + _ = mux.Close() if err != io.EOF { log.Printf("[ERR] plugin: error accepting control connection: %s", err) } @@ -90,7 +90,7 @@ func (s *RPCServer) ServeConn(conn io.ReadWriteCloser) { for i := range stdstream { stdstream[i], err = mux.Accept() if err != nil { - mux.Close() + _ = mux.Close() log.Printf("[ERR] plugin: accepting stream %d: %s", i, err) return } @@ -107,10 +107,10 @@ func (s *RPCServer) ServeConn(conn io.ReadWriteCloser) { // Use the control connection to build the dispenser and serve the // connection. server := rpc.NewServer() - server.RegisterName("Control", &controlServer{ + _ = server.RegisterName("Control", &controlServer{ server: s, }) - server.RegisterName("Dispenser", &dispenseServer{ + _ = server.RegisterName("Dispenser", &dispenseServer{ broker: broker, plugins: s.Plugins, }) diff --git a/vendor/github.com/hashicorp/go-plugin/server.go b/vendor/github.com/hashicorp/go-plugin/server.go index e741bc7fa..b05af92d1 100644 --- a/vendor/github.com/hashicorp/go-plugin/server.go +++ b/vendor/github.com/hashicorp/go-plugin/server.go @@ -290,7 +290,7 @@ func Serve(opts *ServeConfig) { // Close the listener on return. We wrap this in a func() on purpose // because the "listener" reference may change to TLS. defer func() { - listener.Close() + _ = listener.Close() }() var tlsConfig *tls.Config @@ -443,7 +443,7 @@ func Serve(opts *ServeConfig) { protocolLine += fmt.Sprintf("|%v", grpcBrokerMultiplexingSupported) } fmt.Printf("%s\n", protocolLine) - os.Stdout.Sync() + _ = os.Stdout.Sync() } else if ch := opts.Test.ReattachConfigCh; ch != nil { // Send back the reattach config that can be used. This isn't // quite ready if they connect immediately but the client should @@ -505,7 +505,7 @@ func Serve(opts *ServeConfig) { // Cancellation. We can stop the server by closing the listener. // This isn't graceful at all but this is currently only used by // tests and its our only way to stop. - listener.Close() + _ = listener.Close() // If this is a grpc server, then we also ask the server itself to // end which will kill all connections. There isn't an easy way to do @@ -546,7 +546,7 @@ func serverListener_tcp() (net.Listener, error) { default: minPort, err = strconv.ParseInt(envMinPort, 10, 32) if err != nil { - return nil, fmt.Errorf("Couldn't get value from PLUGIN_MIN_PORT: %v", err) + return nil, fmt.Errorf("couldn't get value from PLUGIN_MIN_PORT: %v", err) } } @@ -556,7 +556,7 @@ func serverListener_tcp() (net.Listener, error) { default: maxPort, err = strconv.ParseInt(envMaxPort, 10, 32) if err != nil { - return nil, fmt.Errorf("Couldn't get value from PLUGIN_MAX_PORT: %v", err) + return nil, fmt.Errorf("couldn't get value from PLUGIN_MAX_PORT: %v", err) } } @@ -572,7 +572,7 @@ func serverListener_tcp() (net.Listener, error) { } } - return nil, errors.New("Couldn't bind plugin TCP listener") + return nil, errors.New("couldn't bind plugin TCP listener") } func serverListener_unix(unixSocketCfg UnixSocketConfig) (net.Listener, error) { diff --git a/vendor/github.com/hashicorp/go-plugin/testing.go b/vendor/github.com/hashicorp/go-plugin/testing.go index a8735dfc8..477076da4 100644 --- a/vendor/github.com/hashicorp/go-plugin/testing.go +++ b/vendor/github.com/hashicorp/go-plugin/testing.go @@ -9,11 +9,12 @@ import ( "io" "net" "net/rpc" + "testing" hclog "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-plugin/internal/grpcmux" - "github.com/mitchellh/go-testing-interface" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) // TestOptions allows specifying options that can affect the behavior of the @@ -33,7 +34,7 @@ type TestOptions struct { // TestConn is a helper function for returning a client and server // net.Conn connected to each other. -func TestConn(t testing.T) (net.Conn, net.Conn) { +func TestConn(t testing.TB) (net.Conn, net.Conn) { // Listen to any local port. This listener will be closed // after a single connection is established. l, err := net.Listen("tcp", "127.0.0.1:0") @@ -46,7 +47,7 @@ func TestConn(t testing.T) (net.Conn, net.Conn) { doneCh := make(chan struct{}) go func() { defer close(doneCh) - defer l.Close() + defer func() { _ = l.Close() }() var err error serverConn, err = l.Accept() if err != nil { @@ -67,7 +68,7 @@ func TestConn(t testing.T) (net.Conn, net.Conn) { } // TestRPCConn returns a rpc client and server connected to each other. -func TestRPCConn(t testing.T) (*rpc.Client, *rpc.Server) { +func TestRPCConn(t testing.TB) (*rpc.Client, *rpc.Server) { clientConn, serverConn := TestConn(t) server := rpc.NewServer() @@ -79,7 +80,7 @@ func TestRPCConn(t testing.T) (*rpc.Client, *rpc.Server) { // TestPluginRPCConn returns a plugin RPC client and server that are connected // together and configured. -func TestPluginRPCConn(t testing.T, ps map[string]Plugin, opts *TestOptions) (*RPCClient, *RPCServer) { +func TestPluginRPCConn(t testing.TB, ps map[string]Plugin, opts *TestOptions) (*RPCClient, *RPCServer) { // Create two net.Conns we can use to shuttle our control connection clientConn, serverConn := TestConn(t) @@ -107,7 +108,7 @@ func TestPluginRPCConn(t testing.T, ps map[string]Plugin, opts *TestOptions) (*R // TestGRPCConn returns a gRPC client conn and grpc server that are connected // together and configured. The register function is used to register services // prior to the Serve call. This is used to test gRPC connections. -func TestGRPCConn(t testing.T, register func(*grpc.Server)) (*grpc.ClientConn, *grpc.Server) { +func TestGRPCConn(t testing.TB, register func(*grpc.Server)) (*grpc.ClientConn, *grpc.Server) { // Create a listener l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { @@ -116,26 +117,27 @@ func TestGRPCConn(t testing.T, register func(*grpc.Server)) (*grpc.ClientConn, * server := grpc.NewServer() register(server) - go server.Serve(l) + go func() { _ = server.Serve(l) }() // Connect to the server conn, err := grpc.Dial( l.Addr().String(), grpc.WithBlock(), - grpc.WithInsecure()) + grpc.WithTransportCredentials(insecure.NewCredentials()), + ) if err != nil { t.Fatalf("err: %s", err) } // Connection successful, close the listener - l.Close() + _ = l.Close() return conn, server } // TestPluginGRPCConn returns a plugin gRPC client and server that are connected // together and configured. This is used to test gRPC connections. -func TestPluginGRPCConn(t testing.T, multiplex bool, ps map[string]Plugin) (*GRPCClient, *GRPCServer) { +func TestPluginGRPCConn(t testing.TB, multiplex bool, ps map[string]Plugin) (*GRPCClient, *GRPCServer) { // Create a listener ln, err := serverListener(UnixSocketConfig{}) if err != nil { diff --git a/vendor/github.com/hashicorp/yamux/LICENSE b/vendor/github.com/hashicorp/yamux/LICENSE index f0e5c79e1..b7df72ed2 100644 --- a/vendor/github.com/hashicorp/yamux/LICENSE +++ b/vendor/github.com/hashicorp/yamux/LICENSE @@ -1,3 +1,5 @@ +Copyright (c) 2014 HashiCorp, Inc. + Mozilla Public License, version 2.0 1. Definitions diff --git a/vendor/github.com/hashicorp/yamux/mux.go b/vendor/github.com/hashicorp/yamux/mux.go index 0c3e67b02..d3d5b3fe3 100644 --- a/vendor/github.com/hashicorp/yamux/mux.go +++ b/vendor/github.com/hashicorp/yamux/mux.go @@ -3,7 +3,6 @@ package yamux import ( "fmt" "io" - "log" "os" "time" ) @@ -51,7 +50,12 @@ type Config struct { // Logger is used to pass in the logger to be used. Either Logger or // LogOutput can be set, not both. - Logger *log.Logger + Logger Logger +} + +func (c *Config) Clone() *Config { + c2 := *c + return &c2 } // DefaultConfig is used to return a default configuration diff --git a/vendor/github.com/hashicorp/yamux/session.go b/vendor/github.com/hashicorp/yamux/session.go index 38fe3ed1f..c08c4dac6 100644 --- a/vendor/github.com/hashicorp/yamux/session.go +++ b/vendor/github.com/hashicorp/yamux/session.go @@ -3,6 +3,7 @@ package yamux import ( "bufio" "bytes" + "context" "fmt" "io" "io/ioutil" @@ -34,7 +35,7 @@ type Session struct { config *Config // logger is used for our logs - logger *log.Logger + logger Logger // conn is the underlying connection conn io.ReadWriteCloser @@ -250,6 +251,22 @@ func (s *Session) AcceptStream() (*Stream, error) { } } +// AcceptStream is used to block until the next available stream +// is ready to be accepted. +func (s *Session) AcceptStreamWithContext(ctx context.Context) (*Stream, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case stream := <-s.acceptCh: + if err := stream.sendWindowUpdate(); err != nil { + return nil, err + } + return stream, nil + case <-s.shutdownCh: + return nil, s.shutdownErr + } +} + // Close is used to close the session and all streams. // Attempts to send a GoAway before closing the connection. func (s *Session) Close() error { @@ -339,7 +356,7 @@ func (s *Session) Ping() (time.Duration, error) { } // Compute the RTT - return time.Now().Sub(start), nil + return time.Since(start), nil } // keepalive is a long running goroutine that periodically does diff --git a/vendor/github.com/hashicorp/yamux/spec.md b/vendor/github.com/hashicorp/yamux/spec.md index 183d797bd..cb98618bd 100644 --- a/vendor/github.com/hashicorp/yamux/spec.md +++ b/vendor/github.com/hashicorp/yamux/spec.md @@ -100,7 +100,7 @@ fire a request without waiting for the RTT of the ACK. This does introduce the possibility of a connection being rejected after data has been sent already. This is a slight semantic difference -from TCP, where the conection cannot be refused after it is opened. +from TCP, where the connection cannot be refused after it is opened. Clients should be prepared to handle this by checking for an error that indicates a RST was received. diff --git a/vendor/github.com/hashicorp/yamux/stream.go b/vendor/github.com/hashicorp/yamux/stream.go index 23d08fcc8..31168d929 100644 --- a/vendor/github.com/hashicorp/yamux/stream.go +++ b/vendor/github.com/hashicorp/yamux/stream.go @@ -95,10 +95,12 @@ func (s *Stream) StreamID() uint32 { func (s *Stream) Read(b []byte) (n int, err error) { defer asyncNotify(s.recvNotifyCh) START: + + // If the stream is closed and there's no data buffered, return EOF s.stateLock.Lock() switch s.state { case streamLocalClose: - fallthrough + // LocalClose only prohibits further local writes. Handle reads normally. case streamRemoteClose: fallthrough case streamClosed: @@ -138,19 +140,22 @@ WAIT: var timer *time.Timer readDeadline := s.readDeadline.Load().(time.Time) if !readDeadline.IsZero() { - delay := readDeadline.Sub(time.Now()) + delay := time.Until(readDeadline) timer = time.NewTimer(delay) timeout = timer.C } select { + case <-s.session.shutdownCh: case <-s.recvNotifyCh: - if timer != nil { - timer.Stop() - } - goto START case <-timeout: return 0, ErrTimeout } + if timer != nil { + if !timer.Stop() { + <-timeout + } + } + goto START } // Write is used to write to the stream @@ -219,18 +224,25 @@ START: WAIT: var timeout <-chan time.Time + var timer *time.Timer writeDeadline := s.writeDeadline.Load().(time.Time) if !writeDeadline.IsZero() { - delay := writeDeadline.Sub(time.Now()) - timeout = time.After(delay) + delay := time.Until(writeDeadline) + timer = time.NewTimer(delay) + timeout = timer.C } select { + case <-s.session.shutdownCh: case <-s.sendNotifyCh: - goto START case <-timeout: return 0, ErrTimeout } - return 0, nil + if timer != nil { + if !timer.Stop() { + <-timeout + } + } + goto START } // sendFlags determines any flags that are appropriate @@ -380,7 +392,7 @@ func (s *Stream) closeTimeout() { defer s.sendLock.Unlock() hdr := header(make([]byte, headerSize)) hdr.encode(typeWindowUpdate, flagRST, s.id, 0) - s.session.sendNoWait(hdr) + _ = s.session.sendNoWait(hdr) } // forceClose is used for when the session is exiting diff --git a/vendor/github.com/hashicorp/yamux/util.go b/vendor/github.com/hashicorp/yamux/util.go index 8a73e9249..4462518a1 100644 --- a/vendor/github.com/hashicorp/yamux/util.go +++ b/vendor/github.com/hashicorp/yamux/util.go @@ -5,6 +5,13 @@ import ( "time" ) +// Logger is a abstract of *log.Logger +type Logger interface { + Print(v ...interface{}) + Printf(format string, v ...interface{}) + Println(v ...interface{}) +} + var ( timerPool = &sync.Pool{ New: func() interface{} { diff --git a/vendor/github.com/josharian/intern/README.md b/vendor/github.com/josharian/intern/README.md deleted file mode 100644 index ffc44b219..000000000 --- a/vendor/github.com/josharian/intern/README.md +++ /dev/null @@ -1,5 +0,0 @@ -Docs: https://godoc.org/github.com/josharian/intern - -See also [Go issue 5160](https://golang.org/issue/5160). - -License: MIT diff --git a/vendor/github.com/josharian/intern/intern.go b/vendor/github.com/josharian/intern/intern.go deleted file mode 100644 index 7acb1fe90..000000000 --- a/vendor/github.com/josharian/intern/intern.go +++ /dev/null @@ -1,44 +0,0 @@ -// Package intern interns strings. -// Interning is best effort only. -// Interned strings may be removed automatically -// at any time without notification. -// All functions may be called concurrently -// with themselves and each other. -package intern - -import "sync" - -var ( - pool sync.Pool = sync.Pool{ - New: func() interface{} { - return make(map[string]string) - }, - } -) - -// String returns s, interned. -func String(s string) string { - m := pool.Get().(map[string]string) - c, ok := m[s] - if ok { - pool.Put(m) - return c - } - m[s] = s - pool.Put(m) - return s -} - -// Bytes returns b converted to a string, interned. -func Bytes(b []byte) string { - m := pool.Get().(map[string]string) - c, ok := m[string(b)] - if ok { - pool.Put(m) - return c - } - s := string(b) - m[s] = s - pool.Put(m) - return s -} diff --git a/vendor/github.com/josharian/intern/license.md b/vendor/github.com/josharian/intern/license.md deleted file mode 100644 index 353d3055f..000000000 --- a/vendor/github.com/josharian/intern/license.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Josh Bleecher Snyder - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/mailru/easyjson/LICENSE b/vendor/github.com/mailru/easyjson/LICENSE deleted file mode 100644 index fbff658f7..000000000 --- a/vendor/github.com/mailru/easyjson/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (c) 2016 Mail.Ru Group - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/mailru/easyjson/buffer/pool.go b/vendor/github.com/mailru/easyjson/buffer/pool.go deleted file mode 100644 index 598a54af9..000000000 --- a/vendor/github.com/mailru/easyjson/buffer/pool.go +++ /dev/null @@ -1,278 +0,0 @@ -// Package buffer implements a buffer for serialization, consisting of a chain of []byte-s to -// reduce copying and to allow reuse of individual chunks. -package buffer - -import ( - "io" - "net" - "sync" -) - -// PoolConfig contains configuration for the allocation and reuse strategy. -type PoolConfig struct { - StartSize int // Minimum chunk size that is allocated. - PooledSize int // Minimum chunk size that is reused, reusing chunks too small will result in overhead. - MaxSize int // Maximum chunk size that will be allocated. -} - -var config = PoolConfig{ - StartSize: 128, - PooledSize: 512, - MaxSize: 32768, -} - -// Reuse pool: chunk size -> pool. -var buffers = map[int]*sync.Pool{} - -func initBuffers() { - for l := config.PooledSize; l <= config.MaxSize; l *= 2 { - buffers[l] = new(sync.Pool) - } -} - -func init() { - initBuffers() -} - -// Init sets up a non-default pooling and allocation strategy. Should be run before serialization is done. -func Init(cfg PoolConfig) { - config = cfg - initBuffers() -} - -// putBuf puts a chunk to reuse pool if it can be reused. -func putBuf(buf []byte) { - size := cap(buf) - if size < config.PooledSize { - return - } - if c := buffers[size]; c != nil { - c.Put(buf[:0]) - } -} - -// getBuf gets a chunk from reuse pool or creates a new one if reuse failed. -func getBuf(size int) []byte { - if size >= config.PooledSize { - if c := buffers[size]; c != nil { - v := c.Get() - if v != nil { - return v.([]byte) - } - } - } - return make([]byte, 0, size) -} - -// Buffer is a buffer optimized for serialization without extra copying. -type Buffer struct { - - // Buf is the current chunk that can be used for serialization. - Buf []byte - - toPool []byte - bufs [][]byte -} - -// EnsureSpace makes sure that the current chunk contains at least s free bytes, -// possibly creating a new chunk. -func (b *Buffer) EnsureSpace(s int) { - if cap(b.Buf)-len(b.Buf) < s { - b.ensureSpaceSlow(s) - } -} - -func (b *Buffer) ensureSpaceSlow(s int) { - l := len(b.Buf) - if l > 0 { - if cap(b.toPool) != cap(b.Buf) { - // Chunk was reallocated, toPool can be pooled. - putBuf(b.toPool) - } - if cap(b.bufs) == 0 { - b.bufs = make([][]byte, 0, 8) - } - b.bufs = append(b.bufs, b.Buf) - l = cap(b.toPool) * 2 - } else { - l = config.StartSize - } - - if l > config.MaxSize { - l = config.MaxSize - } - b.Buf = getBuf(l) - b.toPool = b.Buf -} - -// AppendByte appends a single byte to buffer. -func (b *Buffer) AppendByte(data byte) { - b.EnsureSpace(1) - b.Buf = append(b.Buf, data) -} - -// AppendBytes appends a byte slice to buffer. -func (b *Buffer) AppendBytes(data []byte) { - if len(data) <= cap(b.Buf)-len(b.Buf) { - b.Buf = append(b.Buf, data...) // fast path - } else { - b.appendBytesSlow(data) - } -} - -func (b *Buffer) appendBytesSlow(data []byte) { - for len(data) > 0 { - b.EnsureSpace(1) - - sz := cap(b.Buf) - len(b.Buf) - if sz > len(data) { - sz = len(data) - } - - b.Buf = append(b.Buf, data[:sz]...) - data = data[sz:] - } -} - -// AppendString appends a string to buffer. -func (b *Buffer) AppendString(data string) { - if len(data) <= cap(b.Buf)-len(b.Buf) { - b.Buf = append(b.Buf, data...) // fast path - } else { - b.appendStringSlow(data) - } -} - -func (b *Buffer) appendStringSlow(data string) { - for len(data) > 0 { - b.EnsureSpace(1) - - sz := cap(b.Buf) - len(b.Buf) - if sz > len(data) { - sz = len(data) - } - - b.Buf = append(b.Buf, data[:sz]...) - data = data[sz:] - } -} - -// Size computes the size of a buffer by adding sizes of every chunk. -func (b *Buffer) Size() int { - size := len(b.Buf) - for _, buf := range b.bufs { - size += len(buf) - } - return size -} - -// DumpTo outputs the contents of a buffer to a writer and resets the buffer. -func (b *Buffer) DumpTo(w io.Writer) (written int, err error) { - bufs := net.Buffers(b.bufs) - if len(b.Buf) > 0 { - bufs = append(bufs, b.Buf) - } - n, err := bufs.WriteTo(w) - - for _, buf := range b.bufs { - putBuf(buf) - } - putBuf(b.toPool) - - b.bufs = nil - b.Buf = nil - b.toPool = nil - - return int(n), err -} - -// BuildBytes creates a single byte slice with all the contents of the buffer. Data is -// copied if it does not fit in a single chunk. You can optionally provide one byte -// slice as argument that it will try to reuse. -func (b *Buffer) BuildBytes(reuse ...[]byte) []byte { - if len(b.bufs) == 0 { - ret := b.Buf - b.toPool = nil - b.Buf = nil - return ret - } - - var ret []byte - size := b.Size() - - // If we got a buffer as argument and it is big enough, reuse it. - if len(reuse) == 1 && cap(reuse[0]) >= size { - ret = reuse[0][:0] - } else { - ret = make([]byte, 0, size) - } - for _, buf := range b.bufs { - ret = append(ret, buf...) - putBuf(buf) - } - - ret = append(ret, b.Buf...) - putBuf(b.toPool) - - b.bufs = nil - b.toPool = nil - b.Buf = nil - - return ret -} - -type readCloser struct { - offset int - bufs [][]byte -} - -func (r *readCloser) Read(p []byte) (n int, err error) { - for _, buf := range r.bufs { - // Copy as much as we can. - x := copy(p[n:], buf[r.offset:]) - n += x // Increment how much we filled. - - // Did we empty the whole buffer? - if r.offset+x == len(buf) { - // On to the next buffer. - r.offset = 0 - r.bufs = r.bufs[1:] - - // We can release this buffer. - putBuf(buf) - } else { - r.offset += x - } - - if n == len(p) { - break - } - } - // No buffers left or nothing read? - if len(r.bufs) == 0 { - err = io.EOF - } - return -} - -func (r *readCloser) Close() error { - // Release all remaining buffers. - for _, buf := range r.bufs { - putBuf(buf) - } - // In case Close gets called multiple times. - r.bufs = nil - - return nil -} - -// ReadCloser creates an io.ReadCloser with all the contents of the buffer. -func (b *Buffer) ReadCloser() io.ReadCloser { - ret := &readCloser{0, append(b.bufs, b.Buf)} - - b.bufs = nil - b.toPool = nil - b.Buf = nil - - return ret -} diff --git a/vendor/github.com/mailru/easyjson/jlexer/bytestostr.go b/vendor/github.com/mailru/easyjson/jlexer/bytestostr.go deleted file mode 100644 index e68108f86..000000000 --- a/vendor/github.com/mailru/easyjson/jlexer/bytestostr.go +++ /dev/null @@ -1,21 +0,0 @@ -// This file will only be included to the build if neither -// easyjson_nounsafe nor appengine build tag is set. See README notes -// for more details. - -//+build !easyjson_nounsafe -//+build !appengine - -package jlexer - -import ( - "unsafe" -) - -// bytesToStr creates a string pointing at the slice to avoid copying. -// -// Warning: the string returned by the function should be used with care, as the whole input data -// chunk may be either blocked from being freed by GC because of a single string or the buffer.Data -// may be garbage-collected even when the string exists. -func bytesToStr(data []byte) string { - return *(*string)(unsafe.Pointer(&data)) -} diff --git a/vendor/github.com/mailru/easyjson/jlexer/bytestostr_nounsafe.go b/vendor/github.com/mailru/easyjson/jlexer/bytestostr_nounsafe.go deleted file mode 100644 index 864d1be67..000000000 --- a/vendor/github.com/mailru/easyjson/jlexer/bytestostr_nounsafe.go +++ /dev/null @@ -1,13 +0,0 @@ -// This file is included to the build if any of the buildtags below -// are defined. Refer to README notes for more details. - -//+build easyjson_nounsafe appengine - -package jlexer - -// bytesToStr creates a string normally from []byte -// -// Note that this method is roughly 1.5x slower than using the 'unsafe' method. -func bytesToStr(data []byte) string { - return string(data) -} diff --git a/vendor/github.com/mailru/easyjson/jlexer/error.go b/vendor/github.com/mailru/easyjson/jlexer/error.go deleted file mode 100644 index e90ec40d0..000000000 --- a/vendor/github.com/mailru/easyjson/jlexer/error.go +++ /dev/null @@ -1,15 +0,0 @@ -package jlexer - -import "fmt" - -// LexerError implements the error interface and represents all possible errors that can be -// generated during parsing the JSON data. -type LexerError struct { - Reason string - Offset int - Data string -} - -func (l *LexerError) Error() string { - return fmt.Sprintf("parse error: %s near offset %d of '%s'", l.Reason, l.Offset, l.Data) -} diff --git a/vendor/github.com/mailru/easyjson/jlexer/lexer.go b/vendor/github.com/mailru/easyjson/jlexer/lexer.go deleted file mode 100644 index a27705b12..000000000 --- a/vendor/github.com/mailru/easyjson/jlexer/lexer.go +++ /dev/null @@ -1,1257 +0,0 @@ -// Package jlexer contains a JSON lexer implementation. -// -// It is expected that it is mostly used with generated parser code, so the interface is tuned -// for a parser that knows what kind of data is expected. -package jlexer - -import ( - "bytes" - "encoding/base64" - "encoding/json" - "errors" - "fmt" - "io" - "strconv" - "unicode" - "unicode/utf16" - "unicode/utf8" - - "github.com/josharian/intern" -) - -// TokenKind determines type of a token. -type TokenKind byte - -const ( - TokenUndef TokenKind = iota // No token. - TokenDelim // Delimiter: one of '{', '}', '[' or ']'. - TokenString // A string literal, e.g. "abc\u1234" - TokenNumber // Number literal, e.g. 1.5e5 - TokenBool // Boolean literal: true or false. - TokenNull // null keyword. -) - -// token describes a single token: type, position in the input and value. -type token struct { - kind TokenKind // Type of a token. - - boolValue bool // Value if a boolean literal token. - byteValueCloned bool // true if byteValue was allocated and does not refer to original json body - byteValue []byte // Raw value of a token. - delimValue byte -} - -// Lexer is a JSON lexer: it iterates over JSON tokens in a byte slice. -type Lexer struct { - Data []byte // Input data given to the lexer. - - start int // Start of the current token. - pos int // Current unscanned position in the input stream. - token token // Last scanned token, if token.kind != TokenUndef. - - firstElement bool // Whether current element is the first in array or an object. - wantSep byte // A comma or a colon character, which need to occur before a token. - - UseMultipleErrors bool // If we want to use multiple errors. - fatalError error // Fatal error occurred during lexing. It is usually a syntax error. - multipleErrors []*LexerError // Semantic errors occurred during lexing. Marshalling will be continued after finding this errors. -} - -// FetchToken scans the input for the next token. -func (r *Lexer) FetchToken() { - r.token.kind = TokenUndef - r.start = r.pos - - // Check if r.Data has r.pos element - // If it doesn't, it mean corrupted input data - if len(r.Data) < r.pos { - r.errParse("Unexpected end of data") - return - } - // Determine the type of a token by skipping whitespace and reading the - // first character. - for _, c := range r.Data[r.pos:] { - switch c { - case ':', ',': - if r.wantSep == c { - r.pos++ - r.start++ - r.wantSep = 0 - } else { - r.errSyntax() - } - - case ' ', '\t', '\r', '\n': - r.pos++ - r.start++ - - case '"': - if r.wantSep != 0 { - r.errSyntax() - } - - r.token.kind = TokenString - r.fetchString() - return - - case '{', '[': - if r.wantSep != 0 { - r.errSyntax() - } - r.firstElement = true - r.token.kind = TokenDelim - r.token.delimValue = r.Data[r.pos] - r.pos++ - return - - case '}', ']': - if !r.firstElement && (r.wantSep != ',') { - r.errSyntax() - } - r.wantSep = 0 - r.token.kind = TokenDelim - r.token.delimValue = r.Data[r.pos] - r.pos++ - return - - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': - if r.wantSep != 0 { - r.errSyntax() - } - r.token.kind = TokenNumber - r.fetchNumber() - return - - case 'n': - if r.wantSep != 0 { - r.errSyntax() - } - - r.token.kind = TokenNull - r.fetchNull() - return - - case 't': - if r.wantSep != 0 { - r.errSyntax() - } - - r.token.kind = TokenBool - r.token.boolValue = true - r.fetchTrue() - return - - case 'f': - if r.wantSep != 0 { - r.errSyntax() - } - - r.token.kind = TokenBool - r.token.boolValue = false - r.fetchFalse() - return - - default: - r.errSyntax() - return - } - } - r.fatalError = io.EOF - return -} - -// isTokenEnd returns true if the char can follow a non-delimiter token -func isTokenEnd(c byte) bool { - return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '[' || c == ']' || c == '{' || c == '}' || c == ',' || c == ':' -} - -// fetchNull fetches and checks remaining bytes of null keyword. -func (r *Lexer) fetchNull() { - r.pos += 4 - if r.pos > len(r.Data) || - r.Data[r.pos-3] != 'u' || - r.Data[r.pos-2] != 'l' || - r.Data[r.pos-1] != 'l' || - (r.pos != len(r.Data) && !isTokenEnd(r.Data[r.pos])) { - - r.pos -= 4 - r.errSyntax() - } -} - -// fetchTrue fetches and checks remaining bytes of true keyword. -func (r *Lexer) fetchTrue() { - r.pos += 4 - if r.pos > len(r.Data) || - r.Data[r.pos-3] != 'r' || - r.Data[r.pos-2] != 'u' || - r.Data[r.pos-1] != 'e' || - (r.pos != len(r.Data) && !isTokenEnd(r.Data[r.pos])) { - - r.pos -= 4 - r.errSyntax() - } -} - -// fetchFalse fetches and checks remaining bytes of false keyword. -func (r *Lexer) fetchFalse() { - r.pos += 5 - if r.pos > len(r.Data) || - r.Data[r.pos-4] != 'a' || - r.Data[r.pos-3] != 'l' || - r.Data[r.pos-2] != 's' || - r.Data[r.pos-1] != 'e' || - (r.pos != len(r.Data) && !isTokenEnd(r.Data[r.pos])) { - - r.pos -= 5 - r.errSyntax() - } -} - -// fetchNumber scans a number literal token. -func (r *Lexer) fetchNumber() { - hasE := false - afterE := false - hasDot := false - - r.pos++ - for i, c := range r.Data[r.pos:] { - switch { - case c >= '0' && c <= '9': - afterE = false - case c == '.' && !hasDot: - hasDot = true - case (c == 'e' || c == 'E') && !hasE: - hasE = true - hasDot = true - afterE = true - case (c == '+' || c == '-') && afterE: - afterE = false - default: - r.pos += i - if !isTokenEnd(c) { - r.errSyntax() - } else { - r.token.byteValue = r.Data[r.start:r.pos] - } - return - } - } - - r.pos = len(r.Data) - r.token.byteValue = r.Data[r.start:] -} - -// findStringLen tries to scan into the string literal for ending quote char to determine required size. -// The size will be exact if no escapes are present and may be inexact if there are escaped chars. -func findStringLen(data []byte) (isValid bool, length int) { - for { - idx := bytes.IndexByte(data, '"') - if idx == -1 { - return false, len(data) - } - if idx == 0 || (idx > 0 && data[idx-1] != '\\') { - return true, length + idx - } - - // count \\\\\\\ sequences. even number of slashes means quote is not really escaped - cnt := 1 - for idx-cnt-1 >= 0 && data[idx-cnt-1] == '\\' { - cnt++ - } - if cnt%2 == 0 { - return true, length + idx - } - - length += idx + 1 - data = data[idx+1:] - } -} - -// unescapeStringToken performs unescaping of string token. -// if no escaping is needed, original string is returned, otherwise - a new one allocated -func (r *Lexer) unescapeStringToken() (err error) { - data := r.token.byteValue - var unescapedData []byte - - for { - i := bytes.IndexByte(data, '\\') - if i == -1 { - break - } - - escapedRune, escapedBytes, err := decodeEscape(data[i:]) - if err != nil { - r.errParse(err.Error()) - return err - } - - if unescapedData == nil { - unescapedData = make([]byte, 0, len(r.token.byteValue)) - } - - var d [4]byte - s := utf8.EncodeRune(d[:], escapedRune) - unescapedData = append(unescapedData, data[:i]...) - unescapedData = append(unescapedData, d[:s]...) - - data = data[i+escapedBytes:] - } - - if unescapedData != nil { - r.token.byteValue = append(unescapedData, data...) - r.token.byteValueCloned = true - } - return -} - -// getu4 decodes \uXXXX from the beginning of s, returning the hex value, -// or it returns -1. -func getu4(s []byte) rune { - if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { - return -1 - } - var val rune - for i := 2; i < len(s) && i < 6; i++ { - var v byte - c := s[i] - switch c { - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - v = c - '0' - case 'a', 'b', 'c', 'd', 'e', 'f': - v = c - 'a' + 10 - case 'A', 'B', 'C', 'D', 'E', 'F': - v = c - 'A' + 10 - default: - return -1 - } - - val <<= 4 - val |= rune(v) - } - return val -} - -// decodeEscape processes a single escape sequence and returns number of bytes processed. -func decodeEscape(data []byte) (decoded rune, bytesProcessed int, err error) { - if len(data) < 2 { - return 0, 0, errors.New("incorrect escape symbol \\ at the end of token") - } - - c := data[1] - switch c { - case '"', '/', '\\': - return rune(c), 2, nil - case 'b': - return '\b', 2, nil - case 'f': - return '\f', 2, nil - case 'n': - return '\n', 2, nil - case 'r': - return '\r', 2, nil - case 't': - return '\t', 2, nil - case 'u': - rr := getu4(data) - if rr < 0 { - return 0, 0, errors.New("incorrectly escaped \\uXXXX sequence") - } - - read := 6 - if utf16.IsSurrogate(rr) { - rr1 := getu4(data[read:]) - if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { - read += 6 - rr = dec - } else { - rr = unicode.ReplacementChar - } - } - return rr, read, nil - } - - return 0, 0, errors.New("incorrectly escaped bytes") -} - -// fetchString scans a string literal token. -func (r *Lexer) fetchString() { - r.pos++ - data := r.Data[r.pos:] - - isValid, length := findStringLen(data) - if !isValid { - r.pos += length - r.errParse("unterminated string literal") - return - } - r.token.byteValue = data[:length] - r.pos += length + 1 // skip closing '"' as well -} - -// scanToken scans the next token if no token is currently available in the lexer. -func (r *Lexer) scanToken() { - if r.token.kind != TokenUndef || r.fatalError != nil { - return - } - - r.FetchToken() -} - -// consume resets the current token to allow scanning the next one. -func (r *Lexer) consume() { - r.token.kind = TokenUndef - r.token.byteValueCloned = false - r.token.delimValue = 0 -} - -// Ok returns true if no error (including io.EOF) was encountered during scanning. -func (r *Lexer) Ok() bool { - return r.fatalError == nil -} - -const maxErrorContextLen = 13 - -func (r *Lexer) errParse(what string) { - if r.fatalError == nil { - var str string - if len(r.Data)-r.pos <= maxErrorContextLen { - str = string(r.Data) - } else { - str = string(r.Data[r.pos:r.pos+maxErrorContextLen-3]) + "..." - } - r.fatalError = &LexerError{ - Reason: what, - Offset: r.pos, - Data: str, - } - } -} - -func (r *Lexer) errSyntax() { - r.errParse("syntax error") -} - -func (r *Lexer) errInvalidToken(expected string) { - if r.fatalError != nil { - return - } - if r.UseMultipleErrors { - r.pos = r.start - r.consume() - r.SkipRecursive() - switch expected { - case "[": - r.token.delimValue = ']' - r.token.kind = TokenDelim - case "{": - r.token.delimValue = '}' - r.token.kind = TokenDelim - } - r.addNonfatalError(&LexerError{ - Reason: fmt.Sprintf("expected %s", expected), - Offset: r.start, - Data: string(r.Data[r.start:r.pos]), - }) - return - } - - var str string - if len(r.token.byteValue) <= maxErrorContextLen { - str = string(r.token.byteValue) - } else { - str = string(r.token.byteValue[:maxErrorContextLen-3]) + "..." - } - r.fatalError = &LexerError{ - Reason: fmt.Sprintf("expected %s", expected), - Offset: r.pos, - Data: str, - } -} - -func (r *Lexer) GetPos() int { - return r.pos -} - -// Delim consumes a token and verifies that it is the given delimiter. -func (r *Lexer) Delim(c byte) { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - - if !r.Ok() || r.token.delimValue != c { - r.consume() // errInvalidToken can change token if UseMultipleErrors is enabled. - r.errInvalidToken(string([]byte{c})) - } else { - r.consume() - } -} - -// IsDelim returns true if there was no scanning error and next token is the given delimiter. -func (r *Lexer) IsDelim(c byte) bool { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - return !r.Ok() || r.token.delimValue == c -} - -// Null verifies that the next token is null and consumes it. -func (r *Lexer) Null() { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - if !r.Ok() || r.token.kind != TokenNull { - r.errInvalidToken("null") - } - r.consume() -} - -// IsNull returns true if the next token is a null keyword. -func (r *Lexer) IsNull() bool { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - return r.Ok() && r.token.kind == TokenNull -} - -// Skip skips a single token. -func (r *Lexer) Skip() { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - r.consume() -} - -// SkipRecursive skips next array or object completely, or just skips a single token if not -// an array/object. -// -// Note: no syntax validation is performed on the skipped data. -func (r *Lexer) SkipRecursive() { - r.scanToken() - var start, end byte - startPos := r.start - - switch r.token.delimValue { - case '{': - start, end = '{', '}' - case '[': - start, end = '[', ']' - default: - r.consume() - return - } - - r.consume() - - level := 1 - inQuotes := false - wasEscape := false - - for i, c := range r.Data[r.pos:] { - switch { - case c == start && !inQuotes: - level++ - case c == end && !inQuotes: - level-- - if level == 0 { - r.pos += i + 1 - if !json.Valid(r.Data[startPos:r.pos]) { - r.pos = len(r.Data) - r.fatalError = &LexerError{ - Reason: "skipped array/object json value is invalid", - Offset: r.pos, - Data: string(r.Data[r.pos:]), - } - } - return - } - case c == '\\' && inQuotes: - wasEscape = !wasEscape - continue - case c == '"' && inQuotes: - inQuotes = wasEscape - case c == '"': - inQuotes = true - } - wasEscape = false - } - r.pos = len(r.Data) - r.fatalError = &LexerError{ - Reason: "EOF reached while skipping array/object or token", - Offset: r.pos, - Data: string(r.Data[r.pos:]), - } -} - -// Raw fetches the next item recursively as a data slice -func (r *Lexer) Raw() []byte { - r.SkipRecursive() - if !r.Ok() { - return nil - } - return r.Data[r.start:r.pos] -} - -// IsStart returns whether the lexer is positioned at the start -// of an input string. -func (r *Lexer) IsStart() bool { - return r.pos == 0 -} - -// Consumed reads all remaining bytes from the input, publishing an error if -// there is anything but whitespace remaining. -func (r *Lexer) Consumed() { - if r.pos > len(r.Data) || !r.Ok() { - return - } - - for _, c := range r.Data[r.pos:] { - if c != ' ' && c != '\t' && c != '\r' && c != '\n' { - r.AddError(&LexerError{ - Reason: "invalid character '" + string(c) + "' after top-level value", - Offset: r.pos, - Data: string(r.Data[r.pos:]), - }) - return - } - - r.pos++ - r.start++ - } -} - -func (r *Lexer) unsafeString(skipUnescape bool) (string, []byte) { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - if !r.Ok() || r.token.kind != TokenString { - r.errInvalidToken("string") - return "", nil - } - if !skipUnescape { - if err := r.unescapeStringToken(); err != nil { - r.errInvalidToken("string") - return "", nil - } - } - - bytes := r.token.byteValue - ret := bytesToStr(r.token.byteValue) - r.consume() - return ret, bytes -} - -// UnsafeString returns the string value if the token is a string literal. -// -// Warning: returned string may point to the input buffer, so the string should not outlive -// the input buffer. Intended pattern of usage is as an argument to a switch statement. -func (r *Lexer) UnsafeString() string { - ret, _ := r.unsafeString(false) - return ret -} - -// UnsafeBytes returns the byte slice if the token is a string literal. -func (r *Lexer) UnsafeBytes() []byte { - _, ret := r.unsafeString(false) - return ret -} - -// UnsafeFieldName returns current member name string token -func (r *Lexer) UnsafeFieldName(skipUnescape bool) string { - ret, _ := r.unsafeString(skipUnescape) - return ret -} - -// String reads a string literal. -func (r *Lexer) String() string { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - if !r.Ok() || r.token.kind != TokenString { - r.errInvalidToken("string") - return "" - } - if err := r.unescapeStringToken(); err != nil { - r.errInvalidToken("string") - return "" - } - var ret string - if r.token.byteValueCloned { - ret = bytesToStr(r.token.byteValue) - } else { - ret = string(r.token.byteValue) - } - r.consume() - return ret -} - -// StringIntern reads a string literal, and performs string interning on it. -func (r *Lexer) StringIntern() string { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - if !r.Ok() || r.token.kind != TokenString { - r.errInvalidToken("string") - return "" - } - if err := r.unescapeStringToken(); err != nil { - r.errInvalidToken("string") - return "" - } - ret := intern.Bytes(r.token.byteValue) - r.consume() - return ret -} - -// Bytes reads a string literal and base64 decodes it into a byte slice. -func (r *Lexer) Bytes() []byte { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - if !r.Ok() || r.token.kind != TokenString { - r.errInvalidToken("string") - return nil - } - if err := r.unescapeStringToken(); err != nil { - r.errInvalidToken("string") - return nil - } - ret := make([]byte, base64.StdEncoding.DecodedLen(len(r.token.byteValue))) - n, err := base64.StdEncoding.Decode(ret, r.token.byteValue) - if err != nil { - r.fatalError = &LexerError{ - Reason: err.Error(), - } - return nil - } - - r.consume() - return ret[:n] -} - -// Bool reads a true or false boolean keyword. -func (r *Lexer) Bool() bool { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - if !r.Ok() || r.token.kind != TokenBool { - r.errInvalidToken("bool") - return false - } - ret := r.token.boolValue - r.consume() - return ret -} - -func (r *Lexer) number() string { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - if !r.Ok() || r.token.kind != TokenNumber { - r.errInvalidToken("number") - return "" - } - ret := bytesToStr(r.token.byteValue) - r.consume() - return ret -} - -func (r *Lexer) Uint8() uint8 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseUint(s, 10, 8) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return uint8(n) -} - -func (r *Lexer) Uint16() uint16 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseUint(s, 10, 16) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return uint16(n) -} - -func (r *Lexer) Uint32() uint32 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseUint(s, 10, 32) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return uint32(n) -} - -func (r *Lexer) Uint64() uint64 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseUint(s, 10, 64) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return n -} - -func (r *Lexer) Uint() uint { - return uint(r.Uint64()) -} - -func (r *Lexer) Int8() int8 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseInt(s, 10, 8) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return int8(n) -} - -func (r *Lexer) Int16() int16 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseInt(s, 10, 16) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return int16(n) -} - -func (r *Lexer) Int32() int32 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseInt(s, 10, 32) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return int32(n) -} - -func (r *Lexer) Int64() int64 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseInt(s, 10, 64) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return n -} - -func (r *Lexer) Int() int { - return int(r.Int64()) -} - -func (r *Lexer) Uint8Str() uint8 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseUint(s, 10, 8) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return uint8(n) -} - -func (r *Lexer) Uint16Str() uint16 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseUint(s, 10, 16) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return uint16(n) -} - -func (r *Lexer) Uint32Str() uint32 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseUint(s, 10, 32) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return uint32(n) -} - -func (r *Lexer) Uint64Str() uint64 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseUint(s, 10, 64) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return n -} - -func (r *Lexer) UintStr() uint { - return uint(r.Uint64Str()) -} - -func (r *Lexer) UintptrStr() uintptr { - return uintptr(r.Uint64Str()) -} - -func (r *Lexer) Int8Str() int8 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseInt(s, 10, 8) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return int8(n) -} - -func (r *Lexer) Int16Str() int16 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseInt(s, 10, 16) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return int16(n) -} - -func (r *Lexer) Int32Str() int32 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseInt(s, 10, 32) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return int32(n) -} - -func (r *Lexer) Int64Str() int64 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseInt(s, 10, 64) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return n -} - -func (r *Lexer) IntStr() int { - return int(r.Int64Str()) -} - -func (r *Lexer) Float32() float32 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseFloat(s, 32) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return float32(n) -} - -func (r *Lexer) Float32Str() float32 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - n, err := strconv.ParseFloat(s, 32) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return float32(n) -} - -func (r *Lexer) Float64() float64 { - s := r.number() - if !r.Ok() { - return 0 - } - - n, err := strconv.ParseFloat(s, 64) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: s, - }) - } - return n -} - -func (r *Lexer) Float64Str() float64 { - s, b := r.unsafeString(false) - if !r.Ok() { - return 0 - } - n, err := strconv.ParseFloat(s, 64) - if err != nil { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Reason: err.Error(), - Data: string(b), - }) - } - return n -} - -func (r *Lexer) Error() error { - return r.fatalError -} - -func (r *Lexer) AddError(e error) { - if r.fatalError == nil { - r.fatalError = e - } -} - -func (r *Lexer) AddNonFatalError(e error) { - r.addNonfatalError(&LexerError{ - Offset: r.start, - Data: string(r.Data[r.start:r.pos]), - Reason: e.Error(), - }) -} - -func (r *Lexer) addNonfatalError(err *LexerError) { - if r.UseMultipleErrors { - // We don't want to add errors with the same offset. - if len(r.multipleErrors) != 0 && r.multipleErrors[len(r.multipleErrors)-1].Offset == err.Offset { - return - } - r.multipleErrors = append(r.multipleErrors, err) - return - } - r.fatalError = err -} - -func (r *Lexer) GetNonFatalErrors() []*LexerError { - return r.multipleErrors -} - -// JsonNumber fetches and json.Number from 'encoding/json' package. -// Both int, float or string, contains them are valid values -func (r *Lexer) JsonNumber() json.Number { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - if !r.Ok() { - r.errInvalidToken("json.Number") - return json.Number("") - } - - switch r.token.kind { - case TokenString: - return json.Number(r.String()) - case TokenNumber: - return json.Number(r.Raw()) - case TokenNull: - r.Null() - return json.Number("") - default: - r.errSyntax() - return json.Number("") - } -} - -// Interface fetches an interface{} analogous to the 'encoding/json' package. -func (r *Lexer) Interface() interface{} { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - - if !r.Ok() { - return nil - } - switch r.token.kind { - case TokenString: - return r.String() - case TokenNumber: - return r.Float64() - case TokenBool: - return r.Bool() - case TokenNull: - r.Null() - return nil - } - - if r.token.delimValue == '{' { - r.consume() - - ret := map[string]interface{}{} - for !r.IsDelim('}') { - key := r.String() - r.WantColon() - ret[key] = r.Interface() - r.WantComma() - } - r.Delim('}') - - if r.Ok() { - return ret - } else { - return nil - } - } else if r.token.delimValue == '[' { - r.consume() - - ret := []interface{}{} - for !r.IsDelim(']') { - ret = append(ret, r.Interface()) - r.WantComma() - } - r.Delim(']') - - if r.Ok() { - return ret - } else { - return nil - } - } - r.errSyntax() - return nil -} - -// WantComma requires a comma to be present before fetching next token. -func (r *Lexer) WantComma() { - r.wantSep = ',' - r.firstElement = false -} - -// WantColon requires a colon to be present before fetching next token. -func (r *Lexer) WantColon() { - r.wantSep = ':' - r.firstElement = false -} - -// CurrentToken returns current token kind if there were no errors and TokenUndef otherwise -func (r *Lexer) CurrentToken() TokenKind { - if r.token.kind == TokenUndef && r.Ok() { - r.FetchToken() - } - - if !r.Ok() { - return TokenUndef - } - - return r.token.kind -} diff --git a/vendor/github.com/mailru/easyjson/jwriter/writer.go b/vendor/github.com/mailru/easyjson/jwriter/writer.go deleted file mode 100644 index 34b0ade46..000000000 --- a/vendor/github.com/mailru/easyjson/jwriter/writer.go +++ /dev/null @@ -1,417 +0,0 @@ -// Package jwriter contains a JSON writer. -package jwriter - -import ( - "io" - "strconv" - "unicode/utf8" - - "github.com/mailru/easyjson/buffer" -) - -// Flags describe various encoding options. The behavior may be actually implemented in the encoder, but -// Flags field in Writer is used to set and pass them around. -type Flags int - -const ( - NilMapAsEmpty Flags = 1 << iota // Encode nil map as '{}' rather than 'null'. - NilSliceAsEmpty // Encode nil slice as '[]' rather than 'null'. -) - -// Writer is a JSON writer. -type Writer struct { - Flags Flags - - Error error - Buffer buffer.Buffer - NoEscapeHTML bool -} - -// Size returns the size of the data that was written out. -func (w *Writer) Size() int { - return w.Buffer.Size() -} - -// DumpTo outputs the data to given io.Writer, resetting the buffer. -func (w *Writer) DumpTo(out io.Writer) (written int, err error) { - return w.Buffer.DumpTo(out) -} - -// BuildBytes returns writer data as a single byte slice. You can optionally provide one byte slice -// as argument that it will try to reuse. -func (w *Writer) BuildBytes(reuse ...[]byte) ([]byte, error) { - if w.Error != nil { - return nil, w.Error - } - - return w.Buffer.BuildBytes(reuse...), nil -} - -// ReadCloser returns an io.ReadCloser that can be used to read the data. -// ReadCloser also resets the buffer. -func (w *Writer) ReadCloser() (io.ReadCloser, error) { - if w.Error != nil { - return nil, w.Error - } - - return w.Buffer.ReadCloser(), nil -} - -// RawByte appends raw binary data to the buffer. -func (w *Writer) RawByte(c byte) { - w.Buffer.AppendByte(c) -} - -// RawByte appends raw binary data to the buffer. -func (w *Writer) RawString(s string) { - w.Buffer.AppendString(s) -} - -// RawBytesString appends string from bytes to the buffer. -func (w *Writer) RawBytesString(data []byte, err error) { - switch { - case w.Error != nil: - return - case err != nil: - w.Error = err - default: - w.String(string(data)) - } -} - -// Raw appends raw binary data to the buffer or sets the error if it is given. Useful for -// calling with results of MarshalJSON-like functions. -func (w *Writer) Raw(data []byte, err error) { - switch { - case w.Error != nil: - return - case err != nil: - w.Error = err - case len(data) > 0: - w.Buffer.AppendBytes(data) - default: - w.RawString("null") - } -} - -// RawText encloses raw binary data in quotes and appends in to the buffer. -// Useful for calling with results of MarshalText-like functions. -func (w *Writer) RawText(data []byte, err error) { - switch { - case w.Error != nil: - return - case err != nil: - w.Error = err - case len(data) > 0: - w.String(string(data)) - default: - w.RawString("null") - } -} - -// Base64Bytes appends data to the buffer after base64 encoding it -func (w *Writer) Base64Bytes(data []byte) { - if data == nil { - w.Buffer.AppendString("null") - return - } - w.Buffer.AppendByte('"') - w.base64(data) - w.Buffer.AppendByte('"') -} - -func (w *Writer) Uint8(n uint8) { - w.Buffer.EnsureSpace(3) - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10) -} - -func (w *Writer) Uint16(n uint16) { - w.Buffer.EnsureSpace(5) - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10) -} - -func (w *Writer) Uint32(n uint32) { - w.Buffer.EnsureSpace(10) - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10) -} - -func (w *Writer) Uint(n uint) { - w.Buffer.EnsureSpace(20) - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10) -} - -func (w *Writer) Uint64(n uint64) { - w.Buffer.EnsureSpace(20) - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10) -} - -func (w *Writer) Int8(n int8) { - w.Buffer.EnsureSpace(4) - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10) -} - -func (w *Writer) Int16(n int16) { - w.Buffer.EnsureSpace(6) - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10) -} - -func (w *Writer) Int32(n int32) { - w.Buffer.EnsureSpace(11) - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10) -} - -func (w *Writer) Int(n int) { - w.Buffer.EnsureSpace(21) - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10) -} - -func (w *Writer) Int64(n int64) { - w.Buffer.EnsureSpace(21) - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10) -} - -func (w *Writer) Uint8Str(n uint8) { - w.Buffer.EnsureSpace(3) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Uint16Str(n uint16) { - w.Buffer.EnsureSpace(5) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Uint32Str(n uint32) { - w.Buffer.EnsureSpace(10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) UintStr(n uint) { - w.Buffer.EnsureSpace(20) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Uint64Str(n uint64) { - w.Buffer.EnsureSpace(20) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, n, 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) UintptrStr(n uintptr) { - w.Buffer.EnsureSpace(20) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendUint(w.Buffer.Buf, uint64(n), 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Int8Str(n int8) { - w.Buffer.EnsureSpace(4) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Int16Str(n int16) { - w.Buffer.EnsureSpace(6) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Int32Str(n int32) { - w.Buffer.EnsureSpace(11) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) IntStr(n int) { - w.Buffer.EnsureSpace(21) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, int64(n), 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Int64Str(n int64) { - w.Buffer.EnsureSpace(21) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendInt(w.Buffer.Buf, n, 10) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Float32(n float32) { - w.Buffer.EnsureSpace(20) - w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32) -} - -func (w *Writer) Float32Str(n float32) { - w.Buffer.EnsureSpace(20) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 32) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Float64(n float64) { - w.Buffer.EnsureSpace(20) - w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, n, 'g', -1, 64) -} - -func (w *Writer) Float64Str(n float64) { - w.Buffer.EnsureSpace(20) - w.Buffer.Buf = append(w.Buffer.Buf, '"') - w.Buffer.Buf = strconv.AppendFloat(w.Buffer.Buf, float64(n), 'g', -1, 64) - w.Buffer.Buf = append(w.Buffer.Buf, '"') -} - -func (w *Writer) Bool(v bool) { - w.Buffer.EnsureSpace(5) - if v { - w.Buffer.Buf = append(w.Buffer.Buf, "true"...) - } else { - w.Buffer.Buf = append(w.Buffer.Buf, "false"...) - } -} - -const chars = "0123456789abcdef" - -func getTable(falseValues ...int) [128]bool { - table := [128]bool{} - - for i := 0; i < 128; i++ { - table[i] = true - } - - for _, v := range falseValues { - table[v] = false - } - - return table -} - -var ( - htmlEscapeTable = getTable(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, '"', '&', '<', '>', '\\') - htmlNoEscapeTable = getTable(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, '"', '\\') -) - -func (w *Writer) String(s string) { - w.Buffer.AppendByte('"') - - // Portions of the string that contain no escapes are appended as - // byte slices. - - p := 0 // last non-escape symbol - - escapeTable := &htmlEscapeTable - if w.NoEscapeHTML { - escapeTable = &htmlNoEscapeTable - } - - for i := 0; i < len(s); { - c := s[i] - - if c < utf8.RuneSelf { - if escapeTable[c] { - // single-width character, no escaping is required - i++ - continue - } - - w.Buffer.AppendString(s[p:i]) - switch c { - case '\t': - w.Buffer.AppendString(`\t`) - case '\r': - w.Buffer.AppendString(`\r`) - case '\n': - w.Buffer.AppendString(`\n`) - case '\\': - w.Buffer.AppendString(`\\`) - case '"': - w.Buffer.AppendString(`\"`) - default: - w.Buffer.AppendString(`\u00`) - w.Buffer.AppendByte(chars[c>>4]) - w.Buffer.AppendByte(chars[c&0xf]) - } - - i++ - p = i - continue - } - - // broken utf - runeValue, runeWidth := utf8.DecodeRuneInString(s[i:]) - if runeValue == utf8.RuneError && runeWidth == 1 { - w.Buffer.AppendString(s[p:i]) - w.Buffer.AppendString(`\ufffd`) - i++ - p = i - continue - } - - // jsonp stuff - tab separator and line separator - if runeValue == '\u2028' || runeValue == '\u2029' { - w.Buffer.AppendString(s[p:i]) - w.Buffer.AppendString(`\u202`) - w.Buffer.AppendByte(chars[runeValue&0xf]) - i += runeWidth - p = i - continue - } - i += runeWidth - } - w.Buffer.AppendString(s[p:]) - w.Buffer.AppendByte('"') -} - -const encode = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" -const padChar = '=' - -func (w *Writer) base64(in []byte) { - - if len(in) == 0 { - return - } - - w.Buffer.EnsureSpace(((len(in)-1)/3 + 1) * 4) - - si := 0 - n := (len(in) / 3) * 3 - - for si < n { - // Convert 3x 8bit source bytes into 4 bytes - val := uint(in[si+0])<<16 | uint(in[si+1])<<8 | uint(in[si+2]) - - w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>18&0x3F], encode[val>>12&0x3F], encode[val>>6&0x3F], encode[val&0x3F]) - - si += 3 - } - - remain := len(in) - si - if remain == 0 { - return - } - - // Add the remaining small block - val := uint(in[si+0]) << 16 - if remain == 2 { - val |= uint(in[si+1]) << 8 - } - - w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>18&0x3F], encode[val>>12&0x3F]) - - switch remain { - case 2: - w.Buffer.Buf = append(w.Buffer.Buf, encode[val>>6&0x3F], byte(padChar)) - case 1: - w.Buffer.Buf = append(w.Buffer.Buf, byte(padChar), byte(padChar)) - } -} diff --git a/vendor/github.com/mattn/go-isatty/isatty_others.go b/vendor/github.com/mattn/go-isatty/isatty_others.go index 7402e0618..b24a2fadc 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_others.go +++ b/vendor/github.com/mattn/go-isatty/isatty_others.go @@ -1,5 +1,5 @@ -//go:build (appengine || js || nacl || tinygo || wasm) && !windows -// +build appengine js nacl tinygo wasm +//go:build (appengine || js || nacl || tinygo || wasm || wasip1 || wasip2) && !windows +// +build appengine js nacl tinygo wasm wasip1 wasip2 // +build !windows package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go index 8e3c99171..41edab076 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_windows.go +++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go @@ -31,6 +31,10 @@ func init() { if procGetFileInformationByHandleEx.Find() != nil { procGetFileInformationByHandleEx = nil } + // Check if NtQueryObject is available. + if procNtQueryObject.Find() != nil { + procNtQueryObject = nil + } } // IsTerminal return true if the file descriptor is terminal. @@ -45,7 +49,7 @@ func IsTerminal(fd uintptr) bool { // \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master func isCygwinPipeName(name string) bool { token := strings.Split(name, "-") - if len(token) < 5 { + if len(token) != 5 { return false } @@ -75,10 +79,10 @@ func isCygwinPipeName(name string) bool { return true } -// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler +// getFileNameByHandle use the undocumented ntdll NtQueryObject to get file full name from file handler // since GetFileInformationByHandleEx is not available under windows Vista and still some old fashion // guys are using Windows XP, this is a workaround for those guys, it will also work on system from -// Windows vista to 10 +// Windows Vista to 10 // see https://stackoverflow.com/a/18792477 for details func getFileNameByHandle(fd uintptr) (string, error) { if procNtQueryObject == nil { diff --git a/vendor/github.com/mitchellh/go-testing-interface/.travis.yml b/vendor/github.com/mitchellh/go-testing-interface/.travis.yml deleted file mode 100644 index 928d000ec..000000000 --- a/vendor/github.com/mitchellh/go-testing-interface/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -go: - - 1.8 - - 1.x - - tip - -script: - - go test - -matrix: - allow_failures: - - go: tip diff --git a/vendor/github.com/mitchellh/go-testing-interface/LICENSE b/vendor/github.com/mitchellh/go-testing-interface/LICENSE deleted file mode 100644 index a3866a291..000000000 --- a/vendor/github.com/mitchellh/go-testing-interface/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Mitchell Hashimoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/go-testing-interface/README.md b/vendor/github.com/mitchellh/go-testing-interface/README.md deleted file mode 100644 index 26781bbae..000000000 --- a/vendor/github.com/mitchellh/go-testing-interface/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# go-testing-interface - -go-testing-interface is a Go library that exports an interface that -`*testing.T` implements as well as a runtime version you can use in its -place. - -The purpose of this library is so that you can export test helpers as a -public API without depending on the "testing" package, since you can't -create a `*testing.T` struct manually. This lets you, for example, use the -public testing APIs to generate mock data at runtime, rather than just at -test time. - -## Usage & Example - -For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/go-testing-interface). - -Given a test helper written using `go-testing-interface` like this: - - import "github.com/mitchellh/go-testing-interface" - - func TestHelper(t testing.T) { - t.Fatal("I failed") - } - -You can call the test helper in a real test easily: - - import "testing" - - func TestThing(t *testing.T) { - TestHelper(t) - } - -You can also call the test helper at runtime if needed: - - import "github.com/mitchellh/go-testing-interface" - - func main() { - TestHelper(&testing.RuntimeT{}) - } - -## Why?! - -**Why would I call a test helper that takes a *testing.T at runtime?** - -You probably shouldn't. The only use case I've seen (and I've had) for this -is to implement a "dev mode" for a service where the test helpers are used -to populate mock data, create a mock DB, perhaps run service dependencies -in-memory, etc. - -Outside of a "dev mode", I've never seen a use case for this and I think -there shouldn't be one since the point of the `testing.T` interface is that -you can fail immediately. diff --git a/vendor/github.com/mitchellh/go-testing-interface/testing.go b/vendor/github.com/mitchellh/go-testing-interface/testing.go deleted file mode 100644 index 204afb420..000000000 --- a/vendor/github.com/mitchellh/go-testing-interface/testing.go +++ /dev/null @@ -1,84 +0,0 @@ -// +build !go1.9 - -package testing - -import ( - "fmt" - "log" -) - -// T is the interface that mimics the standard library *testing.T. -// -// In unit tests you can just pass a *testing.T struct. At runtime, outside -// of tests, you can pass in a RuntimeT struct from this package. -type T interface { - Error(args ...interface{}) - Errorf(format string, args ...interface{}) - Fail() - FailNow() - Failed() bool - Fatal(args ...interface{}) - Fatalf(format string, args ...interface{}) - Log(args ...interface{}) - Logf(format string, args ...interface{}) - Name() string - Skip(args ...interface{}) - SkipNow() - Skipf(format string, args ...interface{}) - Skipped() bool -} - -// RuntimeT implements T and can be instantiated and run at runtime to -// mimic *testing.T behavior. Unlike *testing.T, this will simply panic -// for calls to Fatal. For calls to Error, you'll have to check the errors -// list to determine whether to exit yourself. Name and Skip methods are -// unimplemented noops. -type RuntimeT struct { - failed bool -} - -func (t *RuntimeT) Error(args ...interface{}) { - log.Println(fmt.Sprintln(args...)) - t.Fail() -} - -func (t *RuntimeT) Errorf(format string, args ...interface{}) { - log.Println(fmt.Sprintf(format, args...)) - t.Fail() -} - -func (t *RuntimeT) Fatal(args ...interface{}) { - log.Println(fmt.Sprintln(args...)) - t.FailNow() -} - -func (t *RuntimeT) Fatalf(format string, args ...interface{}) { - log.Println(fmt.Sprintf(format, args...)) - t.FailNow() -} - -func (t *RuntimeT) Fail() { - t.failed = true -} - -func (t *RuntimeT) FailNow() { - panic("testing.T failed, see logs for output (if any)") -} - -func (t *RuntimeT) Failed() bool { - return t.failed -} - -func (t *RuntimeT) Log(args ...interface{}) { - log.Println(fmt.Sprintln(args...)) -} - -func (t *RuntimeT) Logf(format string, args ...interface{}) { - log.Println(fmt.Sprintf(format, args...)) -} - -func (t *RuntimeT) Name() string { return "" } -func (t *RuntimeT) Skip(args ...interface{}) {} -func (t *RuntimeT) SkipNow() {} -func (t *RuntimeT) Skipf(format string, args ...interface{}) {} -func (t *RuntimeT) Skipped() bool { return false } diff --git a/vendor/github.com/mitchellh/go-testing-interface/testing_go19.go b/vendor/github.com/mitchellh/go-testing-interface/testing_go19.go deleted file mode 100644 index 31b42cadf..000000000 --- a/vendor/github.com/mitchellh/go-testing-interface/testing_go19.go +++ /dev/null @@ -1,108 +0,0 @@ -// +build go1.9 - -// NOTE: This is a temporary copy of testing.go for Go 1.9 with the addition -// of "Helper" to the T interface. Go 1.9 at the time of typing is in RC -// and is set for release shortly. We'll support this on master as the default -// as soon as 1.9 is released. - -package testing - -import ( - "fmt" - "log" -) - -// T is the interface that mimics the standard library *testing.T. -// -// In unit tests you can just pass a *testing.T struct. At runtime, outside -// of tests, you can pass in a RuntimeT struct from this package. -type T interface { - Error(args ...interface{}) - Errorf(format string, args ...interface{}) - Fail() - FailNow() - Failed() bool - Fatal(args ...interface{}) - Fatalf(format string, args ...interface{}) - Log(args ...interface{}) - Logf(format string, args ...interface{}) - Name() string - Skip(args ...interface{}) - SkipNow() - Skipf(format string, args ...interface{}) - Skipped() bool - Helper() -} - -// RuntimeT implements T and can be instantiated and run at runtime to -// mimic *testing.T behavior. Unlike *testing.T, this will simply panic -// for calls to Fatal. For calls to Error, you'll have to check the errors -// list to determine whether to exit yourself. -type RuntimeT struct { - skipped bool - failed bool -} - -func (t *RuntimeT) Error(args ...interface{}) { - log.Println(fmt.Sprintln(args...)) - t.Fail() -} - -func (t *RuntimeT) Errorf(format string, args ...interface{}) { - log.Printf(format, args...) - t.Fail() -} - -func (t *RuntimeT) Fail() { - t.failed = true -} - -func (t *RuntimeT) FailNow() { - panic("testing.T failed, see logs for output (if any)") -} - -func (t *RuntimeT) Failed() bool { - return t.failed -} - -func (t *RuntimeT) Fatal(args ...interface{}) { - log.Print(args...) - t.FailNow() -} - -func (t *RuntimeT) Fatalf(format string, args ...interface{}) { - log.Printf(format, args...) - t.FailNow() -} - -func (t *RuntimeT) Log(args ...interface{}) { - log.Println(fmt.Sprintln(args...)) -} - -func (t *RuntimeT) Logf(format string, args ...interface{}) { - log.Println(fmt.Sprintf(format, args...)) -} - -func (t *RuntimeT) Name() string { - return "" -} - -func (t *RuntimeT) Skip(args ...interface{}) { - log.Print(args...) - t.SkipNow() -} - -func (t *RuntimeT) SkipNow() { - t.skipped = true -} - -func (t *RuntimeT) Skipf(format string, args ...interface{}) { - log.Printf(format, args...) - t.SkipNow() -} - -func (t *RuntimeT) Skipped() bool { - return t.skipped -} - -func (t *RuntimeT) Helper() {} diff --git a/vendor/github.com/oklog/run/.travis.yml b/vendor/github.com/oklog/run/.travis.yml deleted file mode 100644 index 362bdd41c..000000000 --- a/vendor/github.com/oklog/run/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: go -sudo: false -go: - - 1.x - - tip -install: - - go get -v github.com/golang/lint/golint - - go build ./... -script: - - go vet ./... - - $HOME/gopath/bin/golint . - - go test -v -race ./... diff --git a/vendor/github.com/oklog/run/LICENSE b/vendor/github.com/oklog/run/LICENSE index 261eeb9e9..374773d07 100644 --- a/vendor/github.com/oklog/run/LICENSE +++ b/vendor/github.com/oklog/run/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright 2017 Peter Bourgon Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/github.com/oklog/run/README.md b/vendor/github.com/oklog/run/README.md index a7228cd9a..18a10a3d4 100644 --- a/vendor/github.com/oklog/run/README.md +++ b/vendor/github.com/oklog/run/README.md @@ -1,7 +1,7 @@ # run -[![GoDoc](https://godoc.org/github.com/oklog/run?status.svg)](https://godoc.org/github.com/oklog/run) -[![Build Status](https://travis-ci.org/oklog/run.svg?branch=master)](https://travis-ci.org/oklog/run) +[![GoDoc](https://godoc.org/github.com/oklog/run?status.svg)](https://godoc.org/github.com/oklog/run) +[![test](https://github.com/oklog/run/actions/workflows/test.yaml/badge.svg?branch=main&event=push)](https://github.com/oklog/run/actions/workflows/test.yaml) [![Go Report Card](https://goreportcard.com/badge/github.com/oklog/run)](https://goreportcard.com/report/github.com/oklog/run) [![Apache 2 licensed](https://img.shields.io/badge/license-Apache2-blue.svg)](https://raw.githubusercontent.com/oklog/run/master/LICENSE) @@ -10,12 +10,14 @@ run.Group is a universal mechanism to manage goroutine lifecycles. Create a zero-value run.Group, and then add actors to it. Actors are defined as a pair of functions: an **execute** function, which should run synchronously; and an **interrupt** function, which, when invoked, should cause the execute -function to return. Finally, invoke Run, which blocks until the first actor -returns. This general-purpose API allows callers to model pretty much any -runnable task, and achieve well-defined lifecycle semantics for the group. +function to return. Finally, invoke Run, which concurrently runs all of the +actors, waits until the first actor exits, invokes the interrupt functions, and +finally returns control to the caller only once all actors have returned. This +general-purpose API allows callers to model pretty much any runnable task, and +achieve well-defined lifecycle semantics for the group. -run.Group was written to manage component lifecycles in func main for -[OK Log](https://github.com/oklog/oklog). +run.Group was written to manage component lifecycles in func main for +[OK Log](https://github.com/oklog/oklog). But it's useful in any circumstance where you need to orchestrate multiple goroutines as a unit whole. [Click here](https://www.youtube.com/watch?v=LHe1Cb_Ud_M&t=15m45s) to see a @@ -60,14 +62,30 @@ g.Add(func() error { }) ``` +### http.Server graceful Shutdown + +```go +httpServer := &http.Server{ + Addr: "localhost:8080", + Handler: ..., +} +g.Add(func() error { + return httpServer.ListenAndServe() +}, func(error) { + ctx, cancel := context.WithTimeout(context.TODO(), 3*time.Second) + defer cancel() + httpServer.Shutdown(ctx) +}) +``` + ## Comparisons -Package run is somewhat similar to package -[errgroup](https://godoc.org/golang.org/x/sync/errgroup), +Package run is somewhat similar to package +[errgroup](https://godoc.org/golang.org/x/sync/errgroup), except it doesn't require actor goroutines to understand context semantics. It's somewhat similar to package -[tomb.v1](https://godoc.org/gopkg.in/tomb.v1) or +[tomb.v1](https://godoc.org/gopkg.in/tomb.v1) or [tomb.v2](https://godoc.org/gopkg.in/tomb.v2), -except it has a much smaller API surface, delegating e.g. staged shutdown of +except it has a much smaller API surface, delegating e.g. staged shutdown of goroutines to the caller. diff --git a/vendor/github.com/oklog/run/actors.go b/vendor/github.com/oklog/run/actors.go new file mode 100644 index 000000000..ad6aed866 --- /dev/null +++ b/vendor/github.com/oklog/run/actors.go @@ -0,0 +1,96 @@ +package run + +import ( + "context" + "errors" + "fmt" + "os" + "os/signal" +) + +// ContextHandler returns an actor, i.e. an execute and interrupt func, that +// terminates when the provided context is canceled. +func ContextHandler(ctx context.Context) (execute func() error, interrupt func(error)) { + ctx, cancel := context.WithCancel(ctx) + return func() error { + <-ctx.Done() + return ctx.Err() + }, func(error) { + cancel() + } +} + +// SignalHandler returns an actor, i.e. an execute and interrupt func, that +// terminates with ErrSignal when the process receives one of the provided +// signals, or with ctx.Error() when the parent context is canceled. If no +// signals are provided, the actor will terminate on any signal, per +// [signal.Notify]. +func SignalHandler(ctx context.Context, signals ...os.Signal) (execute func() error, interrupt func(error)) { + ctx, cancel := context.WithCancel(ctx) + return func() error { + testc := getTestSigChan(ctx) + sigc := make(chan os.Signal, 1) + signal.Notify(sigc, signals...) + defer signal.Stop(sigc) + select { + case sig := <-testc: + return &SignalError{Signal: sig} + case sig := <-sigc: + return &SignalError{Signal: sig} + case <-ctx.Done(): + return ctx.Err() + } + }, func(error) { + cancel() + } +} + +type testSigChanKey struct{} + +func getTestSigChan(ctx context.Context) <-chan os.Signal { + c, _ := ctx.Value(testSigChanKey{}).(<-chan os.Signal) // can be nil + return c +} + +func putTestSigChan(ctx context.Context, c <-chan os.Signal) context.Context { + return context.WithValue(ctx, testSigChanKey{}, c) +} + +// SignalError is returned by the signal handler's execute function when it +// terminates due to a received signal. +// +// SignalError has a design error that impacts comparison with errors.As. +// Callers should prefer using errors.Is(err, ErrSignal) to check for signal +// errors, and should only use errors.As in the rare case that they need to +// program against the specific os.Signal value. +type SignalError struct { + Signal os.Signal +} + +// Error implements the error interface. +// +// It was a design error to define this method on a value receiver rather than a +// pointer receiver. For compatibility reasons it won't be changed. +func (e SignalError) Error() string { + return fmt.Sprintf("received signal %s", e.Signal) +} + +// Is addresses a design error in the SignalError type, so that errors.Is with +// ErrSignal will return true. +func (e SignalError) Is(err error) bool { + return errors.Is(err, ErrSignal) +} + +// As fixes a design error in the SignalError type, so that errors.As with the +// literal `&SignalError{}` will return true. +func (e SignalError) As(target interface{}) bool { + switch target.(type) { + case *SignalError, SignalError: + return true + default: + return false + } +} + +// ErrSignal is returned by SignalHandler when a signal triggers termination. +var ErrSignal = errors.New("signal error") diff --git a/vendor/github.com/openshift/api/config/v1/types.go b/vendor/github.com/openshift/api/config/v1/types.go index 3e17ca0cc..e7106ef7a 100644 --- a/vendor/github.com/openshift/api/config/v1/types.go +++ b/vendor/github.com/openshift/api/config/v1/types.go @@ -284,7 +284,12 @@ type ClientConnectionOverrides struct { } // GenericControllerConfig provides information to configure a controller +// +// 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 type GenericControllerConfig struct { + metav1.TypeMeta `json:",inline"` + // servingInfo is the HTTP serving information for the controller's endpoints ServingInfo HTTPServingInfo `json:"servingInfo"` diff --git a/vendor/github.com/openshift/api/config/v1/types_apiserver.go b/vendor/github.com/openshift/api/config/v1/types_apiserver.go index 31d888185..b8a4399db 100644 --- a/vendor/github.com/openshift/api/config/v1/types_apiserver.go +++ b/vendor/github.com/openshift/api/config/v1/types_apiserver.go @@ -34,6 +34,7 @@ type APIServer struct { Status APIServerStatus `json:"status"` } +// +openshift:validation:FeatureGateAwareXValidation:featureGate=TLSAdherence,rule="has(oldSelf.tlsAdherence) ? has(self.tlsAdherence) : true",message="tlsAdherence may not be removed once set" type APIServerSpec struct { // servingCert is the TLS cert info for serving secure traffic. If not specified, operator managed certificates // will be used for serving secure traffic. @@ -62,6 +63,39 @@ type APIServerSpec struct { // The current default is the Intermediate profile. // +optional TLSSecurityProfile *TLSSecurityProfile `json:"tlsSecurityProfile,omitempty"` + // tlsAdherence controls if components in the cluster adhere to the TLS security profile + // configured on this APIServer resource. + // + // Valid values are "LegacyAdheringComponentsOnly" and "StrictAllComponents". + // + // When set to "LegacyAdheringComponentsOnly", components that already honor the + // cluster-wide TLS profile continue to do so. Components that do not already honor + // it continue to use their individual TLS configurations. + // + // When set to "StrictAllComponents", all components must honor the configured TLS + // profile unless they have a component-specific TLS configuration that overrides + // it. This mode is recommended for security-conscious deployments and is required + // for certain compliance frameworks. + // + // Note: Some components such as Kubelet and IngressController have their own + // dedicated TLS configuration mechanisms via KubeletConfig and IngressController + // CRs respectively. When these component-specific TLS configurations are set, + // they take precedence over the cluster-wide tlsSecurityProfile. When not set, + // these components fall back to the cluster-wide default. + // + // Components that encounter an unknown value for tlsAdherence should treat it + // as "StrictAllComponents" and log a warning to ensure forward compatibility + // while defaulting to the more secure behavior. + // + // This field is optional. + // 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 LegacyAdheringComponentsOnly. + // + // Once set, this field may be changed to a different value, but may not be removed. + // +openshift:enable:FeatureGate=TLSAdherence + // +optional + TLSAdherence TLSAdherencePolicy `json:"tlsAdherence,omitempty"` // audit specifies the settings for audit configuration to be applied to all OpenShift-provided // API servers in the cluster. // +optional @@ -237,6 +271,35 @@ const ( type APIServerStatus struct { } +// TLSAdherencePolicy defines which components adhere to the TLS security profile. +// Implementors should use the ShouldHonorClusterTLSProfile helper function from library-go +// rather than checking these values directly. +// +kubebuilder:validation:Enum=LegacyAdheringComponentsOnly;StrictAllComponents +type TLSAdherencePolicy string + +const ( + // TLSAdherencePolicyNoOpinion represents an empty/unset value for tlsAdherence. + // This value cannot be explicitly set and is only present when the field is omitted. + // When the field is omitted, the cluster defaults to LegacyAdheringComponentsOnly + // behavior. Components should treat this the same as LegacyAdheringComponentsOnly. + TLSAdherencePolicyNoOpinion TLSAdherencePolicy = "" + + // TLSAdherencePolicyLegacyAdheringComponentsOnly maintains backward-compatible behavior. + // Components that already honor the cluster-wide TLS profile (such as kube-apiserver, + // openshift-apiserver, oauth-apiserver, and others) continue to do so. Components that do + // not already honor it continue to use their individual TLS configurations (e.g., + // IngressController.spec.tlsSecurityProfile, KubeletConfig.spec.tlsSecurityProfile, + // or component defaults). No additional components are required to start honoring the + // cluster-wide profile in this mode. + TLSAdherencePolicyLegacyAdheringComponentsOnly TLSAdherencePolicy = "LegacyAdheringComponentsOnly" + + // TLSAdherencePolicyStrictAllComponents means all components must honor the configured TLS + // profile unless they have a component-specific TLS configuration that overrides it. + // This mode is recommended for security-conscious deployments and is required + // for certain compliance frameworks. + TLSAdherencePolicyStrictAllComponents TLSAdherencePolicy = "StrictAllComponents" +) + // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer). diff --git a/vendor/github.com/openshift/api/config/v1/types_authentication.go b/vendor/github.com/openshift/api/config/v1/types_authentication.go index 64d0f399b..1a036bbb6 100644 --- a/vendor/github.com/openshift/api/config/v1/types_authentication.go +++ b/vendor/github.com/openshift/api/config/v1/types_authentication.go @@ -618,6 +618,7 @@ type OIDCClientReference struct { // +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDC,rule="has(self.claim)",message="claim is required" // +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithUIDAndExtraClaimMappings,rule="has(self.claim)",message="claim is required" // +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithUpstreamParity,rule="has(self.claim) ? !has(self.expression) : has(self.expression)",message="precisely one of claim or expression must be set" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithUpstreamParity,rule="has(self.expression) && size(self.expression) > 0 ? !has(self.prefixPolicy) || self.prefixPolicy != 'Prefix' : true",message="prefixPolicy must not be set to 'Prefix' when expression is set" type UsernameClaimMapping struct { // claim is an optional field that configures the JWT token claim whose value is assigned to the cluster identity field associated with this mapping. // claim is required when the ExternalOIDCWithUpstreamParity feature gate is not enabled. @@ -650,11 +651,9 @@ type UsernameClaimMapping struct { // Allowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string). // // When set to 'Prefix', the value specified in the prefix field will be prepended to the value of the JWT claim. - // // The prefix field must be set when prefixPolicy is 'Prefix'. - // + // Must not be set to 'Prefix' when expression is set. // When set to 'NoPrefix', no prefix will be prepended to the value of the JWT claim. - // // When omitted, this means no opinion and the platform is left to choose any prefixes that are applied which is subject to change over time. // Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim when the claim is not 'email'. // @@ -684,7 +683,7 @@ type UsernameClaimMapping struct { // +enum type UsernamePrefixPolicy string -var ( +const ( // NoOpinion let's the cluster assign prefixes. If the username claim is email, there is no prefix // If the username claim is anything else, it is prefixed by the issuerURL NoOpinion UsernamePrefixPolicy = "" @@ -710,12 +709,14 @@ type UsernamePrefix struct { // PrefixedClaimMapping configures a claim mapping // that allows for an optional prefix. +// +openshift:validation:FeatureGateAwareXValidation:featureGate=ExternalOIDCWithUpstreamParity,rule="has(self.expression) && size(self.expression) > 0 ? (!has(self.prefix) || size(self.prefix) == 0) : true",message="prefix must not be set to a non-empty value when expression is set" type PrefixedClaimMapping struct { TokenClaimMapping `json:",inline"` // prefix is an optional field that configures the prefix that will be applied to the cluster identity attribute during the process of mapping JWT claims to cluster identity attributes. // - // When omitted (""), no prefix is applied to the cluster identity attribute. + // When omitted or set to an empty string (""), no prefix is applied to the cluster identity attribute. + // Must not be set to a non-empty value when expression is set. // // Example: if `prefix` is set to "myoidc:" and the `claim` in JWT contains an array of strings "a", "b" and "c", the mapping will result in an array of string "myoidc:a", "myoidc:b" and "myoidc:c". // @@ -734,10 +735,10 @@ type TokenValidationRuleType string const ( // TokenValidationRuleTypeRequiredClaim indicates that the token must contain a specific claim. // Used as a value for TokenValidationRuleType. - TokenValidationRuleTypeRequiredClaim = "RequiredClaim" + TokenValidationRuleTypeRequiredClaim TokenValidationRuleType = "RequiredClaim" // TokenValidationRuleTypeCEL indicates that the token validation is defined via a CEL expression. // Used as a value for TokenValidationRuleType. - TokenValidationRuleTypeCEL = "CEL" + TokenValidationRuleTypeCEL TokenValidationRuleType = "CEL" ) // TokenClaimValidationRule represents a validation rule based on token claims. 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 5f36f693d..f8d45114a 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 @@ -283,6 +283,16 @@ type UpdateHistory struct { // ClusterID is string RFC4122 uuid. type ClusterID string +// UpdateMode defines how an update should be processed. +// +enum +// +kubebuilder:validation:Enum=Preflight +type UpdateMode string + +const ( + // UpdateModePreflight allows an update to be checked for compatibility without committing to updating the cluster. + UpdateModePreflight UpdateMode = "Preflight" +) + // ClusterVersionArchitecture enumerates valid cluster architectures. // +kubebuilder:validation:Enum="Multi";"" type ClusterVersionArchitecture string @@ -760,6 +770,22 @@ type Update struct { // +listMapKey=name // +optional AcceptRisks []AcceptRisk `json:"acceptRisks,omitempty"` + + // mode determines how an update should be processed. + // The only valid value is "Preflight". + // When omitted, the cluster performs a normal update by applying the specified version or image to the cluster. + // This is the standard update behavior. + // When set to "Preflight", the cluster runs compatibility checks against the target release without + // performing an actual update. Compatibility results, including any detected risks, are reported + // in status.conditionalUpdates and status.conditionalUpdateRisks alongside risks from the update + // recommendation service. + // This allows administrators to assess update readiness and address issues before committing to the update. + // Preflight mode is particularly useful for skip-level updates where upgrade compatibility needs to be + // verified across multiple minor versions. + // When mode is set to "Preflight", the same rules for version, image, and architecture apply as for normal updates. + // +openshift:enable:FeatureGate=ClusterUpdatePreflight + // +optional + Mode UpdateMode `json:"mode,omitempty"` } // AcceptRisk represents a risk that is considered acceptable. diff --git a/vendor/github.com/openshift/api/config/v1/types_dns.go b/vendor/github.com/openshift/api/config/v1/types_dns.go index 06eb75ccf..efbdc3ae5 100644 --- a/vendor/github.com/openshift/api/config/v1/types_dns.go +++ b/vendor/github.com/openshift/api/config/v1/types_dns.go @@ -134,7 +134,14 @@ type AWSDNSSpec struct { // privateZoneIAMRole contains the ARN of an IAM role that should be assumed when performing // operations on the cluster's private hosted zone specified in the cluster DNS config. // When left empty, no role should be assumed. - // +kubebuilder:validation:Pattern:=`^arn:(aws|aws-cn|aws-us-gov):iam::[0-9]{12}:role\/.*$` + // + // The ARN must follow the format: arn::iam:::role/, where: + // is the AWS partition (aws, aws-cn, aws-us-gov, or aws-eusc), + // is a 12-digit numeric identifier for the AWS account, + // is the IAM role name. + // + // +openshift:validation:FeatureGateAwareXValidation:featureGate="",rule=`matches(self, '^arn:(aws|aws-cn|aws-us-gov):iam::[0-9]{12}:role/.*$')`,message=`privateZoneIAMRole must be a valid AWS IAM role ARN in the format: arn::iam:::role/` + // +openshift:validation:FeatureGateAwareXValidation:featureGate=AWSEuropeanSovereignCloudInstall,rule=`matches(self, '^arn:(aws|aws-cn|aws-us-gov|aws-eusc):iam::[0-9]{12}:role/.*$')`,message=`privateZoneIAMRole must be a valid AWS IAM role ARN in the format: arn::iam:::role/` // +optional PrivateZoneIAMRole string `json:"privateZoneIAMRole"` } 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 369ba1e7a..c579be3a1 100644 --- a/vendor/github.com/openshift/api/config/v1/types_infrastructure.go +++ b/vendor/github.com/openshift/api/config/v1/types_infrastructure.go @@ -102,11 +102,11 @@ type InfrastructureStatus struct { // and the operators should not configure the operand for highly-available operation // The 'External' mode indicates that the control plane is hosted externally to the cluster and that // its components are not visible within the cluster. + // The 'HighlyAvailableArbiter' mode indicates that the control plane will consist of 2 control-plane nodes + // that run conventional services and 1 smaller sized arbiter node that runs a bare minimum of services to maintain quorum. // +kubebuilder:default=HighlyAvailable - // +openshift:validation:FeatureGateAwareEnum:featureGate="",enum=HighlyAvailable;SingleReplica;External - // +openshift:validation:FeatureGateAwareEnum:featureGate=HighlyAvailableArbiter,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;External - // +openshift:validation:FeatureGateAwareEnum:featureGate=DualReplica,enum=HighlyAvailable;SingleReplica;DualReplica;External - // +openshift:validation:FeatureGateAwareEnum:requiredFeatureGate=HighlyAvailableArbiter;DualReplica,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;External + // +openshift:validation:FeatureGateAwareEnum:featureGate="",enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;External + // +openshift:validation:FeatureGateAwareEnum:featureGate=DualReplica,enum=HighlyAvailable;HighlyAvailableArbiter;SingleReplica;DualReplica;External // +optional ControlPlaneTopology TopologyMode `json:"controlPlaneTopology"` @@ -787,7 +787,6 @@ type GCPPlatformStatus struct { // // +default={"dnsType": "PlatformDefault"} // +kubebuilder:default={"dnsType": "PlatformDefault"} - // +openshift:enable:FeatureGate=GCPClusterHostedDNSInstall // +optional // +nullable CloudLoadBalancerConfig *CloudLoadBalancerConfig `json:"cloudLoadBalancerConfig,omitempty"` diff --git a/vendor/github.com/openshift/api/config/v1/types_ingress.go b/vendor/github.com/openshift/api/config/v1/types_ingress.go index f70fe8f44..26e0ebf21 100644 --- a/vendor/github.com/openshift/api/config/v1/types_ingress.go +++ b/vendor/github.com/openshift/api/config/v1/types_ingress.go @@ -43,6 +43,7 @@ type IngressSpec struct { // default ingresscontroller domain will follow this pattern: "*.". // // Once set, changing domain is not currently supported. + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="domain is immutable once set" Domain string `json:"domain"` // appsDomain is an optional domain to use instead of the one specified diff --git a/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go index 30b85b78e..a604d2f63 100644 --- a/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go @@ -2560,6 +2560,7 @@ func (in *GenericAPIServerConfig) DeepCopy() *GenericAPIServerConfig { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GenericControllerConfig) DeepCopyInto(out *GenericControllerConfig) { *out = *in + out.TypeMeta = in.TypeMeta in.ServingInfo.DeepCopyInto(&out.ServingInfo) out.LeaderElection = in.LeaderElection out.Authentication = in.Authentication 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 eb7c485e0..84c1443d4 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 @@ -8,6 +8,7 @@ apiservers.config.openshift.io: FeatureGates: - KMSEncryption - KMSEncryptionProvider + - TLSAdherence FilenameOperatorName: config-operator FilenameOperatorOrdering: "01" FilenameRunLevel: "0000_10" @@ -144,6 +145,7 @@ clusterversions.config.openshift.io: Category: "" FeatureGates: - ClusterUpdateAcceptRisks + - ClusterUpdatePreflight - ImageStreamImportMode - SignatureStores FilenameOperatorName: cluster-version-operator @@ -204,7 +206,8 @@ dnses.config.openshift.io: CRDName: dnses.config.openshift.io Capability: "" Category: "" - FeatureGates: [] + FeatureGates: + - AWSEuropeanSovereignCloudInstall FilenameOperatorName: config-operator FilenameOperatorOrdering: "01" FilenameRunLevel: "0000_10" @@ -370,9 +373,6 @@ infrastructures.config.openshift.io: - AzureDualStackInstall - DualReplica - DyanmicServiceEndpointIBMCloud - - GCPClusterHostedDNSInstall - - HighlyAvailableArbiter - - HighlyAvailableArbiter+DualReplica - NutanixMultiSubnets - OnPremDNSRecords - VSphereHostVMGroupZonal 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 621dbbebd..4a5346dba 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 @@ -137,7 +137,7 @@ func (GenericAPIServerConfig) SwaggerDoc() map[string]string { } var map_GenericControllerConfig = map[string]string{ - "": "GenericControllerConfig provides information to configure a controller", + "": "GenericControllerConfig provides information to configure a controller\n\nCompatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", "servingInfo": "servingInfo is the HTTP serving information for the controller's endpoints", "leaderElection": "leaderElection provides information to elect a leader. Only override this if you have a specific need", "authentication": "authentication allows configuration of authentication for the endpoints", @@ -319,6 +319,7 @@ var map_APIServerSpec = map[string]string{ "additionalCORSAllowedOrigins": "additionalCORSAllowedOrigins lists additional, user-defined regular expressions describing hosts for which the API server allows access using the CORS headers. This may be needed to access the API and the integrated OAuth server from JavaScript applications. The values are regular expressions that correspond to the Golang regular expression language.", "encryption": "encryption allows the configuration of encryption of resources at the datastore layer.", "tlsSecurityProfile": "tlsSecurityProfile specifies settings for TLS connections for externally exposed servers.\n\nWhen omitted, this means no opinion and the platform is left to choose a reasonable default, which is subject to change over time. The current default is the Intermediate profile.", + "tlsAdherence": "tlsAdherence controls if components in the cluster adhere to the TLS security profile configured on this APIServer resource.\n\nValid values are \"LegacyAdheringComponentsOnly\" and \"StrictAllComponents\".\n\nWhen set to \"LegacyAdheringComponentsOnly\", components that already honor the cluster-wide TLS profile continue to do so. Components that do not already honor it continue to use their individual TLS configurations.\n\nWhen set to \"StrictAllComponents\", all components must honor the configured TLS profile unless they have a component-specific TLS configuration that overrides it. This mode is recommended for security-conscious deployments and is required for certain compliance frameworks.\n\nNote: Some components such as Kubelet and IngressController have their own dedicated TLS configuration mechanisms via KubeletConfig and IngressController CRs respectively. When these component-specific TLS configurations are set, they take precedence over the cluster-wide tlsSecurityProfile. When not set, these components fall back to the cluster-wide default.\n\nComponents that encounter an unknown value for tlsAdherence should treat it as \"StrictAllComponents\" and log a warning to ensure forward compatibility while defaulting to the more secure behavior.\n\nThis field is optional. 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 LegacyAdheringComponentsOnly.\n\nOnce set, this field may be changed to a different value, but may not be removed.", "audit": "audit specifies the settings for audit configuration to be applied to all OpenShift-provided API servers in the cluster.", } @@ -458,7 +459,7 @@ func (OIDCProvider) SwaggerDoc() map[string]string { var map_PrefixedClaimMapping = map[string]string{ "": "PrefixedClaimMapping configures a claim mapping that allows for an optional prefix.", - "prefix": "prefix is an optional field that configures the prefix that will be applied to the cluster identity attribute during the process of mapping JWT claims to cluster identity attributes.\n\nWhen omitted (\"\"), no prefix is applied to the cluster identity attribute.\n\nExample: if `prefix` is set to \"myoidc:\" and the `claim` in JWT contains an array of strings \"a\", \"b\" and \"c\", the mapping will result in an array of string \"myoidc:a\", \"myoidc:b\" and \"myoidc:c\".", + "prefix": "prefix is an optional field that configures the prefix that will be applied to the cluster identity attribute during the process of mapping JWT claims to cluster identity attributes.\n\nWhen omitted or set to an empty string (\"\"), no prefix is applied to the cluster identity attribute. Must not be set to a non-empty value when expression is set.\n\nExample: if `prefix` is set to \"myoidc:\" and the `claim` in JWT contains an array of strings \"a\", \"b\" and \"c\", the mapping will result in an array of string \"myoidc:a\", \"myoidc:b\" and \"myoidc:c\".", } func (PrefixedClaimMapping) SwaggerDoc() map[string]string { @@ -549,7 +550,7 @@ func (TokenUserValidationRule) SwaggerDoc() map[string]string { var map_UsernameClaimMapping = map[string]string{ "claim": "claim is an optional field that configures the JWT token claim whose value is assigned to the cluster identity field associated with this mapping. claim is required when the ExternalOIDCWithUpstreamParity feature gate is not enabled. When the ExternalOIDCWithUpstreamParity feature gate is enabled, claim must not be set when expression is set.\n\nclaim must not be an empty string (\"\") and must not exceed 256 characters.", "expression": "expression is an optional CEL expression used to derive the username from JWT claims.\n\nCEL expressions have access to the token claims through a CEL variable, 'claims'.\n\nexpression must be at least 1 character and must not exceed 1024 characters in length. expression must not be set when claim is set.", - "prefixPolicy": "prefixPolicy is an optional field that configures how a prefix should be applied to the value of the JWT claim specified in the 'claim' field.\n\nAllowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).\n\nWhen set to 'Prefix', the value specified in the prefix field will be prepended to the value of the JWT claim.\n\nThe prefix field must be set when prefixPolicy is 'Prefix'.\n\nWhen set to 'NoPrefix', no prefix will be prepended to the value of the JWT claim.\n\nWhen omitted, this means no opinion and the platform is left to choose any prefixes that are applied which is subject to change over time. Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim when the claim is not 'email'.\n\nAs an example, consider the following scenario:\n\n `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,\n the JWT claims include \"username\":\"userA\" and \"email\":\"userA@myoidc.tld\",\n and `claim` is set to:\n - \"username\": the mapped value will be \"https://myoidc.tld#userA\"\n - \"email\": the mapped value will be \"userA@myoidc.tld\"", + "prefixPolicy": "prefixPolicy is an optional field that configures how a prefix should be applied to the value of the JWT claim specified in the 'claim' field.\n\nAllowed values are 'Prefix', 'NoPrefix', and omitted (not provided or an empty string).\n\nWhen set to 'Prefix', the value specified in the prefix field will be prepended to the value of the JWT claim. The prefix field must be set when prefixPolicy is 'Prefix'. Must not be set to 'Prefix' when expression is set. When set to 'NoPrefix', no prefix will be prepended to the value of the JWT claim. When omitted, this means no opinion and the platform is left to choose any prefixes that are applied which is subject to change over time. Currently, the platform prepends `{issuerURL}#` to the value of the JWT claim when the claim is not 'email'.\n\nAs an example, consider the following scenario:\n\n `prefix` is unset, `issuerURL` is set to `https://myoidc.tld`,\n the JWT claims include \"username\":\"userA\" and \"email\":\"userA@myoidc.tld\",\n and `claim` is set to:\n - \"username\": the mapped value will be \"https://myoidc.tld#userA\"\n - \"email\": the mapped value will be \"userA@myoidc.tld\"", "prefix": "prefix configures the prefix that should be prepended to the value of the JWT claim.\n\nprefix must be set when prefixPolicy is set to 'Prefix' and must be unset otherwise.", } @@ -917,6 +918,7 @@ var map_Update = map[string]string{ "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 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.", "acceptRisks": "acceptRisks is an optional set of names of conditional update risks that are considered acceptable. A conditional update is performed only if all of its risks are acceptable. This list may contain entries that apply to current, previous or future updates. The entries therefore may not map directly to a risk in .status.conditionalUpdateRisks. acceptRisks must not contain more than 1000 entries. Entries in this list must be unique.", + "mode": "mode determines how an update should be processed. The only valid value is \"Preflight\". When omitted, the cluster performs a normal update by applying the specified version or image to the cluster. This is the standard update behavior. When set to \"Preflight\", the cluster runs compatibility checks against the target release without performing an actual update. Compatibility results, including any detected risks, are reported in status.conditionalUpdates and status.conditionalUpdateRisks alongside risks from the update recommendation service. This allows administrators to assess update readiness and address issues before committing to the update. Preflight mode is particularly useful for skip-level updates where upgrade compatibility needs to be verified across multiple minor versions. When mode is set to \"Preflight\", the same rules for version, image, and architecture apply as for normal updates.", } func (Update) SwaggerDoc() map[string]string { @@ -986,7 +988,7 @@ func (ConsoleStatus) SwaggerDoc() map[string]string { var map_AWSDNSSpec = map[string]string{ "": "AWSDNSSpec contains DNS configuration specific to the Amazon Web Services cloud provider.", - "privateZoneIAMRole": "privateZoneIAMRole contains the ARN of an IAM role that should be assumed when performing operations on the cluster's private hosted zone specified in the cluster DNS config. When left empty, no role should be assumed.", + "privateZoneIAMRole": "privateZoneIAMRole contains the ARN of an IAM role that should be assumed when performing operations on the cluster's private hosted zone specified in the cluster DNS config. When left empty, no role should be assumed.\n\nThe ARN must follow the format: arn::iam:::role/, where: is the AWS partition (aws, aws-cn, aws-us-gov, or aws-eusc), is a 12-digit numeric identifier for the AWS account, is the IAM role name.", } func (AWSDNSSpec) SwaggerDoc() map[string]string { @@ -1752,7 +1754,7 @@ var map_InfrastructureStatus = map[string]string{ "etcdDiscoveryDomain": "etcdDiscoveryDomain is the domain used to fetch the SRV records for discovering etcd servers and clients. For more info: https://github.com/etcd-io/etcd/blob/329be66e8b3f9e2e6af83c123ff89297e49ebd15/Documentation/op-guide/clustering.md#dns-discovery deprecated: as of 4.7, this field is no longer set or honored. It will be removed in a future release.", "apiServerURL": "apiServerURL is a valid URI with scheme 'https', address and optionally a port (defaulting to 443). apiServerURL can be used by components like the web console to tell users where to find the Kubernetes API.", "apiServerInternalURI": "apiServerInternalURL is a valid URI with scheme 'https', address and optionally a port (defaulting to 443). apiServerInternalURL can be used by components like kubelets, to contact the Kubernetes API server using the infrastructure provider rather than Kubernetes networking.", - "controlPlaneTopology": "controlPlaneTopology expresses the expectations for operands that normally run on control nodes. The default is 'HighlyAvailable', which represents the behavior operators have in a \"normal\" cluster. The 'SingleReplica' mode will be used in single-node deployments and the operators should not configure the operand for highly-available operation The 'External' mode indicates that the control plane is hosted externally to the cluster and that its components are not visible within the cluster.", + "controlPlaneTopology": "controlPlaneTopology expresses the expectations for operands that normally run on control nodes. The default is 'HighlyAvailable', which represents the behavior operators have in a \"normal\" cluster. The 'SingleReplica' mode will be used in single-node deployments and the operators should not configure the operand for highly-available operation The 'External' mode indicates that the control plane is hosted externally to the cluster and that its components are not visible within the cluster. The 'HighlyAvailableArbiter' mode indicates that the control plane will consist of 2 control-plane nodes that run conventional services and 1 smaller sized arbiter node that runs a bare minimum of services to maintain quorum.", "infrastructureTopology": "infrastructureTopology expresses the expectations for infrastructure services that do not run on control plane nodes, usually indicated by a node selector for a `role` value other than `master`. The default is 'HighlyAvailable', which represents the behavior operators have in a \"normal\" cluster. The 'SingleReplica' mode will be used in single-node deployments and the operators should not configure the operand for highly-available operation NOTE: External topology mode is not applicable for this field.", "cpuPartitioning": "cpuPartitioning expresses if CPU partitioning is a currently enabled feature in the cluster. CPU Partitioning means that this cluster can support partitioning workloads to specific CPU Sets. Valid values are \"None\" and \"AllNodes\". When omitted, the default value is \"None\". The default value of \"None\" indicates that no nodes will be setup with CPU partitioning. The \"AllNodes\" value indicates that all nodes have been setup with CPU partitioning, and can then be further configured via the PerformanceProfile API.", } diff --git a/vendor/github.com/openshift/api/machine/v1/Makefile b/vendor/github.com/openshift/api/machine/v1/Makefile new file mode 100644 index 000000000..767014ac1 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/Makefile @@ -0,0 +1,3 @@ +.PHONY: test +test: + make -C ../../tests test GINKGO_EXTRA_ARGS=--focus="machine.openshift.io/v1" diff --git a/vendor/github.com/openshift/api/machine/v1/common.go b/vendor/github.com/openshift/api/machine/v1/common.go new file mode 100644 index 000000000..941d22b1c --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/common.go @@ -0,0 +1,13 @@ +package v1 + +// InstanceTenancy indicates if instance should run on shared or single-tenant hardware. +type InstanceTenancy string + +const ( + // DefaultTenancy instance runs on shared hardware + DefaultTenancy InstanceTenancy = "default" + // DedicatedTenancy instance runs on single-tenant hardware + DedicatedTenancy InstanceTenancy = "dedicated" + // HostTenancy instance runs on a Dedicated Host, which is an isolated server with configurations that you can control. + HostTenancy InstanceTenancy = "host" +) diff --git a/vendor/github.com/openshift/api/machine/v1/doc.go b/vendor/github.com/openshift/api/machine/v1/doc.go new file mode 100644 index 000000000..7bd97c950 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/doc.go @@ -0,0 +1,7 @@ +// +k8s:deepcopy-gen=package,register +// +k8s:defaulter-gen=TypeMeta +// +k8s:openapi-gen=true + +// +kubebuilder:validation:Optional +// +groupName=machine.openshift.io +package v1 diff --git a/vendor/github.com/openshift/api/machine/v1/register.go b/vendor/github.com/openshift/api/machine/v1/register.go new file mode 100644 index 000000000..b950169bf --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/register.go @@ -0,0 +1,40 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + GroupName = "machine.openshift.io" + GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // Install is a function which adds this version to a scheme + Install = schemeBuilder.AddToScheme + + // SchemeGroupVersion generated code relies on this name + // Deprecated + SchemeGroupVersion = GroupVersion + // AddToScheme exists solely to keep the old generators creating valid code + // DEPRECATED + AddToScheme = schemeBuilder.AddToScheme +) + +// Resource generated code relies on this being here, but it logically belongs to the group +// DEPRECATED +func Resource(resource string) schema.GroupResource { + return schema.GroupResource{Group: GroupName, Resource: resource} +} + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + metav1.AddToGroupVersion(scheme, GroupVersion) + + scheme.AddKnownTypes(GroupVersion, + &ControlPlaneMachineSet{}, + &ControlPlaneMachineSetList{}, + ) + + return nil +} diff --git a/vendor/github.com/openshift/api/machine/v1/types_alibabaprovider.go b/vendor/github.com/openshift/api/machine/v1/types_alibabaprovider.go new file mode 100644 index 000000000..12a819672 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/types_alibabaprovider.go @@ -0,0 +1,376 @@ +/* +Copyright 2021 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 v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// AlibabaDiskPerformanceLevel enum attribute to describe a disk's performance level +type AlibabaDiskPerformanceLevel string + +// AlibabaDiskCatagory enum attribute to deescribe a disk's category +type AlibabaDiskCategory string + +// AlibabaDiskEncryptionMode enum attribute to describe whether to enable or disable disk encryption +type AlibabaDiskEncryptionMode string + +// AlibabaDiskPreservationPolicy enum attribute to describe whether to preserve or delete a disk upon instance removal +type AlibabaDiskPreservationPolicy string + +// AlibabaResourceReferenceType enum attribute to identify the type of resource reference +type AlibabaResourceReferenceType string + +const ( + // DeleteWithInstance enum property to delete disk with instance deletion + DeleteWithInstance AlibabaDiskPreservationPolicy = "DeleteWithInstance" + // PreserveDisk enum property to determine disk preservation with instance deletion + PreserveDisk AlibabaDiskPreservationPolicy = "PreserveDisk" + + // AlibabaDiskEncryptionEnabled enum property to enable disk encryption + AlibabaDiskEncryptionEnabled AlibabaDiskEncryptionMode = "encrypted" + // AlibabaDiskEncryptionDisabled enum property to disable disk encryption + AlibabaDiskEncryptionDisabled AlibabaDiskEncryptionMode = "disabled" + + // AlibabaDiskPerformanceLevel0 enum property to set the level at PL0 + PL0 AlibabaDiskPerformanceLevel = "PL0" + // AlibabaDiskPerformanceLevel1 enum property to set the level at PL1 + PL1 AlibabaDiskPerformanceLevel = "PL1" + // AlibabaDiskPerformanceLevel2 enum property to set the level at PL2 + PL2 AlibabaDiskPerformanceLevel = "PL2" + // AlibabaDiskPerformanceLevel3 enum property to set the level at PL3 + PL3 AlibabaDiskPerformanceLevel = "PL3" + + // AlibabaDiskCategoryUltraDisk enum proprty to set the category of disk to ultra disk + AlibabaDiskCatagoryUltraDisk AlibabaDiskCategory = "cloud_efficiency" + // AlibabaDiskCategorySSD enum proprty to set the category of disk to standard SSD + AlibabaDiskCatagorySSD AlibabaDiskCategory = "cloud_ssd" + // AlibabaDiskCategoryESSD enum proprty to set the category of disk to ESSD + AlibabaDiskCatagoryESSD AlibabaDiskCategory = "cloud_essd" + // AlibabaDiskCategoryBasic enum proprty to set the category of disk to basic + AlibabaDiskCatagoryBasic AlibabaDiskCategory = "cloud" + + // AlibabaResourceReferenceTypeID enum property to identify an ID type resource reference + AlibabaResourceReferenceTypeID AlibabaResourceReferenceType = "ID" + // AlibabaResourceReferenceTypeName enum property to identify an Name type resource reference + AlibabaResourceReferenceTypeName AlibabaResourceReferenceType = "Name" + // AlibabaResourceReferenceTypeTags enum property to identify a tags type resource reference + AlibabaResourceReferenceTypeTags AlibabaResourceReferenceType = "Tags" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AlibabaCloudMachineProviderConfig is the Schema for the alibabacloudmachineproviderconfig API +// 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 +// +k8s:openapi-gen=true +type AlibabaCloudMachineProviderConfig struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + + // More detail about alibabacloud ECS + // https://www.alibabacloud.com/help/doc-detail/25499.htm?spm=a2c63.l28256.b99.727.496d7453jF7Moz + + //The instance type of the instance. + InstanceType string `json:"instanceType"` + + // The ID of the vpc + VpcID string `json:"vpcId"` + + // The ID of the region in which to create the instance. You can call the DescribeRegions operation to query the most recent region list. + RegionID string `json:"regionId"` + + // The ID of the zone in which to create the instance. You can call the DescribeZones operation to query the most recent region list. + ZoneID string `json:"zoneId"` + + // The ID of the image used to create the instance. + ImageID string `json:"imageId"` + + // DataDisks holds information regarding the extra disks attached to the instance + // +optional + DataDisks []DataDiskProperties `json:"dataDisk,omitempty"` + + // securityGroups is a list of security group references to assign to the instance. + // A reference holds either the security group ID, the resource name, or the required tags to search. + // When more than one security group is returned for a tag search, all the groups are associated with the instance up to the + // maximum number of security groups to which an instance can belong. + // For more information, see the "Security group limits" section in Limits. + // https://www.alibabacloud.com/help/en/doc-detail/25412.htm + SecurityGroups []AlibabaResourceReference `json:"securityGroups,omitempty"` + + // bandwidth describes the internet bandwidth strategy for the instance + // +optional + Bandwidth BandwidthProperties `json:"bandwidth,omitempty"` + + // systemDisk holds the properties regarding the system disk for the instance + // +optional + SystemDisk SystemDiskProperties `json:"systemDisk,omitempty"` + + // vSwitch is a reference to the vswitch to use for this instance. + // A reference holds either the vSwitch ID, the resource name, or the required tags to search. + // When more than one vSwitch is returned for a tag search, only the first vSwitch returned will be used. + // This parameter is required when you create an instance of the VPC type. + // You can call the DescribeVSwitches operation to query the created vSwitches. + VSwitch AlibabaResourceReference `json:"vSwitch"` + + // ramRoleName is the name of the instance Resource Access Management (RAM) role. This allows the instance to perform API calls as this specified RAM role. + // +optional + RAMRoleName string `json:"ramRoleName,omitempty"` + + // resourceGroup references the resource group to which to assign the instance. + // A reference holds either the resource group ID, the resource name, or the required tags to search. + // When more than one resource group are returned for a search, an error will be produced and the Machine will not be created. + // Resource Groups do not support searching by tags. + ResourceGroup AlibabaResourceReference `json:"resourceGroup"` + + // tenancy specifies whether to create the instance on a dedicated host. + // Valid values: + // + // default: creates the instance on a non-dedicated host. + // host: creates the instance on a dedicated host. If you do not specify the DedicatedHostID parameter, Alibaba Cloud automatically selects a dedicated host for the instance. + // Empty value means no opinion and the platform chooses the a default, which is subject to change over time. + // Currently the default is `default`. + // +optional + Tenancy InstanceTenancy `json:"tenancy,omitempty"` + + // userDataSecret contains a local reference to a secret that contains the + // UserData to apply to the instance + // +optional + UserDataSecret *corev1.LocalObjectReference `json:"userDataSecret,omitempty"` + + // credentialsSecret is a reference to the secret with alibabacloud credentials. Otherwise, defaults to permissions + // provided by attached RAM role where the actuator is running. + // +optional + CredentialsSecret *corev1.LocalObjectReference `json:"credentialsSecret,omitempty"` + + // Tags are the set of metadata to add to an instance. + // +optional + Tags []Tag `json:"tag,omitempty"` +} + +// ResourceTagReference is a reference to a specific AlibabaCloud resource by ID, or tags. +// Only one of ID or Tags may be specified. Specifying more than one will result in +// a validation error. +type AlibabaResourceReference struct { + // type identifies the resource reference type for this entry. + Type AlibabaResourceReferenceType `json:"type"` + + // id of resource + // +optional + ID *string `json:"id,omitempty"` + + // name of the resource + // +optional + Name *string `json:"name,omitempty"` + + // tags is a set of metadata based upon ECS object tags used to identify a resource. + // For details about usage when multiple resources are found, please see the owning parent field documentation. + // +optional + Tags *[]Tag `json:"tags,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AlibabaCloudMachineProviderConfigList contains a list of AlibabaCloudMachineProviderConfig +// 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 +type AlibabaCloudMachineProviderConfigList struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard list's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ListMeta `json:"metadata,omitempty"` + + Items []AlibabaCloudMachineProviderConfig `json:"items"` +} + +// AlibabaCloudMachineProviderStatus is the Schema for the alibabacloudmachineproviderconfig API +// 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 +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type AlibabaCloudMachineProviderStatus struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + + // instanceId is the instance ID of the machine created in alibabacloud + // +optional + InstanceID *string `json:"instanceId,omitempty"` + + // instanceState is the state of the alibabacloud instance for this machine + // +optional + InstanceState *string `json:"instanceState,omitempty"` + + // conditions is a set of conditions associated with the Machine to indicate + // errors or other status + // +optional + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// SystemDiskProperties contains the information regarding the system disk including performance, size, name, and category +type SystemDiskProperties struct { + // category is the category of the system disk. + // Valid values: + // cloud_essd: ESSD. When the parameter is set to this value, you can use the SystemDisk.PerformanceLevel parameter to specify the performance level of the disk. + // cloud_efficiency: ultra disk. + // cloud_ssd: standard SSD. + // cloud: basic disk. + // Empty value means no opinion and the platform chooses the a default, which is subject to change over time. + // Currently for non-I/O optimized instances of retired instance types, the default is `cloud`. + // Currently for other instances, the default is `cloud_efficiency`. + // +kubebuilder:validation:Enum="cloud_efficiency"; "cloud_ssd"; "cloud_essd"; "cloud" + // +optional + Category string `json:"category,omitempty"` + + // performanceLevel is the performance level of the ESSD used as the system disk. + // Valid values: + // + // PL0: A single ESSD can deliver up to 10,000 random read/write IOPS. + // PL1: A single ESSD can deliver up to 50,000 random read/write IOPS. + // PL2: A single ESSD can deliver up to 100,000 random read/write IOPS. + // PL3: A single ESSD can deliver up to 1,000,000 random read/write IOPS. + // Empty value means no opinion and the platform chooses a default, which is subject to change over time. + // Currently the default is `PL1`. + // For more information about ESSD performance levels, see ESSDs. + // +kubebuilder:validation:Enum="PL0"; "PL1"; "PL2"; "PL3" + // +optional + PerformanceLevel string `json:"performanceLevel,omitempty"` + + // name is the name of the system disk. If the name is specified the name must be 2 to 128 characters in length. It must start with a letter and cannot start with http:// or https://. It can contain letters, digits, colons (:), underscores (_), and hyphens (-). + // Empty value means the platform chooses a default, which is subject to change over time. + // Currently the default is `""`. + // +kubebuilder:validation:MaxLength=128 + // +optional + Name string `json:"name,omitempty"` + + // size is the size of the system disk. Unit: GiB. Valid values: 20 to 500. + // The value must be at least 20 and greater than or equal to the size of the image. + // Empty value means the platform chooses a default, which is subject to change over time. + // Currently the default is `40` or the size of the image depending on whichever is greater. + // +optional + Size int64 `json:"size,omitempty"` +} + +// DataDisk contains the information regarding the datadisk attached to an instance +type DataDiskProperties struct { + // Name is the name of data disk N. If the name is specified the name must be 2 to 128 characters in length. It must start with a letter and cannot start with http:// or https://. It can contain letters, digits, colons (:), underscores (_), and hyphens (-). + // + // Empty value means the platform chooses a default, which is subject to change over time. + // Currently the default is `""`. + // +optional + Name string `name:"diskName,omitempty"` + + // SnapshotID is the ID of the snapshot used to create data disk N. Valid values of N: 1 to 16. + // + // When the DataDisk.N.SnapshotID parameter is specified, the DataDisk.N.Size parameter is ignored. The data disk is created based on the size of the specified snapshot. + // Use snapshots created after July 15, 2013. Otherwise, an error is returned and your request is rejected. + // + // +optional + SnapshotID string `name:"snapshotId,omitempty"` + + // Size of the data disk N. Valid values of N: 1 to 16. Unit: GiB. Valid values: + // + // Valid values when DataDisk.N.Category is set to cloud_efficiency: 20 to 32768 + // Valid values when DataDisk.N.Category is set to cloud_ssd: 20 to 32768 + // Valid values when DataDisk.N.Category is set to cloud_essd: 20 to 32768 + // Valid values when DataDisk.N.Category is set to cloud: 5 to 2000 + // The value of this parameter must be greater than or equal to the size of the snapshot specified by the SnapshotID parameter. + // +optional + Size int64 `name:"size,omitempty"` + + // DiskEncryption specifies whether to encrypt data disk N. + // + // Empty value means the platform chooses a default, which is subject to change over time. + // Currently the default is `disabled`. + // +kubebuilder:validation:Enum="encrypted";"disabled" + // +optional + DiskEncryption AlibabaDiskEncryptionMode `name:"diskEncryption,omitempty"` + + // PerformanceLevel is the performance level of the ESSD used as as data disk N. The N value must be the same as that in DataDisk.N.Category when DataDisk.N.Category is set to cloud_essd. + // Empty value means no opinion and the platform chooses a default, which is subject to change over time. + // Currently the default is `PL1`. + // Valid values: + // + // PL0: A single ESSD can deliver up to 10,000 random read/write IOPS. + // PL1: A single ESSD can deliver up to 50,000 random read/write IOPS. + // PL2: A single ESSD can deliver up to 100,000 random read/write IOPS. + // PL3: A single ESSD can deliver up to 1,000,000 random read/write IOPS. + // For more information about ESSD performance levels, see ESSDs. + // +kubebuilder:validation:Enum="PL0"; "PL1"; "PL2"; "PL3" + // +optional + PerformanceLevel AlibabaDiskPerformanceLevel `name:"performanceLevel,omitempty"` + + // Category describes the type of data disk N. + // Valid values: + // cloud_efficiency: ultra disk + // cloud_ssd: standard SSD + // cloud_essd: ESSD + // cloud: basic disk + // Empty value means no opinion and the platform chooses the a default, which is subject to change over time. + // Currently for non-I/O optimized instances of retired instance types, the default is `cloud`. + // Currently for other instances, the default is `cloud_efficiency`. + // +kubebuilder:validation:Enum="cloud_efficiency"; "cloud_ssd"; "cloud_essd"; "cloud" + // +optional + Category AlibabaDiskCategory `name:"category,omitempty"` + + // KMSKeyID is the ID of the Key Management Service (KMS) key to be used by data disk N. + // Empty value means no opinion and the platform chooses the a default, which is subject to change over time. + // Currently the default is `""` which is interpreted as do not use KMSKey encryption. + // +optional + KMSKeyID string `name:"kmsKeyId,omitempty"` + + // DiskPreservation specifies whether to release data disk N along with the instance. + // Empty value means no opinion and the platform chooses the a default, which is subject to change over time. + // Currently the default is `DeleteWithInstance` + // +kubebuilder:validation:Enum="DeleteWithInstance";"PreserveDisk" + // +optional + DiskPreservation AlibabaDiskPreservationPolicy `name:"diskPreservation,omitempty"` +} + +// Tag The tags of ECS Instance +type Tag struct { + // Key is the name of the key pair + Key string `name:"Key"` + // Value is the value or data of the key pair + Value string `name:"value"` +} + +// Bandwidth describes the bandwidth strategy for the network of the instance +type BandwidthProperties struct { + // internetMaxBandwidthIn is the maximum inbound public bandwidth. Unit: Mbit/s. Valid values: + // When the purchased outbound public bandwidth is less than or equal to 10 Mbit/s, the valid values of this parameter are 1 to 10. + // Currently the default is `10` when outbound bandwidth is less than or equal to 10 Mbit/s. + // When the purchased outbound public bandwidth is greater than 10, the valid values are 1 to the InternetMaxBandwidthOut value. + // Currently the default is the value used for `InternetMaxBandwidthOut` when outbound public bandwidth is greater than 10. + // +optional + InternetMaxBandwidthIn int64 `json:"internetMaxBandwidthIn,omitempty"` + + // internetMaxBandwidthOut is the maximum outbound public bandwidth. Unit: Mbit/s. Valid values: 0 to 100. + // When a value greater than 0 is used then a public IP address is assigned to the instance. + // Empty value means no opinion and the platform chooses the a default, which is subject to change over time. + // Currently the default is `0` + // +optional + InternetMaxBandwidthOut int64 `json:"internetMaxBandwidthOut,omitempty"` +} diff --git a/vendor/github.com/openshift/api/machine/v1/types_aws.go b/vendor/github.com/openshift/api/machine/v1/types_aws.go new file mode 100644 index 000000000..5ad2b923f --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/types_aws.go @@ -0,0 +1,51 @@ +package v1 + +// AWSResourceReference is a reference to a specific AWS resource by ID, ARN, or filters. +// Only one of ID, ARN or Filters may be specified. Specifying more than one will result in +// a validation error. +// +union +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'ID' ? has(self.id) : !has(self.id)",message="id is required when type is ID, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'ARN' ? has(self.arn) : !has(self.arn)",message="arn is required when type is ARN, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Filters' ? has(self.filters) : !has(self.filters)",message="filters is required when type is Filters, and forbidden otherwise" +type AWSResourceReference struct { + // type determines how the reference will fetch the AWS resource. + // +unionDiscriminator + // +required + Type AWSResourceReferenceType `json:"type"` + // id of resource. + // +optional + ID *string `json:"id,omitempty"` + // arn of resource. + // +optional + ARN *string `json:"arn,omitempty"` + // filters is a set of filters used to identify a resource. + // +optional + // +listType=atomic + Filters *[]AWSResourceFilter `json:"filters,omitempty"` +} + +// AWSResourceReferenceType is an enumeration of different resource reference types. +// +kubebuilder:validation:Enum:="ID";"ARN";"Filters" +type AWSResourceReferenceType string + +const ( + // AWSIDReferenceType is a resource reference based on the object ID. + AWSIDReferenceType AWSResourceReferenceType = "ID" + + // AWSARNReferenceType is a resource reference based on the object ARN. + AWSARNReferenceType AWSResourceReferenceType = "ARN" + + // AWSFiltersReferenceType is a resource reference based on filters. + AWSFiltersReferenceType AWSResourceReferenceType = "Filters" +) + +// AWSResourceFilter is a filter used to identify an AWS resource +type AWSResourceFilter struct { + // name of the filter. Filter names are case-sensitive. + // +required + Name string `json:"name"` + // values includes one or more filter values. Filter values are case-sensitive. + // +optional + // +listType=atomic + Values []string `json:"values,omitempty"` +} diff --git a/vendor/github.com/openshift/api/machine/v1/types_controlplanemachineset.go b/vendor/github.com/openshift/api/machine/v1/types_controlplanemachineset.go new file mode 100644 index 000000000..25ffc9f46 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/types_controlplanemachineset.go @@ -0,0 +1,486 @@ +package v1 + +import ( + configv1 "github.com/openshift/api/config/v1" + machinev1beta1 "github.com/openshift/api/machine/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +k8s:openapi-gen=true +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=controlplanemachinesets,scope=Namespaced +// +kubebuilder:subresource:status +// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas +// +kubebuilder:printcolumn:name="Desired",type="integer",JSONPath=".spec.replicas",description="Desired Replicas" +// +kubebuilder:printcolumn:name="Current",type="integer",JSONPath=".status.replicas",description="Current Replicas" +// +kubebuilder:printcolumn:name="Ready",type="integer",JSONPath=".status.readyReplicas",description="Ready Replicas" +// +kubebuilder:printcolumn:name="Updated",type="integer",JSONPath=".status.updatedReplicas",description="Updated Replicas" +// +kubebuilder:printcolumn:name="Unavailable",type="integer",JSONPath=".status.unavailableReplicas",description="Observed number of unavailable replicas" +// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".spec.state",description="ControlPlaneMachineSet state" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="ControlPlaneMachineSet age" +// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/1112 +// +openshift:file-pattern=cvoRunLevel=0000_10,operatorName=control-plane-machine-set,operatorOrdering=01 +// +openshift:capability=MachineAPI +// +kubebuilder:metadata:annotations="exclude.release.openshift.io/internal-openshift-hosted=true" +// +kubebuilder:metadata:annotations=include.release.openshift.io/self-managed-high-availability=true + +// ControlPlaneMachineSet ensures that a specified number of control plane machine replicas are running at any given time. +// 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 +type ControlPlaneMachineSet struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ControlPlaneMachineSetSpec `json:"spec,omitempty"` + Status ControlPlaneMachineSetStatus `json:"status,omitempty"` +} + +// ControlPlaneMachineSet represents the configuration of the ControlPlaneMachineSet. +type ControlPlaneMachineSetSpec struct { + // machineNamePrefix is the prefix used when creating machine names. + // Each machine name will consist of this prefix, followed by + // a randomly generated string of 5 characters, and the index of the machine. + // It must be a lowercase RFC 1123 subdomain, consisting of lowercase + // alphanumeric characters, hyphens ('-'), and periods ('.'). + // Each block, separated by periods, must start and end with an alphanumeric character. + // Hyphens are not allowed at the start or end of a block, and consecutive periods are not permitted. + // The prefix must be between 1 and 245 characters in length. + // For example, if machineNamePrefix is set to 'control-plane', + // and three machines are created, their names might be: + // control-plane-abcde-0, control-plane-fghij-1, control-plane-klmno-2 + // +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="a lowercase RFC 1123 subdomain must consist of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'). Each block, separated by periods, must start and end with an alphanumeric character. Hyphens are not allowed at the start or end of a block, and consecutive periods are not permitted." + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=245 + // +optional + MachineNamePrefix string `json:"machineNamePrefix,omitempty"` + + // state defines whether the ControlPlaneMachineSet is Active or Inactive. + // When Inactive, the ControlPlaneMachineSet will not take any action on the + // state of the Machines within the cluster. + // When Active, the ControlPlaneMachineSet will reconcile the Machines and + // will update the Machines as necessary. + // Once Active, a ControlPlaneMachineSet cannot be made Inactive. To prevent + // further action please remove the ControlPlaneMachineSet. + // +kubebuilder:default:="Inactive" + // +default="Inactive" + // +kubebuilder:validation:XValidation:rule="oldSelf != 'Active' || self == oldSelf",message="state cannot be changed once Active" + // +optional + State ControlPlaneMachineSetState `json:"state,omitempty"` + + // replicas defines how many Control Plane Machines should be + // created by this ControlPlaneMachineSet. + // This field is immutable and cannot be changed after cluster + // installation. + // The ControlPlaneMachineSet only operates with 3 or 5 node control planes, + // 3 and 5 are the only valid values for this field. + // +kubebuilder:validation:Enum:=3;5 + // +kubebuilder:default:=3 + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="replicas is immutable" + // +required + Replicas *int32 `json:"replicas"` + + // strategy defines how the ControlPlaneMachineSet will update + // Machines when it detects a change to the ProviderSpec. + // +kubebuilder:default:={type: RollingUpdate} + // +optional + Strategy ControlPlaneMachineSetStrategy `json:"strategy,omitempty"` + + // Label selector for Machines. Existing Machines selected by this + // selector will be the ones affected by this ControlPlaneMachineSet. + // It must match the template's labels. + // This field is considered immutable after creation of the resource. + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="selector is immutable" + // +required + Selector metav1.LabelSelector `json:"selector"` + + // template describes the Control Plane Machines that will be created + // by this ControlPlaneMachineSet. + // +required + Template ControlPlaneMachineSetTemplate `json:"template"` +} + +// ControlPlaneMachineSetState is an enumeration of the possible states of the +// ControlPlaneMachineSet resource. It allows it to be either Active or Inactive. +// +kubebuilder:validation:Enum:="Active";"Inactive" +type ControlPlaneMachineSetState string + +const ( + // ControlPlaneMachineSetStateActive is the value used to denote the ControlPlaneMachineSet + // should be active and should perform updates as required. + ControlPlaneMachineSetStateActive ControlPlaneMachineSetState = "Active" + + // ControlPlaneMachineSetStateInactive is the value used to denote the ControlPlaneMachineSet + // should be not active and should no perform any updates. + ControlPlaneMachineSetStateInactive ControlPlaneMachineSetState = "Inactive" +) + +// ControlPlaneMachineSetTemplate is a template used by the ControlPlaneMachineSet +// to create the Machines that it will manage in the future. +// +union +// + --- +// + This struct is a discriminated union which allows users to select the type of Machine +// + that the ControlPlaneMachineSet should create and manage. +// + For now, the only supported type is the OpenShift Machine API Machine, but in the future +// + we plan to expand this to allow other Machine types such as Cluster API Machines or a +// + future version of the Machine API Machine. +// +kubebuilder:validation:XValidation:rule="has(self.machineType) && self.machineType == 'machines_v1beta1_machine_openshift_io' ? has(self.machines_v1beta1_machine_openshift_io) : !has(self.machines_v1beta1_machine_openshift_io)",message="machines_v1beta1_machine_openshift_io configuration is required when machineType is machines_v1beta1_machine_openshift_io, and forbidden otherwise" +type ControlPlaneMachineSetTemplate struct { + // machineType determines the type of Machines that should be managed by the ControlPlaneMachineSet. + // Currently, the only valid value is machines_v1beta1_machine_openshift_io. + // +unionDiscriminator + // +required + MachineType ControlPlaneMachineSetMachineType `json:"machineType"` + + // OpenShiftMachineV1Beta1Machine defines the template for creating Machines + // from the v1beta1.machine.openshift.io API group. + // +optional + OpenShiftMachineV1Beta1Machine *OpenShiftMachineV1Beta1MachineTemplate `json:"machines_v1beta1_machine_openshift_io,omitempty"` +} + +// ControlPlaneMachineSetMachineType is a enumeration of valid Machine types +// supported by the ControlPlaneMachineSet. +// +kubebuilder:validation:Enum:=machines_v1beta1_machine_openshift_io +type ControlPlaneMachineSetMachineType string + +const ( + // OpenShiftMachineV1Beta1MachineType is the OpenShift Machine API v1beta1 Machine type. + OpenShiftMachineV1Beta1MachineType ControlPlaneMachineSetMachineType = "machines_v1beta1_machine_openshift_io" +) + +// OpenShiftMachineV1Beta1MachineTemplate is a template for the ControlPlaneMachineSet to create +// Machines from the v1beta1.machine.openshift.io API group. +type OpenShiftMachineV1Beta1MachineTemplate struct { + // failureDomains is the list of failure domains (sometimes called + // availability zones) in which the ControlPlaneMachineSet should balance + // the Control Plane Machines. + // This will be merged into the ProviderSpec given in the template. + // This field is optional on platforms that do not require placement information. + // +optional + FailureDomains *FailureDomains `json:"failureDomains,omitempty"` + + // ObjectMeta is the standard object metadata + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + // Labels are required to match the ControlPlaneMachineSet selector. + // +required + ObjectMeta ControlPlaneMachineSetTemplateObjectMeta `json:"metadata"` + + // spec contains the desired configuration of the Control Plane Machines. + // The ProviderSpec within contains platform specific details + // for creating the Control Plane Machines. + // The ProviderSe should be complete apart from the platform specific + // failure domain field. This will be overridden when the Machines + // are created based on the FailureDomains field. + // +required + Spec machinev1beta1.MachineSpec `json:"spec"` +} + +// ControlPlaneMachineSetTemplateObjectMeta is a subset of the metav1.ObjectMeta struct. +// It allows users to specify labels and annotations that will be copied onto Machines +// created from this template. +type ControlPlaneMachineSetTemplateObjectMeta struct { + // Map of string keys and values that can be used to organize and categorize + // (scope and select) objects. May match selectors of replication controllers + // and services. + // More info: http://kubernetes.io/docs/user-guide/labels. + // This field must contain both the 'machine.openshift.io/cluster-api-machine-role' and 'machine.openshift.io/cluster-api-machine-type' labels, both with a value of 'master'. + // It must also contain a label with the key 'machine.openshift.io/cluster-api-cluster'. + // +kubebuilder:validation:XValidation:rule="'machine.openshift.io/cluster-api-machine-role' in self && self['machine.openshift.io/cluster-api-machine-role'] == 'master'",message="label 'machine.openshift.io/cluster-api-machine-role' is required, and must have value 'master'" + // +kubebuilder:validation:XValidation:rule="'machine.openshift.io/cluster-api-machine-type' in self && self['machine.openshift.io/cluster-api-machine-type'] == 'master'",message="label 'machine.openshift.io/cluster-api-machine-type' is required, and must have value 'master'" + // +kubebuilder:validation:XValidation:rule="'machine.openshift.io/cluster-api-cluster' in self",message="label 'machine.openshift.io/cluster-api-cluster' is required" + // +required + Labels map[string]string `json:"labels"` + + // annotations is an unstructured key value map stored with a resource that may be + // set by external tools to store and retrieve arbitrary metadata. They are not + // queryable and should be preserved when modifying objects. + // More info: http://kubernetes.io/docs/user-guide/annotations + // +optional + Annotations map[string]string `json:"annotations,omitempty"` +} + +// ControlPlaneMachineSetStrategy defines the strategy for applying updates to the +// Control Plane Machines managed by the ControlPlaneMachineSet. +type ControlPlaneMachineSetStrategy struct { + // type defines the type of update strategy that should be + // used when updating Machines owned by the ControlPlaneMachineSet. + // Valid values are "RollingUpdate" and "OnDelete". + // The current default value is "RollingUpdate". + // +kubebuilder:default:="RollingUpdate" + // +default="RollingUpdate" + // +kubebuilder:validation:Enum:="RollingUpdate";"OnDelete" + // +optional + Type ControlPlaneMachineSetStrategyType `json:"type,omitempty"` + + // This is left as a struct to allow future rolling update + // strategy configuration to be added later. +} + +// ControlPlaneMachineSetStrategyType is an enumeration of different update strategies +// for the Control Plane Machines. +type ControlPlaneMachineSetStrategyType string + +const ( + // RollingUpdate is the default update strategy type for a + // ControlPlaneMachineSet. This will cause the ControlPlaneMachineSet to + // first create a new Machine and wait for this to be Ready + // before removing the Machine chosen for replacement. + RollingUpdate ControlPlaneMachineSetStrategyType = "RollingUpdate" + + // Recreate causes the ControlPlaneMachineSet controller to first + // remove a ControlPlaneMachine before creating its + // replacement. This allows for scenarios with limited capacity + // such as baremetal environments where additional capacity to + // perform rolling updates is not available. + Recreate ControlPlaneMachineSetStrategyType = "Recreate" + + // OnDelete causes the ControlPlaneMachineSet to only replace a + // Machine once it has been marked for deletion. This strategy + // makes the rollout of updated specifications into a manual + // process. This allows users to test new configuration on + // a single Machine without forcing the rollout of all of their + // Control Plane Machines. + OnDelete ControlPlaneMachineSetStrategyType = "OnDelete" +) + +// FailureDomain represents the different configurations required to spread Machines +// across failure domains on different platforms. +// +union +// +kubebuilder:validation:XValidation:rule="has(self.platform) && self.platform == 'AWS' ? has(self.aws) : !has(self.aws)",message="aws configuration is required when platform is AWS, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="has(self.platform) && self.platform == 'Azure' ? has(self.azure) : !has(self.azure)",message="azure configuration is required when platform is Azure, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="has(self.platform) && self.platform == 'GCP' ? has(self.gcp) : !has(self.gcp)",message="gcp configuration is required when platform is GCP, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="has(self.platform) && self.platform == 'OpenStack' ? has(self.openstack) : !has(self.openstack)",message="openstack configuration is required when platform is OpenStack, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="has(self.platform) && self.platform == 'VSphere' ? has(self.vsphere) : !has(self.vsphere)",message="vsphere configuration is required when platform is VSphere, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="has(self.platform) && self.platform == 'Nutanix' ? has(self.nutanix) : !has(self.nutanix)",message="nutanix configuration is required when platform is Nutanix, and forbidden otherwise" +type FailureDomains struct { + // platform identifies the platform for which the FailureDomain represents. + // Currently supported values are AWS, Azure, GCP, OpenStack, VSphere and Nutanix. + // +unionDiscriminator + // +required + Platform configv1.PlatformType `json:"platform"` + + // aws configures failure domain information for the AWS platform. + // +listType=atomic + // +optional + AWS *[]AWSFailureDomain `json:"aws,omitempty"` + + // azure configures failure domain information for the Azure platform. + // +listType=atomic + // +optional + Azure *[]AzureFailureDomain `json:"azure,omitempty"` + + // gcp configures failure domain information for the GCP platform. + // +listType=atomic + // +optional + GCP *[]GCPFailureDomain `json:"gcp,omitempty"` + + // vsphere configures failure domain information for the VSphere platform. + // +listType=map + // +listMapKey=name + // +optional + VSphere []VSphereFailureDomain `json:"vsphere,omitempty"` + + // openstack configures failure domain information for the OpenStack platform. + // + // + --- + // + Unlike other platforms, OpenStack failure domains can be empty. + // + Some OpenStack deployments may not have availability zones or root volumes. + // + Therefore we'll check the length of the list to determine if it's empty instead + // + of nil if it would be a pointer. + // +listType=atomic + // +optional + OpenStack []OpenStackFailureDomain `json:"openstack,omitempty"` + + // nutanix configures failure domain information for the Nutanix platform. + // +listType=map + // +listMapKey=name + // +optional + Nutanix []NutanixFailureDomainReference `json:"nutanix,omitempty"` +} + +// AWSFailureDomain configures failure domain information for the AWS platform. +// +kubebuilder:validation:MinProperties:=1 +type AWSFailureDomain struct { + // subnet is a reference to the subnet to use for this instance. + // +optional + Subnet *AWSResourceReference `json:"subnet,omitempty"` + + // placement configures the placement information for this instance. + // +optional + Placement AWSFailureDomainPlacement `json:"placement,omitempty"` +} + +// AWSFailureDomainPlacement configures the placement information for the AWSFailureDomain. +type AWSFailureDomainPlacement struct { + // availabilityZone is the availability zone of the instance. + // +required + AvailabilityZone string `json:"availabilityZone"` +} + +// AzureFailureDomain configures failure domain information for the Azure platform. +type AzureFailureDomain struct { + // Availability Zone for the virtual machine. + // If nil, the virtual machine should be deployed to no zone. + // +required + Zone string `json:"zone"` + + // subnet is the name of the network subnet in which the VM will be created. + // When omitted, the subnet value from the machine providerSpec template will be used. + // +kubebuilder:validation:MaxLength=80 + // +kubebuilder:validation:Pattern=`^[a-zA-Z0-9](?:[a-zA-Z0-9._-]*[a-zA-Z0-9_])?$` + // +optional + Subnet string `json:"subnet,omitempty"` +} + +// GCPFailureDomain configures failure domain information for the GCP platform +type GCPFailureDomain struct { + // zone is the zone in which the GCP machine provider will create the VM. + // +required + Zone string `json:"zone"` +} + +// VSphereFailureDomain configures failure domain information for the vSphere platform +type VSphereFailureDomain struct { + // name of the failure domain in which the vSphere machine provider will create the VM. + // Failure domains are defined in a cluster's config.openshift.io/Infrastructure resource. + // When balancing machines across failure domains, the control plane machine set will inject configuration from the + // Infrastructure resource into the machine providerSpec to allocate the machine to a failure domain. + // +required + Name string `json:"name"` +} + +// OpenStackFailureDomain configures failure domain information for the OpenStack platform. +// +kubebuilder:validation:MinProperties:=1 +// +kubebuilder:validation:XValidation:rule="!has(self.availabilityZone) || !has(self.rootVolume) || has(self.rootVolume.availabilityZone)",message="rootVolume.availabilityZone is required when availabilityZone is set" +type OpenStackFailureDomain struct { + // availabilityZone is the nova availability zone in which the OpenStack machine provider will create the VM. + // If not specified, the VM will be created in the default availability zone specified in the nova configuration. + // Availability zone names must NOT contain : since it is used by admin users to specify hosts where instances + // are launched in server creation. Also, it must not contain spaces otherwise it will lead to node that belongs + // to this availability zone register failure, see kubernetes/cloud-provider-openstack#1379 for further information. + // The maximum length of availability zone name is 63 as per labels limits. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:Pattern=`^[^: ]*$` + // +kubebuilder:validation:MaxLength=63 + // +optional + AvailabilityZone string `json:"availabilityZone,omitempty"` + + // rootVolume contains settings that will be used by the OpenStack machine provider to create the root volume attached to the VM. + // If not specified, no root volume will be created. + // + // + --- + // + RootVolume must be a pointer to allow us to require at least one valid property is set within the failure domain. + // + If it were a reference then omitempty doesn't work and the minProperties validations are no longer valid. + // +optional + RootVolume *RootVolume `json:"rootVolume,omitempty"` +} + +// NutanixFailureDomainReference refers to the failure domain of the Nutanix platform. +type NutanixFailureDomainReference struct { + // name of the failure domain in which the nutanix machine provider will create the VM. + // Failure domains are defined in a cluster's config.openshift.io/Infrastructure resource. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + // +kubebuilder:validation:Pattern=`[a-z0-9]([-a-z0-9]*[a-z0-9])?` + Name string `json:"name"` +} + +// RootVolume represents the volume metadata to boot from. +// The original RootVolume struct is defined in the v1alpha1 but it's not best practice to use it directly here so we define a new one +// that should stay in sync with the original one. +type RootVolume struct { + // availabilityZone specifies the Cinder availability zone where the root volume will be created. + // If not specifified, the root volume will be created in the availability zone specified by the volume type in the cinder configuration. + // If the volume type (configured in the OpenStack cluster) does not specify an availability zone, the root volume will be created in the default availability + // zone specified in the cinder configuration. See https://docs.openstack.org/cinder/latest/admin/availability-zone-type.html for more details. + // If the OpenStack cluster is deployed with the cross_az_attach configuration option set to false, the root volume will have to be in the same + // availability zone as the VM (defined by OpenStackFailureDomain.AvailabilityZone). + // Availability zone names must NOT contain spaces otherwise it will lead to volume that belongs to this availability zone register failure, + // see kubernetes/cloud-provider-openstack#1379 for further information. + // The maximum length of availability zone name is 63 as per labels limits. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern=`^[^ ]*$` + // +optional + AvailabilityZone string `json:"availabilityZone,omitempty"` + + // volumeType specifies the type of the root volume that will be provisioned. + // The maximum length of a volume type name is 255 characters, as per the OpenStack limit. + // + --- + // + Historically, the installer has always required a volume type to be specified when deploying + // + the control plane with a root volume. This is because the default volume type in Cinder is not guaranteed + // + to be available, therefore we prefer the user to be explicit about the volume type to use. + // + We apply the same logic in CPMS: if the failure domain specifies a root volume, we require the user to specify a volume type. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=255 + VolumeType string `json:"volumeType"` +} + +// ControlPlaneMachineSetStatus represents the status of the ControlPlaneMachineSet CRD. +type ControlPlaneMachineSetStatus struct { + // conditions represents the observations of the ControlPlaneMachineSet's current state. + // Known .status.conditions.type are: Available, Degraded and Progressing. + // +listType=map + // +listMapKey=type + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // observedGeneration is the most recent generation observed for this + // ControlPlaneMachineSet. It corresponds to the ControlPlaneMachineSets's generation, + // which is updated on mutation by the API Server. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // replicas is the number of Control Plane Machines created by the + // ControlPlaneMachineSet controller. + // Note that during update operations this value may differ from the + // desired replica count. + // +optional + Replicas int32 `json:"replicas,omitempty"` + + // readyReplicas is the number of Control Plane Machines created by the + // ControlPlaneMachineSet controller which are ready. + // Note that this value may be higher than the desired number of replicas + // while rolling updates are in-progress. + // +optional + ReadyReplicas int32 `json:"readyReplicas,omitempty"` + + // updatedReplicas is the number of non-terminated Control Plane Machines + // created by the ControlPlaneMachineSet controller that have the desired + // provider spec and are ready. + // This value is set to 0 when a change is detected to the desired spec. + // When the update strategy is RollingUpdate, this will also coincide + // with starting the process of updating the Machines. + // When the update strategy is OnDelete, this value will remain at 0 until + // a user deletes an existing replica and its replacement has become ready. + // +optional + UpdatedReplicas int32 `json:"updatedReplicas,omitempty"` + + // unavailableReplicas is the number of Control Plane Machines that are + // still required before the ControlPlaneMachineSet reaches the desired + // available capacity. When this value is non-zero, the number of + // ReadyReplicas is less than the desired Replicas. + // +optional + UnavailableReplicas int32 `json:"unavailableReplicas,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ControlPlaneMachineSetList contains a list of ControlPlaneMachineSet +// 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 +type ControlPlaneMachineSetList struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard list's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ListMeta `json:"metadata,omitempty"` + + Items []ControlPlaneMachineSet `json:"items"` +} diff --git a/vendor/github.com/openshift/api/machine/v1/types_nutanixprovider.go b/vendor/github.com/openshift/api/machine/v1/types_nutanixprovider.go new file mode 100644 index 000000000..446082efb --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/types_nutanixprovider.go @@ -0,0 +1,345 @@ +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// NutanixMachineProviderConfig is the Schema for the nutanixmachineproviderconfigs API +// 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 +// +k8s:openapi-gen=true +type NutanixMachineProviderConfig struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + + // cluster is to identify the cluster (the Prism Element under management + // of the Prism Central), in which the Machine's VM will be created. + // The cluster identifier (uuid or name) can be obtained from the Prism Central console + // or using the prism_central API. + // +required + Cluster NutanixResourceIdentifier `json:"cluster"` + + // image is to identify the rhcos image uploaded to the Prism Central (PC) + // The image identifier (uuid or name) can be obtained from the Prism Central console + // or using the prism_central API. + // +required + Image NutanixResourceIdentifier `json:"image"` + + // subnets holds a list of identifiers (one or more) of the cluster's network subnets + // for the Machine's VM to connect to. The subnet identifiers (uuid or name) can be + // obtained from the Prism Central console or using the prism_central API. + // +required + // +kubebuilder:validation:MinItems=1 + Subnets []NutanixResourceIdentifier `json:"subnets"` + + // vcpusPerSocket is the number of vCPUs per socket of the VM + // +required + // +kubebuilder:validation:Minimum=1 + VCPUsPerSocket int32 `json:"vcpusPerSocket"` + + // vcpuSockets is the number of vCPU sockets of the VM + // +required + // +kubebuilder:validation:Minimum=1 + VCPUSockets int32 `json:"vcpuSockets"` + + // memorySize is the memory size (in Quantity format) of the VM + // The minimum memorySize is 2Gi bytes + // +required + MemorySize resource.Quantity `json:"memorySize"` + + // systemDiskSize is size (in Quantity format) of the system disk of the VM + // The minimum systemDiskSize is 20Gi bytes + // +required + SystemDiskSize resource.Quantity `json:"systemDiskSize"` + + // bootType indicates the boot type (Legacy, UEFI or SecureBoot) the Machine's VM uses to boot. + // If this field is empty or omitted, the VM will use the default boot type "Legacy" to boot. + // "SecureBoot" depends on "UEFI" boot, i.e., enabling "SecureBoot" means that "UEFI" boot is also enabled. + // +kubebuilder:validation:Enum="";Legacy;UEFI;SecureBoot + // +optional + BootType NutanixBootType `json:"bootType"` + + // project optionally identifies a Prism project for the Machine's VM to associate with. + // +optional + Project NutanixResourceIdentifier `json:"project"` + + // categories optionally adds one or more prism categories (each with key and value) for + // the Machine's VM to associate with. All the category key and value pairs specified must + // already exist in the prism central. + // +listType=map + // +listMapKey=key + // +optional + Categories []NutanixCategory `json:"categories"` + + // gpus is a list of GPU devices to attach to the machine's VM. + // The GPU devices should already exist in Prism Central and associated with + // one of the Prism Element's hosts and available for the VM to attach (in "UNUSED" status). + // +listType=set + // +optional + GPUs []NutanixGPU `json:"gpus"` + + // dataDisks holds information of the data disks to attach to the Machine's VM + // +listType=set + // +optional + DataDisks []NutanixVMDisk `json:"dataDisks"` + + // userDataSecret is a local reference to a secret that contains the + // UserData to apply to the VM + UserDataSecret *corev1.LocalObjectReference `json:"userDataSecret,omitempty"` + + // credentialsSecret is a local reference to a secret that contains the + // credentials data to access Nutanix PC client + // +required + CredentialsSecret *corev1.LocalObjectReference `json:"credentialsSecret"` + + // failureDomain refers to the name of the FailureDomain with which this Machine is associated. + // If this is configured, the Nutanix machine controller will use the prism_central endpoint + // and credentials defined in the referenced FailureDomain to communicate to the prism_central. + // It will also verify that the 'cluster' and subnets' configuration in the NutanixMachineProviderConfig + // is consistent with that in the referenced failureDomain. + // +optional + FailureDomain *NutanixFailureDomainReference `json:"failureDomain"` +} + +// NutanixCategory identifies a pair of prism category key and value +type NutanixCategory struct { + // key is the prism category key name + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + // +required + Key string `json:"key"` + + // value is the prism category value associated with the key + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + // +required + Value string `json:"value"` +} + +// NutanixBootType is an enumeration of different boot types for Nutanix VM. +type NutanixBootType string + +const ( + // NutanixLegacyBoot is the legacy BIOS boot type + NutanixLegacyBoot NutanixBootType = "Legacy" + + // NutanixUEFIBoot is the UEFI boot type + NutanixUEFIBoot NutanixBootType = "UEFI" + + // NutanixSecureBoot is the Secure boot type + NutanixSecureBoot NutanixBootType = "SecureBoot" +) + +// NutanixIdentifierType is an enumeration of different resource identifier types. +type NutanixIdentifierType string + +const ( + // NutanixIdentifierUUID is a resource identifier identifying the object by UUID. + NutanixIdentifierUUID NutanixIdentifierType = "uuid" + + // NutanixIdentifierName is a resource identifier identifying the object by Name. + NutanixIdentifierName NutanixIdentifierType = "name" +) + +// NutanixResourceIdentifier holds the identity of a Nutanix PC resource (cluster, image, subnet, etc.) +// +union +type NutanixResourceIdentifier struct { + // type is the identifier type to use for this resource. + // +unionDiscriminator + // +required + // +kubebuilder:validation:Enum:=uuid;name + Type NutanixIdentifierType `json:"type"` + + // uuid is the UUID of the resource in the PC. + // +optional + UUID *string `json:"uuid,omitempty"` + + // name is the resource name in the PC + // +optional + Name *string `json:"name,omitempty"` +} + +// NutanixGPUIdentifierType is an enumeration of different resource identifier types for GPU entities. +// +kubebuilder:validation:Enum:=Name;DeviceID +type NutanixGPUIdentifierType string + +const ( + // NutanixGPUIdentifierName identifies a GPU by Name. + NutanixGPUIdentifierName NutanixGPUIdentifierType = "Name" + + // NutanixGPUIdentifierDeviceID identifies a GPU by device ID. + NutanixGPUIdentifierDeviceID NutanixGPUIdentifierType = "DeviceID" +) + +// NutanixGPU holds the identity of a Nutanix GPU resource in the Prism Central +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'DeviceID' ? has(self.deviceID) : !has(self.deviceID)",message="deviceID configuration is required when type is DeviceID, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'Name' ? has(self.name) : !has(self.name)",message="name configuration is required when type is Name, and forbidden otherwise" +// +union +type NutanixGPU struct { + // type is the identifier type of the GPU device. + // Valid values are Name and DeviceID. + // +unionDiscriminator + // +required + Type NutanixGPUIdentifierType `json:"type"` + + // deviceID is the GPU device ID with the integer value. + // +optional + // +unionMember + DeviceID *int32 `json:"deviceID,omitempty"` + + // name is the GPU device name + // +optional + // +unionMember + Name *string `json:"name,omitempty"` +} + +// NutanixDiskMode is an enumeration of different disk modes. +// +kubebuilder:validation:Enum=Standard;Flash +type NutanixDiskMode string + +const ( + // NutanixDiskModeStandard represents the disk standard mode (not flash). + NutanixDiskModeStandard NutanixDiskMode = "Standard" + + // NutanixDiskModeFlash represents the disk flash mode. + NutanixDiskModeFlash NutanixDiskMode = "Flash" +) + +// NutanixStorageResourceIdentifier holds the identity of a Nutanix storage resource (storage_container, etc.) +// +kubebuilder:validation:XValidation:rule="has(self.type) && self.type == 'uuid' ? has(self.uuid) : !has(self.uuid)",message="uuid configuration is required when type is uuid, and forbidden otherwise" +// +union +type NutanixStorageResourceIdentifier struct { + // type is the identifier type to use for this resource. + // The valid value is "uuid". + // +unionDiscriminator + // +required + // +kubebuilder:validation:Enum:=uuid + Type NutanixIdentifierType `json:"type"` + + // uuid is the UUID of the storage resource in the PC. + // +optional + // +unionMember + UUID *string `json:"uuid,omitempty"` +} + +// NutanixVMStorageConfig specifies the storage configuration parameters for VM disks. +type NutanixVMStorageConfig struct { + // diskMode specifies the disk mode. + // The valid values are Standard and Flash, and the default is Standard. + // +kubebuilder:default=Standard + DiskMode NutanixDiskMode `json:"diskMode"` + + // storageContainer refers to the storage_container used by the VM disk. + // +optional + StorageContainer *NutanixStorageResourceIdentifier `json:"storageContainer,omitempty"` +} + +// NutanixDiskDeviceType is the VM disk device type. +// +kubebuilder:validation:Enum=Disk;CDRom +type NutanixDiskDeviceType string + +const ( + // NutanixDiskDeviceTypeDisk represents the VM disk device type "Disk". + NutanixDiskDeviceTypeDisk NutanixDiskDeviceType = "Disk" + + // NutanixDiskDeviceTypeCDROM represents the VM disk device type "CDRom". + NutanixDiskDeviceTypeCDROM NutanixDiskDeviceType = "CDRom" +) + +// NutanixDiskAdapterType is an enumeration of different disk device adapter types. +// +kubebuilder:validation:Enum:=SCSI;IDE;PCI;SATA;SPAPR +type NutanixDiskAdapterType string + +const ( + // NutanixDiskAdapterTypeSCSI represents the disk adapter type "SCSI". + NutanixDiskAdapterTypeSCSI NutanixDiskAdapterType = "SCSI" + + // NutanixDiskAdapterTypeIDE represents the disk adapter type "IDE". + NutanixDiskAdapterTypeIDE NutanixDiskAdapterType = "IDE" + + // NutanixDiskAdapterTypePCI represents the disk adapter type "PCI". + NutanixDiskAdapterTypePCI NutanixDiskAdapterType = "PCI" + + // NutanixDiskAdapterTypeSATA represents the disk adapter type "SATA". + NutanixDiskAdapterTypeSATA NutanixDiskAdapterType = "SATA" + + // NutanixDiskAdapterTypeSPAPR represents the disk adapter type "SPAPR". + NutanixDiskAdapterTypeSPAPR NutanixDiskAdapterType = "SPAPR" +) + +// NutanixVMDiskDeviceProperties specifies the disk device properties. +type NutanixVMDiskDeviceProperties struct { + // deviceType specifies the disk device type. + // The valid values are "Disk" and "CDRom", and the default is "Disk". + // +kubebuilder:default=Disk + // +required + DeviceType NutanixDiskDeviceType `json:"deviceType"` + + // adapterType is the adapter type of the disk address. + // If the deviceType is "Disk", the valid adapterType can be "SCSI", "IDE", "PCI", "SATA" or "SPAPR". + // If the deviceType is "CDRom", the valid adapterType can be "IDE" or "SATA". + // +required + AdapterType NutanixDiskAdapterType `json:"adapterType"` + + // deviceIndex is the index of the disk address. The valid values are non-negative integers, with the default value 0. + // For a Machine VM, the deviceIndex for the disks with the same deviceType.adapterType combination should + // start from 0 and increase consecutively afterwards. Note that for each Machine VM, the Disk.SCSI.0 + // and CDRom.IDE.0 are reserved to be used by the VM's system. So for dataDisks of Disk.SCSI and CDRom.IDE, + // the deviceIndex should start from 1. + // +kubebuilder:default=0 + // +kubebuilder:validation:Minimum=0 + // +required + DeviceIndex int32 `json:"deviceIndex,omitempty"` +} + +// NutanixDataDisk specifies the VM data disk configuration parameters. +type NutanixVMDisk struct { + // diskSize is size (in Quantity format) of the disk attached to the VM. + // See https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Format for the Quantity format and example documentation. + // The minimum diskSize is 1GB. + // +required + DiskSize resource.Quantity `json:"diskSize"` + + // deviceProperties are the properties of the disk device. + // +optional + DeviceProperties *NutanixVMDiskDeviceProperties `json:"deviceProperties,omitempty"` + + // storageConfig are the storage configuration parameters of the VM disks. + // +optional + StorageConfig *NutanixVMStorageConfig `json:"storageConfig,omitempty"` + + // dataSource refers to a data source image for the VM disk. + // +optional + DataSource *NutanixResourceIdentifier `json:"dataSource,omitempty"` +} + +// NutanixMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. +// It contains nutanix-specific status information. +// 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 +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type NutanixMachineProviderStatus struct { + metav1.TypeMeta `json:",inline"` + + // conditions is a set of conditions associated with the Machine to indicate + // errors or other status + // +optional + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // vmUUID is the Machine associated VM's UUID + // The field is missing before the VM is created. + // Once the VM is created, the field is filled with the VM's UUID and it will not change. + // The vmUUID is used to find the VM when updating the Machine status, + // and to delete the VM when the Machine is deleted. + // +optional + VmUUID *string `json:"vmUUID,omitempty"` +} diff --git a/vendor/github.com/openshift/api/machine/v1/types_powervsprovider.go b/vendor/github.com/openshift/api/machine/v1/types_powervsprovider.go new file mode 100644 index 000000000..d3a4c6ec8 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/types_powervsprovider.go @@ -0,0 +1,225 @@ +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// PowerVSResourceType enum attribute to identify the type of resource reference +type PowerVSResourceType string + +// PowerVSProcessorType enum attribute to identify the PowerVS instance processor type +type PowerVSProcessorType string + +// IBMVPCLoadBalancerType is the type of LoadBalancer to use when registering +// an instance with load balancers specified in LoadBalancerNames +type IBMVPCLoadBalancerType string + +// ApplicationLoadBalancerType is possible values for IBMVPCLoadBalancerType. +const ( + ApplicationLoadBalancerType IBMVPCLoadBalancerType = "Application" // Application Load Balancer for VPC (ALB) +) + +const ( + // PowerVSResourceTypeID enum property to identify an ID type resource reference + PowerVSResourceTypeID PowerVSResourceType = "ID" + // PowerVSResourceTypeName enum property to identify a Name type resource reference + PowerVSResourceTypeName PowerVSResourceType = "Name" + // PowerVSResourceTypeRegEx enum property to identify a tags type resource reference + PowerVSResourceTypeRegEx PowerVSResourceType = "RegEx" + // PowerVSProcessorTypeDedicated enum property to identify a Dedicated Power VS processor type + PowerVSProcessorTypeDedicated PowerVSProcessorType = "Dedicated" + // PowerVSProcessorTypeShared enum property to identify a Shared Power VS processor type + PowerVSProcessorTypeShared PowerVSProcessorType = "Shared" + // PowerVSProcessorTypeCapped enum property to identify a Capped Power VS processor type + PowerVSProcessorTypeCapped PowerVSProcessorType = "Capped" +) + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// PowerVSMachineProviderConfig is the type that will be embedded in a Machine.Spec.ProviderSpec field +// for a PowerVS virtual machine. It is used by the PowerVS machine actuator to create a single Machine. +// +// 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 +// +k8s:openapi-gen=true +type PowerVSMachineProviderConfig struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + + // userDataSecret contains a local reference to a secret that contains the + // UserData to apply to the instance. + // +optional + UserDataSecret *PowerVSSecretReference `json:"userDataSecret,omitempty"` + + // credentialsSecret is a reference to the secret with IBM Cloud credentials. + // +optional + CredentialsSecret *PowerVSSecretReference `json:"credentialsSecret,omitempty"` + + // serviceInstance is the reference to the Power VS service on which the server instance(VM) will be created. + // Power VS service is a container for all Power VS instances at a specific geographic region. + // serviceInstance can be created via IBM Cloud catalog or CLI. + // supported serviceInstance identifier in PowerVSResource are Name and ID and that can be obtained from IBM Cloud UI or IBM Cloud cli. + // More detail about Power VS service instance. + // https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-creating-power-virtual-server + // +kubebuilder:validation:=Required + ServiceInstance PowerVSResource `json:"serviceInstance"` + + // image is to identify the rhcos image uploaded to IBM COS bucket which is used to create the instance. + // supported image identifier in PowerVSResource are Name and ID and that can be obtained from IBM Cloud UI or IBM Cloud cli. + // +kubebuilder:validation:=Required + Image PowerVSResource `json:"image"` + + // network is the reference to the Network to use for this instance. + // supported network identifier in PowerVSResource are Name, ID and RegEx and that can be obtained from IBM Cloud UI or IBM Cloud cli. + // +kubebuilder:validation:=Required + Network PowerVSResource `json:"network"` + + // keyPairName is the name of the KeyPair to use for SSH. + // The key pair will be exposed to the instance via the instance metadata service. + // On boot, the OS will copy the public keypair into the authorized keys for the core user. + // +kubebuilder:validation:=Required + KeyPairName string `json:"keyPairName"` + + // systemType is the System type used to host the instance. + // systemType determines the number of cores and memory that is available. + // Few of the supported SystemTypes are s922,e880,e980. + // e880 systemType available only in Dallas Datacenters. + // e980 systemType available in Datacenters except Dallas and Washington. + // When omitted, this means that the user has no opinion and the platform is left to choose a + // reasonable default, which is subject to change over time. The current default is s922 which is generally available. + // + This is not an enum because we expect other values to be added later which should be supported implicitly. + // +optional + SystemType string `json:"systemType,omitempty"` + + // processorType is the VM instance processor type. + // It must be set to one of the following values: Dedicated, Capped or Shared. + // Dedicated: resources are allocated for a specific client, The hypervisor makes a 1:1 binding of a partition’s processor to a physical processor core. + // Shared: Shared among other clients. + // Capped: Shared, but resources do not expand beyond those that are requested, the amount of CPU time is Capped to the value specified for the entitlement. + // if the processorType is selected as Dedicated, then processors value cannot be fractional. + // When omitted, this means that the user has no opinion and the platform is left to choose a + // reasonable default, which is subject to change over time. The current default is Shared. + // +kubebuilder:validation:Enum:="Dedicated";"Shared";"Capped";"" + // +optional + ProcessorType PowerVSProcessorType `json:"processorType,omitempty"` + + // processors is the number of virtual processors in a virtual machine. + // when the processorType is selected as Dedicated the processors value cannot be fractional. + // maximum value for the Processors depends on the selected SystemType. + // when SystemType is set to e880 or e980 maximum Processors value is 143. + // when SystemType is set to s922 maximum Processors value is 15. + // minimum value for Processors depends on the selected ProcessorType. + // when ProcessorType is set as Shared or Capped, The minimum processors is 0.5. + // when ProcessorType is set as Dedicated, The minimum processors is 1. + // When omitted, this means that the user has no opinion and the platform is left to choose a + // reasonable default, which is subject to change over time. The default is set based on the selected ProcessorType. + // when ProcessorType selected as Dedicated, the default is set to 1. + // when ProcessorType selected as Shared or Capped, the default is set to 0.5. + // +optional + Processors intstr.IntOrString `json:"processors,omitempty"` + + // memoryGiB is the size of a virtual machine's memory, in GiB. + // maximum value for the MemoryGiB depends on the selected SystemType. + // when SystemType is set to e880 maximum MemoryGiB value is 7463 GiB. + // when SystemType is set to e980 maximum MemoryGiB value is 15307 GiB. + // when SystemType is set to s922 maximum MemoryGiB value is 942 GiB. + // The minimum memory is 32 GiB. + // When omitted, this means the user has no opinion and the platform is left to choose a reasonable + // default, which is subject to change over time. The current default is 32. + // +optional + MemoryGiB int32 `json:"memoryGiB,omitempty"` + + // loadBalancers is the set of load balancers to which the new control plane instance + // should be added once it is created. + // +optional + LoadBalancers []LoadBalancerReference `json:"loadBalancers,omitempty"` +} + +// PowerVSResource is a reference to a specific PowerVS resource by ID, Name or RegEx +// Only one of ID, Name or RegEx may be specified. Specifying more than one will result in +// a validation error. +// +union +type PowerVSResource struct { + // type identifies the resource type for this entry. + // Valid values are ID, Name and RegEx + // +kubebuilder:validation:Enum:=ID;Name;RegEx + // +optional + Type PowerVSResourceType `json:"type,omitempty"` + // id of resource + // +optional + ID *string `json:"id,omitempty"` + // name of resource + // +optional + Name *string `json:"name,omitempty"` + // regex to find resource + // Regex contains the pattern to match to find a resource + // +optional + RegEx *string `json:"regex,omitempty"` +} + +// PowerVSMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. +// It contains PowerVS-specific status information. +// +// 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 +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type PowerVSMachineProviderStatus struct { + metav1.TypeMeta `json:",inline"` + + // conditions is a set of conditions associated with the Machine to indicate + // errors or other status + // +listType=map + // +listMapKey=type + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // instanceId is the instance ID of the machine created in PowerVS + // instanceId uniquely identifies a Power VS server instance(VM) under a Power VS service. + // This will help in updating or deleting a VM in Power VS Cloud + // +optional + InstanceID *string `json:"instanceId,omitempty"` + + // serviceInstanceID is the reference to the Power VS ServiceInstance on which the machine instance will be created. + // serviceInstanceID uniquely identifies the Power VS service + // By setting serviceInstanceID it will become easy and efficient to fetch a server instance(VM) within Power VS Cloud. + // +optional + ServiceInstanceID *string `json:"serviceInstanceID,omitempty"` + + // instanceState is the state of the PowerVS instance for this machine + // Possible instance states are Active, Build, ShutOff, Reboot + // This is used to display additional information to user regarding instance current state + // +optional + InstanceState *string `json:"instanceState,omitempty"` +} + +// PowerVSSecretReference contains enough information to locate the +// referenced secret inside the same namespace. +// +structType=atomic +type PowerVSSecretReference struct { + // name of the secret. + // +optional + Name string `json:"name,omitempty"` +} + +// LoadBalancerReference is a reference to a load balancer on IBM Cloud virtual private cloud(VPC). +type LoadBalancerReference struct { + // name of the LoadBalancer in IBM Cloud VPC. + // The name should be between 1 and 63 characters long and may consist of lowercase alphanumeric characters and hyphens only. + // The value must not end with a hyphen. + // It is a reference to existing LoadBalancer created by openshift installer component. + // +required + // +kubebuilder:validation:Pattern=`^([a-z]|[a-z][-a-z0-9]*[a-z0-9]|[0-9][-a-z0-9]*([a-z]|[-a-z][-a-z0-9]*[a-z0-9]))$` + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + Name string `json:"name"` + // type of the LoadBalancer service supported by IBM Cloud VPC. + // Currently, only Application LoadBalancer is supported. + // More details about Application LoadBalancer + // https://cloud.ibm.com/docs/vpc?topic=vpc-load-balancers-about&interface=ui + // Supported values are Application. + // +required + // +kubebuilder:validation:Enum:="Application" + Type IBMVPCLoadBalancerType `json:"type"` +} diff --git a/vendor/github.com/openshift/api/machine/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/machine/v1/zz_generated.deepcopy.go new file mode 100644 index 000000000..61294ef58 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/zz_generated.deepcopy.go @@ -0,0 +1,1123 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by codegen. DO NOT EDIT. + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSFailureDomain) DeepCopyInto(out *AWSFailureDomain) { + *out = *in + if in.Subnet != nil { + in, out := &in.Subnet, &out.Subnet + *out = new(AWSResourceReference) + (*in).DeepCopyInto(*out) + } + out.Placement = in.Placement + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSFailureDomain. +func (in *AWSFailureDomain) DeepCopy() *AWSFailureDomain { + if in == nil { + return nil + } + out := new(AWSFailureDomain) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSFailureDomainPlacement) DeepCopyInto(out *AWSFailureDomainPlacement) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSFailureDomainPlacement. +func (in *AWSFailureDomainPlacement) DeepCopy() *AWSFailureDomainPlacement { + if in == nil { + return nil + } + out := new(AWSFailureDomainPlacement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSResourceFilter) DeepCopyInto(out *AWSResourceFilter) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSResourceFilter. +func (in *AWSResourceFilter) DeepCopy() *AWSResourceFilter { + if in == nil { + return nil + } + out := new(AWSResourceFilter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSResourceReference) DeepCopyInto(out *AWSResourceReference) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.ARN != nil { + in, out := &in.ARN, &out.ARN + *out = new(string) + **out = **in + } + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = new([]AWSResourceFilter) + if **in != nil { + in, out := *in, *out + *out = make([]AWSResourceFilter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSResourceReference. +func (in *AWSResourceReference) DeepCopy() *AWSResourceReference { + if in == nil { + return nil + } + out := new(AWSResourceReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AlibabaCloudMachineProviderConfig) DeepCopyInto(out *AlibabaCloudMachineProviderConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.DataDisks != nil { + in, out := &in.DataDisks, &out.DataDisks + *out = make([]DataDiskProperties, len(*in)) + copy(*out, *in) + } + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]AlibabaResourceReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + out.Bandwidth = in.Bandwidth + out.SystemDisk = in.SystemDisk + in.VSwitch.DeepCopyInto(&out.VSwitch) + in.ResourceGroup.DeepCopyInto(&out.ResourceGroup) + if in.UserDataSecret != nil { + in, out := &in.UserDataSecret, &out.UserDataSecret + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.CredentialsSecret != nil { + in, out := &in.CredentialsSecret, &out.CredentialsSecret + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]Tag, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlibabaCloudMachineProviderConfig. +func (in *AlibabaCloudMachineProviderConfig) DeepCopy() *AlibabaCloudMachineProviderConfig { + if in == nil { + return nil + } + out := new(AlibabaCloudMachineProviderConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AlibabaCloudMachineProviderConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AlibabaCloudMachineProviderConfigList) DeepCopyInto(out *AlibabaCloudMachineProviderConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AlibabaCloudMachineProviderConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlibabaCloudMachineProviderConfigList. +func (in *AlibabaCloudMachineProviderConfigList) DeepCopy() *AlibabaCloudMachineProviderConfigList { + if in == nil { + return nil + } + out := new(AlibabaCloudMachineProviderConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AlibabaCloudMachineProviderConfigList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AlibabaCloudMachineProviderStatus) DeepCopyInto(out *AlibabaCloudMachineProviderStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.InstanceID != nil { + in, out := &in.InstanceID, &out.InstanceID + *out = new(string) + **out = **in + } + if in.InstanceState != nil { + in, out := &in.InstanceState, &out.InstanceState + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlibabaCloudMachineProviderStatus. +func (in *AlibabaCloudMachineProviderStatus) DeepCopy() *AlibabaCloudMachineProviderStatus { + if in == nil { + return nil + } + out := new(AlibabaCloudMachineProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AlibabaCloudMachineProviderStatus) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AlibabaResourceReference) DeepCopyInto(out *AlibabaResourceReference) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = new([]Tag) + if **in != nil { + in, out := *in, *out + *out = make([]Tag, len(*in)) + copy(*out, *in) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlibabaResourceReference. +func (in *AlibabaResourceReference) DeepCopy() *AlibabaResourceReference { + if in == nil { + return nil + } + out := new(AlibabaResourceReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AzureFailureDomain) DeepCopyInto(out *AzureFailureDomain) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureFailureDomain. +func (in *AzureFailureDomain) DeepCopy() *AzureFailureDomain { + if in == nil { + return nil + } + out := new(AzureFailureDomain) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BandwidthProperties) DeepCopyInto(out *BandwidthProperties) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BandwidthProperties. +func (in *BandwidthProperties) DeepCopy() *BandwidthProperties { + if in == nil { + return nil + } + out := new(BandwidthProperties) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneMachineSet) DeepCopyInto(out *ControlPlaneMachineSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneMachineSet. +func (in *ControlPlaneMachineSet) DeepCopy() *ControlPlaneMachineSet { + if in == nil { + return nil + } + out := new(ControlPlaneMachineSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ControlPlaneMachineSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneMachineSetList) DeepCopyInto(out *ControlPlaneMachineSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ControlPlaneMachineSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneMachineSetList. +func (in *ControlPlaneMachineSetList) DeepCopy() *ControlPlaneMachineSetList { + if in == nil { + return nil + } + out := new(ControlPlaneMachineSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ControlPlaneMachineSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneMachineSetSpec) DeepCopyInto(out *ControlPlaneMachineSetSpec) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + out.Strategy = in.Strategy + in.Selector.DeepCopyInto(&out.Selector) + in.Template.DeepCopyInto(&out.Template) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneMachineSetSpec. +func (in *ControlPlaneMachineSetSpec) DeepCopy() *ControlPlaneMachineSetSpec { + if in == nil { + return nil + } + out := new(ControlPlaneMachineSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneMachineSetStatus) DeepCopyInto(out *ControlPlaneMachineSetStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneMachineSetStatus. +func (in *ControlPlaneMachineSetStatus) DeepCopy() *ControlPlaneMachineSetStatus { + if in == nil { + return nil + } + out := new(ControlPlaneMachineSetStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneMachineSetStrategy) DeepCopyInto(out *ControlPlaneMachineSetStrategy) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneMachineSetStrategy. +func (in *ControlPlaneMachineSetStrategy) DeepCopy() *ControlPlaneMachineSetStrategy { + if in == nil { + return nil + } + out := new(ControlPlaneMachineSetStrategy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneMachineSetTemplate) DeepCopyInto(out *ControlPlaneMachineSetTemplate) { + *out = *in + if in.OpenShiftMachineV1Beta1Machine != nil { + in, out := &in.OpenShiftMachineV1Beta1Machine, &out.OpenShiftMachineV1Beta1Machine + *out = new(OpenShiftMachineV1Beta1MachineTemplate) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneMachineSetTemplate. +func (in *ControlPlaneMachineSetTemplate) DeepCopy() *ControlPlaneMachineSetTemplate { + if in == nil { + return nil + } + out := new(ControlPlaneMachineSetTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControlPlaneMachineSetTemplateObjectMeta) DeepCopyInto(out *ControlPlaneMachineSetTemplateObjectMeta) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControlPlaneMachineSetTemplateObjectMeta. +func (in *ControlPlaneMachineSetTemplateObjectMeta) DeepCopy() *ControlPlaneMachineSetTemplateObjectMeta { + if in == nil { + return nil + } + out := new(ControlPlaneMachineSetTemplateObjectMeta) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataDiskProperties) DeepCopyInto(out *DataDiskProperties) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataDiskProperties. +func (in *DataDiskProperties) DeepCopy() *DataDiskProperties { + if in == nil { + return nil + } + out := new(DataDiskProperties) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FailureDomains) DeepCopyInto(out *FailureDomains) { + *out = *in + if in.AWS != nil { + in, out := &in.AWS, &out.AWS + *out = new([]AWSFailureDomain) + if **in != nil { + in, out := *in, *out + *out = make([]AWSFailureDomain, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + } + if in.Azure != nil { + in, out := &in.Azure, &out.Azure + *out = new([]AzureFailureDomain) + if **in != nil { + in, out := *in, *out + *out = make([]AzureFailureDomain, len(*in)) + copy(*out, *in) + } + } + if in.GCP != nil { + in, out := &in.GCP, &out.GCP + *out = new([]GCPFailureDomain) + if **in != nil { + in, out := *in, *out + *out = make([]GCPFailureDomain, len(*in)) + copy(*out, *in) + } + } + if in.VSphere != nil { + in, out := &in.VSphere, &out.VSphere + *out = make([]VSphereFailureDomain, len(*in)) + copy(*out, *in) + } + if in.OpenStack != nil { + in, out := &in.OpenStack, &out.OpenStack + *out = make([]OpenStackFailureDomain, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Nutanix != nil { + in, out := &in.Nutanix, &out.Nutanix + *out = make([]NutanixFailureDomainReference, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FailureDomains. +func (in *FailureDomains) DeepCopy() *FailureDomains { + if in == nil { + return nil + } + out := new(FailureDomains) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPFailureDomain) DeepCopyInto(out *GCPFailureDomain) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPFailureDomain. +func (in *GCPFailureDomain) DeepCopy() *GCPFailureDomain { + if in == nil { + return nil + } + out := new(GCPFailureDomain) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoadBalancerReference) DeepCopyInto(out *LoadBalancerReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancerReference. +func (in *LoadBalancerReference) DeepCopy() *LoadBalancerReference { + if in == nil { + return nil + } + out := new(LoadBalancerReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixCategory) DeepCopyInto(out *NutanixCategory) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixCategory. +func (in *NutanixCategory) DeepCopy() *NutanixCategory { + if in == nil { + return nil + } + out := new(NutanixCategory) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixFailureDomainReference) DeepCopyInto(out *NutanixFailureDomainReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixFailureDomainReference. +func (in *NutanixFailureDomainReference) DeepCopy() *NutanixFailureDomainReference { + if in == nil { + return nil + } + out := new(NutanixFailureDomainReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixGPU) DeepCopyInto(out *NutanixGPU) { + *out = *in + if in.DeviceID != nil { + in, out := &in.DeviceID, &out.DeviceID + *out = new(int32) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixGPU. +func (in *NutanixGPU) DeepCopy() *NutanixGPU { + if in == nil { + return nil + } + out := new(NutanixGPU) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixMachineProviderConfig) DeepCopyInto(out *NutanixMachineProviderConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Cluster.DeepCopyInto(&out.Cluster) + in.Image.DeepCopyInto(&out.Image) + if in.Subnets != nil { + in, out := &in.Subnets, &out.Subnets + *out = make([]NutanixResourceIdentifier, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + out.MemorySize = in.MemorySize.DeepCopy() + out.SystemDiskSize = in.SystemDiskSize.DeepCopy() + in.Project.DeepCopyInto(&out.Project) + if in.Categories != nil { + in, out := &in.Categories, &out.Categories + *out = make([]NutanixCategory, len(*in)) + copy(*out, *in) + } + if in.GPUs != nil { + in, out := &in.GPUs, &out.GPUs + *out = make([]NutanixGPU, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.DataDisks != nil { + in, out := &in.DataDisks, &out.DataDisks + *out = make([]NutanixVMDisk, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.UserDataSecret != nil { + in, out := &in.UserDataSecret, &out.UserDataSecret + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.CredentialsSecret != nil { + in, out := &in.CredentialsSecret, &out.CredentialsSecret + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.FailureDomain != nil { + in, out := &in.FailureDomain, &out.FailureDomain + *out = new(NutanixFailureDomainReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixMachineProviderConfig. +func (in *NutanixMachineProviderConfig) DeepCopy() *NutanixMachineProviderConfig { + if in == nil { + return nil + } + out := new(NutanixMachineProviderConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NutanixMachineProviderConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixMachineProviderStatus) DeepCopyInto(out *NutanixMachineProviderStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.VmUUID != nil { + in, out := &in.VmUUID, &out.VmUUID + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixMachineProviderStatus. +func (in *NutanixMachineProviderStatus) DeepCopy() *NutanixMachineProviderStatus { + if in == nil { + return nil + } + out := new(NutanixMachineProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NutanixMachineProviderStatus) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixResourceIdentifier) DeepCopyInto(out *NutanixResourceIdentifier) { + *out = *in + if in.UUID != nil { + in, out := &in.UUID, &out.UUID + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixResourceIdentifier. +func (in *NutanixResourceIdentifier) DeepCopy() *NutanixResourceIdentifier { + if in == nil { + return nil + } + out := new(NutanixResourceIdentifier) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixStorageResourceIdentifier) DeepCopyInto(out *NutanixStorageResourceIdentifier) { + *out = *in + if in.UUID != nil { + in, out := &in.UUID, &out.UUID + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixStorageResourceIdentifier. +func (in *NutanixStorageResourceIdentifier) DeepCopy() *NutanixStorageResourceIdentifier { + if in == nil { + return nil + } + out := new(NutanixStorageResourceIdentifier) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixVMDisk) DeepCopyInto(out *NutanixVMDisk) { + *out = *in + out.DiskSize = in.DiskSize.DeepCopy() + if in.DeviceProperties != nil { + in, out := &in.DeviceProperties, &out.DeviceProperties + *out = new(NutanixVMDiskDeviceProperties) + **out = **in + } + if in.StorageConfig != nil { + in, out := &in.StorageConfig, &out.StorageConfig + *out = new(NutanixVMStorageConfig) + (*in).DeepCopyInto(*out) + } + if in.DataSource != nil { + in, out := &in.DataSource, &out.DataSource + *out = new(NutanixResourceIdentifier) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixVMDisk. +func (in *NutanixVMDisk) DeepCopy() *NutanixVMDisk { + if in == nil { + return nil + } + out := new(NutanixVMDisk) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixVMDiskDeviceProperties) DeepCopyInto(out *NutanixVMDiskDeviceProperties) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixVMDiskDeviceProperties. +func (in *NutanixVMDiskDeviceProperties) DeepCopy() *NutanixVMDiskDeviceProperties { + if in == nil { + return nil + } + out := new(NutanixVMDiskDeviceProperties) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NutanixVMStorageConfig) DeepCopyInto(out *NutanixVMStorageConfig) { + *out = *in + if in.StorageContainer != nil { + in, out := &in.StorageContainer, &out.StorageContainer + *out = new(NutanixStorageResourceIdentifier) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixVMStorageConfig. +func (in *NutanixVMStorageConfig) DeepCopy() *NutanixVMStorageConfig { + if in == nil { + return nil + } + out := new(NutanixVMStorageConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenShiftMachineV1Beta1MachineTemplate) DeepCopyInto(out *OpenShiftMachineV1Beta1MachineTemplate) { + *out = *in + if in.FailureDomains != nil { + in, out := &in.FailureDomains, &out.FailureDomains + *out = new(FailureDomains) + (*in).DeepCopyInto(*out) + } + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenShiftMachineV1Beta1MachineTemplate. +func (in *OpenShiftMachineV1Beta1MachineTemplate) DeepCopy() *OpenShiftMachineV1Beta1MachineTemplate { + if in == nil { + return nil + } + out := new(OpenShiftMachineV1Beta1MachineTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenStackFailureDomain) DeepCopyInto(out *OpenStackFailureDomain) { + *out = *in + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(RootVolume) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackFailureDomain. +func (in *OpenStackFailureDomain) DeepCopy() *OpenStackFailureDomain { + if in == nil { + return nil + } + out := new(OpenStackFailureDomain) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PowerVSMachineProviderConfig) DeepCopyInto(out *PowerVSMachineProviderConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.UserDataSecret != nil { + in, out := &in.UserDataSecret, &out.UserDataSecret + *out = new(PowerVSSecretReference) + **out = **in + } + if in.CredentialsSecret != nil { + in, out := &in.CredentialsSecret, &out.CredentialsSecret + *out = new(PowerVSSecretReference) + **out = **in + } + in.ServiceInstance.DeepCopyInto(&out.ServiceInstance) + in.Image.DeepCopyInto(&out.Image) + in.Network.DeepCopyInto(&out.Network) + out.Processors = in.Processors + if in.LoadBalancers != nil { + in, out := &in.LoadBalancers, &out.LoadBalancers + *out = make([]LoadBalancerReference, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PowerVSMachineProviderConfig. +func (in *PowerVSMachineProviderConfig) DeepCopy() *PowerVSMachineProviderConfig { + if in == nil { + return nil + } + out := new(PowerVSMachineProviderConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PowerVSMachineProviderConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PowerVSMachineProviderStatus) DeepCopyInto(out *PowerVSMachineProviderStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.InstanceID != nil { + in, out := &in.InstanceID, &out.InstanceID + *out = new(string) + **out = **in + } + if in.ServiceInstanceID != nil { + in, out := &in.ServiceInstanceID, &out.ServiceInstanceID + *out = new(string) + **out = **in + } + if in.InstanceState != nil { + in, out := &in.InstanceState, &out.InstanceState + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PowerVSMachineProviderStatus. +func (in *PowerVSMachineProviderStatus) DeepCopy() *PowerVSMachineProviderStatus { + if in == nil { + return nil + } + out := new(PowerVSMachineProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *PowerVSMachineProviderStatus) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PowerVSResource) DeepCopyInto(out *PowerVSResource) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.RegEx != nil { + in, out := &in.RegEx, &out.RegEx + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PowerVSResource. +func (in *PowerVSResource) DeepCopy() *PowerVSResource { + if in == nil { + return nil + } + out := new(PowerVSResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PowerVSSecretReference) DeepCopyInto(out *PowerVSSecretReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PowerVSSecretReference. +func (in *PowerVSSecretReference) DeepCopy() *PowerVSSecretReference { + if in == nil { + return nil + } + out := new(PowerVSSecretReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RootVolume) DeepCopyInto(out *RootVolume) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RootVolume. +func (in *RootVolume) DeepCopy() *RootVolume { + if in == nil { + return nil + } + out := new(RootVolume) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SystemDiskProperties) DeepCopyInto(out *SystemDiskProperties) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SystemDiskProperties. +func (in *SystemDiskProperties) DeepCopy() *SystemDiskProperties { + if in == nil { + return nil + } + out := new(SystemDiskProperties) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Tag) DeepCopyInto(out *Tag) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Tag. +func (in *Tag) DeepCopy() *Tag { + if in == nil { + return nil + } + out := new(Tag) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereFailureDomain) DeepCopyInto(out *VSphereFailureDomain) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereFailureDomain. +func (in *VSphereFailureDomain) DeepCopy() *VSphereFailureDomain { + if in == nil { + return nil + } + out := new(VSphereFailureDomain) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/openshift/api/machine/v1/zz_generated.featuregated-crd-manifests.yaml b/vendor/github.com/openshift/api/machine/v1/zz_generated.featuregated-crd-manifests.yaml new file mode 100644 index 000000000..b001170fa --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/zz_generated.featuregated-crd-manifests.yaml @@ -0,0 +1,52 @@ +controlplanemachinesets.machine.openshift.io: + Annotations: + exclude.release.openshift.io/internal-openshift-hosted: "true" + include.release.openshift.io/self-managed-high-availability: "true" + ApprovedPRNumber: https://github.com/openshift/api/pull/1112 + CRDName: controlplanemachinesets.machine.openshift.io + Capability: MachineAPI + Category: "" + FeatureGates: + - MachineAPIMigration + FilenameOperatorName: control-plane-machine-set + FilenameOperatorOrdering: "01" + FilenameRunLevel: "0000_10" + GroupName: machine.openshift.io + HasStatus: true + KindName: ControlPlaneMachineSet + Labels: {} + PluralName: controlplanemachinesets + PrinterColumns: + - description: Desired Replicas + jsonPath: .spec.replicas + name: Desired + type: integer + - description: Current Replicas + jsonPath: .status.replicas + name: Current + type: integer + - description: Ready Replicas + jsonPath: .status.readyReplicas + name: Ready + type: integer + - description: Updated Replicas + jsonPath: .status.updatedReplicas + name: Updated + type: integer + - description: Observed number of unavailable replicas + jsonPath: .status.unavailableReplicas + name: Unavailable + type: integer + - description: ControlPlaneMachineSet state + jsonPath: .spec.state + name: State + type: string + - description: ControlPlaneMachineSet age + jsonPath: .metadata.creationTimestamp + name: Age + type: date + Scope: Namespaced + ShortNames: null + TopLevelFeatureGates: [] + Version: v1 + diff --git a/vendor/github.com/openshift/api/machine/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/machine/v1/zz_generated.swagger_doc_generated.go new file mode 100644 index 000000000..2e35df7e2 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1/zz_generated.swagger_doc_generated.go @@ -0,0 +1,490 @@ +package v1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE +var map_AlibabaCloudMachineProviderConfig = map[string]string{ + "": "AlibabaCloudMachineProviderConfig is the Schema for the alibabacloudmachineproviderconfig API Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "instanceType": "The instance type of the instance.", + "vpcId": "The ID of the vpc", + "regionId": "The ID of the region in which to create the instance. You can call the DescribeRegions operation to query the most recent region list.", + "zoneId": "The ID of the zone in which to create the instance. You can call the DescribeZones operation to query the most recent region list.", + "imageId": "The ID of the image used to create the instance.", + "dataDisk": "DataDisks holds information regarding the extra disks attached to the instance", + "securityGroups": "securityGroups is a list of security group references to assign to the instance. A reference holds either the security group ID, the resource name, or the required tags to search. When more than one security group is returned for a tag search, all the groups are associated with the instance up to the maximum number of security groups to which an instance can belong. For more information, see the \"Security group limits\" section in Limits. https://www.alibabacloud.com/help/en/doc-detail/25412.htm", + "bandwidth": "bandwidth describes the internet bandwidth strategy for the instance", + "systemDisk": "systemDisk holds the properties regarding the system disk for the instance", + "vSwitch": "vSwitch is a reference to the vswitch to use for this instance. A reference holds either the vSwitch ID, the resource name, or the required tags to search. When more than one vSwitch is returned for a tag search, only the first vSwitch returned will be used. This parameter is required when you create an instance of the VPC type. You can call the DescribeVSwitches operation to query the created vSwitches.", + "ramRoleName": "ramRoleName is the name of the instance Resource Access Management (RAM) role. This allows the instance to perform API calls as this specified RAM role.", + "resourceGroup": "resourceGroup references the resource group to which to assign the instance. A reference holds either the resource group ID, the resource name, or the required tags to search. When more than one resource group are returned for a search, an error will be produced and the Machine will not be created. Resource Groups do not support searching by tags.", + "tenancy": "tenancy specifies whether to create the instance on a dedicated host. Valid values:\n\ndefault: creates the instance on a non-dedicated host. host: creates the instance on a dedicated host. If you do not specify the DedicatedHostID parameter, Alibaba Cloud automatically selects a dedicated host for the instance. Empty value means no opinion and the platform chooses the a default, which is subject to change over time. Currently the default is `default`.", + "userDataSecret": "userDataSecret contains a local reference to a secret that contains the UserData to apply to the instance", + "credentialsSecret": "credentialsSecret is a reference to the secret with alibabacloud credentials. Otherwise, defaults to permissions provided by attached RAM role where the actuator is running.", + "tag": "Tags are the set of metadata to add to an instance.", +} + +func (AlibabaCloudMachineProviderConfig) SwaggerDoc() map[string]string { + return map_AlibabaCloudMachineProviderConfig +} + +var map_AlibabaCloudMachineProviderConfigList = map[string]string{ + "": "AlibabaCloudMachineProviderConfigList contains a list of AlibabaCloudMachineProviderConfig Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard list's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", +} + +func (AlibabaCloudMachineProviderConfigList) SwaggerDoc() map[string]string { + return map_AlibabaCloudMachineProviderConfigList +} + +var map_AlibabaCloudMachineProviderStatus = map[string]string{ + "": "AlibabaCloudMachineProviderStatus is the Schema for the alibabacloudmachineproviderconfig API Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "instanceId": "instanceId is the instance ID of the machine created in alibabacloud", + "instanceState": "instanceState is the state of the alibabacloud instance for this machine", + "conditions": "conditions is a set of conditions associated with the Machine to indicate errors or other status", +} + +func (AlibabaCloudMachineProviderStatus) SwaggerDoc() map[string]string { + return map_AlibabaCloudMachineProviderStatus +} + +var map_AlibabaResourceReference = map[string]string{ + "": "ResourceTagReference is a reference to a specific AlibabaCloud resource by ID, or tags. Only one of ID or Tags may be specified. Specifying more than one will result in a validation error.", + "type": "type identifies the resource reference type for this entry.", + "id": "id of resource", + "name": "name of the resource", + "tags": "tags is a set of metadata based upon ECS object tags used to identify a resource. For details about usage when multiple resources are found, please see the owning parent field documentation.", +} + +func (AlibabaResourceReference) SwaggerDoc() map[string]string { + return map_AlibabaResourceReference +} + +var map_BandwidthProperties = map[string]string{ + "": "Bandwidth describes the bandwidth strategy for the network of the instance", + "internetMaxBandwidthIn": "internetMaxBandwidthIn is the maximum inbound public bandwidth. Unit: Mbit/s. Valid values: When the purchased outbound public bandwidth is less than or equal to 10 Mbit/s, the valid values of this parameter are 1 to 10. Currently the default is `10` when outbound bandwidth is less than or equal to 10 Mbit/s. When the purchased outbound public bandwidth is greater than 10, the valid values are 1 to the InternetMaxBandwidthOut value. Currently the default is the value used for `InternetMaxBandwidthOut` when outbound public bandwidth is greater than 10.", + "internetMaxBandwidthOut": "internetMaxBandwidthOut is the maximum outbound public bandwidth. Unit: Mbit/s. Valid values: 0 to 100. When a value greater than 0 is used then a public IP address is assigned to the instance. Empty value means no opinion and the platform chooses the a default, which is subject to change over time. Currently the default is `0`", +} + +func (BandwidthProperties) SwaggerDoc() map[string]string { + return map_BandwidthProperties +} + +var map_DataDiskProperties = map[string]string{ + "": "DataDisk contains the information regarding the datadisk attached to an instance", + "Name": "Name is the name of data disk N. If the name is specified the name must be 2 to 128 characters in length. It must start with a letter and cannot start with http:// or https://. It can contain letters, digits, colons (:), underscores (_), and hyphens (-).\n\nEmpty value means the platform chooses a default, which is subject to change over time. Currently the default is `\"\"`.", + "SnapshotID": "SnapshotID is the ID of the snapshot used to create data disk N. Valid values of N: 1 to 16.\n\nWhen the DataDisk.N.SnapshotID parameter is specified, the DataDisk.N.Size parameter is ignored. The data disk is created based on the size of the specified snapshot. Use snapshots created after July 15, 2013. Otherwise, an error is returned and your request is rejected.", + "Size": "Size of the data disk N. Valid values of N: 1 to 16. Unit: GiB. Valid values:\n\nValid values when DataDisk.N.Category is set to cloud_efficiency: 20 to 32768 Valid values when DataDisk.N.Category is set to cloud_ssd: 20 to 32768 Valid values when DataDisk.N.Category is set to cloud_essd: 20 to 32768 Valid values when DataDisk.N.Category is set to cloud: 5 to 2000 The value of this parameter must be greater than or equal to the size of the snapshot specified by the SnapshotID parameter.", + "DiskEncryption": "DiskEncryption specifies whether to encrypt data disk N.\n\nEmpty value means the platform chooses a default, which is subject to change over time. Currently the default is `disabled`.", + "PerformanceLevel": "PerformanceLevel is the performance level of the ESSD used as as data disk N. The N value must be the same as that in DataDisk.N.Category when DataDisk.N.Category is set to cloud_essd. Empty value means no opinion and the platform chooses a default, which is subject to change over time. Currently the default is `PL1`. Valid values:\n\nPL0: A single ESSD can deliver up to 10,000 random read/write IOPS. PL1: A single ESSD can deliver up to 50,000 random read/write IOPS. PL2: A single ESSD can deliver up to 100,000 random read/write IOPS. PL3: A single ESSD can deliver up to 1,000,000 random read/write IOPS. For more information about ESSD performance levels, see ESSDs.", + "Category": "Category describes the type of data disk N. Valid values: cloud_efficiency: ultra disk cloud_ssd: standard SSD cloud_essd: ESSD cloud: basic disk Empty value means no opinion and the platform chooses the a default, which is subject to change over time. Currently for non-I/O optimized instances of retired instance types, the default is `cloud`. Currently for other instances, the default is `cloud_efficiency`.", + "KMSKeyID": "KMSKeyID is the ID of the Key Management Service (KMS) key to be used by data disk N. Empty value means no opinion and the platform chooses the a default, which is subject to change over time. Currently the default is `\"\"` which is interpreted as do not use KMSKey encryption.", + "DiskPreservation": "DiskPreservation specifies whether to release data disk N along with the instance. Empty value means no opinion and the platform chooses the a default, which is subject to change over time. Currently the default is `DeleteWithInstance`", +} + +func (DataDiskProperties) SwaggerDoc() map[string]string { + return map_DataDiskProperties +} + +var map_SystemDiskProperties = map[string]string{ + "": "SystemDiskProperties contains the information regarding the system disk including performance, size, name, and category", + "category": "category is the category of the system disk. Valid values: cloud_essd: ESSD. When the parameter is set to this value, you can use the SystemDisk.PerformanceLevel parameter to specify the performance level of the disk. cloud_efficiency: ultra disk. cloud_ssd: standard SSD. cloud: basic disk. Empty value means no opinion and the platform chooses the a default, which is subject to change over time. Currently for non-I/O optimized instances of retired instance types, the default is `cloud`. Currently for other instances, the default is `cloud_efficiency`.", + "performanceLevel": "performanceLevel is the performance level of the ESSD used as the system disk. Valid values:\n\nPL0: A single ESSD can deliver up to 10,000 random read/write IOPS. PL1: A single ESSD can deliver up to 50,000 random read/write IOPS. PL2: A single ESSD can deliver up to 100,000 random read/write IOPS. PL3: A single ESSD can deliver up to 1,000,000 random read/write IOPS. Empty value means no opinion and the platform chooses a default, which is subject to change over time. Currently the default is `PL1`. For more information about ESSD performance levels, see ESSDs.", + "name": "name is the name of the system disk. If the name is specified the name must be 2 to 128 characters in length. It must start with a letter and cannot start with http:// or https://. It can contain letters, digits, colons (:), underscores (_), and hyphens (-). Empty value means the platform chooses a default, which is subject to change over time. Currently the default is `\"\"`.", + "size": "size is the size of the system disk. Unit: GiB. Valid values: 20 to 500. The value must be at least 20 and greater than or equal to the size of the image. Empty value means the platform chooses a default, which is subject to change over time. Currently the default is `40` or the size of the image depending on whichever is greater.", +} + +func (SystemDiskProperties) SwaggerDoc() map[string]string { + return map_SystemDiskProperties +} + +var map_Tag = map[string]string{ + "": "Tag The tags of ECS Instance", + "Key": "Key is the name of the key pair", + "Value": "Value is the value or data of the key pair", +} + +func (Tag) SwaggerDoc() map[string]string { + return map_Tag +} + +var map_AWSResourceFilter = map[string]string{ + "": "AWSResourceFilter is a filter used to identify an AWS resource", + "name": "name of the filter. Filter names are case-sensitive.", + "values": "values includes one or more filter values. Filter values are case-sensitive.", +} + +func (AWSResourceFilter) SwaggerDoc() map[string]string { + return map_AWSResourceFilter +} + +var map_AWSResourceReference = map[string]string{ + "": "AWSResourceReference is a reference to a specific AWS resource by ID, ARN, or filters. Only one of ID, ARN or Filters may be specified. Specifying more than one will result in a validation error.", + "type": "type determines how the reference will fetch the AWS resource.", + "id": "id of resource.", + "arn": "arn of resource.", + "filters": "filters is a set of filters used to identify a resource.", +} + +func (AWSResourceReference) SwaggerDoc() map[string]string { + return map_AWSResourceReference +} + +var map_AWSFailureDomain = map[string]string{ + "": "AWSFailureDomain configures failure domain information for the AWS platform.", + "subnet": "subnet is a reference to the subnet to use for this instance.", + "placement": "placement configures the placement information for this instance.", +} + +func (AWSFailureDomain) SwaggerDoc() map[string]string { + return map_AWSFailureDomain +} + +var map_AWSFailureDomainPlacement = map[string]string{ + "": "AWSFailureDomainPlacement configures the placement information for the AWSFailureDomain.", + "availabilityZone": "availabilityZone is the availability zone of the instance.", +} + +func (AWSFailureDomainPlacement) SwaggerDoc() map[string]string { + return map_AWSFailureDomainPlacement +} + +var map_AzureFailureDomain = map[string]string{ + "": "AzureFailureDomain configures failure domain information for the Azure platform.", + "zone": "Availability Zone for the virtual machine. If nil, the virtual machine should be deployed to no zone.", + "subnet": "subnet is the name of the network subnet in which the VM will be created. When omitted, the subnet value from the machine providerSpec template will be used.", +} + +func (AzureFailureDomain) SwaggerDoc() map[string]string { + return map_AzureFailureDomain +} + +var map_ControlPlaneMachineSet = map[string]string{ + "": "ControlPlaneMachineSet ensures that a specified number of control plane machine replicas are running at any given time. Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", +} + +func (ControlPlaneMachineSet) SwaggerDoc() map[string]string { + return map_ControlPlaneMachineSet +} + +var map_ControlPlaneMachineSetList = map[string]string{ + "": "ControlPlaneMachineSetList contains a list of ControlPlaneMachineSet Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard list's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", +} + +func (ControlPlaneMachineSetList) SwaggerDoc() map[string]string { + return map_ControlPlaneMachineSetList +} + +var map_ControlPlaneMachineSetSpec = map[string]string{ + "": "ControlPlaneMachineSet represents the configuration of the ControlPlaneMachineSet.", + "machineNamePrefix": "machineNamePrefix is the prefix used when creating machine names. Each machine name will consist of this prefix, followed by a randomly generated string of 5 characters, and the index of the machine. It must be a lowercase RFC 1123 subdomain, consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.'). Each block, separated by periods, must start and end with an alphanumeric character. Hyphens are not allowed at the start or end of a block, and consecutive periods are not permitted. The prefix must be between 1 and 245 characters in length. For example, if machineNamePrefix is set to 'control-plane', and three machines are created, their names might be: control-plane-abcde-0, control-plane-fghij-1, control-plane-klmno-2", + "state": "state defines whether the ControlPlaneMachineSet is Active or Inactive. When Inactive, the ControlPlaneMachineSet will not take any action on the state of the Machines within the cluster. When Active, the ControlPlaneMachineSet will reconcile the Machines and will update the Machines as necessary. Once Active, a ControlPlaneMachineSet cannot be made Inactive. To prevent further action please remove the ControlPlaneMachineSet.", + "replicas": "replicas defines how many Control Plane Machines should be created by this ControlPlaneMachineSet. This field is immutable and cannot be changed after cluster installation. The ControlPlaneMachineSet only operates with 3 or 5 node control planes, 3 and 5 are the only valid values for this field.", + "strategy": "strategy defines how the ControlPlaneMachineSet will update Machines when it detects a change to the ProviderSpec.", + "selector": "Label selector for Machines. Existing Machines selected by this selector will be the ones affected by this ControlPlaneMachineSet. It must match the template's labels. This field is considered immutable after creation of the resource.", + "template": "template describes the Control Plane Machines that will be created by this ControlPlaneMachineSet.", +} + +func (ControlPlaneMachineSetSpec) SwaggerDoc() map[string]string { + return map_ControlPlaneMachineSetSpec +} + +var map_ControlPlaneMachineSetStatus = map[string]string{ + "": "ControlPlaneMachineSetStatus represents the status of the ControlPlaneMachineSet CRD.", + "conditions": "conditions represents the observations of the ControlPlaneMachineSet's current state. Known .status.conditions.type are: Available, Degraded and Progressing.", + "observedGeneration": "observedGeneration is the most recent generation observed for this ControlPlaneMachineSet. It corresponds to the ControlPlaneMachineSets's generation, which is updated on mutation by the API Server.", + "replicas": "replicas is the number of Control Plane Machines created by the ControlPlaneMachineSet controller. Note that during update operations this value may differ from the desired replica count.", + "readyReplicas": "readyReplicas is the number of Control Plane Machines created by the ControlPlaneMachineSet controller which are ready. Note that this value may be higher than the desired number of replicas while rolling updates are in-progress.", + "updatedReplicas": "updatedReplicas is the number of non-terminated Control Plane Machines created by the ControlPlaneMachineSet controller that have the desired provider spec and are ready. This value is set to 0 when a change is detected to the desired spec. When the update strategy is RollingUpdate, this will also coincide with starting the process of updating the Machines. When the update strategy is OnDelete, this value will remain at 0 until a user deletes an existing replica and its replacement has become ready.", + "unavailableReplicas": "unavailableReplicas is the number of Control Plane Machines that are still required before the ControlPlaneMachineSet reaches the desired available capacity. When this value is non-zero, the number of ReadyReplicas is less than the desired Replicas.", +} + +func (ControlPlaneMachineSetStatus) SwaggerDoc() map[string]string { + return map_ControlPlaneMachineSetStatus +} + +var map_ControlPlaneMachineSetStrategy = map[string]string{ + "": "ControlPlaneMachineSetStrategy defines the strategy for applying updates to the Control Plane Machines managed by the ControlPlaneMachineSet.", + "type": "type defines the type of update strategy that should be used when updating Machines owned by the ControlPlaneMachineSet. Valid values are \"RollingUpdate\" and \"OnDelete\". The current default value is \"RollingUpdate\".", +} + +func (ControlPlaneMachineSetStrategy) SwaggerDoc() map[string]string { + return map_ControlPlaneMachineSetStrategy +} + +var map_ControlPlaneMachineSetTemplate = map[string]string{ + "": "ControlPlaneMachineSetTemplate is a template used by the ControlPlaneMachineSet to create the Machines that it will manage in the future. ", + "machineType": "machineType determines the type of Machines that should be managed by the ControlPlaneMachineSet. Currently, the only valid value is machines_v1beta1_machine_openshift_io.", + "machines_v1beta1_machine_openshift_io": "OpenShiftMachineV1Beta1Machine defines the template for creating Machines from the v1beta1.machine.openshift.io API group.", +} + +func (ControlPlaneMachineSetTemplate) SwaggerDoc() map[string]string { + return map_ControlPlaneMachineSetTemplate +} + +var map_ControlPlaneMachineSetTemplateObjectMeta = map[string]string{ + "": "ControlPlaneMachineSetTemplateObjectMeta is a subset of the metav1.ObjectMeta struct. It allows users to specify labels and annotations that will be copied onto Machines created from this template.", + "labels": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels. This field must contain both the 'machine.openshift.io/cluster-api-machine-role' and 'machine.openshift.io/cluster-api-machine-type' labels, both with a value of 'master'. It must also contain a label with the key 'machine.openshift.io/cluster-api-cluster'.", + "annotations": "annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations", +} + +func (ControlPlaneMachineSetTemplateObjectMeta) SwaggerDoc() map[string]string { + return map_ControlPlaneMachineSetTemplateObjectMeta +} + +var map_FailureDomains = map[string]string{ + "": "FailureDomain represents the different configurations required to spread Machines across failure domains on different platforms.", + "platform": "platform identifies the platform for which the FailureDomain represents. Currently supported values are AWS, Azure, GCP, OpenStack, VSphere and Nutanix.", + "aws": "aws configures failure domain information for the AWS platform.", + "azure": "azure configures failure domain information for the Azure platform.", + "gcp": "gcp configures failure domain information for the GCP platform.", + "vsphere": "vsphere configures failure domain information for the VSphere platform.", + "openstack": "openstack configures failure domain information for the OpenStack platform.", + "nutanix": "nutanix configures failure domain information for the Nutanix platform.", +} + +func (FailureDomains) SwaggerDoc() map[string]string { + return map_FailureDomains +} + +var map_GCPFailureDomain = map[string]string{ + "": "GCPFailureDomain configures failure domain information for the GCP platform", + "zone": "zone is the zone in which the GCP machine provider will create the VM.", +} + +func (GCPFailureDomain) SwaggerDoc() map[string]string { + return map_GCPFailureDomain +} + +var map_NutanixFailureDomainReference = map[string]string{ + "": "NutanixFailureDomainReference refers to the failure domain of the Nutanix platform.", + "name": "name of the failure domain in which the nutanix machine provider will create the VM. Failure domains are defined in a cluster's config.openshift.io/Infrastructure resource.", +} + +func (NutanixFailureDomainReference) SwaggerDoc() map[string]string { + return map_NutanixFailureDomainReference +} + +var map_OpenShiftMachineV1Beta1MachineTemplate = map[string]string{ + "": "OpenShiftMachineV1Beta1MachineTemplate is a template for the ControlPlaneMachineSet to create Machines from the v1beta1.machine.openshift.io API group.", + "failureDomains": "failureDomains is the list of failure domains (sometimes called availability zones) in which the ControlPlaneMachineSet should balance the Control Plane Machines. This will be merged into the ProviderSpec given in the template. This field is optional on platforms that do not require placement information.", + "metadata": "ObjectMeta is the standard object metadata More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata Labels are required to match the ControlPlaneMachineSet selector.", + "spec": "spec contains the desired configuration of the Control Plane Machines. The ProviderSpec within contains platform specific details for creating the Control Plane Machines. The ProviderSe should be complete apart from the platform specific failure domain field. This will be overridden when the Machines are created based on the FailureDomains field.", +} + +func (OpenShiftMachineV1Beta1MachineTemplate) SwaggerDoc() map[string]string { + return map_OpenShiftMachineV1Beta1MachineTemplate +} + +var map_OpenStackFailureDomain = map[string]string{ + "": "OpenStackFailureDomain configures failure domain information for the OpenStack platform.", + "availabilityZone": "availabilityZone is the nova availability zone in which the OpenStack machine provider will create the VM. If not specified, the VM will be created in the default availability zone specified in the nova configuration. Availability zone names must NOT contain : since it is used by admin users to specify hosts where instances are launched in server creation. Also, it must not contain spaces otherwise it will lead to node that belongs to this availability zone register failure, see kubernetes/cloud-provider-openstack#1379 for further information. The maximum length of availability zone name is 63 as per labels limits.", + "rootVolume": "rootVolume contains settings that will be used by the OpenStack machine provider to create the root volume attached to the VM. If not specified, no root volume will be created.", +} + +func (OpenStackFailureDomain) SwaggerDoc() map[string]string { + return map_OpenStackFailureDomain +} + +var map_RootVolume = map[string]string{ + "": "RootVolume represents the volume metadata to boot from. The original RootVolume struct is defined in the v1alpha1 but it's not best practice to use it directly here so we define a new one that should stay in sync with the original one.", + "availabilityZone": "availabilityZone specifies the Cinder availability zone where the root volume will be created. If not specifified, the root volume will be created in the availability zone specified by the volume type in the cinder configuration. If the volume type (configured in the OpenStack cluster) does not specify an availability zone, the root volume will be created in the default availability zone specified in the cinder configuration. See https://docs.openstack.org/cinder/latest/admin/availability-zone-type.html for more details. If the OpenStack cluster is deployed with the cross_az_attach configuration option set to false, the root volume will have to be in the same availability zone as the VM (defined by OpenStackFailureDomain.AvailabilityZone). Availability zone names must NOT contain spaces otherwise it will lead to volume that belongs to this availability zone register failure, see kubernetes/cloud-provider-openstack#1379 for further information. The maximum length of availability zone name is 63 as per labels limits.", + "volumeType": "volumeType specifies the type of the root volume that will be provisioned. The maximum length of a volume type name is 255 characters, as per the OpenStack limit. ", +} + +func (RootVolume) SwaggerDoc() map[string]string { + return map_RootVolume +} + +var map_VSphereFailureDomain = map[string]string{ + "": "VSphereFailureDomain configures failure domain information for the vSphere platform", + "name": "name of the failure domain in which the vSphere machine provider will create the VM. Failure domains are defined in a cluster's config.openshift.io/Infrastructure resource. When balancing machines across failure domains, the control plane machine set will inject configuration from the Infrastructure resource into the machine providerSpec to allocate the machine to a failure domain.", +} + +func (VSphereFailureDomain) SwaggerDoc() map[string]string { + return map_VSphereFailureDomain +} + +var map_NutanixCategory = map[string]string{ + "": "NutanixCategory identifies a pair of prism category key and value", + "key": "key is the prism category key name", + "value": "value is the prism category value associated with the key", +} + +func (NutanixCategory) SwaggerDoc() map[string]string { + return map_NutanixCategory +} + +var map_NutanixGPU = map[string]string{ + "": "NutanixGPU holds the identity of a Nutanix GPU resource in the Prism Central", + "type": "type is the identifier type of the GPU device. Valid values are Name and DeviceID.", + "deviceID": "deviceID is the GPU device ID with the integer value.", + "name": "name is the GPU device name", +} + +func (NutanixGPU) SwaggerDoc() map[string]string { + return map_NutanixGPU +} + +var map_NutanixMachineProviderConfig = map[string]string{ + "": "NutanixMachineProviderConfig is the Schema for the nutanixmachineproviderconfigs API Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "cluster": "cluster is to identify the cluster (the Prism Element under management of the Prism Central), in which the Machine's VM will be created. The cluster identifier (uuid or name) can be obtained from the Prism Central console or using the prism_central API.", + "image": "image is to identify the rhcos image uploaded to the Prism Central (PC) The image identifier (uuid or name) can be obtained from the Prism Central console or using the prism_central API.", + "subnets": "subnets holds a list of identifiers (one or more) of the cluster's network subnets for the Machine's VM to connect to. The subnet identifiers (uuid or name) can be obtained from the Prism Central console or using the prism_central API.", + "vcpusPerSocket": "vcpusPerSocket is the number of vCPUs per socket of the VM", + "vcpuSockets": "vcpuSockets is the number of vCPU sockets of the VM", + "memorySize": "memorySize is the memory size (in Quantity format) of the VM The minimum memorySize is 2Gi bytes", + "systemDiskSize": "systemDiskSize is size (in Quantity format) of the system disk of the VM The minimum systemDiskSize is 20Gi bytes", + "bootType": "bootType indicates the boot type (Legacy, UEFI or SecureBoot) the Machine's VM uses to boot. If this field is empty or omitted, the VM will use the default boot type \"Legacy\" to boot. \"SecureBoot\" depends on \"UEFI\" boot, i.e., enabling \"SecureBoot\" means that \"UEFI\" boot is also enabled.", + "project": "project optionally identifies a Prism project for the Machine's VM to associate with.", + "categories": "categories optionally adds one or more prism categories (each with key and value) for the Machine's VM to associate with. All the category key and value pairs specified must already exist in the prism central.", + "gpus": "gpus is a list of GPU devices to attach to the machine's VM. The GPU devices should already exist in Prism Central and associated with one of the Prism Element's hosts and available for the VM to attach (in \"UNUSED\" status).", + "dataDisks": "dataDisks holds information of the data disks to attach to the Machine's VM", + "userDataSecret": "userDataSecret is a local reference to a secret that contains the UserData to apply to the VM", + "credentialsSecret": "credentialsSecret is a local reference to a secret that contains the credentials data to access Nutanix PC client", + "failureDomain": "failureDomain refers to the name of the FailureDomain with which this Machine is associated. If this is configured, the Nutanix machine controller will use the prism_central endpoint and credentials defined in the referenced FailureDomain to communicate to the prism_central. It will also verify that the 'cluster' and subnets' configuration in the NutanixMachineProviderConfig is consistent with that in the referenced failureDomain.", +} + +func (NutanixMachineProviderConfig) SwaggerDoc() map[string]string { + return map_NutanixMachineProviderConfig +} + +var map_NutanixMachineProviderStatus = map[string]string{ + "": "NutanixMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. It contains nutanix-specific status information. Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "conditions": "conditions is a set of conditions associated with the Machine to indicate errors or other status", + "vmUUID": "vmUUID is the Machine associated VM's UUID The field is missing before the VM is created. Once the VM is created, the field is filled with the VM's UUID and it will not change. The vmUUID is used to find the VM when updating the Machine status, and to delete the VM when the Machine is deleted.", +} + +func (NutanixMachineProviderStatus) SwaggerDoc() map[string]string { + return map_NutanixMachineProviderStatus +} + +var map_NutanixResourceIdentifier = map[string]string{ + "": "NutanixResourceIdentifier holds the identity of a Nutanix PC resource (cluster, image, subnet, etc.)", + "type": "type is the identifier type to use for this resource.", + "uuid": "uuid is the UUID of the resource in the PC.", + "name": "name is the resource name in the PC", +} + +func (NutanixResourceIdentifier) SwaggerDoc() map[string]string { + return map_NutanixResourceIdentifier +} + +var map_NutanixStorageResourceIdentifier = map[string]string{ + "": "NutanixStorageResourceIdentifier holds the identity of a Nutanix storage resource (storage_container, etc.)", + "type": "type is the identifier type to use for this resource. The valid value is \"uuid\".", + "uuid": "uuid is the UUID of the storage resource in the PC.", +} + +func (NutanixStorageResourceIdentifier) SwaggerDoc() map[string]string { + return map_NutanixStorageResourceIdentifier +} + +var map_NutanixVMDisk = map[string]string{ + "": "NutanixDataDisk specifies the VM data disk configuration parameters.", + "diskSize": "diskSize is size (in Quantity format) of the disk attached to the VM. See https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Format for the Quantity format and example documentation. The minimum diskSize is 1GB.", + "deviceProperties": "deviceProperties are the properties of the disk device.", + "storageConfig": "storageConfig are the storage configuration parameters of the VM disks.", + "dataSource": "dataSource refers to a data source image for the VM disk.", +} + +func (NutanixVMDisk) SwaggerDoc() map[string]string { + return map_NutanixVMDisk +} + +var map_NutanixVMDiskDeviceProperties = map[string]string{ + "": "NutanixVMDiskDeviceProperties specifies the disk device properties.", + "deviceType": "deviceType specifies the disk device type. The valid values are \"Disk\" and \"CDRom\", and the default is \"Disk\".", + "adapterType": "adapterType is the adapter type of the disk address. If the deviceType is \"Disk\", the valid adapterType can be \"SCSI\", \"IDE\", \"PCI\", \"SATA\" or \"SPAPR\". If the deviceType is \"CDRom\", the valid adapterType can be \"IDE\" or \"SATA\".", + "deviceIndex": "deviceIndex is the index of the disk address. The valid values are non-negative integers, with the default value 0. For a Machine VM, the deviceIndex for the disks with the same deviceType.adapterType combination should start from 0 and increase consecutively afterwards. Note that for each Machine VM, the Disk.SCSI.0 and CDRom.IDE.0 are reserved to be used by the VM's system. So for dataDisks of Disk.SCSI and CDRom.IDE, the deviceIndex should start from 1.", +} + +func (NutanixVMDiskDeviceProperties) SwaggerDoc() map[string]string { + return map_NutanixVMDiskDeviceProperties +} + +var map_NutanixVMStorageConfig = map[string]string{ + "": "NutanixVMStorageConfig specifies the storage configuration parameters for VM disks.", + "diskMode": "diskMode specifies the disk mode. The valid values are Standard and Flash, and the default is Standard.", + "storageContainer": "storageContainer refers to the storage_container used by the VM disk.", +} + +func (NutanixVMStorageConfig) SwaggerDoc() map[string]string { + return map_NutanixVMStorageConfig +} + +var map_LoadBalancerReference = map[string]string{ + "": "LoadBalancerReference is a reference to a load balancer on IBM Cloud virtual private cloud(VPC).", + "name": "name of the LoadBalancer in IBM Cloud VPC. The name should be between 1 and 63 characters long and may consist of lowercase alphanumeric characters and hyphens only. The value must not end with a hyphen. It is a reference to existing LoadBalancer created by openshift installer component.", + "type": "type of the LoadBalancer service supported by IBM Cloud VPC. Currently, only Application LoadBalancer is supported. More details about Application LoadBalancer https://cloud.ibm.com/docs/vpc?topic=vpc-load-balancers-about&interface=ui Supported values are Application.", +} + +func (LoadBalancerReference) SwaggerDoc() map[string]string { + return map_LoadBalancerReference +} + +var map_PowerVSMachineProviderConfig = map[string]string{ + "": "PowerVSMachineProviderConfig is the type that will be embedded in a Machine.Spec.ProviderSpec field for a PowerVS virtual machine. It is used by the PowerVS machine actuator to create a single Machine.\n\nCompatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "userDataSecret": "userDataSecret contains a local reference to a secret that contains the UserData to apply to the instance.", + "credentialsSecret": "credentialsSecret is a reference to the secret with IBM Cloud credentials.", + "serviceInstance": "serviceInstance is the reference to the Power VS service on which the server instance(VM) will be created. Power VS service is a container for all Power VS instances at a specific geographic region. serviceInstance can be created via IBM Cloud catalog or CLI. supported serviceInstance identifier in PowerVSResource are Name and ID and that can be obtained from IBM Cloud UI or IBM Cloud cli. More detail about Power VS service instance. https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-creating-power-virtual-server", + "image": "image is to identify the rhcos image uploaded to IBM COS bucket which is used to create the instance. supported image identifier in PowerVSResource are Name and ID and that can be obtained from IBM Cloud UI or IBM Cloud cli.", + "network": "network is the reference to the Network to use for this instance. supported network identifier in PowerVSResource are Name, ID and RegEx and that can be obtained from IBM Cloud UI or IBM Cloud cli.", + "keyPairName": "keyPairName is the name of the KeyPair to use for SSH. The key pair will be exposed to the instance via the instance metadata service. On boot, the OS will copy the public keypair into the authorized keys for the core user.", + "systemType": "systemType is the System type used to host the instance. systemType determines the number of cores and memory that is available. Few of the supported SystemTypes are s922,e880,e980. e880 systemType available only in Dallas Datacenters. e980 systemType available in Datacenters except Dallas and Washington. When omitted, this means that the user has no opinion and the platform is left to choose a reasonable default, which is subject to change over time. The current default is s922 which is generally available.", + "processorType": "processorType is the VM instance processor type. It must be set to one of the following values: Dedicated, Capped or Shared. Dedicated: resources are allocated for a specific client, The hypervisor makes a 1:1 binding of a partition’s processor to a physical processor core. Shared: Shared among other clients. Capped: Shared, but resources do not expand beyond those that are requested, the amount of CPU time is Capped to the value specified for the entitlement. if the processorType is selected as Dedicated, then processors value cannot be fractional. When omitted, this means that the user has no opinion and the platform is left to choose a reasonable default, which is subject to change over time. The current default is Shared.", + "processors": "processors is the number of virtual processors in a virtual machine. when the processorType is selected as Dedicated the processors value cannot be fractional. maximum value for the Processors depends on the selected SystemType. when SystemType is set to e880 or e980 maximum Processors value is 143. when SystemType is set to s922 maximum Processors value is 15. minimum value for Processors depends on the selected ProcessorType. when ProcessorType is set as Shared or Capped, The minimum processors is 0.5. when ProcessorType is set as Dedicated, The minimum processors is 1. When omitted, this means that the user has no opinion and the platform is left to choose a reasonable default, which is subject to change over time. The default is set based on the selected ProcessorType. when ProcessorType selected as Dedicated, the default is set to 1. when ProcessorType selected as Shared or Capped, the default is set to 0.5.", + "memoryGiB": "memoryGiB is the size of a virtual machine's memory, in GiB. maximum value for the MemoryGiB depends on the selected SystemType. when SystemType is set to e880 maximum MemoryGiB value is 7463 GiB. when SystemType is set to e980 maximum MemoryGiB value is 15307 GiB. when SystemType is set to s922 maximum MemoryGiB value is 942 GiB. The minimum memory is 32 GiB. When omitted, this means the user has no opinion and the platform is left to choose a reasonable default, which is subject to change over time. The current default is 32.", + "loadBalancers": "loadBalancers is the set of load balancers to which the new control plane instance should be added once it is created.", +} + +func (PowerVSMachineProviderConfig) SwaggerDoc() map[string]string { + return map_PowerVSMachineProviderConfig +} + +var map_PowerVSMachineProviderStatus = map[string]string{ + "": "PowerVSMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. It contains PowerVS-specific status information.\n\nCompatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).", + "conditions": "conditions is a set of conditions associated with the Machine to indicate errors or other status", + "instanceId": "instanceId is the instance ID of the machine created in PowerVS instanceId uniquely identifies a Power VS server instance(VM) under a Power VS service. This will help in updating or deleting a VM in Power VS Cloud", + "serviceInstanceID": "serviceInstanceID is the reference to the Power VS ServiceInstance on which the machine instance will be created. serviceInstanceID uniquely identifies the Power VS service By setting serviceInstanceID it will become easy and efficient to fetch a server instance(VM) within Power VS Cloud.", + "instanceState": "instanceState is the state of the PowerVS instance for this machine Possible instance states are Active, Build, ShutOff, Reboot This is used to display additional information to user regarding instance current state", +} + +func (PowerVSMachineProviderStatus) SwaggerDoc() map[string]string { + return map_PowerVSMachineProviderStatus +} + +var map_PowerVSResource = map[string]string{ + "": "PowerVSResource is a reference to a specific PowerVS resource by ID, Name or RegEx Only one of ID, Name or RegEx may be specified. Specifying more than one will result in a validation error.", + "type": "type identifies the resource type for this entry. Valid values are ID, Name and RegEx", + "id": "id of resource", + "name": "name of resource", + "regex": "regex to find resource Regex contains the pattern to match to find a resource", +} + +func (PowerVSResource) SwaggerDoc() map[string]string { + return map_PowerVSResource +} + +var map_PowerVSSecretReference = map[string]string{ + "": "PowerVSSecretReference contains enough information to locate the referenced secret inside the same namespace.", + "name": "name of the secret.", +} + +func (PowerVSSecretReference) SwaggerDoc() map[string]string { + return map_PowerVSSecretReference +} + +// AUTO-GENERATED FUNCTIONS END HERE diff --git a/vendor/github.com/openshift/api/machine/v1beta1/Makefile b/vendor/github.com/openshift/api/machine/v1beta1/Makefile new file mode 100644 index 000000000..fee9e68fc --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/Makefile @@ -0,0 +1,3 @@ +.PHONY: test +test: + make -C ../../tests test GINKGO_EXTRA_ARGS=--focus="machine.openshift.io/v1beta1" diff --git a/vendor/github.com/openshift/api/machine/v1beta1/doc.go b/vendor/github.com/openshift/api/machine/v1beta1/doc.go new file mode 100644 index 000000000..e14fc64e3 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/doc.go @@ -0,0 +1,7 @@ +// +k8s:deepcopy-gen=package,register +// +k8s:defaulter-gen=TypeMeta +// +k8s:openapi-gen=true + +// +kubebuilder:validation:Optional +// +groupName=machine.openshift.io +package v1beta1 diff --git a/vendor/github.com/openshift/api/machine/v1beta1/register.go b/vendor/github.com/openshift/api/machine/v1beta1/register.go new file mode 100644 index 000000000..a3678c007 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/register.go @@ -0,0 +1,44 @@ +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + GroupName = "machine.openshift.io" + GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"} + schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // Install is a function which adds this version to a scheme + Install = schemeBuilder.AddToScheme + + // SchemeGroupVersion generated code relies on this name + // Deprecated + SchemeGroupVersion = GroupVersion + // AddToScheme exists solely to keep the old generators creating valid code + // DEPRECATED + AddToScheme = schemeBuilder.AddToScheme +) + +// Resource generated code relies on this being here, but it logically belongs to the group +// DEPRECATED +func Resource(resource string) schema.GroupResource { + return schema.GroupResource{Group: GroupName, Resource: resource} +} + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + metav1.AddToGroupVersion(scheme, GroupVersion) + + scheme.AddKnownTypes(GroupVersion, + &Machine{}, + &MachineList{}, + &MachineSet{}, + &MachineSetList{}, + &MachineHealthCheck{}, + &MachineHealthCheckList{}, + ) + + return nil +} diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_awsprovider.go b/vendor/github.com/openshift/api/machine/v1beta1/types_awsprovider.go new file mode 100644 index 000000000..e3508d667 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_awsprovider.go @@ -0,0 +1,557 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// AWSMachineProviderConfig is the Schema for the awsmachineproviderconfigs API +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type AWSMachineProviderConfig struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + // ami is the reference to the AMI from which to create the machine instance. + AMI AWSResourceReference `json:"ami"` + // instanceType is the type of instance to create. Example: m4.xlarge + InstanceType string `json:"instanceType"` + // cpuOptions defines CPU-related settings for the instance, including the confidential computing policy. + // When omitted, this means no opinion and the AWS platform is left to choose a reasonable default. + // More info: + // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CpuOptionsRequest.html, + // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/cpu-options-supported-instances-values.html + // +optional + CPUOptions *CPUOptions `json:"cpuOptions,omitempty,omitzero"` + // tags is the set of tags to add to apply to an instance, in addition to the ones + // added by default by the actuator. These tags are additive. The actuator will ensure + // these tags are present, but will not remove any other tags that may exist on the + // instance. + // +optional + Tags []TagSpecification `json:"tags,omitempty"` + // iamInstanceProfile is a reference to an IAM role to assign to the instance + // +optional + IAMInstanceProfile *AWSResourceReference `json:"iamInstanceProfile,omitempty"` + // userDataSecret contains a local reference to a secret that contains the + // UserData to apply to the instance + // +optional + UserDataSecret *corev1.LocalObjectReference `json:"userDataSecret,omitempty"` + // credentialsSecret is a reference to the secret with AWS credentials. Otherwise, defaults to permissions + // provided by attached IAM role where the actuator is running. + // +optional + CredentialsSecret *corev1.LocalObjectReference `json:"credentialsSecret,omitempty"` + // keyName is the name of the KeyPair to use for SSH + // +optional + KeyName *string `json:"keyName,omitempty"` + // deviceIndex is the index of the device on the instance for the network interface attachment. + // Defaults to 0. + DeviceIndex int64 `json:"deviceIndex"` + // publicIp specifies whether the instance should get a public IP. If not present, + // it should use the default of its subnet. + // +optional + PublicIP *bool `json:"publicIp,omitempty"` + // networkInterfaceType specifies the type of network interface to be used for the primary + // network interface. + // Valid values are "ENA", "EFA", and omitted, which means no opinion and the platform + // chooses a good default which may change over time. + // The current default value is "ENA". + // Please visit https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa.html to learn more + // about the AWS Elastic Fabric Adapter interface option. + // +kubebuilder:validation:Enum:="ENA";"EFA" + // +optional + NetworkInterfaceType AWSNetworkInterfaceType `json:"networkInterfaceType,omitempty"` + // securityGroups is an array of references to security groups that should be applied to the + // instance. + // +optional + SecurityGroups []AWSResourceReference `json:"securityGroups,omitempty"` + // subnet is a reference to the subnet to use for this instance + Subnet AWSResourceReference `json:"subnet"` + // placement specifies where to create the instance in AWS + Placement Placement `json:"placement"` + // loadBalancers is the set of load balancers to which the new instance + // should be added once it is created. + // +optional + LoadBalancers []LoadBalancerReference `json:"loadBalancers,omitempty"` + // blockDevices is the set of block device mapping associated to this instance, + // block device without a name will be used as a root device and only one device without a name is allowed + // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html + // +optional + BlockDevices []BlockDeviceMappingSpec `json:"blockDevices,omitempty"` + // spotMarketOptions allows users to configure instances to be run using AWS Spot instances. + // +optional + SpotMarketOptions *SpotMarketOptions `json:"spotMarketOptions,omitempty"` + // metadataServiceOptions allows users to configure instance metadata service interaction options. + // If nothing specified, default AWS IMDS settings will be applied. + // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InstanceMetadataOptionsRequest.html + // +optional + MetadataServiceOptions MetadataServiceOptions `json:"metadataServiceOptions,omitempty"` + // placementGroupName specifies the name of the placement group in which to launch the instance. + // The placement group must already be created and may use any placement strategy. + // When omitted, no placement group is used when creating the EC2 instance. + // +optional + PlacementGroupName string `json:"placementGroupName,omitempty"` + // 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. + // +kubebuilder:validation:Minimum:=1 + // +kubebuilder:validation:Maximum:=7 + // +optional + PlacementGroupPartition *int32 `json:"placementGroupPartition,omitempty"` + // 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-*** + // +optional + CapacityReservationID string `json:"capacityReservationId"` + // marketType specifies the type of market for the EC2 instance. + // Valid values are OnDemand, Spot, CapacityBlock and omitted. + // + // Defaults to OnDemand. + // When SpotMarketOptions is provided, the marketType defaults to "Spot". + // + // When 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. + // +optional + MarketType MarketType `json:"marketType,omitempty"` + + // Tombstone: This field was moved into the Placement struct to belong w/ the Tenancy field due to involvement with the setting. + // 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. +// +kubebuilder:validation:Enum=Disabled;AMDEncryptedVirtualizationNestedPaging +type AWSConfidentialComputePolicy string + +const ( + // AWSConfidentialComputePolicyDisabled disables confidential computing for the instance. + AWSConfidentialComputePolicyDisabled AWSConfidentialComputePolicy = "Disabled" + // AWSConfidentialComputePolicySEVSNP enables AMD SEV-SNP as the confidential computing technology for the instance. + AWSConfidentialComputePolicySEVSNP AWSConfidentialComputePolicy = "AMDEncryptedVirtualizationNestedPaging" +) + +// CPUOptions defines CPU-related settings for the instance, including the confidential computing policy. +// If provided, it must not be empty — at least one field must be set. +// +kubebuilder:validation:MinProperties=1 +type CPUOptions struct { + // confidentialCompute specifies whether confidential computing should be enabled for the instance, + // and, if so, which confidential computing technology to use. + // Valid values are: Disabled, AMDEncryptedVirtualizationNestedPaging and omitted. + // When set to Disabled, confidential computing will be disabled for the instance. + // When set to AMDEncryptedVirtualizationNestedPaging, AMD SEV-SNP will be used as the confidential computing technology for the instance. + // In this case, ensure the following conditions are met: + // 1) The selected instance type supports AMD SEV-SNP. + // 2) The selected AWS region supports AMD SEV-SNP. + // 3) The selected AMI supports AMD SEV-SNP. + // More details can be checked at https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sev-snp.html + // When omitted, this means no opinion and the AWS platform is left to choose a reasonable default, + // which is subject to change without notice. The current default is Disabled. + // +optional + ConfidentialCompute *AWSConfidentialComputePolicy `json:"confidentialCompute,omitempty"` +} + +// BlockDeviceMappingSpec describes a block device mapping +type BlockDeviceMappingSpec struct { + // The device name exposed to the machine (for example, /dev/sdh or xvdh). + // +optional + DeviceName *string `json:"deviceName,omitempty"` + // Parameters used to automatically set up EBS volumes when the machine is + // launched. + // +optional + EBS *EBSBlockDeviceSpec `json:"ebs,omitempty"` + // Suppresses the specified device included in the block device mapping of the + // AMI. + // +optional + NoDevice *string `json:"noDevice,omitempty"` + // The virtual device name (ephemeralN). Machine store volumes are numbered + // starting from 0. An machine type with 2 available machine store volumes + // can specify mappings for ephemeral0 and ephemeral1.The number of available + // machine store volumes depends on the machine type. After you connect to + // the machine, you must mount the volume. + // + // Constraints: For M3 machines, you must specify machine store volumes in + // the block device mapping for the machine. When you launch an M3 machine, + // we ignore any machine store volumes specified in the block device mapping + // for the AMI. + // +optional + VirtualName *string `json:"virtualName,omitempty"` +} + +// EBSBlockDeviceSpec describes a block device for an EBS volume. +// https://docs.aws.amazon.com/goto/WebAPI/ec2-2016-11-15/EbsBlockDevice +type EBSBlockDeviceSpec struct { + // Indicates whether the EBS volume is deleted on machine termination. + // + // Deprecated: setting this field has no effect. + // +optional + DeprecatedDeleteOnTermination *bool `json:"deleteOnTermination,omitempty"` + // Indicates whether the EBS volume is encrypted. Encrypted Amazon EBS volumes + // may only be attached to machines that support Amazon EBS encryption. + // +optional + Encrypted *bool `json:"encrypted,omitempty"` + // Indicates the KMS key that should be used to encrypt the Amazon EBS volume. + // +optional + KMSKey AWSResourceReference `json:"kmsKey,omitempty"` + // The number of I/O operations per second (IOPS) that the volume supports. + // For io1, this represents the number of IOPS that are provisioned for the + // volume. For gp2, this represents the baseline performance of the volume and + // the rate at which the volume accumulates I/O credits for bursting. For more + // information about General Purpose SSD baseline performance, I/O credits, + // and bursting, see Amazon EBS Volume Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html) + // in the Amazon Elastic Compute Cloud User Guide. + // + // Minimal and maximal IOPS for io1 and gp2 are constrained. Please, check + // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html + // for precise boundaries for individual volumes. + // + // Condition: This parameter is required for requests to create io1 volumes; + // it is not used in requests to create gp2, st1, sc1, or standard volumes. + // +optional + Iops *int64 `json:"iops,omitempty"` + // throughputMib to provision in MiB/s supported for the volume type. Not applicable to all types. + // + // This parameter is valid only for gp3 volumes. + // Valid Range: Minimum value of 125. Maximum value of 2000. + // + // When omitted, this means no opinion, and the platform is left to + // choose a reasonable default, which is subject to change over time. + // The current default is 125. + // + // +kubebuilder:validation:Minimum:=125 + // +kubebuilder:validation:Maximum:=2000 + // +optional + ThroughputMib *int32 `json:"throughputMib,omitempty"` + // The size of the volume, in GiB. + // + // Constraints: 1-16384 for General Purpose SSD (gp2), 4-16384 for Provisioned + // IOPS SSD (io1), 500-16384 for Throughput Optimized HDD (st1), 500-16384 for + // Cold HDD (sc1), and 1-1024 for Magnetic (standard) volumes. If you specify + // a snapshot, the volume size must be equal to or larger than the snapshot + // size. + // + // Default: If you're creating the volume from a snapshot and don't specify + // a volume size, the default is the snapshot size. + // +optional + VolumeSize *int64 `json:"volumeSize,omitempty"` + // volumeType can be of type gp2, gp3, io1, st1, sc1, or standard. + // Default: standard + // +optional + VolumeType *string `json:"volumeType,omitempty"` +} + +// SpotMarketOptions defines the options available to a user when configuring +// Machines to run on Spot instances. +// Most users should provide an empty struct. +type SpotMarketOptions struct { + // The maximum price the user is willing to pay for their instances + // Default: On-Demand price + // +optional + MaxPrice *string `json:"maxPrice,omitempty"` +} + +type MetadataServiceAuthentication string + +const ( + // MetadataServiceAuthenticationRequired enforces sending of a signed token header with any instance metadata retrieval (GET) requests. + // Enforces IMDSv2 usage. + MetadataServiceAuthenticationRequired = "Required" + // MetadataServiceAuthenticationOptional allows IMDSv1 usage along with IMDSv2 + MetadataServiceAuthenticationOptional = "Optional" +) + +// MetadataServiceOptions defines the options available to a user when configuring +// Instance Metadata Service (IMDS) Options. +type MetadataServiceOptions struct { + // authentication determines whether or not the host requires the use of authentication when interacting with the metadata service. + // When using authentication, this enforces v2 interaction method (IMDSv2) with the metadata service. + // When omitted, this means the user has no opinion and the value is left to the platform to choose a good + // default, which is subject to change over time. The current default is optional. + // At this point this field represents `HttpTokens` parameter from `InstanceMetadataOptionsRequest` structure in AWS EC2 API + // https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InstanceMetadataOptionsRequest.html + // +kubebuilder:validation:Enum=Required;Optional + // +optional + Authentication MetadataServiceAuthentication `json:"authentication,omitempty"` +} + +// AWSResourceReference is a reference to a specific AWS resource by ID, ARN, or filters. +// Only one of ID, ARN or Filters may be specified. Specifying more than one will result in +// a validation error. +type AWSResourceReference struct { + // id of resource + // +optional + ID *string `json:"id,omitempty"` + // arn of resource + // +optional + ARN *string `json:"arn,omitempty"` + // filters is a set of filters used to identify a resource + // +optional + Filters []Filter `json:"filters,omitempty"` +} + +// Placement indicates where to create the instance in AWS +// +kubebuilder:validation:XValidation:rule="has(self.tenancy) && self.tenancy == 'host' ? true : !has(self.host)",message="host may only be specified when tenancy is host" +type Placement struct { + // region is the region to use to create the instance + // +optional + Region string `json:"region,omitempty"` + // availabilityZone is the availability zone of the instance + // +optional + AvailabilityZone string `json:"availabilityZone,omitempty"` + // tenancy indicates if instance should run on shared or single-tenant hardware. There are + // supported 3 options: default, dedicated and host. + // When set to default Runs on shared multi-tenant hardware. + // When dedicated Runs on single-tenant hardware (any dedicated instance hardware). + // When host and the host object is not provided: Runs on Dedicated Host; best-effort restart on same host. + // When `host` and `host` object is provided with affinity `dedicatedHost` defined: Runs on specified Dedicated Host. + // +optional + Tenancy InstanceTenancy `json:"tenancy,omitempty"` + // host 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 + Host *HostPlacement `json:"host,omitempty"` +} + +// Filter is a filter used to identify an AWS resource +type Filter struct { + // name of the filter. Filter names are case-sensitive. + Name string `json:"name"` + // values includes one or more filter values. Filter values are case-sensitive. + // +optional + Values []string `json:"values,omitempty"` +} + +// TagSpecification is the name/value pair for a tag +type TagSpecification struct { + // name of the tag. + // This field is required and must be a non-empty string. + // Must be between 1 and 128 characters in length. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=128 + // +required + Name string `json:"name"` + // value of the tag. + // When omitted, this creates a tag with an empty string as the value. + // +optional + Value string `json:"value"` +} + +// AWSMachineProviderConfigList contains a list of AWSMachineProviderConfig +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type AWSMachineProviderConfigList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + Items []AWSMachineProviderConfig `json:"items"` +} + +// LoadBalancerReference is a reference to a load balancer on AWS. +type LoadBalancerReference struct { + Name string `json:"name"` + Type AWSLoadBalancerType `json:"type"` +} + +// AWSLoadBalancerType is the type of LoadBalancer to use when registering +// an instance with load balancers specified in LoadBalancerNames +type AWSLoadBalancerType string + +// InstanceTenancy indicates if instance should run on shared or single-tenant hardware. +type InstanceTenancy string + +const ( + // DefaultTenancy instance runs on shared hardware + DefaultTenancy InstanceTenancy = "default" + // DedicatedTenancy instance runs on single-tenant hardware + DedicatedTenancy InstanceTenancy = "dedicated" + // HostTenancy instance runs on a Dedicated Host, which is an isolated server with configurations that you can control. + HostTenancy InstanceTenancy = "host" +) + +// Possible values for AWSLoadBalancerType. Add to this list as other types +// of load balancer are supported by the actuator. +const ( + ClassicLoadBalancerType AWSLoadBalancerType = "classic" // AWS classic ELB + NetworkLoadBalancerType AWSLoadBalancerType = "network" // AWS Network Load Balancer (NLB) +) + +// AWSNetworkInterfaceType defines the network interface type of the the +// AWS EC2 network interface. +type AWSNetworkInterfaceType string + +const ( + // AWSENANetworkInterfaceType is the default network interface type, + // the EC2 Elastic Network Adapter commonly used with EC2 instances. + // This should be used for standard network operations. + AWSENANetworkInterfaceType AWSNetworkInterfaceType = "ENA" + // AWSEFANetworkInterfaceType is the Elastic Fabric Adapter network interface type. + AWSEFANetworkInterfaceType AWSNetworkInterfaceType = "EFA" +) + +// AWSMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. +// It contains AWS-specific status information. +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type AWSMachineProviderStatus struct { + metav1.TypeMeta `json:",inline"` + // instanceId is the instance ID of the machine created in AWS + // +optional + InstanceID *string `json:"instanceId,omitempty"` + // instanceState is the state of the AWS instance for this machine + // +optional + InstanceState *string `json:"instanceState,omitempty"` + // conditions is a set of conditions associated with the Machine to indicate + // errors or other status + // +optional + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty"` + // dedicatedHost tracks the dynamically allocated dedicated host. + // This field is populated when allocationStrategy is Dynamic (with or without DynamicHostAllocation). + // When omitted, this indicates that the dedicated host has not yet been allocated, or allocation is in progress. + // +optional + DedicatedHost *DedicatedHostStatus `json:"dedicatedHost,omitempty"` +} + +// DedicatedHostStatus defines the observed state of a dynamically allocated dedicated host +// associated with an AWSMachine. This struct is used to track the ID of the dedicated host. +type DedicatedHostStatus struct { + // id tracks the dynamically allocated dedicated host ID. + // This field is populated when allocationStrategy is Dynamic (with or without DynamicHostAllocation). + // The value must start with "h-" followed by either 8 or 17 lowercase hexadecimal characters (0-9 and a-f). + // The use of 8 lowercase hexadecimal characters is for older legacy hosts that may not have been migrated to newer format. + // Must be either 10 or 19 characters in length. + // +kubebuilder:validation:XValidation:rule="self.matches('^h-([0-9a-f]{8}|[0-9a-f]{17})$')",message="id must start with 'h-' followed by either 8 or 17 lowercase hexadecimal characters (0-9 and a-f)" + // +kubebuilder:validation:MinLength=10 + // +kubebuilder:validation:MaxLength=19 + // +required + ID string `json:"id,omitempty"` +} + +// MarketType describes the market type of an EC2 Instance +// +kubebuilder:validation:Enum:=OnDemand;Spot;CapacityBlock +type MarketType string + +const ( + + // MarketTypeOnDemand is a MarketType enum value + // When set to OnDemand the instance runs as a standard OnDemand instance. + MarketTypeOnDemand MarketType = "OnDemand" + + // MarketTypeSpot is a MarketType enum value + // When set to Spot the instance runs as a Spot instance. + MarketTypeSpot MarketType = "Spot" + + // MarketTypeCapacityBlock is a MarketType enum value + // 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.affinity) && self.affinity == 'DedicatedHost' ? has(self.dedicatedHost) : true",message="dedicatedHost is required when affinity is DedicatedHost, and optional 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. + // When Affinity is set to AnyAvailable and the `dedicatedHost` field is defined, it runs on specified Dedicated Host, but may move if stopped. + // +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 optional 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" +) + +// AllocationStrategy selects how a dedicated host is provided to the system for assigning to the instance. +// +kubebuilder:validation:Enum:=UserProvided;Dynamic +// +enum +type AllocationStrategy string + +const ( + // AllocationStrategyUserProvided specifies that the system should assign instances to a user-provided dedicated host. + AllocationStrategyUserProvided AllocationStrategy = "UserProvided" + + // AllocationStrategyDynamic specifies that the system should dynamically allocate a dedicated host for instances. + AllocationStrategyDynamic AllocationStrategy = "Dynamic" +) + +// DedicatedHost represents the configuration for the usage of dedicated host. +// +kubebuilder:validation:XValidation:rule="self.allocationStrategy == 'UserProvided' ? has(self.id) : !has(self.id)",message="id is required when allocationStrategy is UserProvided, and forbidden otherwise" +// +kubebuilder:validation:XValidation:rule="has(self.dynamicHostAllocation) ? self.allocationStrategy == 'Dynamic' : true",message="dynamicHostAllocation is only allowed when allocationStrategy is Dynamic" +// +union +type DedicatedHost struct { + // allocationStrategy specifies if the dedicated host will be provided by the admin through the id field or if the host will be dynamically allocated. + // Valid values are UserProvided and Dynamic. + // When omitted, the value defaults to "UserProvided", which requires the id field to be set. + // When allocationStrategy is set to UserProvided, an ID of the dedicated host to assign must be provided. + // When allocationStrategy is set to Dynamic, a dedicated host will be allocated and used to assign instances. + // When allocationStrategy is set to Dynamic, and dynamicHostAllocation is configured, a dedicated host will be allocated and the tags in dynamicHostAllocation will be assigned to that host. + // +optional + // +unionDiscriminator + // +default="UserProvided" + AllocationStrategy *AllocationStrategy `json:"allocationStrategy,omitempty"` + + // id identifies the AWS Dedicated Host on which the instance must run. + // The value must start with "h-" followed by either 8 or 17 lowercase hexadecimal characters (0-9 and a-f). + // The use of 8 lowercase hexadecimal characters is for older legacy hosts that may not have been migrated to newer format. + // Must be either 10 or 19 characters in length. + // This field is required when allocationStrategy is UserProvided, and forbidden otherwise. + // When omitted with allocationStrategy set to Dynamic, the platform will dynamically allocate a dedicated host. + // +kubebuilder:validation:XValidation:rule="self.matches('^h-([0-9a-f]{8}|[0-9a-f]{17})$')",message="id must start with 'h-' followed by either 8 or 17 lowercase hexadecimal characters (0-9 and a-f)" + // +kubebuilder:validation:MinLength=10 + // +kubebuilder:validation:MaxLength=19 + // +optional + // +unionMember=UserProvided + ID string `json:"id,omitempty"` + + // dynamicHostAllocation specifies tags to apply to a dynamically allocated dedicated host. + // This field is only allowed when allocationStrategy is Dynamic, and is mutually exclusive with id. + // When specified, a dedicated host will be allocated with the provided tags applied. + // When omitted (and allocationStrategy is Dynamic), a dedicated host will be allocated without any additional tags. + // +optional + // +unionMember=Dynamic + DynamicHostAllocation *DynamicHostAllocationSpec `json:"dynamicHostAllocation,omitempty"` +} + +// DynamicHostAllocationSpec defines the configuration for dynamic dedicated host allocation. +// This specification always allocates exactly one dedicated host per machine. +// At least one property must be specified when this struct is used. +// Currently only Tags are available for configuring, but in the future more configs may become available. +// +kubebuilder:validation:MinProperties=1 +type DynamicHostAllocationSpec struct { + // tags specifies a set of key-value pairs to apply to the allocated dedicated host. + // When omitted, no additional user-defined tags will be applied to the allocated host. + // A maximum of 50 tags can be specified. + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=50 + // +listType=map + // +listMapKey=name + // +optional + Tags *[]TagSpecification `json:"tags,omitempty"` +} diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_azureprovider.go b/vendor/github.com/openshift/api/machine/v1beta1/types_azureprovider.go new file mode 100644 index 000000000..2cb43d431 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_azureprovider.go @@ -0,0 +1,577 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// SecurityEncryptionTypes represents the Encryption Type when the Azure Virtual Machine is a +// Confidential VM. +type SecurityEncryptionTypes string + +const ( + // SecurityEncryptionTypesVMGuestStateOnly disables OS disk confidential encryption. + SecurityEncryptionTypesVMGuestStateOnly SecurityEncryptionTypes = "VMGuestStateOnly" + // SecurityEncryptionTypesDiskWithVMGuestState enables OS disk confidential encryption with a + // platform-managed key (PMK) or a customer-managed key (CMK). + SecurityEncryptionTypesDiskWithVMGuestState SecurityEncryptionTypes = "DiskWithVMGuestState" +) + +// SecurityTypes represents the SecurityType of the virtual machine. +type SecurityTypes string + +const ( + // SecurityTypesConfidentialVM defines the SecurityType of the virtual machine as a Confidential VM. + SecurityTypesConfidentialVM SecurityTypes = "ConfidentialVM" + // SecurityTypesTrustedLaunch defines the SecurityType of the virtual machine as a Trusted Launch VM. + SecurityTypesTrustedLaunch SecurityTypes = "TrustedLaunch" +) + +// AzureMachineProviderSpec is the type that will be embedded in a Machine.Spec.ProviderSpec field +// for an Azure virtual machine. It is used by the Azure machine actuator to create a single Machine. +// Required parameters such as location that are not specified by this configuration, will be defaulted +// by the actuator. +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type AzureMachineProviderSpec struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + // userDataSecret contains a local reference to a secret that contains the + // UserData to apply to the instance + // +optional + UserDataSecret *corev1.SecretReference `json:"userDataSecret,omitempty"` + // credentialsSecret is a reference to the secret with Azure credentials. + // +optional + CredentialsSecret *corev1.SecretReference `json:"credentialsSecret,omitempty"` + // location is the region to use to create the instance + // +optional + Location string `json:"location,omitempty"` + // vmSize is the size of the VM to create. + // +optional + VMSize string `json:"vmSize,omitempty"` + // image is the OS image to use to create the instance. + Image Image `json:"image"` + // osDisk represents the parameters for creating the OS disk. + OSDisk OSDisk `json:"osDisk"` + // DataDisk specifies the parameters that are used to add one or more data disks to the machine. + // +optional + DataDisks []DataDisk `json:"dataDisks,omitempty"` + // sshPublicKey is the public key to use to SSH to the virtual machine. + // +optional + SSHPublicKey string `json:"sshPublicKey,omitempty"` + // publicIP if true a public IP will be used + PublicIP bool `json:"publicIP"` + // tags is a list of tags to apply to the machine. + // +optional + Tags map[string]string `json:"tags,omitempty"` + // Network Security Group that needs to be attached to the machine's interface. + // No security group will be attached if empty. + // +optional + SecurityGroup string `json:"securityGroup,omitempty"` + // Application Security Groups that need to be attached to the machine's interface. + // No application security groups will be attached if zero-length. + // +optional + ApplicationSecurityGroups []string `json:"applicationSecurityGroups,omitempty"` + // subnet to use for this instance + Subnet string `json:"subnet"` + // publicLoadBalancer to use for this instance + // +optional + PublicLoadBalancer string `json:"publicLoadBalancer,omitempty"` + // InternalLoadBalancerName to use for this instance + // +optional + InternalLoadBalancer string `json:"internalLoadBalancer,omitempty"` + // natRule to set inbound NAT rule of the load balancer + // +optional + NatRule *int64 `json:"natRule,omitempty"` + // managedIdentity to set managed identity name + // +optional + ManagedIdentity string `json:"managedIdentity,omitempty"` + // vnet to set virtual network name + // +optional + Vnet string `json:"vnet,omitempty"` + // Availability Zone for the virtual machine. + // If nil, the virtual machine should be deployed to no zone + // +optional + Zone string `json:"zone,omitempty"` + // networkResourceGroup is the resource group for the virtual machine's network + // +optional + NetworkResourceGroup string `json:"networkResourceGroup,omitempty"` + // resourceGroup is the resource group for the virtual machine + // +optional + ResourceGroup string `json:"resourceGroup,omitempty"` + // spotVMOptions allows the ability to specify the Machine should use a Spot VM + // +optional + SpotVMOptions *SpotVMOptions `json:"spotVMOptions,omitempty"` + // securityProfile specifies the Security profile settings for a virtual machine. + // +optional + SecurityProfile *SecurityProfile `json:"securityProfile,omitempty"` + // ultraSSDCapability enables or disables Azure UltraSSD capability for a virtual machine. + // This can be used to allow/disallow binding of Azure UltraSSD to the Machine both as Data Disks or via Persistent Volumes. + // This Azure feature is subject to a specific scope and certain limitations. + // More informations on this can be found in the official Azure documentation for Ultra Disks: + // (https://docs.microsoft.com/en-us/azure/virtual-machines/disks-enable-ultra-ssd?tabs=azure-portal#ga-scope-and-limitations). + // + // When omitted, if at least one Data Disk of type UltraSSD is specified, the platform will automatically enable the capability. + // If a Perisistent Volume backed by an UltraSSD is bound to a Pod on the Machine, when this field is ommitted, the platform will *not* automatically enable the capability (unless already enabled by the presence of an UltraSSD as Data Disk). + // This may manifest in the Pod being stuck in `ContainerCreating` phase. + // This defaulting behaviour may be subject to change in future. + // + // When set to "Enabled", if the capability is available for the Machine based on the scope and limitations described above, the capability will be set on the Machine. + // This will thus allow UltraSSD both as Data Disks and Persistent Volumes. + // If set to "Enabled" when the capability can't be available due to scope and limitations, the Machine will go into "Failed" state. + // + // When set to "Disabled", UltraSSDs will not be allowed either as Data Disks nor as Persistent Volumes. + // In this case if any UltraSSDs are specified as Data Disks on a Machine, the Machine will go into a "Failed" state. + // If instead any UltraSSDs are backing the volumes (via Persistent Volumes) of any Pods scheduled on a Node which is backed by the Machine, the Pod may get stuck in `ContainerCreating` phase. + // + // +kubebuilder:validation:Enum:="Enabled";"Disabled" + // +optional + UltraSSDCapability AzureUltraSSDCapabilityState `json:"ultraSSDCapability,omitempty"` + // acceleratedNetworking enables or disables Azure accelerated networking feature. + // Set to false by default. If true, then this will depend on whether the requested + // VMSize is supported. If set to true with an unsupported VMSize, Azure will return an error. + // +optional + AcceleratedNetworking bool `json:"acceleratedNetworking,omitempty"` + // availabilitySet specifies the availability set to use for this instance. + // Availability set should be precreated, before using this field. + // +optional + AvailabilitySet string `json:"availabilitySet,omitempty"` + // diagnostics configures the diagnostics settings for the virtual machine. + // This allows you to configure boot diagnostics such as capturing serial output from + // the virtual machine on boot. + // This is useful for debugging software based launch issues. + // +optional + Diagnostics AzureDiagnostics `json:"diagnostics,omitempty"` + // capacityReservationGroupID specifies the capacity reservation group resource id that should be + // used for allocating the virtual machine. + // The field size should be greater than 0 and the field input must start with '/'. + // The input for capacityReservationGroupID must be similar to '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/capacityReservationGroups/{capacityReservationGroupName}'. + // The keys which are used should be among 'subscriptions', 'providers' and 'resourcegroups' followed by valid ID or names respectively. + // +optional + CapacityReservationGroupID string `json:"capacityReservationGroupID,omitempty"` +} + +// SpotVMOptions defines the options relevant to running the Machine on Spot VMs +type SpotVMOptions struct { + // maxPrice defines the maximum price the user is willing to pay for Spot VM instances + // +optional + MaxPrice *resource.Quantity `json:"maxPrice,omitempty"` +} + +// AzureDiagnostics is used to configure the diagnostic settings of the virtual machine. +type AzureDiagnostics struct { + // AzureBootDiagnostics configures the boot diagnostics settings for the virtual machine. + // This allows you to configure capturing serial output from the virtual machine on boot. + // This is useful for debugging software based launch issues. + // + This is a pointer so that we can validate required fields only when the structure is + // + configured by the user. + // +optional + Boot *AzureBootDiagnostics `json:"boot,omitempty"` +} + +// AzureBootDiagnostics configures the boot diagnostics settings for the virtual machine. +// This allows you to configure capturing serial output from the virtual machine on boot. +// This is useful for debugging software based launch issues. +// +union +type AzureBootDiagnostics struct { + // storageAccountType determines if the storage account for storing the diagnostics data + // should be provisioned by Azure (AzureManaged) or by the customer (CustomerManaged). + // +required + // +unionDiscriminator + StorageAccountType AzureBootDiagnosticsStorageAccountType `json:"storageAccountType"` + + // customerManaged provides reference to the customer manager storage account. + // +optional + CustomerManaged *AzureCustomerManagedBootDiagnostics `json:"customerManaged,omitempty"` +} + +// AzureCustomerManagedBootDiagnostics provides reference to a customer managed +// storage account. +type AzureCustomerManagedBootDiagnostics struct { + // storageAccountURI is the URI of the customer managed storage account. + // The URI typically will be `https://.blob.core.windows.net/` + // but may differ if you are using Azure DNS zone endpoints. + // You can find the correct endpoint by looking for the Blob Primary Endpoint in the + // endpoints tab in the Azure console. + // +required + // +kubebuilder:validation:Pattern=`^https://` + // +kubebuilder:validation:MaxLength=1024 + StorageAccountURI string `json:"storageAccountURI"` +} + +// AzureBootDiagnosticsStorageAccountType defines the list of valid storage account types +// for the boot diagnostics. +// +kubebuilder:validation:Enum:="AzureManaged";"CustomerManaged" +type AzureBootDiagnosticsStorageAccountType string + +const ( + // AzureManagedAzureDiagnosticsStorage is used to determine that the diagnostics storage account + // should be provisioned by Azure. + AzureManagedAzureDiagnosticsStorage AzureBootDiagnosticsStorageAccountType = "AzureManaged" + + // CustomerManagedAzureDiagnosticsStorage is used to determine that the diagnostics storage account + // should be provisioned by the Customer. + CustomerManagedAzureDiagnosticsStorage AzureBootDiagnosticsStorageAccountType = "CustomerManaged" +) + +// AzureMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. +// It contains Azure-specific status information. +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type AzureMachineProviderStatus struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + // vmId is the ID of the virtual machine created in Azure. + // +optional + VMID *string `json:"vmId,omitempty"` + // vmState is the provisioning state of the Azure virtual machine. + // +optional + VMState *AzureVMState `json:"vmState,omitempty"` + // conditions is a set of conditions associated with the Machine to indicate + // errors or other status. + // +optional + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// VMState describes the state of an Azure virtual machine. +type AzureVMState string + +const ( + // ProvisioningState related values + // VMStateCreating ... + VMStateCreating = AzureVMState("Creating") + // VMStateDeleting ... + VMStateDeleting = AzureVMState("Deleting") + // VMStateFailed ... + VMStateFailed = AzureVMState("Failed") + // VMStateMigrating ... + VMStateMigrating = AzureVMState("Migrating") + // VMStateSucceeded ... + VMStateSucceeded = AzureVMState("Succeeded") + // VMStateUpdating ... + VMStateUpdating = AzureVMState("Updating") + + // PowerState related values + // VMStateStarting ... + VMStateStarting = AzureVMState("Starting") + // VMStateRunning ... + VMStateRunning = AzureVMState("Running") + // VMStateStopping ... + VMStateStopping = AzureVMState("Stopping") + // VMStateStopped ... + VMStateStopped = AzureVMState("Stopped") + // VMStateDeallocating ... + VMStateDeallocating = AzureVMState("Deallocating") + // VMStateDeallocated ... + VMStateDeallocated = AzureVMState("Deallocated") + // VMStateUnknown ... + VMStateUnknown = AzureVMState("Unknown") +) + +// Image is a mirror of azure sdk compute.ImageReference +type Image struct { + // publisher is the name of the organization that created the image + Publisher string `json:"publisher"` + // offer specifies the name of a group of related images created by the publisher. + // For example, UbuntuServer, WindowsServer + Offer string `json:"offer"` + // sku specifies an instance of an offer, such as a major release of a distribution. + // For example, 18.04-LTS, 2019-Datacenter + SKU string `json:"sku"` + // version specifies the version of an image sku. The allowed formats + // are Major.Minor.Build or 'latest'. Major, Minor, and Build are decimal numbers. + // Specify 'latest' to use the latest version of an image available at deploy time. + // Even if you use 'latest', the VM image will not automatically update after deploy + // time even if a new version becomes available. + Version string `json:"version"` + // resourceID specifies an image to use by ID + ResourceID string `json:"resourceID"` + // type identifies the source of the image and related information, such as purchase plans. + // Valid values are "ID", "MarketplaceWithPlan", "MarketplaceNoPlan", and omitted, which + // means no opinion and the platform chooses a good default which may change over time. + // Currently that default is "MarketplaceNoPlan" if publisher data is supplied, or "ID" if not. + // For more information about purchase plans, see: + // https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-ps-findimage#check-the-purchase-plan-information + // +optional + Type AzureImageType `json:"type,omitempty"` +} + +// AzureImageType provides an enumeration for the valid image types. +type AzureImageType string + +const ( + // AzureImageTypeID specifies that the image should be referenced by its resource ID. + AzureImageTypeID AzureImageType = "ID" + // AzureImageTypeMarketplaceNoPlan are images available from the marketplace that do not require a purchase plan. + AzureImageTypeMarketplaceNoPlan AzureImageType = "MarketplaceNoPlan" + // AzureImageTypeMarketplaceWithPlan require a purchase plan. Upstream these images are referred to as "ThirdParty." + AzureImageTypeMarketplaceWithPlan AzureImageType = "MarketplaceWithPlan" +) + +type OSDisk struct { + // osType is the operating system type of the OS disk. Possible values include "Linux" and "Windows". + OSType string `json:"osType"` + // managedDisk specifies the Managed Disk parameters for the OS disk. + ManagedDisk OSDiskManagedDiskParameters `json:"managedDisk"` + // diskSizeGB is the size in GB to assign to the data disk. + DiskSizeGB int32 `json:"diskSizeGB"` + // diskSettings describe ephemeral disk settings for the os disk. + // +optional + DiskSettings DiskSettings `json:"diskSettings,omitempty"` + // cachingType specifies the caching requirements. + // Possible values include: 'None', 'ReadOnly', 'ReadWrite'. + // Empty value means no opinion and the platform chooses a default, which is subject to change over + // time. Currently the default is `None`. + // +optional + // +kubebuilder:validation:Enum=None;ReadOnly;ReadWrite + CachingType string `json:"cachingType,omitempty"` +} + +// DataDisk specifies the parameters that are used to add one or more data disks to the machine. +// A Data Disk is a managed disk that's attached to a virtual machine to store application data. +// It differs from an OS Disk as it doesn't come with a pre-installed OS, and it cannot contain the boot volume. +// It is registered as SCSI drive and labeled with the chosen `lun`. e.g. for `lun: 0` the raw disk device will be available at `/dev/disk/azure/scsi1/lun0`. +// +// As the Data Disk disk device is attached raw to the virtual machine, it will need to be partitioned, formatted with a filesystem and mounted, in order for it to be usable. +// This can be done by creating a custom userdata Secret with custom Ignition configuration to achieve the desired initialization. +// At this stage the previously defined `lun` is to be used as the "device" key for referencing the raw disk device to be initialized. +// Once the custom userdata Secret has been created, it can be referenced in the Machine's `.providerSpec.userDataSecret`. +// For further guidance and examples, please refer to the official OpenShift docs. +type DataDisk struct { + // nameSuffix is the suffix to be appended to the machine name to generate the disk name. + // Each disk name will be in format _. + // NameSuffix name must start and finish with an alphanumeric character and can only contain letters, numbers, underscores, periods or hyphens. + // The overall disk name must not exceed 80 chars in length. + // +kubebuilder:validation:Pattern:=`^[a-zA-Z0-9](?:[\w\.-]*[a-zA-Z0-9])?$` + // +kubebuilder:validation:MaxLength:=78 + // +required + NameSuffix string `json:"nameSuffix"` + // diskSizeGB is the size in GB to assign to the data disk. + // +kubebuilder:validation:Minimum=4 + // +required + DiskSizeGB int32 `json:"diskSizeGB"` + // managedDisk specifies the Managed Disk parameters for the data disk. + // Empty value means no opinion and the platform chooses a default, which is subject to change over time. + // Currently the default is a ManagedDisk with with storageAccountType: "Premium_LRS" and diskEncryptionSet.id: "Default". + // +optional + ManagedDisk DataDiskManagedDiskParameters `json:"managedDisk,omitempty"` + // lun Specifies the logical unit number of the data disk. + // This value is used to identify data disks within the VM and therefore must be unique for each data disk attached to a VM. + // This value is also needed for referencing the data disks devices within userdata to perform disk initialization through Ignition (e.g. partition/format/mount). + // The value must be between 0 and 63. + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=63 + // +required + Lun int32 `json:"lun"` + // cachingType specifies the caching requirements. + // Empty value means no opinion and the platform chooses a default, which is subject to change over time. + // Currently the default is CachingTypeNone. + // +optional + // +kubebuilder:validation:Enum=None;ReadOnly;ReadWrite + CachingType CachingTypeOption `json:"cachingType,omitempty"` + // deletionPolicy specifies the data disk deletion policy upon Machine deletion. + // Possible values are "Delete","Detach". + // When "Delete" is used the data disk is deleted when the Machine is deleted. + // When "Detach" is used the data disk is detached from the Machine and retained when the Machine is deleted. + // +kubebuilder:validation:Enum=Delete;Detach + // +required + DeletionPolicy DiskDeletionPolicyType `json:"deletionPolicy"` +} + +// DiskDeletionPolicyType defines the possible values for DeletionPolicy. +type DiskDeletionPolicyType string + +// These are the valid DiskDeletionPolicyType values. +const ( + // DiskDeletionPolicyTypeDelete means the DiskDeletionPolicyType is "Delete". + DiskDeletionPolicyTypeDelete DiskDeletionPolicyType = "Delete" + // DiskDeletionPolicyTypeDetach means the DiskDeletionPolicyType is "Detach". + DiskDeletionPolicyTypeDetach DiskDeletionPolicyType = "Detach" +) + +// CachingTypeOption defines the different values for a CachingType. +type CachingTypeOption string + +// These are the valid CachingTypeOption values. +const ( + // CachingTypeReadOnly means the CachingType is "ReadOnly". + CachingTypeReadOnly CachingTypeOption = "ReadOnly" + // CachingTypeReadWrite means the CachingType is "ReadWrite". + CachingTypeReadWrite CachingTypeOption = "ReadWrite" + // CachingTypeNone means the CachingType is "None". + CachingTypeNone CachingTypeOption = "None" +) + +// DiskSettings describe ephemeral disk settings for the os disk. +type DiskSettings struct { + // ephemeralStorageLocation enables ephemeral OS when set to 'Local'. + // Possible values include: 'Local'. + // See https://docs.microsoft.com/en-us/azure/virtual-machines/ephemeral-os-disks for full details. + // Empty value means no opinion and the platform chooses a default, which is subject to change over + // time. Currently the default is that disks are saved to remote Azure storage. + // +optional + // +kubebuilder:validation:Enum=Local + EphemeralStorageLocation string `json:"ephemeralStorageLocation,omitempty"` +} + +// OSDiskManagedDiskParameters is the parameters of a OSDisk managed disk. +type OSDiskManagedDiskParameters struct { + // storageAccountType is the storage account type to use. + // Possible values include "Standard_LRS", "Premium_LRS". + StorageAccountType string `json:"storageAccountType"` + // diskEncryptionSet is the disk encryption set properties + // +optional + DiskEncryptionSet *DiskEncryptionSetParameters `json:"diskEncryptionSet,omitempty"` + // securityProfile specifies the security profile for the managed disk. + // +optional + SecurityProfile VMDiskSecurityProfile `json:"securityProfile,omitempty"` +} + +// VMDiskSecurityProfile specifies the security profile settings for the managed disk. +// It can be set only for Confidential VMs. +type VMDiskSecurityProfile struct { + // diskEncryptionSet specifies the customer managed disk encryption set resource id for the + // managed disk that is used for Customer Managed Key encrypted ConfidentialVM OS Disk and + // VMGuest blob. + // +optional + DiskEncryptionSet DiskEncryptionSetParameters `json:"diskEncryptionSet,omitempty"` + // securityEncryptionType specifies the encryption type of the managed disk. + // It is set to DiskWithVMGuestState to encrypt the managed disk along with the VMGuestState + // blob, and to VMGuestStateOnly to encrypt the VMGuestState blob only. + // When set to VMGuestStateOnly, the vTPM should be enabled. + // When set to DiskWithVMGuestState, both SecureBoot and vTPM should be enabled. + // If the above conditions are not fulfilled, the VM will not be created and the respective error + // will be returned. + // It can be set only for Confidential VMs. Confidential VMs are defined by their + // SecurityProfile.SecurityType being set to ConfidentialVM, the SecurityEncryptionType of their + // OS disk being set to one of the allowed values and by enabling the respective + // SecurityProfile.UEFISettings of the VM (i.e. vTPM and SecureBoot), depending on the selected + // SecurityEncryptionType. + // For further details on Azure Confidential VMs, please refer to the respective documentation: + // https://learn.microsoft.com/azure/confidential-computing/confidential-vm-overview + // +kubebuilder:validation:Enum=VMGuestStateOnly;DiskWithVMGuestState + // +optional + SecurityEncryptionType SecurityEncryptionTypes `json:"securityEncryptionType,omitempty"` +} + +// DataDiskManagedDiskParameters is the parameters of a DataDisk managed disk. +type DataDiskManagedDiskParameters struct { + // storageAccountType is the storage account type to use. + // Possible values include "Standard_LRS", "Premium_LRS" and "UltraSSD_LRS". + // +kubebuilder:validation:Enum=Standard_LRS;Premium_LRS;UltraSSD_LRS + StorageAccountType StorageAccountType `json:"storageAccountType"` + // diskEncryptionSet is the disk encryption set properties. + // Empty value means no opinion and the platform chooses a default, which is subject to change over time. + // Currently the default is a DiskEncryptionSet with id: "Default". + // +optional + DiskEncryptionSet *DiskEncryptionSetParameters `json:"diskEncryptionSet,omitempty"` +} + +// StorageAccountType defines the different storage types to use for a ManagedDisk. +type StorageAccountType string + +// These are the valid StorageAccountType types. +const ( + // "StorageAccountStandardLRS" means the Standard_LRS storage type. + StorageAccountStandardLRS StorageAccountType = "Standard_LRS" + // "StorageAccountPremiumLRS" means the Premium_LRS storage type. + StorageAccountPremiumLRS StorageAccountType = "Premium_LRS" + // "StorageAccountUltraSSDLRS" means the UltraSSD_LRS storage type. + StorageAccountUltraSSDLRS StorageAccountType = "UltraSSD_LRS" +) + +// DiskEncryptionSetParameters is the disk encryption set properties +type DiskEncryptionSetParameters struct { + // id is the disk encryption set ID + // Empty value means no opinion and the platform chooses a default, which is subject to change over time. + // Currently the default is: "Default". + // +optional + ID string `json:"id,omitempty"` +} + +// SecurityProfile specifies the Security profile settings for a +// virtual machine or virtual machine scale set. +type SecurityProfile struct { + // encryptionAtHost indicates whether Host Encryption should be enabled or disabled for a virtual + // machine or virtual machine scale set. + // This should be disabled when SecurityEncryptionType is set to DiskWithVMGuestState. + // Default is disabled. + // +optional + EncryptionAtHost *bool `json:"encryptionAtHost,omitempty"` + // settings specify the security type and the UEFI settings of the virtual machine. This field can + // be set for Confidential VMs and Trusted Launch for VMs. + // +optional + Settings SecuritySettings `json:"settings,omitempty"` +} + +// SecuritySettings define the security type and the UEFI settings of the virtual machine. +// +union +type SecuritySettings struct { + // securityType specifies the SecurityType of the virtual machine. It has to be set to any specified value to + // enable UEFISettings. The default behavior is: UEFISettings will not be enabled unless this property is set. + // +kubebuilder:validation:Enum=ConfidentialVM;TrustedLaunch + // +required + // +unionDiscriminator + SecurityType SecurityTypes `json:"securityType"` + // confidentialVM specifies the security configuration of the virtual machine. + // For more information regarding Confidential VMs, please refer to: + // https://learn.microsoft.com/azure/confidential-computing/confidential-vm-overview + // +optional + ConfidentialVM *ConfidentialVM `json:"confidentialVM,omitempty"` + // trustedLaunch specifies the security configuration of the virtual machine. + // For more information regarding TrustedLaunch for VMs, please refer to: + // https://learn.microsoft.com/azure/virtual-machines/trusted-launch + // +optional + TrustedLaunch *TrustedLaunch `json:"trustedLaunch,omitempty"` +} + +// ConfidentialVM defines the UEFI settings for the virtual machine. +type ConfidentialVM struct { + // uefiSettings specifies the security settings like secure boot and vTPM used while creating the virtual machine. + // +required + UEFISettings UEFISettings `json:"uefiSettings"` +} + +// TrustedLaunch defines the UEFI settings for the virtual machine. +type TrustedLaunch struct { + // uefiSettings specifies the security settings like secure boot and vTPM used while creating the virtual machine. + // +required + UEFISettings UEFISettings `json:"uefiSettings"` +} + +// UEFISettings specifies the security settings like secure boot and vTPM used while creating the +// virtual machine. +type UEFISettings struct { + // secureBoot specifies whether secure boot should be enabled on the virtual machine. + // Secure Boot verifies the digital signature of all boot components and halts the boot process if + // signature verification fails. + // If omitted, the platform chooses a default, which is subject to change over time, currently that default is disabled. + // +kubebuilder:validation:Enum=Enabled;Disabled + // +optional + SecureBoot SecureBootPolicy `json:"secureBoot,omitempty"` + // virtualizedTrustedPlatformModule specifies whether vTPM should be enabled on the virtual machine. + // When enabled the virtualized trusted platform module measurements are used to create a known good boot integrity policy baseline. + // The integrity policy baseline is used for comparison with measurements from subsequent VM boots to determine if anything has changed. + // This is required to be enabled if SecurityEncryptionType is defined. + // If omitted, the platform chooses a default, which is subject to change over time, currently that default is disabled. + // +kubebuilder:validation:Enum=Enabled;Disabled + // +optional + VirtualizedTrustedPlatformModule VirtualizedTrustedPlatformModulePolicy `json:"virtualizedTrustedPlatformModule,omitempty"` +} + +// AzureUltraSSDCapabilityState defines the different states of an UltraSSDCapability +type AzureUltraSSDCapabilityState string + +// These are the valid AzureUltraSSDCapabilityState states. +const ( + // "AzureUltraSSDCapabilityEnabled" means the Azure UltraSSDCapability is Enabled + AzureUltraSSDCapabilityEnabled AzureUltraSSDCapabilityState = "Enabled" + // "AzureUltraSSDCapabilityDisabled" means the Azure UltraSSDCapability is Disabled + AzureUltraSSDCapabilityDisabled AzureUltraSSDCapabilityState = "Disabled" +) diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_gcpprovider.go b/vendor/github.com/openshift/api/machine/v1beta1/types_gcpprovider.go new file mode 100644 index 000000000..9713a4e4a --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_gcpprovider.go @@ -0,0 +1,362 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// GCPHostMaintenanceType is a type representing acceptable values for OnHostMaintenance field in GCPMachineProviderSpec +type GCPHostMaintenanceType string + +const ( + // MigrateHostMaintenanceType [default] - causes Compute Engine to live migrate an instance when there is a maintenance event. + MigrateHostMaintenanceType GCPHostMaintenanceType = "Migrate" + // TerminateHostMaintenanceType - stops an instance instead of migrating it. + TerminateHostMaintenanceType GCPHostMaintenanceType = "Terminate" +) + +// GCPHostMaintenanceType is a type representing acceptable values for RestartPolicy field in GCPMachineProviderSpec +type GCPRestartPolicyType string + +const ( + // Restart an instance if an instance crashes or the underlying infrastructure provider stops the instance as part of a maintenance event. + RestartPolicyAlways GCPRestartPolicyType = "Always" + // Do not restart an instance if an instance crashes or the underlying infrastructure provider stops the instance as part of a maintenance event. + 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 + +const ( + // SecureBootPolicyEnabled enables the secure boot configuration for the GCP machine. + SecureBootPolicyEnabled SecureBootPolicy = "Enabled" + // SecureBootPolicyDisabled disables the secure boot configuration for the GCP machine. + SecureBootPolicyDisabled SecureBootPolicy = "Disabled" +) + +// VirtualizedTrustedPlatformModulePolicy represents the virtualized trusted platform module configuration for the GCP machine. +type VirtualizedTrustedPlatformModulePolicy string + +const ( + // VirtualizedTrustedPlatformModulePolicyEnabled enables the virtualized trusted platform module configuration for the GCP machine. + VirtualizedTrustedPlatformModulePolicyEnabled VirtualizedTrustedPlatformModulePolicy = "Enabled" + // VirtualizedTrustedPlatformModulePolicyDisabled disables the virtualized trusted platform module configuration for the GCP machine. + VirtualizedTrustedPlatformModulePolicyDisabled VirtualizedTrustedPlatformModulePolicy = "Disabled" +) + +// IntegrityMonitoringPolicy represents the integrity monitoring configuration for the GCP machine. +type IntegrityMonitoringPolicy string + +const ( + // IntegrityMonitoringPolicyEnabled enables integrity monitoring for the GCP machine. + IntegrityMonitoringPolicyEnabled IntegrityMonitoringPolicy = "Enabled" + // IntegrityMonitoringPolicyDisabled disables integrity monitoring for the GCP machine. + IntegrityMonitoringPolicyDisabled IntegrityMonitoringPolicy = "Disabled" +) + +// ConfidentialComputePolicy represents the confidential compute configuration for the GCP machine. +type ConfidentialComputePolicy string + +const ( + // ConfidentialComputePolicyEnabled enables confidential compute for the GCP machine. + ConfidentialComputePolicyEnabled ConfidentialComputePolicy = "Enabled" + // ConfidentialComputePolicyDisabled disables confidential compute for the GCP machine. + ConfidentialComputePolicyDisabled ConfidentialComputePolicy = "Disabled" + // ConfidentialComputePolicySEV sets AMD SEV as the VM instance's confidential computing technology of choice. + ConfidentialComputePolicySEV ConfidentialComputePolicy = "AMDEncryptedVirtualization" + // ConfidentialComputePolicySEVSNP sets AMD SEV-SNP as the VM instance's confidential computing technology of choice. + ConfidentialComputePolicySEVSNP ConfidentialComputePolicy = "AMDEncryptedVirtualizationNestedPaging" + // ConfidentialComputePolicyTDX sets Intel TDX as the VM instance's confidential computing technology of choice. + ConfidentialComputePolicyTDX ConfidentialComputePolicy = "IntelTrustedDomainExtensions" +) + +// GCPMachineProviderSpec is the type that will be embedded in a Machine.Spec.ProviderSpec field +// for an GCP virtual machine. It is used by the GCP machine actuator to create a single Machine. +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type GCPMachineProviderSpec struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + // userDataSecret contains a local reference to a secret that contains the + // UserData to apply to the instance + // +optional + UserDataSecret *corev1.LocalObjectReference `json:"userDataSecret,omitempty"` + // credentialsSecret is a reference to the secret with GCP credentials. + // +optional + CredentialsSecret *corev1.LocalObjectReference `json:"credentialsSecret,omitempty"` + // canIPForward Allows this instance to send and receive packets with non-matching destination or source IPs. + // This is required if you plan to use this instance to forward routes. + CanIPForward bool `json:"canIPForward"` + // deletionProtection whether the resource should be protected against deletion. + DeletionProtection bool `json:"deletionProtection"` + // disks is a list of disks to be attached to the VM. + // +optional + Disks []*GCPDisk `json:"disks,omitempty"` + // labels list of labels to apply to the VM. + // +optional + Labels map[string]string `json:"labels,omitempty"` + // Metadata key/value pairs to apply to the VM. + // +optional + Metadata []*GCPMetadata `json:"gcpMetadata,omitempty"` + // networkInterfaces is a list of network interfaces to be attached to the VM. + // +optional + NetworkInterfaces []*GCPNetworkInterface `json:"networkInterfaces,omitempty"` + // serviceAccounts is a list of GCP service accounts to be used by the VM. + ServiceAccounts []GCPServiceAccount `json:"serviceAccounts"` + // tags list of network tags to apply to the VM. + Tags []string `json:"tags,omitempty"` + // targetPools are used for network TCP/UDP load balancing. A target pool references member instances, + // an associated legacy HttpHealthCheck resource, and, optionally, a backup target pool + // +optional + TargetPools []string `json:"targetPools,omitempty"` + // machineType is the machine type to use for the VM. + MachineType string `json:"machineType"` + // region is the region in which the GCP machine provider will create the VM. + Region string `json:"region"` + // zone is the zone in which the GCP machine provider will create the VM. + Zone string `json:"zone"` + // projectID is the project in which the GCP machine provider will create the VM. + // +optional + ProjectID string `json:"projectID,omitempty"` + // gpus is a list of GPUs to be attached to the VM. + // +optional + GPUs []GCPGPUConfig `json:"gpus,omitempty"` + // 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". + // If omitted, the platform chooses a default, which is subject to change over time, currently that default is "Migrate". + // +kubebuilder:validation:Enum=Migrate;Terminate; + // +optional + OnHostMaintenance GCPHostMaintenanceType `json:"onHostMaintenance,omitempty"` + // 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 + // +kubebuilder:validation:Enum=Always;Never; + // +optional + RestartPolicy GCPRestartPolicyType `json:"restartPolicy,omitempty"` + + // shieldedInstanceConfig is the Shielded VM configuration for the VM + // +optional + ShieldedInstanceConfig GCPShieldedInstanceConfig `json:"shieldedInstanceConfig,omitempty"` + + // confidentialCompute is an optional field defining whether the instance should have confidential compute enabled or not, and the confidential computing technology of choice. + // Allowed values are omitted, Disabled, Enabled, AMDEncryptedVirtualization, AMDEncryptedVirtualizationNestedPaging, and IntelTrustedDomainExtensions + // When set to Disabled, the machine will not be configured to be a confidential computing instance. + // When set to Enabled, the machine will be configured as a confidential computing instance with no preference on the confidential compute policy used. In this mode, the platform chooses a default that is subject to change over time. Currently, the default is to use AMD Secure Encrypted Virtualization. + // When set to AMDEncryptedVirtualization, the machine will be configured as a confidential computing instance with AMD Secure Encrypted Virtualization (AMD SEV) as the confidential computing technology. + // When set to AMDEncryptedVirtualizationNestedPaging, the machine will be configured as a confidential computing instance with AMD Secure Encrypted Virtualization Secure Nested Paging (AMD SEV-SNP) as the confidential computing technology. + // When set to IntelTrustedDomainExtensions, the machine will be configured as a confidential computing instance with Intel Trusted Domain Extensions (Intel TDX) as the confidential computing technology. + // If any value other than Disabled is set the selected machine type must support that specific confidential computing technology. The machine series supporting confidential computing technologies can be checked at https://cloud.google.com/confidential-computing/confidential-vm/docs/supported-configurations#all-confidential-vm-instances + // Currently, AMDEncryptedVirtualization is supported in c2d, n2d, and c3d machines. + // AMDEncryptedVirtualizationNestedPaging is supported in n2d machines. + // IntelTrustedDomainExtensions is supported in c3 machines. + // If any value other than Disabled is set, the selected region must support that specific confidential computing technology. The list of regions supporting confidential computing technologies can be checked at https://cloud.google.com/confidential-computing/confidential-vm/docs/supported-configurations#supported-zones + // If any value other than Disabled is set onHostMaintenance is required to be set to "Terminate". + // If omitted, the platform chooses a default, which is subject to change over time, currently that default is Disabled. + // +kubebuilder:validation:Enum="";Enabled;Disabled;AMDEncryptedVirtualization;AMDEncryptedVirtualizationNestedPaging;IntelTrustedDomainExtensions + // +optional + ConfidentialCompute ConfidentialComputePolicy `json:"confidentialCompute,omitempty"` + + // resourceManagerTags is an optional list of tags to apply to the GCP resources created for + // the cluster. See https://cloud.google.com/resource-manager/docs/tags/tags-overview for + // information on tagging GCP resources. GCP supports a maximum of 50 tags per resource. + // +kubebuilder:validation:MaxItems=50 + // +listType=map + // +listMapKey=key + // +optional + ResourceManagerTags []ResourceManagerTag `json:"resourceManagerTags,omitempty"` +} + +// ResourceManagerTag is a tag to apply to GCP resources created for the cluster. +type ResourceManagerTag struct { + // parentID is the ID of the hierarchical resource where the tags are defined + // e.g. at the Organization or the Project level. To find the Organization or Project ID ref + // https://cloud.google.com/resource-manager/docs/creating-managing-organization#retrieving_your_organization_id + // https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects + // An OrganizationID can have a maximum of 32 characters and must consist of decimal numbers, and + // cannot have leading zeroes. A ProjectID must be 6 to 30 characters in length, can only contain + // lowercase letters, numbers, and hyphens, and must start with a letter, and cannot end with a hyphen. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=32 + // +kubebuilder:validation:Pattern=`(^[1-9][0-9]{0,31}$)|(^[a-z][a-z0-9-]{4,28}[a-z0-9]$)` + ParentID string `json:"parentID"` + + // key is the key part of the tag. A tag key can have a maximum of 63 characters and cannot be empty. + // Tag key must begin and end with an alphanumeric character, and must contain only uppercase, lowercase + // alphanumeric characters, and the following special characters `._-`. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern=`^[a-zA-Z0-9]([0-9A-Za-z_.-]{0,61}[a-zA-Z0-9])?$` + Key string `json:"key"` + + // value is the value part of the tag. A tag value can have a maximum of 63 characters and cannot be empty. + // Tag value must begin and end with an alphanumeric character, and must contain only uppercase, lowercase + // alphanumeric characters, and the following special characters `_-.@%=+:,*#&(){}[]` and spaces. + // +required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=63 + // +kubebuilder:validation:Pattern=`^[a-zA-Z0-9]([0-9A-Za-z_.@%=+:,*#&()\[\]{}\-\s]{0,61}[a-zA-Z0-9])?$` + Value string `json:"value"` +} + +// GCPDisk describes disks for GCP. +type GCPDisk struct { + // autoDelete indicates if the disk will be auto-deleted when the instance is deleted (default false). + AutoDelete bool `json:"autoDelete"` + // boot indicates if this is a boot disk (default false). + Boot bool `json:"boot"` + // sizeGb is the size of the disk (in GB). + SizeGB int64 `json:"sizeGb"` + // type is the type of the disk (eg: pd-standard). + Type string `json:"type"` + // image is the source image to create this disk. + Image string `json:"image"` + // labels list of labels to apply to the disk. + Labels map[string]string `json:"labels"` + // encryptionKey is the customer-supplied encryption key of the disk. + // +optional + EncryptionKey *GCPEncryptionKeyReference `json:"encryptionKey,omitempty"` +} + +// GCPMetadata describes metadata for GCP. +type GCPMetadata struct { + // key is the metadata key. + Key string `json:"key"` + // value is the metadata value. + Value *string `json:"value"` +} + +// GCPNetworkInterface describes network interfaces for GCP +type GCPNetworkInterface struct { + // publicIP indicates if true a public IP will be used + PublicIP bool `json:"publicIP,omitempty"` + // network is the network name. + Network string `json:"network,omitempty"` + // projectID is the project in which the GCP machine provider will create the VM. + ProjectID string `json:"projectID,omitempty"` + // subnetwork is the subnetwork name. + Subnetwork string `json:"subnetwork,omitempty"` +} + +// GCPServiceAccount describes service accounts for GCP. +type GCPServiceAccount struct { + // email is the service account email. + Email string `json:"email"` + // scopes list of scopes to be assigned to the service account. + Scopes []string `json:"scopes"` +} + +// GCPEncryptionKeyReference describes the encryptionKey to use for a disk's encryption. +type GCPEncryptionKeyReference struct { + // KMSKeyName is the reference KMS key, in the format + // +optional + KMSKey *GCPKMSKeyReference `json:"kmsKey,omitempty"` + // kmsKeyServiceAccount is the service account being used for the + // encryption request for the given KMS key. If absent, the Compute + // Engine default service account is used. + // See https://cloud.google.com/compute/docs/access/service-accounts#compute_engine_service_account + // for details on the default service account. + // +optional + KMSKeyServiceAccount string `json:"kmsKeyServiceAccount,omitempty"` +} + +// GCPKMSKeyReference gathers required fields for looking up a GCP KMS Key +type GCPKMSKeyReference struct { + // name is the name of the customer managed encryption key to be used for the disk encryption. + Name string `json:"name"` + // keyRing is the name of the KMS Key Ring which the KMS Key belongs to. + KeyRing string `json:"keyRing"` + // projectID is the ID of the Project in which the KMS Key Ring exists. + // Defaults to the VM ProjectID if not set. + // +optional + ProjectID string `json:"projectID,omitempty"` + // location is the GCP location in which the Key Ring exists. + Location string `json:"location"` +} + +// GCPGPUConfig describes type and count of GPUs attached to the instance on GCP. +type GCPGPUConfig struct { + // count is the number of GPUs to be attached to an instance. + Count int32 `json:"count"` + // type is the type of GPU to be attached to an instance. + // Supported GPU types are: nvidia-tesla-k80, nvidia-tesla-p100, nvidia-tesla-v100, nvidia-tesla-p4, nvidia-tesla-t4 + // +kubebuilder:validation:Pattern=`^nvidia-tesla-(k80|p100|v100|p4|t4)$` + Type string `json:"type"` +} + +// GCPMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. +// It contains GCP-specific status information. +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type GCPMachineProviderStatus struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + // instanceId is the ID of the instance in GCP + // +optional + InstanceID *string `json:"instanceId,omitempty"` + // instanceState is the provisioning state of the GCP Instance. + // +optional + InstanceState *string `json:"instanceState,omitempty"` + // conditions is a set of conditions associated with the Machine to indicate + // errors or other status + // +optional + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// GCPShieldedInstanceConfig describes the shielded VM configuration of the instance on GCP. +// Shielded VM configuration allow users to enable and disable Secure Boot, vTPM, and Integrity Monitoring. +type GCPShieldedInstanceConfig struct { + // secureBoot Defines whether the instance should have secure boot enabled. + // Secure Boot verify the digital signature of all boot components, and halting the boot process if signature verification fails. + // If omitted, the platform chooses a default, which is subject to change over time, currently that default is Disabled. + // +kubebuilder:validation:Enum=Enabled;Disabled + //+optional + SecureBoot SecureBootPolicy `json:"secureBoot,omitempty"` + + // virtualizedTrustedPlatformModule enable virtualized trusted platform module measurements to create a known good boot integrity policy baseline. + // The integrity policy baseline is used for comparison with measurements from subsequent VM boots to determine if anything has changed. + // This is required to be set to "Enabled" if IntegrityMonitoring is enabled. + // If omitted, the platform chooses a default, which is subject to change over time, currently that default is Enabled. + // +kubebuilder:validation:Enum=Enabled;Disabled + // +optional + VirtualizedTrustedPlatformModule VirtualizedTrustedPlatformModulePolicy `json:"virtualizedTrustedPlatformModule,omitempty"` + + // integrityMonitoring determines whether the instance should have integrity monitoring that verify the runtime boot integrity. + // Compares the most recent boot measurements to the integrity policy baseline and return + // a pair of pass/fail results depending on whether they match or not. + // If omitted, the platform chooses a default, which is subject to change over time, currently that default is Enabled. + // +kubebuilder:validation:Enum=Enabled;Disabled + // +optional + IntegrityMonitoring IntegrityMonitoringPolicy `json:"integrityMonitoring,omitempty"` +} diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_machine.go b/vendor/github.com/openshift/api/machine/v1beta1/types_machine.go new file mode 100644 index 000000000..6bfe85081 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_machine.go @@ -0,0 +1,468 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +const ( + // MachineFinalizer is set on PrepareForCreate callback. + MachineFinalizer = "machine.machine.openshift.io" + + // MachineClusterLabelName is the label set on machines linked to a cluster. + MachineClusterLabelName = "cluster.k8s.io/cluster-name" + + // MachineClusterIDLabel is the label that a machine must have to identify the + // cluster to which it belongs. + MachineClusterIDLabel = "machine.openshift.io/cluster-api-cluster" + + // IPClaimProtectionFinalizer is placed on an IPAddressClaim by the machine reconciler + // when an IPAddressClaim associated with a machine is created. This finalizer is removed + // from the IPAddressClaim when the associated machine is deleted. + IPClaimProtectionFinalizer = "machine.openshift.io/ip-claim-protection" +) + +type MachineStatusError string + +const ( + // Represents that the combination of configuration in the MachineSpec + // is not supported by this cluster. This is not a transient error, but + // indicates a state that must be fixed before progress can be made. + // + // Example: the ProviderSpec specifies an instance type that doesn't exist, + InvalidConfigurationMachineError MachineStatusError = "InvalidConfiguration" + + // This indicates that the MachineSpec has been updated in a way that + // is not supported for reconciliation on this cluster. The spec may be + // completely valid from a configuration standpoint, but the controller + // does not support changing the real world state to match the new + // spec. + // + // Example: the responsible controller is not capable of changing the + // container runtime from docker to rkt. + UnsupportedChangeMachineError MachineStatusError = "UnsupportedChange" + + // This generally refers to exceeding one's quota in a cloud provider, + // or running out of physical machines in an on-premise environment. + InsufficientResourcesMachineError MachineStatusError = "InsufficientResources" + + // There was an error while trying to create a Node to match this + // Machine. This may indicate a transient problem that will be fixed + // automatically with time, such as a service outage, or a terminal + // error during creation that doesn't match a more specific + // MachineStatusError value. + // + // Example: timeout trying to connect to GCE. + CreateMachineError MachineStatusError = "CreateError" + + // There was an error while trying to update a Node that this + // Machine represents. This may indicate a transient problem that will be + // fixed automatically with time, such as a service outage, + // + // Example: error updating load balancers + UpdateMachineError MachineStatusError = "UpdateError" + + // An error was encountered while trying to delete the Node that this + // Machine represents. This could be a transient or terminal error, but + // will only be observable if the provider's Machine controller has + // added a finalizer to the object to more gracefully handle deletions. + // + // Example: cannot resolve EC2 IP address. + DeleteMachineError MachineStatusError = "DeleteError" + + // TemplateClonedFromGroupKindAnnotation is the infrastructure machine + // annotation that stores the group-kind of the infrastructure template resource + // that was cloned for the machine. This annotation is set only during cloning a + // template. Older/adopted machines will not have this annotation. + TemplateClonedFromGroupKindAnnotation = "machine.openshift.io/cloned-from-groupkind" + + // TemplateClonedFromNameAnnotation is the infrastructure machine annotation that + // stores the name of the infrastructure template resource + // that was cloned for the machine. This annotation is set only during cloning a + // template. Older/adopted machines will not have this annotation. + TemplateClonedFromNameAnnotation = "machine.openshift.io/cloned-from-name" + + // This error indicates that the machine did not join the cluster + // as a new node within the expected timeframe after instance + // creation at the provider succeeded + // + // Example use case: A controller that deletes Machines which do + // not result in a Node joining the cluster within a given timeout + // and that are managed by a MachineSet + JoinClusterTimeoutMachineError = "JoinClusterTimeoutError" + + // IPAddressInvalidReason is set to indicate that the claimed IP address is not valid. + IPAddressInvalidReason MachineStatusError = "IPAddressInvalid" +) + +type ClusterStatusError string + +const ( + // InvalidConfigurationClusterError indicates that the cluster + // configuration is invalid. + InvalidConfigurationClusterError ClusterStatusError = "InvalidConfiguration" + + // UnsupportedChangeClusterError indicates that the cluster + // spec has been updated in an unsupported way. That cannot be + // reconciled. + UnsupportedChangeClusterError ClusterStatusError = "UnsupportedChange" + + // CreateClusterError indicates that an error was encountered + // when trying to create the cluster. + CreateClusterError ClusterStatusError = "CreateError" + + // UpdateClusterError indicates that an error was encountered + // when trying to update the cluster. + UpdateClusterError ClusterStatusError = "UpdateError" + + // DeleteClusterError indicates that an error was encountered + // when trying to delete the cluster. + DeleteClusterError ClusterStatusError = "DeleteError" +) + +type MachineSetStatusError string + +const ( + // Represents that the combination of configuration in the MachineTemplateSpec + // is not supported by this cluster. This is not a transient error, but + // indicates a state that must be fixed before progress can be made. + // + // Example: the ProviderSpec specifies an instance type that doesn't exist. + InvalidConfigurationMachineSetError MachineSetStatusError = "InvalidConfiguration" +) + +type MachineDeploymentStrategyType string + +const ( + // Replace the old MachineSet by new one using rolling update + // i.e. gradually scale down the old MachineSet and scale up the new one. + RollingUpdateMachineDeploymentStrategyType MachineDeploymentStrategyType = "RollingUpdate" +) + +const ( + // PhaseFailed indicates a state that will need to be fixed before progress can be made. + // Failed machines have encountered a terminal error and must be deleted. + // https://github.com/openshift/enhancements/blob/master/enhancements/machine-instance-lifecycle.md + // e.g. Instance does NOT exist but Machine has providerID/addresses. + // e.g. Cloud service returns a 4xx response. + PhaseFailed string = "Failed" + + // PhaseProvisioning indicates the instance does NOT exist. + // The machine has NOT been given a providerID or addresses. + // Provisioning implies that the Machine API is in the process of creating the instance. + PhaseProvisioning string = "Provisioning" + + // PhaseProvisioned indicates the instance exists. + // The machine has been given a providerID and addresses. + // The machine API successfully provisioned an instance which has not yet joined the cluster, + // as such, the machine has NOT yet been given a nodeRef. + PhaseProvisioned string = "Provisioned" + + // PhaseRunning indicates the instance exists and the node has joined the cluster. + // The machine has been given a providerID, addresses, and a nodeRef. + PhaseRunning string = "Running" + + // PhaseDeleting indicates the machine has a deletion timestamp and that the + // Machine API is now in the process of removing the machine from the cluster. + PhaseDeleting string = "Deleting" +) + +type MachineAuthority string + +const ( + // MachineAuthorityMachineAPI indicates that the Machine API resource should be the authoritative API. + MachineAuthorityMachineAPI MachineAuthority = "MachineAPI" + + // MachineAuthorityClusterAPI indicates that the Cluster API resource should be the authoritative API. + MachineAuthorityClusterAPI MachineAuthority = "ClusterAPI" + + // MachineAuthorityMigrating indicates that the authoritative API is currently migrating between states. + // Only applicable for status usages of the MachineAuthority. + MachineAuthorityMigrating MachineAuthority = "Migrating" +) + +// SynchronizedAPI holds the last stable value of authoritativeAPI. +// +kubebuilder:validation:Enum=MachineAPI;ClusterAPI +type SynchronizedAPI string + +const ( + // MachineAPISynchronized indicates that the Machine API is the last synchronized API. + MachineAPISynchronized SynchronizedAPI = "MachineAPI" + + // ClusterAPISynchronized indicates that the Cluster API is the last synchronized API. + ClusterAPISynchronized SynchronizedAPI = "ClusterAPI" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Machine is the Schema for the machines API +// +k8s:openapi-gen=true +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=machines,scope=Namespaced +// +kubebuilder:subresource:status +// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/948 +// +openshift:file-pattern=cvoRunLevel=0000_10,operatorName=machine-api,operatorOrdering=01 +// +openshift:capability=MachineAPI +// +kubebuilder:metadata:annotations="exclude.release.openshift.io/internal-openshift-hosted=true" +// +kubebuilder:metadata:annotations="include.release.openshift.io/self-managed-high-availability=true" +// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="Phase of machine" +// +kubebuilder:printcolumn:name="Type",type="string",JSONPath=".metadata.labels['machine\\.openshift\\.io/instance-type']",description="Type of instance" +// +kubebuilder:printcolumn:name="Region",type="string",JSONPath=".metadata.labels['machine\\.openshift\\.io/region']",description="Region associated with machine" +// +kubebuilder:printcolumn:name="Zone",type="string",JSONPath=".metadata.labels['machine\\.openshift\\.io/zone']",description="Zone associated with machine" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Machine age" +// +kubebuilder:printcolumn:name="Node",type="string",JSONPath=".status.nodeRef.name",description="Node associated with machine",priority=1 +// +kubebuilder:printcolumn:name="ProviderID",type="string",JSONPath=".spec.providerID",description="Provider ID of machine created in cloud provider",priority=1 +// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".metadata.annotations['machine\\.openshift\\.io/instance-state']",description="State of instance",priority=1 +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type Machine struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec MachineSpec `json:"spec,omitempty"` + Status MachineStatus `json:"status,omitempty"` +} + +// MachineSpec defines the desired state of Machine +type MachineSpec struct { + // ObjectMeta will autopopulate the Node created. Use this to + // indicate what labels, annotations, name prefix, etc., should be used + // when creating the Node. + // +optional + ObjectMeta `json:"metadata,omitempty"` + + // lifecycleHooks allow users to pause operations on the machine at + // certain predefined points within the machine lifecycle. + // +optional + LifecycleHooks LifecycleHooks `json:"lifecycleHooks,omitempty"` + + // The list of the taints to be applied to the corresponding Node in additive + // manner. This list will not overwrite any other taints added to the Node on + // an ongoing basis by other entities. These taints should be actively reconciled + // e.g. if you ask the machine controller to apply a taint and then manually remove + // the taint the machine controller will put it back) but not have the machine controller + // remove any taints + // +optional + // +listType=atomic + Taints []corev1.Taint `json:"taints,omitempty"` + + // providerSpec details Provider-specific configuration to use during node creation. + // +optional + ProviderSpec ProviderSpec `json:"providerSpec"` + + // providerID is the identification ID of the machine provided by the provider. + // This field must match the provider ID as seen on the node object corresponding to this machine. + // This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler + // with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out + // machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a + // generic out-of-tree provider for autoscaler, this field is required by autoscaler to be + // able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver + // and then a comparison is done to find out unregistered machines and are marked for delete. + // This field will be set by the actuators and consumed by higher level entities like autoscaler that will + // be interfacing with cluster-api as generic provider. + // +optional + ProviderID *string `json:"providerID,omitempty"` + + // authoritativeAPI is the API that is authoritative for this resource. + // Valid values are MachineAPI and ClusterAPI. + // When set to MachineAPI, writes to the spec of the machine.openshift.io copy of this resource will be reflected into the cluster.x-k8s.io copy. + // When set to ClusterAPI, writes to the spec of the cluster.x-k8s.io copy of this resource will be reflected into the machine.openshift.io copy. + // Updates to the status will be reflected in both copies of the resource, based on the controller implementing the functionality of the API. + // Currently the authoritative API determines which controller will manage the resource, this will change in a future release. + // To ensure the change has been accepted, please verify that the `status.authoritativeAPI` field has been updated to the desired value and that the `Synchronized` condition is present and set to `True`. + // +kubebuilder:validation:Enum=MachineAPI;ClusterAPI + // +kubebuilder:validation:Default=MachineAPI + // +default="MachineAPI" + // +openshift:enable:FeatureGate=MachineAPIMigration + // +optional + AuthoritativeAPI MachineAuthority `json:"authoritativeAPI,omitempty"` +} + +// LifecycleHooks allow users to pause operations on the machine at +// certain prefedined points within the machine lifecycle. +type LifecycleHooks struct { + // preDrain hooks prevent the machine from being drained. + // This also blocks further lifecycle events, such as termination. + // +listType=map + // +listMapKey=name + // +optional + PreDrain []LifecycleHook `json:"preDrain,omitempty"` + + // preTerminate hooks prevent the machine from being terminated. + // PreTerminate hooks be actioned after the Machine has been drained. + // +listType=map + // +listMapKey=name + // +optional + PreTerminate []LifecycleHook `json:"preTerminate,omitempty"` +} + +// LifecycleHook represents a single instance of a lifecycle hook +type LifecycleHook struct { + // name defines a unique name for the lifcycle hook. + // The name should be unique and descriptive, ideally 1-3 words, in CamelCase or + // it may be namespaced, eg. foo.example.com/CamelCase. + // Names must be unique and should only be managed by a single entity. + // +kubebuilder:validation: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])$` + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:MaxLength=256 + // +required + Name string `json:"name"` + + // owner defines the owner of the lifecycle hook. + // This should be descriptive enough so that users can identify + // who/what is responsible for blocking the lifecycle. + // This could be the name of a controller (e.g. clusteroperator/etcd) + // or an administrator managing the hook. + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:MaxLength=512 + // +required + Owner string `json:"owner"` +} + +// MachineStatus defines the observed state of Machine +// +openshift:validation:FeatureGateAwareXValidation:featureGate=MachineAPIMigration,rule="!has(oldSelf.synchronizedGeneration) || (has(self.synchronizedGeneration) && self.synchronizedGeneration >= oldSelf.synchronizedGeneration) || (oldSelf.authoritativeAPI == 'Migrating' && self.authoritativeAPI != 'Migrating')",message="synchronizedGeneration must not decrease unless authoritativeAPI is transitioning from Migrating to another value" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=MachineAPIMigration,rule="has(self.authoritativeAPI) || !has(oldSelf.authoritativeAPI)",message="authoritativeAPI may not be removed once set" +type MachineStatus struct { + // nodeRef will point to the corresponding Node if it exists. + // +optional + NodeRef *corev1.ObjectReference `json:"nodeRef,omitempty"` + + // lastUpdated identifies when this status was last observed. + // +optional + LastUpdated *metav1.Time `json:"lastUpdated,omitempty"` + + // errorReason will be set in the event that there is a terminal problem + // reconciling the Machine and will contain a succinct value suitable + // for machine interpretation. + // + // This field should not be set for transitive errors that a controller + // faces that are expected to be fixed automatically over + // time (like service outages), but instead indicate that something is + // fundamentally wrong with the Machine's spec or the configuration of + // the controller, and that manual intervention is required. Examples + // of terminal errors would be invalid combinations of settings in the + // spec, values that are unsupported by the controller, or the + // responsible controller itself being critically misconfigured. + // + // Any transient errors that occur during the reconciliation of Machines + // can be added as events to the Machine object and/or logged in the + // controller's output. + // +optional + ErrorReason *MachineStatusError `json:"errorReason,omitempty"` + + // errorMessage will be set in the event that there is a terminal problem + // reconciling the Machine and will contain a more verbose string suitable + // for logging and human consumption. + // + // This field should not be set for transitive errors that a controller + // faces that are expected to be fixed automatically over + // time (like service outages), but instead indicate that something is + // fundamentally wrong with the Machine's spec or the configuration of + // the controller, and that manual intervention is required. Examples + // of terminal errors would be invalid combinations of settings in the + // spec, values that are unsupported by the controller, or the + // responsible controller itself being critically misconfigured. + // + // Any transient errors that occur during the reconciliation of Machines + // can be added as events to the Machine object and/or logged in the + // controller's output. + // +optional + ErrorMessage *string `json:"errorMessage,omitempty"` + + // providerStatus details a Provider-specific status. + // It is recommended that providers maintain their + // own versioned API types that should be + // serialized/deserialized from this field. + // +optional + // +kubebuilder:validation:XPreserveUnknownFields + ProviderStatus *runtime.RawExtension `json:"providerStatus,omitempty"` + + // addresses is a list of addresses assigned to the machine. Queried from cloud provider, if available. + // +optional + // +listType=atomic + Addresses []corev1.NodeAddress `json:"addresses,omitempty"` + + // lastOperation describes the last-operation performed by the machine-controller. + // This API should be useful as a history in terms of the latest operation performed on the + // specific machine. It should also convey the state of the latest-operation for example if + // it is still on-going, failed or completed successfully. + // +optional + LastOperation *LastOperation `json:"lastOperation,omitempty"` + + // phase represents the current phase of machine actuation. + // One of: Failed, Provisioning, Provisioned, Running, Deleting + // +optional + Phase *string `json:"phase,omitempty"` + + // conditions defines the current state of the Machine + // +listType=map + // +listMapKey=type + // +optional + Conditions []Condition `json:"conditions,omitempty"` + + // authoritativeAPI is the API that is authoritative for this resource. + // Valid values are MachineAPI, ClusterAPI and Migrating. + // This value is updated by the migration controller to reflect the authoritative API. + // Machine API and Cluster API controllers use this value to determine whether or not to reconcile the resource. + // When set to Migrating, the migration controller is currently performing the handover of authority from one API to the other. + // +kubebuilder:validation:Enum=MachineAPI;ClusterAPI;Migrating + // +kubebuilder:validation:XValidation:rule="self == 'Migrating' || self == oldSelf || oldSelf == 'Migrating'",message="The authoritativeAPI field must not transition directly from MachineAPI to ClusterAPI or vice versa. It must transition through Migrating." + // +openshift:enable:FeatureGate=MachineAPIMigration + // +optional + AuthoritativeAPI MachineAuthority `json:"authoritativeAPI,omitempty"` + + // synchronizedAPI holds the last stable value of authoritativeAPI. + // It is used to detect migration cancellation requests and to restore the resource to its previous state. + // Valid values are "MachineAPI" and "ClusterAPI". + // When omitted, the resource has not yet been reconciled by the migration controller. + // +openshift:enable:FeatureGate=MachineAPIMigration + // +optional + SynchronizedAPI SynchronizedAPI `json:"synchronizedAPI,omitempty"` + + // synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with. + // This field is set when the authoritative resource is updated and the sync controller has updated the non-authoritative resource to match. + // +kubebuilder:validation:Minimum=0 + // +openshift:enable:FeatureGate=MachineAPIMigration + // +optional + SynchronizedGeneration int64 `json:"synchronizedGeneration,omitempty"` +} + +// LastOperation represents the detail of the last performed operation on the MachineObject. +type LastOperation struct { + // description is the human-readable description of the last operation. + Description *string `json:"description,omitempty"` + + // lastUpdated is the timestamp at which LastOperation API was last-updated. + LastUpdated *metav1.Time `json:"lastUpdated,omitempty"` + + // state is the current status of the last performed operation. + // E.g. Processing, Failed, Successful etc + State *string `json:"state,omitempty"` + + // type is the type of operation which was last performed. + // E.g. Create, Delete, Update etc + Type *string `json:"type,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineList contains a list of Machine +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type MachineList struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard list's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ListMeta `json:"metadata,omitempty"` + + Items []Machine `json:"items"` +} diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_machinehealthcheck.go b/vendor/github.com/openshift/api/machine/v1beta1/types_machinehealthcheck.go new file mode 100644 index 000000000..f80d716a0 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_machinehealthcheck.go @@ -0,0 +1,152 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" +) + +// RemediationStrategyType contains remediation strategy type +type RemediationStrategyType string + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineHealthCheck is the Schema for the machinehealthchecks API +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=machinehealthchecks,scope=Namespaced,shortName=mhc;mhcs +// +kubebuilder:subresource:status +// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/1032 +// +openshift:file-pattern=cvoRunLevel=0000_10,operatorName=machine-api,operatorOrdering=01 +// +openshift:capability=MachineAPI +// +kubebuilder:metadata:annotations="exclude.release.openshift.io/internal-openshift-hosted=true" +// +kubebuilder:metadata:annotations="include.release.openshift.io/self-managed-high-availability=true" +// +k8s:openapi-gen=true +// +kubebuilder:printcolumn:name="MaxUnhealthy",type="string",JSONPath=".spec.maxUnhealthy",description="Maximum number of unhealthy machines allowed" +// +kubebuilder:printcolumn:name="ExpectedMachines",type="integer",JSONPath=".status.expectedMachines",description="Number of machines currently monitored" +// +kubebuilder:printcolumn:name="CurrentHealthy",type="integer",JSONPath=".status.currentHealthy",description="Current observed healthy machines" +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type MachineHealthCheck struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Specification of machine health check policy + // +optional + Spec MachineHealthCheckSpec `json:"spec,omitempty"` + + // Most recently observed status of MachineHealthCheck resource + // +optional + Status MachineHealthCheckStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineHealthCheckList contains a list of MachineHealthCheck +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type MachineHealthCheckList struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard list's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ListMeta `json:"metadata,omitempty"` + + Items []MachineHealthCheck `json:"items"` +} + +// MachineHealthCheckSpec defines the desired state of MachineHealthCheck +type MachineHealthCheckSpec struct { + // Label selector to match machines whose health will be exercised. + // Note: An empty selector will match all machines. + Selector metav1.LabelSelector `json:"selector"` + + // unhealthyConditions contains a list of the conditions that determine + // whether a node is considered unhealthy. The conditions are combined in a + // logical OR, i.e. if any of the conditions is met, the node is unhealthy. + // + // +kubebuilder:validation:MinItems=1 + UnhealthyConditions []UnhealthyCondition `json:"unhealthyConditions"` + + // Any farther remediation is only allowed if at most "MaxUnhealthy" machines selected by + // "selector" are not healthy. + // Expects either a postive integer value or a percentage value. + // Percentage values must be positive whole numbers and are capped at 100%. + // Both 0 and 0% are valid and will block all remediation. + // Defaults to 100% if not set. + // +kubebuilder:default:="100%" + // +kubebuilder:validation:XIntOrString + // +kubebuilder:validation:Pattern="^((100|[0-9]{1,2})%|[0-9]+)$" + // +optional + MaxUnhealthy *intstr.IntOrString `json:"maxUnhealthy,omitempty"` + + // Machines older than this duration without a node will be considered to have + // failed and will be remediated. + // To prevent Machines without Nodes from being removed, disable startup checks + // by setting this value explicitly to "0". + // Expects an unsigned duration string of decimal numbers each with optional + // fraction and a unit suffix, eg "300ms", "1.5h" or "2h45m". + // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". + // +kubebuilder:default:="10m" + // +kubebuilder:validation:Pattern="^0|([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" + // +kubebuilder:validation:Type:=string + // +optional + NodeStartupTimeout *metav1.Duration `json:"nodeStartupTimeout,omitempty"` + + // remediationTemplate is a reference to a remediation template + // provided by an infrastructure provider. + // + // This field is completely optional, when filled, the MachineHealthCheck controller + // creates a new object from the template referenced and hands off remediation of the machine to + // a controller that lives outside of Machine API Operator. + // +optional + RemediationTemplate *corev1.ObjectReference `json:"remediationTemplate,omitempty"` +} + +// UnhealthyCondition represents a Node condition type and value with a timeout +// specified as a duration. When the named condition has been in the given +// status for at least the timeout value, a node is considered unhealthy. +type UnhealthyCondition struct { + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:MinLength=1 + Type corev1.NodeConditionType `json:"type"` + + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:MinLength=1 + Status corev1.ConditionStatus `json:"status"` + + // Expects an unsigned duration string of decimal numbers each with optional + // fraction and a unit suffix, eg "300ms", "1.5h" or "2h45m". + // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" + // +kubebuilder:validation:Type:=string + Timeout metav1.Duration `json:"timeout"` +} + +// MachineHealthCheckStatus defines the observed state of MachineHealthCheck +type MachineHealthCheckStatus struct { + // total number of machines counted by this machine health check + // +kubebuilder:validation:Minimum=0 + // +optional + ExpectedMachines *int `json:"expectedMachines"` + + // total number of machines counted by this machine health check + // +kubebuilder:validation:Minimum=0 + // +optional + CurrentHealthy *int `json:"currentHealthy"` + + // remediationsAllowed is the number of further remediations allowed by this machine health check before + // maxUnhealthy short circuiting will be applied + // +kubebuilder:validation:Minimum=0 + // +optional + RemediationsAllowed int32 `json:"remediationsAllowed"` + + // conditions defines the current state of the MachineHealthCheck + // +optional + // +listType=map + // +listMapKey=type + Conditions []Condition `json:"conditions,omitempty"` +} diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_machineset.go b/vendor/github.com/openshift/api/machine/v1beta1/types_machineset.go new file mode 100644 index 000000000..cbbe0b337 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_machineset.go @@ -0,0 +1,209 @@ +package v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineSet ensures that a specified number of machines replicas are running at any given time. +// +k8s:openapi-gen=true +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=machinesets,scope=Namespaced +// +kubebuilder:subresource:status +// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/1032 +// +openshift:file-pattern=cvoRunLevel=0000_10,operatorName=machine-api,operatorOrdering=01 +// +openshift:capability=MachineAPI +// +kubebuilder:metadata:annotations="exclude.release.openshift.io/internal-openshift-hosted=true" +// +kubebuilder:metadata:annotations="include.release.openshift.io/self-managed-high-availability=true" +// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.labelSelector +// +kubebuilder:printcolumn:name="Desired",type="integer",JSONPath=".spec.replicas",description="Desired Replicas" +// +kubebuilder:printcolumn:name="Current",type="integer",JSONPath=".status.replicas",description="Current Replicas" +// +kubebuilder:printcolumn:name="Ready",type="integer",JSONPath=".status.readyReplicas",description="Ready Replicas" +// +kubebuilder:printcolumn:name="Available",type="string",JSONPath=".status.availableReplicas",description="Observed number of available replicas" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Machineset age" +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type MachineSet struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec MachineSetSpec `json:"spec,omitempty"` + Status MachineSetStatus `json:"status,omitempty"` +} + +// MachineSetSpec defines the desired state of MachineSet +type MachineSetSpec struct { + // replicas is the number of desired replicas. + // This is a pointer to distinguish between explicit zero and unspecified. + // Defaults to 1. + // +kubebuilder:default=1 + Replicas *int32 `json:"replicas,omitempty"` + // minReadySeconds is the minimum number of seconds for which a newly created machine should be ready. + // Defaults to 0 (machine will be considered available as soon as it is ready) + // +optional + MinReadySeconds int32 `json:"minReadySeconds,omitempty"` + // deletePolicy defines the policy used to identify nodes to delete when downscaling. + // Defaults to "Random". Valid values are "Random, "Newest", "Oldest" + // +kubebuilder:validation:Enum=Random;Newest;Oldest + DeletePolicy string `json:"deletePolicy,omitempty"` + // selector is a label query over machines that should match the replica count. + // Label keys and values that must match in order to be controlled by this MachineSet. + // It must match the machine template's labels. + // More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors + Selector metav1.LabelSelector `json:"selector"` + // template is the object that describes the machine that will be created if + // insufficient replicas are detected. + // +optional + Template MachineTemplateSpec `json:"template,omitempty"` + + // authoritativeAPI is the API that is authoritative for this resource. + // Valid values are MachineAPI and ClusterAPI. + // When set to MachineAPI, writes to the spec of the machine.openshift.io copy of this resource will be reflected into the cluster.x-k8s.io copy. + // When set to ClusterAPI, writes to the spec of the cluster.x-k8s.io copy of this resource will be reflected into the machine.openshift.io copy. + // Updates to the status will be reflected in both copies of the resource, based on the controller implementing the functionality of the API. + // Currently the authoritative API determines which controller will manage the resource, this will change in a future release. + // To ensure the change has been accepted, please verify that the `status.authoritativeAPI` field has been updated to the desired value and that the `Synchronized` condition is present and set to `True`. + // +kubebuilder:validation:Enum=MachineAPI;ClusterAPI + // +kubebuilder:validation:Default=MachineAPI + // +default="MachineAPI" + // +openshift:enable:FeatureGate=MachineAPIMigration + // +optional + AuthoritativeAPI MachineAuthority `json:"authoritativeAPI,omitempty"` +} + +// MachineSetDeletePolicy defines how priority is assigned to nodes to delete when +// downscaling a MachineSet. Defaults to "Random". +type MachineSetDeletePolicy string + +const ( + // RandomMachineSetDeletePolicy prioritizes both Machines that have the annotation + // "cluster.k8s.io/delete-machine=yes" and Machines that are unhealthy + // (Status.ErrorReason or Status.ErrorMessage are set to a non-empty value). + // Finally, it picks Machines at random to delete. + RandomMachineSetDeletePolicy MachineSetDeletePolicy = "Random" + // NewestMachineSetDeletePolicy prioritizes both Machines that have the annotation + // "cluster.k8s.io/delete-machine=yes" and Machines that are unhealthy + // (Status.ErrorReason or Status.ErrorMessage are set to a non-empty value). + // It then prioritizes the newest Machines for deletion based on the Machine's CreationTimestamp. + NewestMachineSetDeletePolicy MachineSetDeletePolicy = "Newest" + // OldestMachineSetDeletePolicy prioritizes both Machines that have the annotation + // "cluster.k8s.io/delete-machine=yes" and Machines that are unhealthy + // (Status.ErrorReason or Status.ErrorMessage are set to a non-empty value). + // It then prioritizes the oldest Machines for deletion based on the Machine's CreationTimestamp. + OldestMachineSetDeletePolicy MachineSetDeletePolicy = "Oldest" +) + +// MachineTemplateSpec describes the data needed to create a Machine from a template +type MachineTemplateSpec struct { + // Standard object's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + // +optional + ObjectMeta `json:"metadata,omitempty"` + // Specification of the desired behavior of the machine. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status + // +optional + Spec MachineSpec `json:"spec,omitempty"` +} + +// MachineSetStatus defines the observed state of MachineSet +// +openshift:validation:FeatureGateAwareXValidation:featureGate=MachineAPIMigration,rule="!has(oldSelf.synchronizedGeneration) || (has(self.synchronizedGeneration) && self.synchronizedGeneration >= oldSelf.synchronizedGeneration) || (oldSelf.authoritativeAPI == 'Migrating' && self.authoritativeAPI != 'Migrating')",message="synchronizedGeneration must not decrease unless authoritativeAPI is transitioning from Migrating to another value" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=MachineAPIMigration,rule="has(self.authoritativeAPI) || !has(oldSelf.authoritativeAPI)",message="authoritativeAPI may not be removed once set" +type MachineSetStatus struct { + // replicas is the most recently observed number of replicas. + // +optional + Replicas int32 `json:"replicas"` + // The number of replicas that have labels matching the labels of the machine template of the MachineSet. + // +optional + FullyLabeledReplicas int32 `json:"fullyLabeledReplicas,omitempty"` + // The number of ready replicas for this MachineSet. A machine is considered ready when the node has been created and is "Ready". + // +optional + ReadyReplicas int32 `json:"readyReplicas,omitempty"` + // The number of available replicas (ready for at least minReadySeconds) for this MachineSet. + // +optional + AvailableReplicas int32 `json:"availableReplicas,omitempty"` + // observedGeneration reflects the generation of the most recently observed MachineSet. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // labelSelector is a label selector, in string format, for Machines corresponding to the MachineSet. + // It is exposed via the scale subresource as status.selector. + // When omitted, the MachineSet controller has not yet reconciled spec.selector into status.labelSelector. + // When present, it must not be empty and must not exceed 4096 characters. + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=4096 + // +optional + LabelSelector string `json:"labelSelector,omitempty"` + // In the event that there is a terminal problem reconciling the + // replicas, both ErrorReason and ErrorMessage will be set. ErrorReason + // will be populated with a succinct value suitable for machine + // interpretation, while ErrorMessage will contain a more verbose + // string suitable for logging and human consumption. + // + // These fields should not be set for transitive errors that a + // controller faces that are expected to be fixed automatically over + // time (like service outages), but instead indicate that something is + // fundamentally wrong with the MachineTemplate's spec or the configuration of + // the machine controller, and that manual intervention is required. Examples + // of terminal errors would be invalid combinations of settings in the + // spec, values that are unsupported by the machine controller, or the + // responsible machine controller itself being critically misconfigured. + // + // Any transient errors that occur during the reconciliation of Machines + // can be added as events to the MachineSet object and/or logged in the + // controller's output. + // +optional + ErrorReason *MachineSetStatusError `json:"errorReason,omitempty"` + // +optional + ErrorMessage *string `json:"errorMessage,omitempty"` + + // conditions defines the current state of the MachineSet + // +listType=map + // +listMapKey=type + // +optional + Conditions []Condition `json:"conditions,omitempty"` + + // authoritativeAPI is the API that is authoritative for this resource. + // Valid values are MachineAPI, ClusterAPI and Migrating. + // This value is updated by the migration controller to reflect the authoritative API. + // Machine API and Cluster API controllers use this value to determine whether or not to reconcile the resource. + // When set to Migrating, the migration controller is currently performing the handover of authority from one API to the other. + // +kubebuilder:validation:Enum=MachineAPI;ClusterAPI;Migrating + // +kubebuilder:validation:XValidation:rule="self == 'Migrating' || self == oldSelf || oldSelf == 'Migrating'",message="The authoritativeAPI field must not transition directly from MachineAPI to ClusterAPI or vice versa. It must transition through Migrating." + // +openshift:enable:FeatureGate=MachineAPIMigration + // +optional + AuthoritativeAPI MachineAuthority `json:"authoritativeAPI,omitempty"` + + // synchronizedAPI holds the last stable value of authoritativeAPI. + // It is used to detect migration cancellation requests and to restore the resource to its previous state. + // Valid values are "MachineAPI" and "ClusterAPI". + // When omitted, the resource has not yet been reconciled by the migration controller. + // +openshift:enable:FeatureGate=MachineAPIMigration + // +optional + SynchronizedAPI SynchronizedAPI `json:"synchronizedAPI,omitempty"` + + // synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with. + // This field is set when the authoritative resource is updated and the sync controller has updated the non-authoritative resource to match. + // +kubebuilder:validation:Minimum=0 + // +openshift:enable:FeatureGate=MachineAPIMigration + // +optional + SynchronizedGeneration int64 `json:"synchronizedGeneration,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// MachineSetList contains a list of MachineSet +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type MachineSetList struct { + metav1.TypeMeta `json:",inline"` + + // metadata is the standard list's metadata. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata + metav1.ListMeta `json:"metadata,omitempty"` + + Items []MachineSet `json:"items"` +} diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_provider.go b/vendor/github.com/openshift/api/machine/v1beta1/types_provider.go new file mode 100644 index 000000000..b67cb3243 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_provider.go @@ -0,0 +1,228 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// ProviderSpec defines the configuration to use during node creation. +type ProviderSpec struct { + + // No more than one of the following may be specified. + + // value is an inlined, serialized representation of the resource + // configuration. It is recommended that providers maintain their own + // versioned API types that should be serialized/deserialized from this + // field, akin to component config. + // +optional + // +kubebuilder:validation:XPreserveUnknownFields + Value *runtime.RawExtension `json:"value,omitempty"` +} + +// ObjectMeta is metadata that all persisted resources must have, which includes all objects +// users must create. This is a copy of customizable fields from metav1.ObjectMeta. +// +// ObjectMeta is embedded in `Machine.Spec`, `MachineDeployment.Template` and `MachineSet.Template`, +// which are not top-level Kubernetes objects. Given that metav1.ObjectMeta has lots of special cases +// and read-only fields which end up in the generated CRD validation, having it as a subset simplifies +// the API and some issues that can impact user experience. +// +// During the [upgrade to controller-tools@v2](https://github.com/kubernetes-sigs/cluster-api/pull/1054) +// for v1alpha2, we noticed a failure would occur running Cluster API test suite against the new CRDs, +// specifically `spec.metadata.creationTimestamp in body must be of type string: "null"`. +// The investigation showed that `controller-tools@v2` behaves differently than its previous version +// when handling types from [metav1](k8s.io/apimachinery/pkg/apis/meta/v1) package. +// +// In more details, we found that embedded (non-top level) types that embedded `metav1.ObjectMeta` +// had validation properties, including for `creationTimestamp` (metav1.Time). +// The `metav1.Time` type specifies a custom json marshaller that, when IsZero() is true, returns `null` +// which breaks validation because the field isn't marked as nullable. +// +// In future versions, controller-tools@v2 might allow overriding the type and validation for embedded +// types. When that happens, this hack should be revisited. +type ObjectMeta struct { + // name must be unique within a namespace. Is required when creating resources, although + // some resources may allow a client to request the generation of an appropriate name + // automatically. Name is primarily intended for creation idempotence and configuration + // definition. + // Cannot be updated. + // More info: http://kubernetes.io/docs/user-guide/identifiers#names + // +optional + Name string `json:"name,omitempty"` + + // generateName is an optional prefix, used by the server, to generate a unique + // name ONLY IF the Name field has not been provided. + // If this field is used, the name returned to the client will be different + // than the name passed. This value will also be combined with a unique suffix. + // The provided value has the same validation rules as the Name field, + // and may be truncated by the length of the suffix required to make the value + // unique on the server. + // + // If this field is specified and the generated name exists, the server will + // NOT return a 409 - instead, it will either return 201 Created or 500 with Reason + // ServerTimeout indicating a unique name could not be found in the time allotted, and the client + // should retry (optionally after the time indicated in the Retry-After header). + // + // Applied only if Name is not specified. + // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency + // +optional + GenerateName string `json:"generateName,omitempty"` + + // namespace defines the space within each name must be unique. An empty namespace is + // equivalent to the "default" namespace, but "default" is the canonical representation. + // Not all objects are required to be scoped to a namespace - the value of this field for + // those objects will be empty. + // + // Must be a DNS_LABEL. + // Cannot be updated. + // More info: http://kubernetes.io/docs/user-guide/namespaces + // +optional + Namespace string `json:"namespace,omitempty"` + + // Map of string keys and values that can be used to organize and categorize + // (scope and select) objects. May match selectors of replication controllers + // and services. + // More info: http://kubernetes.io/docs/user-guide/labels + // +optional + Labels map[string]string `json:"labels,omitempty"` + + // annotations is an unstructured key value map stored with a resource that may be + // set by external tools to store and retrieve arbitrary metadata. They are not + // queryable and should be preserved when modifying objects. + // More info: http://kubernetes.io/docs/user-guide/annotations + // +optional + Annotations map[string]string `json:"annotations,omitempty"` + + // List of objects depended by this object. If ALL objects in the list have + // been deleted, this object will be garbage collected. If this object is managed by a controller, + // then an entry in this list will point to this controller, with the controller field set to true. + // There cannot be more than one managing controller. + // +optional + // +patchMergeKey=uid + // +patchStrategy=merge + // +listType=map + // +listMapKey=uid + OwnerReferences []metav1.OwnerReference `json:"ownerReferences,omitempty" patchStrategy:"merge" patchMergeKey:"uid"` +} + +// ConditionSeverity expresses the severity of a Condition Type failing. +type ConditionSeverity string + +const ( + // ConditionSeverityError specifies that a condition with `Status=False` is an error. + ConditionSeverityError ConditionSeverity = "Error" + + // ConditionSeverityWarning specifies that a condition with `Status=False` is a warning. + ConditionSeverityWarning ConditionSeverity = "Warning" + + // ConditionSeverityInfo specifies that a condition with `Status=False` is informative. + ConditionSeverityInfo ConditionSeverity = "Info" + + // ConditionSeverityNone should apply only to conditions with `Status=True`. + ConditionSeverityNone ConditionSeverity = "" +) + +// ConditionType is a valid value for Condition.Type. +type ConditionType string + +// Valid conditions for a machine. +const ( + // MachineCreated indicates whether the machine has been created or not. If not, + // it should include a reason and message for the failure. + // NOTE: MachineCreation is here for historical reasons, MachineCreated should be used instead + MachineCreation ConditionType = "MachineCreation" + // MachineCreated indicates whether the machine has been created or not. If not, + // it should include a reason and message for the failure. + MachineCreated ConditionType = "MachineCreated" + // InstanceExistsCondition is set on the Machine to show whether a virtual mahcine has been created by the cloud provider. + InstanceExistsCondition ConditionType = "InstanceExists" + // RemediationAllowedCondition is set on MachineHealthChecks to show the status of whether the MachineHealthCheck is + // allowed to remediate any Machines or whether it is blocked from remediating any further. + RemediationAllowedCondition ConditionType = "RemediationAllowed" + // ExternalRemediationTemplateAvailable is set on machinehealthchecks when MachineHealthCheck controller uses external remediation. + // ExternalRemediationTemplateAvailable is set to false if external remediation template is not found. + ExternalRemediationTemplateAvailable ConditionType = "ExternalRemediationTemplateAvailable" + // ExternalRemediationRequestAvailable is set on machinehealthchecks when MachineHealthCheck controller uses external remediation. + // ExternalRemediationRequestAvailable is set to false if creating external remediation request fails. + ExternalRemediationRequestAvailable ConditionType = "ExternalRemediationRequestAvailable" + // MachineDrained is set on a machine to indicate that the machine has been drained. When an error occurs during + // the drain process, the condition will be added with a false status and details of the error. + MachineDrained ConditionType = "Drained" + // MachineDrainable is set on a machine to indicate whether or not the machine can be drained, or, whether some + // deletion hook is blocking the drain operation. + MachineDrainable ConditionType = "Drainable" + // MachineTerminable is set on a machine to indicate whether or not the machine can be terminated, or, whether some + // deletion hook is blocking the termination operation. + MachineTerminable ConditionType = "Terminable" + // IPAddressClaimedCondition is set to indicate that a machine has a claimed an IP address. + IPAddressClaimedCondition ConditionType = "IPAddressClaimed" +) + +const ( + // MachineCreationSucceeded indicates machine creation success. + MachineCreationSucceededConditionReason string = "MachineCreationSucceeded" + // MachineCreationFailed indicates machine creation failure. + MachineCreationFailedConditionReason string = "MachineCreationFailed" + // ErrorCheckingProviderReason is the reason used when the exist operation fails. + // This would normally be because we cannot contact the provider. + ErrorCheckingProviderReason = "ErrorCheckingProvider" + // InstanceMissingReason is the reason used when the machine was provisioned, but the instance has gone missing. + InstanceMissingReason = "InstanceMissing" + // InstanceNotCreatedReason is the reason used when the machine has not yet been provisioned. + InstanceNotCreatedReason = "InstanceNotCreated" + // TooManyUnhealthy is the reason used when too many Machines are unhealthy and the MachineHealthCheck is blocked + // from making any further remediations. + TooManyUnhealthyReason = "TooManyUnhealthy" + // ExternalRemediationTemplateNotFound is the reason used when a machine health check fails to find external remediation template. + ExternalRemediationTemplateNotFound = "ExternalRemediationTemplateNotFound" + // ExternalRemediationRequestCreationFailed is the reason used when a machine health check fails to create external remediation request. + ExternalRemediationRequestCreationFailed = "ExternalRemediationRequestCreationFailed" + // MachineHookPresent indicates that a machine lifecycle hook is blocking part of the lifecycle of the machine. + // This should be used with the `Drainable` and `Terminable` machine condition types. + MachineHookPresent = "HookPresent" + // MachineDrainError indicates an error occurred when draining the machine. + // This should be used with the `Drained` condition type. + MachineDrainError = "DrainError" + // WaitingForIPAddressReason is set to indicate that a machine is + // currently waiting for an IP address to be provisioned. + WaitingForIPAddressReason string = "WaitingForIPAddress" + // IPAddressClaimedReason is set to indicate the machine was able to claim an IP address during provisioning. + IPAddressClaimedReason string = "IPAddressesClaimed" +) + +// Condition defines an observation of a Machine API resource operational state. +type Condition struct { + // type of condition in CamelCase or in foo.example.com/CamelCase. + // Many .condition.type values are consistent across resources like Available, but because arbitrary conditions + // can be useful (see .node.status.conditions), the ability to deconflict is important. + // +required + Type ConditionType `json:"type"` + + // status of the condition, one of True, False, Unknown. + // +required + Status corev1.ConditionStatus `json:"status"` + + // severity provides an explicit classification of Reason code, so the users or machines can immediately + // understand the current situation and act accordingly. + // The Severity field MUST be set only when Status=False. + // +optional + Severity ConditionSeverity `json:"severity,omitempty"` + + // 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. + // +required + LastTransitionTime metav1.Time `json:"lastTransitionTime"` + + // The reason for the condition's last transition in CamelCase. + // The specific API may choose whether or not this field is considered a guaranteed API. + // This field may not be empty. + // +optional + Reason string `json:"reason,omitempty"` + + // A human readable message indicating details about the transition. + // This field may be empty. + // +optional + Message string `json:"message,omitempty"` +} diff --git a/vendor/github.com/openshift/api/machine/v1beta1/types_vsphereprovider.go b/vendor/github.com/openshift/api/machine/v1beta1/types_vsphereprovider.go new file mode 100644 index 000000000..fe6626f72 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/types_vsphereprovider.go @@ -0,0 +1,277 @@ +package v1beta1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// VSphereMachineProviderSpec is the type that will be embedded in a Machine.Spec.ProviderSpec field +// for an VSphere virtual machine. It is used by the vSphere machine actuator to create a single Machine. +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type VSphereMachineProviderSpec struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + // userDataSecret contains a local reference to a secret that contains the + // UserData to apply to the instance + // +optional + UserDataSecret *corev1.LocalObjectReference `json:"userDataSecret,omitempty"` + // credentialsSecret is a reference to the secret with vSphere credentials. + // +optional + CredentialsSecret *corev1.LocalObjectReference `json:"credentialsSecret,omitempty"` + // template is the name, inventory path, or instance UUID of the template + // used to clone new machines. + Template string `json:"template"` + // workspace describes the workspace to use for the machine. + // +optional + Workspace *Workspace `json:"workspace,omitempty"` + // network is the network configuration for this machine's VM. + Network NetworkSpec `json:"network"` + // numCPUs is the number of virtual processors in a virtual machine. + // Defaults to the analogue property value in the template from which this + // machine is cloned. + // +optional + NumCPUs int32 `json:"numCPUs,omitempty"` + // NumCPUs is the number of cores among which to distribute CPUs in this + // virtual machine. + // Defaults to the analogue property value in the template from which this + // machine is cloned. + // +optional + NumCoresPerSocket int32 `json:"numCoresPerSocket,omitempty"` + // memoryMiB is the size of a virtual machine's memory, in MiB. + // Defaults to the analogue property value in the template from which this + // machine is cloned. + // +optional + MemoryMiB int64 `json:"memoryMiB,omitempty"` + // diskGiB is the size of a virtual machine's disk, in GiB. + // Defaults to the analogue property value in the template from which this + // machine is cloned. + // This parameter will be ignored if 'LinkedClone' CloneMode is set. + // +optional + DiskGiB int32 `json:"diskGiB,omitempty"` + // tagIDs is an optional set of tags to add to an instance. Specified tagIDs + // must use URN-notation instead of display names. A maximum of 10 tag IDs may be specified. + // +kubebuilder:validation:Pattern="^(urn):(vmomi):(InventoryServiceTag):([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}):([^:]+)$" + // +kubebuilder:example="urn:vmomi:InventoryServiceTag:5736bf56-49f5-4667-b38c-b97e09dc9578:GLOBAL" + // +optional + TagIDs []string `json:"tagIDs,omitempty"` + // snapshot is the name of the snapshot from which the VM was cloned + // +optional + Snapshot string `json:"snapshot"` + // cloneMode specifies the type of clone operation. + // The LinkedClone mode is only support for templates that have at least + // one snapshot. If the template has no snapshots, then CloneMode defaults + // to FullClone. + // When LinkedClone mode is enabled the DiskGiB field is ignored as it is + // not possible to expand disks of linked clones. + // Defaults to FullClone. + // When using LinkedClone, if no snapshots exist for the source template, falls back to FullClone. + // +optional + CloneMode CloneMode `json:"cloneMode,omitempty"` + // dataDisks is a list of non OS disks to be created and attached to the VM. The max number of disk allowed to be attached is + // currently 29. The max number of disks for any controller is 30, but VM template will always have OS disk so that will leave + // 29 disks on any controller type. + // +openshift:enable:FeatureGate=VSphereMultiDisk + // +optional + // +listType=map + // +listMapKey=name + // +kubebuilder:validation:MaxItems=29 + DataDisks []VSphereDisk `json:"dataDisks,omitempty"` +} + +// CloneMode is the type of clone operation used to clone a VM from a template. +type CloneMode string + +const ( + // FullClone indicates a VM will have no relationship to the source of the + // clone operation once the operation is complete. This is the safest clone + // mode, but it is not the fastest. + FullClone CloneMode = "fullClone" + // LinkedClone means resulting VMs will be dependent upon the snapshot of + // the source VM/template from which the VM was cloned. This is the fastest + // clone mode, but it also prevents expanding a VMs disk beyond the size of + // the source VM/template. + LinkedClone CloneMode = "linkedClone" +) + +// NetworkSpec defines the virtual machine's network configuration. +type NetworkSpec struct { + // devices defines the virtual machine's network interfaces. + Devices []NetworkDeviceSpec `json:"devices"` +} + +// AddressesFromPool is an IPAddressPool that will be used to create +// IPAddressClaims for fulfillment by an external controller. +type AddressesFromPool struct { + // group of the IP address pool type known to an external IPAM controller. + // This should be a fully qualified domain name, for example, externalipam.controller.io. + // +kubebuilder:example=externalipam.controller.io + // +kubebuilder:validation:Pattern="^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?(.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$" + // +required + Group string `json:"group"` + // resource of the IP address pool type known to an external IPAM controller. + // It is normally the plural form of the resource kind in lowercase, for example, + // ippools. + // +kubebuilder:example=ippools + // +kubebuilder:validation:Pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + // +required + Resource string `json:"resource"` + // name of an IP address pool, for example, pool-config-1. + // +kubebuilder:example=pool-config-1 + // +kubebuilder:validation:Pattern="^[a-z0-9]([-a-z0-9]*[a-z0-9])?$" + // +required + Name string `json:"name"` +} + +// NetworkDeviceSpec defines the network configuration for a virtual machine's +// network device. +type NetworkDeviceSpec struct { + // networkName is the name of the vSphere network or port group to which the network + // device will be connected, for example, port-group-1. When not provided, the vCenter + // API will attempt to select a default network. + // The available networks (port groups) can be listed using `govc ls 'network/*'` + // +kubebuilder:example=port-group-1 + // +kubebuilder:validation:MaxLength=80 + // +optional + NetworkName string `json:"networkName,omitempty"` + + // gateway is an IPv4 or IPv6 address which represents the subnet gateway, + // for example, 192.168.1.1. + // +kubebuilder:validation:Format=ipv4 + // +kubebuilder:validation:Format=ipv6 + // +kubebuilder:example="192.168.1.1" + // +kubebuilder:example="2001:DB8:0000:0000:244:17FF:FEB6:D37D" + // +optional + Gateway string `json:"gateway,omitempty"` + + // ipAddrs is a list of one or more IPv4 and/or IPv6 addresses and CIDR to assign to + // this device, for example, 192.168.1.100/24. IP addresses provided via ipAddrs are + // intended to allow explicit assignment of a machine's IP address. IP pool configurations + // provided via addressesFromPool, however, defer IP address assignment to an external controller. + // If both addressesFromPool and ipAddrs are empty or not defined, DHCP will be used to assign + // an IP address. If both ipAddrs and addressesFromPools are defined, the IP addresses associated with + // ipAddrs will be applied first followed by IP addresses from addressesFromPools. + // +kubebuilder:validation:Format=ipv4 + // +kubebuilder:validation:Format=ipv6 + // +kubebuilder:example="192.168.1.100/24" + // +kubebuilder:example="2001:DB8:0000:0000:244:17FF:FEB6:D37D/64" + // +optional + IPAddrs []string `json:"ipAddrs,omitempty"` + + // nameservers is a list of IPv4 and/or IPv6 addresses used as DNS nameservers, for example, + // 8.8.8.8. a nameserver is not provided by a fulfilled IPAddressClaim. If DHCP is not the + // source of IP addresses for this network device, nameservers should include a valid nameserver. + // +kubebuilder:validation:Format=ipv4 + // +kubebuilder:validation:Format=ipv6 + // +kubebuilder:example="8.8.8.8" + // +optional + Nameservers []string `json:"nameservers,omitempty"` + + // addressesFromPools is a list of references to IP pool types and instances which are handled + // by an external controller. addressesFromPool configurations provided via addressesFromPools + // defer IP address assignment to an external controller. IP addresses provided via ipAddrs, + // however, are intended to allow explicit assignment of a machine's IP address. If both + // addressesFromPool and ipAddrs are empty or not defined, DHCP will assign an IP address. + // If both ipAddrs and addressesFromPools are defined, the IP addresses associated with + // ipAddrs will be applied first followed by IP addresses from addressesFromPools. + // +kubebuilder:validation:Format=ipv4 + // +optional + AddressesFromPools []AddressesFromPool `json:"addressesFromPools,omitempty"` +} + +// VSphereDisk describes additional disks for vSphere. +type VSphereDisk struct { + // name is used to identify the disk definition. name is required needs to be unique so that it can be used to + // clearly identify purpose of the disk. + // It must be at most 80 characters in length and must consist only of alphanumeric characters, hyphens and underscores, + // and must start and end with an alphanumeric character. + // +kubebuilder:example=images_1 + // +kubebuilder:validation:MaxLength=80 + // +kubebuilder:validation:Pattern="^[a-zA-Z0-9]([-_a-zA-Z0-9]*[a-zA-Z0-9])?$" + // +required + Name string `json:"name"` + // sizeGiB is the size of the disk in GiB. + // The maximum supported size 16384 GiB. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=16384 + // +required + SizeGiB int32 `json:"sizeGiB"` + // provisioningMode is an optional field that specifies the provisioning type to be used by this vSphere data disk. + // Allowed values are "Thin", "Thick", "EagerlyZeroed", and omitted. + // When set to Thin, the disk will be made using thin provisioning allocating the bare minimum space. + // When set to Thick, the full disk size will be allocated when disk is created. + // When set to EagerlyZeroed, the disk will be created using eager zero provisioning. An eager zeroed thick disk has all space allocated and wiped clean of any previous contents on the physical media at creation time. Such disks may take longer time during creation compared to other disk formats. + // When omitted, no setting will be applied to the data disk and the provisioning mode for the disk will be determined by the default storage policy configured for the datastore in vSphere. + // +optional + ProvisioningMode ProvisioningMode `json:"provisioningMode,omitempty"` +} + +// provisioningMode represents the various provisioning types available to a VMs disk. +// +kubebuilder:validation:Enum=Thin;Thick;EagerlyZeroed +type ProvisioningMode string + +const ( + // ProvisioningModeThin creates the disk using thin provisioning. This means a sparse (allocate on demand) + // format with additional space optimizations. + ProvisioningModeThin ProvisioningMode = "Thin" + + // ProvisioningModeThick creates the disk with all space allocated. + ProvisioningModeThick ProvisioningMode = "Thick" + + // ProvisioningModeEagerlyZeroed creates the disk using eager zero provisioning. An eager zeroed thick disk + // has all space allocated and wiped clean of any previous contents on the physical media at + // creation time. Such disks may take longer time during creation compared to other disk formats. + ProvisioningModeEagerlyZeroed ProvisioningMode = "EagerlyZeroed" +) + +// WorkspaceConfig defines a workspace configuration for the vSphere cloud +// provider. +type Workspace struct { + // server is the IP address or FQDN of the vSphere endpoint. + // +optional + Server string `gcfg:"server,omitempty" json:"server,omitempty"` + // datacenter is the datacenter in which VMs are created/located. + // +optional + Datacenter string `gcfg:"datacenter,omitempty" json:"datacenter,omitempty"` + // folder is the folder in which VMs are created/located. + // +optional + Folder string `gcfg:"folder,omitempty" json:"folder,omitempty"` + // datastore is the datastore in which VMs are created/located. + // +optional + Datastore string `gcfg:"default-datastore,omitempty" json:"datastore,omitempty"` + // resourcePool is the resource pool in which VMs are created/located. + // +optional + ResourcePool string `gcfg:"resourcepool-path,omitempty" json:"resourcePool,omitempty"` + // vmGroup is the cluster vm group in which virtual machines will be added for vm host group based zonal. + // +openshift:validation:featureGate=VSphereHostVMGroupZonal + // +optional + VMGroup string `gcfg:"vmGroup,omitempty" json:"vmGroup,omitempty"` +} + +// VSphereMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. +// It contains VSphere-specific status information. +// Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer). +// +openshift:compatibility-gen:level=2 +type VSphereMachineProviderStatus struct { + metav1.TypeMeta `json:",inline"` + + // instanceId is the ID of the instance in VSphere + // +optional + InstanceID *string `json:"instanceId,omitempty"` + // instanceState is the provisioning state of the VSphere Instance. + // +optional + InstanceState *string `json:"instanceState,omitempty"` + // conditions is a set of conditions associated with the Machine to indicate + // errors or other status + // +listType=map + // +listMapKey=type + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + // taskRef is a managed object reference to a Task related to the machine. + // This value is set automatically at runtime and should not be set or + // modified by users. + // +optional + TaskRef string `json:"taskRef,omitempty"` +} 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 new file mode 100644 index 000000000..63b9bb5ff --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,2032 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by codegen. DO NOT EDIT. + +package v1beta1 + +import ( + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + intstr "k8s.io/apimachinery/pkg/util/intstr" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSMachineProviderConfig) DeepCopyInto(out *AWSMachineProviderConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.AMI.DeepCopyInto(&out.AMI) + if in.CPUOptions != nil { + in, out := &in.CPUOptions, &out.CPUOptions + *out = new(CPUOptions) + (*in).DeepCopyInto(*out) + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]TagSpecification, len(*in)) + copy(*out, *in) + } + if in.IAMInstanceProfile != nil { + in, out := &in.IAMInstanceProfile, &out.IAMInstanceProfile + *out = new(AWSResourceReference) + (*in).DeepCopyInto(*out) + } + if in.UserDataSecret != nil { + in, out := &in.UserDataSecret, &out.UserDataSecret + *out = new(v1.LocalObjectReference) + **out = **in + } + if in.CredentialsSecret != nil { + in, out := &in.CredentialsSecret, &out.CredentialsSecret + *out = new(v1.LocalObjectReference) + **out = **in + } + if in.KeyName != nil { + in, out := &in.KeyName, &out.KeyName + *out = new(string) + **out = **in + } + if in.PublicIP != nil { + in, out := &in.PublicIP, &out.PublicIP + *out = new(bool) + **out = **in + } + if in.SecurityGroups != nil { + in, out := &in.SecurityGroups, &out.SecurityGroups + *out = make([]AWSResourceReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Subnet.DeepCopyInto(&out.Subnet) + in.Placement.DeepCopyInto(&out.Placement) + if in.LoadBalancers != nil { + in, out := &in.LoadBalancers, &out.LoadBalancers + *out = make([]LoadBalancerReference, len(*in)) + copy(*out, *in) + } + if in.BlockDevices != nil { + in, out := &in.BlockDevices, &out.BlockDevices + *out = make([]BlockDeviceMappingSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.SpotMarketOptions != nil { + in, out := &in.SpotMarketOptions, &out.SpotMarketOptions + *out = new(SpotMarketOptions) + (*in).DeepCopyInto(*out) + } + out.MetadataServiceOptions = in.MetadataServiceOptions + if in.PlacementGroupPartition != nil { + in, out := &in.PlacementGroupPartition, &out.PlacementGroupPartition + *out = new(int32) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSMachineProviderConfig. +func (in *AWSMachineProviderConfig) DeepCopy() *AWSMachineProviderConfig { + if in == nil { + return nil + } + out := new(AWSMachineProviderConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AWSMachineProviderConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSMachineProviderConfigList) DeepCopyInto(out *AWSMachineProviderConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AWSMachineProviderConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSMachineProviderConfigList. +func (in *AWSMachineProviderConfigList) DeepCopy() *AWSMachineProviderConfigList { + if in == nil { + return nil + } + out := new(AWSMachineProviderConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSMachineProviderStatus) DeepCopyInto(out *AWSMachineProviderStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.InstanceID != nil { + in, out := &in.InstanceID, &out.InstanceID + *out = new(string) + **out = **in + } + if in.InstanceState != nil { + in, out := &in.InstanceState, &out.InstanceState + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.DedicatedHost != nil { + in, out := &in.DedicatedHost, &out.DedicatedHost + *out = new(DedicatedHostStatus) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSMachineProviderStatus. +func (in *AWSMachineProviderStatus) DeepCopy() *AWSMachineProviderStatus { + if in == nil { + return nil + } + out := new(AWSMachineProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSResourceReference) DeepCopyInto(out *AWSResourceReference) { + *out = *in + if in.ID != nil { + in, out := &in.ID, &out.ID + *out = new(string) + **out = **in + } + if in.ARN != nil { + in, out := &in.ARN, &out.ARN + *out = new(string) + **out = **in + } + if in.Filters != nil { + in, out := &in.Filters, &out.Filters + *out = make([]Filter, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSResourceReference. +func (in *AWSResourceReference) DeepCopy() *AWSResourceReference { + if in == nil { + return nil + } + out := new(AWSResourceReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AddressesFromPool) DeepCopyInto(out *AddressesFromPool) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddressesFromPool. +func (in *AddressesFromPool) DeepCopy() *AddressesFromPool { + if in == nil { + return nil + } + out := new(AddressesFromPool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AzureBootDiagnostics) DeepCopyInto(out *AzureBootDiagnostics) { + *out = *in + if in.CustomerManaged != nil { + in, out := &in.CustomerManaged, &out.CustomerManaged + *out = new(AzureCustomerManagedBootDiagnostics) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureBootDiagnostics. +func (in *AzureBootDiagnostics) DeepCopy() *AzureBootDiagnostics { + if in == nil { + return nil + } + out := new(AzureBootDiagnostics) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AzureCustomerManagedBootDiagnostics) DeepCopyInto(out *AzureCustomerManagedBootDiagnostics) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureCustomerManagedBootDiagnostics. +func (in *AzureCustomerManagedBootDiagnostics) DeepCopy() *AzureCustomerManagedBootDiagnostics { + if in == nil { + return nil + } + out := new(AzureCustomerManagedBootDiagnostics) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AzureDiagnostics) DeepCopyInto(out *AzureDiagnostics) { + *out = *in + if in.Boot != nil { + in, out := &in.Boot, &out.Boot + *out = new(AzureBootDiagnostics) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureDiagnostics. +func (in *AzureDiagnostics) DeepCopy() *AzureDiagnostics { + if in == nil { + return nil + } + out := new(AzureDiagnostics) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AzureMachineProviderSpec) DeepCopyInto(out *AzureMachineProviderSpec) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.UserDataSecret != nil { + in, out := &in.UserDataSecret, &out.UserDataSecret + *out = new(v1.SecretReference) + **out = **in + } + if in.CredentialsSecret != nil { + in, out := &in.CredentialsSecret, &out.CredentialsSecret + *out = new(v1.SecretReference) + **out = **in + } + out.Image = in.Image + in.OSDisk.DeepCopyInto(&out.OSDisk) + if in.DataDisks != nil { + in, out := &in.DataDisks, &out.DataDisks + *out = make([]DataDisk, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.ApplicationSecurityGroups != nil { + in, out := &in.ApplicationSecurityGroups, &out.ApplicationSecurityGroups + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.NatRule != nil { + in, out := &in.NatRule, &out.NatRule + *out = new(int64) + **out = **in + } + if in.SpotVMOptions != nil { + in, out := &in.SpotVMOptions, &out.SpotVMOptions + *out = new(SpotVMOptions) + (*in).DeepCopyInto(*out) + } + if in.SecurityProfile != nil { + in, out := &in.SecurityProfile, &out.SecurityProfile + *out = new(SecurityProfile) + (*in).DeepCopyInto(*out) + } + in.Diagnostics.DeepCopyInto(&out.Diagnostics) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureMachineProviderSpec. +func (in *AzureMachineProviderSpec) DeepCopy() *AzureMachineProviderSpec { + if in == nil { + return nil + } + out := new(AzureMachineProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *AzureMachineProviderSpec) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AzureMachineProviderStatus) DeepCopyInto(out *AzureMachineProviderStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.VMID != nil { + in, out := &in.VMID, &out.VMID + *out = new(string) + **out = **in + } + if in.VMState != nil { + in, out := &in.VMState, &out.VMState + *out = new(AzureVMState) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AzureMachineProviderStatus. +func (in *AzureMachineProviderStatus) DeepCopy() *AzureMachineProviderStatus { + if in == nil { + return nil + } + out := new(AzureMachineProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BlockDeviceMappingSpec) DeepCopyInto(out *BlockDeviceMappingSpec) { + *out = *in + if in.DeviceName != nil { + in, out := &in.DeviceName, &out.DeviceName + *out = new(string) + **out = **in + } + if in.EBS != nil { + in, out := &in.EBS, &out.EBS + *out = new(EBSBlockDeviceSpec) + (*in).DeepCopyInto(*out) + } + if in.NoDevice != nil { + in, out := &in.NoDevice, &out.NoDevice + *out = new(string) + **out = **in + } + if in.VirtualName != nil { + in, out := &in.VirtualName, &out.VirtualName + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BlockDeviceMappingSpec. +func (in *BlockDeviceMappingSpec) DeepCopy() *BlockDeviceMappingSpec { + if in == nil { + return nil + } + out := new(BlockDeviceMappingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CPUOptions) DeepCopyInto(out *CPUOptions) { + *out = *in + if in.ConfidentialCompute != nil { + in, out := &in.ConfidentialCompute, &out.ConfidentialCompute + *out = new(AWSConfidentialComputePolicy) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPUOptions. +func (in *CPUOptions) DeepCopy() *CPUOptions { + if in == nil { + return nil + } + out := new(CPUOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Condition) DeepCopyInto(out *Condition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. +func (in *Condition) DeepCopy() *Condition { + if in == nil { + return nil + } + out := new(Condition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfidentialVM) DeepCopyInto(out *ConfidentialVM) { + *out = *in + out.UEFISettings = in.UEFISettings + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfidentialVM. +func (in *ConfidentialVM) DeepCopy() *ConfidentialVM { + if in == nil { + return nil + } + out := new(ConfidentialVM) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataDisk) DeepCopyInto(out *DataDisk) { + *out = *in + in.ManagedDisk.DeepCopyInto(&out.ManagedDisk) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataDisk. +func (in *DataDisk) DeepCopy() *DataDisk { + if in == nil { + return nil + } + out := new(DataDisk) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DataDiskManagedDiskParameters) DeepCopyInto(out *DataDiskManagedDiskParameters) { + *out = *in + if in.DiskEncryptionSet != nil { + in, out := &in.DiskEncryptionSet, &out.DiskEncryptionSet + *out = new(DiskEncryptionSetParameters) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataDiskManagedDiskParameters. +func (in *DataDiskManagedDiskParameters) DeepCopy() *DataDiskManagedDiskParameters { + if in == nil { + return nil + } + out := new(DataDiskManagedDiskParameters) + in.DeepCopyInto(out) + 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 + if in.AllocationStrategy != nil { + in, out := &in.AllocationStrategy, &out.AllocationStrategy + *out = new(AllocationStrategy) + **out = **in + } + if in.DynamicHostAllocation != nil { + in, out := &in.DynamicHostAllocation, &out.DynamicHostAllocation + *out = new(DynamicHostAllocationSpec) + (*in).DeepCopyInto(*out) + } + 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 *DedicatedHostStatus) DeepCopyInto(out *DedicatedHostStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DedicatedHostStatus. +func (in *DedicatedHostStatus) DeepCopy() *DedicatedHostStatus { + if in == nil { + return nil + } + out := new(DedicatedHostStatus) + 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 + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskEncryptionSetParameters. +func (in *DiskEncryptionSetParameters) DeepCopy() *DiskEncryptionSetParameters { + if in == nil { + return nil + } + out := new(DiskEncryptionSetParameters) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DiskSettings) DeepCopyInto(out *DiskSettings) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DiskSettings. +func (in *DiskSettings) DeepCopy() *DiskSettings { + if in == nil { + return nil + } + out := new(DiskSettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DynamicHostAllocationSpec) DeepCopyInto(out *DynamicHostAllocationSpec) { + *out = *in + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = new([]TagSpecification) + if **in != nil { + in, out := *in, *out + *out = make([]TagSpecification, len(*in)) + copy(*out, *in) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DynamicHostAllocationSpec. +func (in *DynamicHostAllocationSpec) DeepCopy() *DynamicHostAllocationSpec { + if in == nil { + return nil + } + out := new(DynamicHostAllocationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EBSBlockDeviceSpec) DeepCopyInto(out *EBSBlockDeviceSpec) { + *out = *in + if in.DeprecatedDeleteOnTermination != nil { + in, out := &in.DeprecatedDeleteOnTermination, &out.DeprecatedDeleteOnTermination + *out = new(bool) + **out = **in + } + if in.Encrypted != nil { + in, out := &in.Encrypted, &out.Encrypted + *out = new(bool) + **out = **in + } + in.KMSKey.DeepCopyInto(&out.KMSKey) + if in.Iops != nil { + in, out := &in.Iops, &out.Iops + *out = new(int64) + **out = **in + } + if in.ThroughputMib != nil { + in, out := &in.ThroughputMib, &out.ThroughputMib + *out = new(int32) + **out = **in + } + if in.VolumeSize != nil { + in, out := &in.VolumeSize, &out.VolumeSize + *out = new(int64) + **out = **in + } + if in.VolumeType != nil { + in, out := &in.VolumeType, &out.VolumeType + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EBSBlockDeviceSpec. +func (in *EBSBlockDeviceSpec) DeepCopy() *EBSBlockDeviceSpec { + if in == nil { + return nil + } + out := new(EBSBlockDeviceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Filter) DeepCopyInto(out *Filter) { + *out = *in + if in.Values != nil { + in, out := &in.Values, &out.Values + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Filter. +func (in *Filter) DeepCopy() *Filter { + if in == nil { + return nil + } + out := new(Filter) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPDisk) DeepCopyInto(out *GCPDisk) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.EncryptionKey != nil { + in, out := &in.EncryptionKey, &out.EncryptionKey + *out = new(GCPEncryptionKeyReference) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPDisk. +func (in *GCPDisk) DeepCopy() *GCPDisk { + if in == nil { + return nil + } + out := new(GCPDisk) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPEncryptionKeyReference) DeepCopyInto(out *GCPEncryptionKeyReference) { + *out = *in + if in.KMSKey != nil { + in, out := &in.KMSKey, &out.KMSKey + *out = new(GCPKMSKeyReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPEncryptionKeyReference. +func (in *GCPEncryptionKeyReference) DeepCopy() *GCPEncryptionKeyReference { + if in == nil { + return nil + } + out := new(GCPEncryptionKeyReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPGPUConfig) DeepCopyInto(out *GCPGPUConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPGPUConfig. +func (in *GCPGPUConfig) DeepCopy() *GCPGPUConfig { + if in == nil { + return nil + } + out := new(GCPGPUConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPKMSKeyReference) DeepCopyInto(out *GCPKMSKeyReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPKMSKeyReference. +func (in *GCPKMSKeyReference) DeepCopy() *GCPKMSKeyReference { + if in == nil { + return nil + } + out := new(GCPKMSKeyReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPMachineProviderSpec) DeepCopyInto(out *GCPMachineProviderSpec) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.UserDataSecret != nil { + in, out := &in.UserDataSecret, &out.UserDataSecret + *out = new(v1.LocalObjectReference) + **out = **in + } + if in.CredentialsSecret != nil { + in, out := &in.CredentialsSecret, &out.CredentialsSecret + *out = new(v1.LocalObjectReference) + **out = **in + } + if in.Disks != nil { + in, out := &in.Disks, &out.Disks + *out = make([]*GCPDisk, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(GCPDisk) + (*in).DeepCopyInto(*out) + } + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Metadata != nil { + in, out := &in.Metadata, &out.Metadata + *out = make([]*GCPMetadata, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(GCPMetadata) + (*in).DeepCopyInto(*out) + } + } + } + if in.NetworkInterfaces != nil { + in, out := &in.NetworkInterfaces, &out.NetworkInterfaces + *out = make([]*GCPNetworkInterface, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(GCPNetworkInterface) + **out = **in + } + } + } + if in.ServiceAccounts != nil { + in, out := &in.ServiceAccounts, &out.ServiceAccounts + *out = make([]GCPServiceAccount, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.TargetPools != nil { + in, out := &in.TargetPools, &out.TargetPools + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.GPUs != nil { + in, out := &in.GPUs, &out.GPUs + *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 + *out = make([]ResourceManagerTag, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPMachineProviderSpec. +func (in *GCPMachineProviderSpec) DeepCopy() *GCPMachineProviderSpec { + if in == nil { + return nil + } + out := new(GCPMachineProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *GCPMachineProviderSpec) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPMachineProviderStatus) DeepCopyInto(out *GCPMachineProviderStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.InstanceID != nil { + in, out := &in.InstanceID, &out.InstanceID + *out = new(string) + **out = **in + } + if in.InstanceState != nil { + in, out := &in.InstanceState, &out.InstanceState + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPMachineProviderStatus. +func (in *GCPMachineProviderStatus) DeepCopy() *GCPMachineProviderStatus { + if in == nil { + return nil + } + out := new(GCPMachineProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPMetadata) DeepCopyInto(out *GCPMetadata) { + *out = *in + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPMetadata. +func (in *GCPMetadata) DeepCopy() *GCPMetadata { + if in == nil { + return nil + } + out := new(GCPMetadata) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPNetworkInterface) DeepCopyInto(out *GCPNetworkInterface) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPNetworkInterface. +func (in *GCPNetworkInterface) DeepCopy() *GCPNetworkInterface { + if in == nil { + return nil + } + out := new(GCPNetworkInterface) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPServiceAccount) DeepCopyInto(out *GCPServiceAccount) { + *out = *in + if in.Scopes != nil { + in, out := &in.Scopes, &out.Scopes + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPServiceAccount. +func (in *GCPServiceAccount) DeepCopy() *GCPServiceAccount { + if in == nil { + return nil + } + out := new(GCPServiceAccount) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPShieldedInstanceConfig) DeepCopyInto(out *GCPShieldedInstanceConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPShieldedInstanceConfig. +func (in *GCPShieldedInstanceConfig) DeepCopy() *GCPShieldedInstanceConfig { + if in == nil { + return nil + } + out := new(GCPShieldedInstanceConfig) + in.DeepCopyInto(out) + 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) + (*in).DeepCopyInto(*out) + } + 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 + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Image. +func (in *Image) DeepCopy() *Image { + if in == nil { + return nil + } + out := new(Image) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LastOperation) DeepCopyInto(out *LastOperation) { + *out = *in + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } + if in.LastUpdated != nil { + in, out := &in.LastUpdated, &out.LastUpdated + *out = (*in).DeepCopy() + } + if in.State != nil { + in, out := &in.State, &out.State + *out = new(string) + **out = **in + } + if in.Type != nil { + in, out := &in.Type, &out.Type + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LastOperation. +func (in *LastOperation) DeepCopy() *LastOperation { + if in == nil { + return nil + } + out := new(LastOperation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LifecycleHook) DeepCopyInto(out *LifecycleHook) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LifecycleHook. +func (in *LifecycleHook) DeepCopy() *LifecycleHook { + if in == nil { + return nil + } + out := new(LifecycleHook) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LifecycleHooks) DeepCopyInto(out *LifecycleHooks) { + *out = *in + if in.PreDrain != nil { + in, out := &in.PreDrain, &out.PreDrain + *out = make([]LifecycleHook, len(*in)) + copy(*out, *in) + } + if in.PreTerminate != nil { + in, out := &in.PreTerminate, &out.PreTerminate + *out = make([]LifecycleHook, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LifecycleHooks. +func (in *LifecycleHooks) DeepCopy() *LifecycleHooks { + if in == nil { + return nil + } + out := new(LifecycleHooks) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LoadBalancerReference) DeepCopyInto(out *LoadBalancerReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LoadBalancerReference. +func (in *LoadBalancerReference) DeepCopy() *LoadBalancerReference { + if in == nil { + return nil + } + out := new(LoadBalancerReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Machine) DeepCopyInto(out *Machine) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Machine. +func (in *Machine) DeepCopy() *Machine { + if in == nil { + return nil + } + out := new(Machine) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Machine) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineHealthCheck) DeepCopyInto(out *MachineHealthCheck) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineHealthCheck. +func (in *MachineHealthCheck) DeepCopy() *MachineHealthCheck { + if in == nil { + return nil + } + out := new(MachineHealthCheck) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineHealthCheck) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineHealthCheckList) DeepCopyInto(out *MachineHealthCheckList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]MachineHealthCheck, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineHealthCheckList. +func (in *MachineHealthCheckList) DeepCopy() *MachineHealthCheckList { + if in == nil { + return nil + } + out := new(MachineHealthCheckList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineHealthCheckList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineHealthCheckSpec) DeepCopyInto(out *MachineHealthCheckSpec) { + *out = *in + in.Selector.DeepCopyInto(&out.Selector) + if in.UnhealthyConditions != nil { + in, out := &in.UnhealthyConditions, &out.UnhealthyConditions + *out = make([]UnhealthyCondition, len(*in)) + copy(*out, *in) + } + if in.MaxUnhealthy != nil { + in, out := &in.MaxUnhealthy, &out.MaxUnhealthy + *out = new(intstr.IntOrString) + **out = **in + } + if in.NodeStartupTimeout != nil { + in, out := &in.NodeStartupTimeout, &out.NodeStartupTimeout + *out = new(metav1.Duration) + **out = **in + } + if in.RemediationTemplate != nil { + in, out := &in.RemediationTemplate, &out.RemediationTemplate + *out = new(v1.ObjectReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineHealthCheckSpec. +func (in *MachineHealthCheckSpec) DeepCopy() *MachineHealthCheckSpec { + if in == nil { + return nil + } + out := new(MachineHealthCheckSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineHealthCheckStatus) DeepCopyInto(out *MachineHealthCheckStatus) { + *out = *in + if in.ExpectedMachines != nil { + in, out := &in.ExpectedMachines, &out.ExpectedMachines + *out = new(int) + **out = **in + } + if in.CurrentHealthy != nil { + in, out := &in.CurrentHealthy, &out.CurrentHealthy + *out = new(int) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineHealthCheckStatus. +func (in *MachineHealthCheckStatus) DeepCopy() *MachineHealthCheckStatus { + if in == nil { + return nil + } + out := new(MachineHealthCheckStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineList) DeepCopyInto(out *MachineList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Machine, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineList. +func (in *MachineList) DeepCopy() *MachineList { + if in == nil { + return nil + } + out := new(MachineList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSet) DeepCopyInto(out *MachineSet) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSet. +func (in *MachineSet) DeepCopy() *MachineSet { + if in == nil { + return nil + } + out := new(MachineSet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineSet) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSetList) DeepCopyInto(out *MachineSetList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]MachineSet, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSetList. +func (in *MachineSetList) DeepCopy() *MachineSetList { + if in == nil { + return nil + } + out := new(MachineSetList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *MachineSetList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSetSpec) DeepCopyInto(out *MachineSetSpec) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + in.Selector.DeepCopyInto(&out.Selector) + in.Template.DeepCopyInto(&out.Template) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSetSpec. +func (in *MachineSetSpec) DeepCopy() *MachineSetSpec { + if in == nil { + return nil + } + out := new(MachineSetSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSetStatus) DeepCopyInto(out *MachineSetStatus) { + *out = *in + if in.ErrorReason != nil { + in, out := &in.ErrorReason, &out.ErrorReason + *out = new(MachineSetStatusError) + **out = **in + } + if in.ErrorMessage != nil { + in, out := &in.ErrorMessage, &out.ErrorMessage + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSetStatus. +func (in *MachineSetStatus) DeepCopy() *MachineSetStatus { + if in == nil { + return nil + } + out := new(MachineSetStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineSpec) DeepCopyInto(out *MachineSpec) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.LifecycleHooks.DeepCopyInto(&out.LifecycleHooks) + if in.Taints != nil { + in, out := &in.Taints, &out.Taints + *out = make([]v1.Taint, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.ProviderSpec.DeepCopyInto(&out.ProviderSpec) + if in.ProviderID != nil { + in, out := &in.ProviderID, &out.ProviderID + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineSpec. +func (in *MachineSpec) DeepCopy() *MachineSpec { + if in == nil { + return nil + } + out := new(MachineSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineStatus) DeepCopyInto(out *MachineStatus) { + *out = *in + if in.NodeRef != nil { + in, out := &in.NodeRef, &out.NodeRef + *out = new(v1.ObjectReference) + **out = **in + } + if in.LastUpdated != nil { + in, out := &in.LastUpdated, &out.LastUpdated + *out = (*in).DeepCopy() + } + if in.ErrorReason != nil { + in, out := &in.ErrorReason, &out.ErrorReason + *out = new(MachineStatusError) + **out = **in + } + if in.ErrorMessage != nil { + in, out := &in.ErrorMessage, &out.ErrorMessage + *out = new(string) + **out = **in + } + if in.ProviderStatus != nil { + in, out := &in.ProviderStatus, &out.ProviderStatus + *out = new(runtime.RawExtension) + (*in).DeepCopyInto(*out) + } + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]v1.NodeAddress, len(*in)) + copy(*out, *in) + } + if in.LastOperation != nil { + in, out := &in.LastOperation, &out.LastOperation + *out = new(LastOperation) + (*in).DeepCopyInto(*out) + } + if in.Phase != nil { + in, out := &in.Phase, &out.Phase + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineStatus. +func (in *MachineStatus) DeepCopy() *MachineStatus { + if in == nil { + return nil + } + out := new(MachineStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachineTemplateSpec) DeepCopyInto(out *MachineTemplateSpec) { + *out = *in + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachineTemplateSpec. +func (in *MachineTemplateSpec) DeepCopy() *MachineTemplateSpec { + if in == nil { + return nil + } + out := new(MachineTemplateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MetadataServiceOptions) DeepCopyInto(out *MetadataServiceOptions) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MetadataServiceOptions. +func (in *MetadataServiceOptions) DeepCopy() *MetadataServiceOptions { + if in == nil { + return nil + } + out := new(MetadataServiceOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkDeviceSpec) DeepCopyInto(out *NetworkDeviceSpec) { + *out = *in + if in.IPAddrs != nil { + in, out := &in.IPAddrs, &out.IPAddrs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Nameservers != nil { + in, out := &in.Nameservers, &out.Nameservers + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.AddressesFromPools != nil { + in, out := &in.AddressesFromPools, &out.AddressesFromPools + *out = make([]AddressesFromPool, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkDeviceSpec. +func (in *NetworkDeviceSpec) DeepCopy() *NetworkDeviceSpec { + if in == nil { + return nil + } + out := new(NetworkDeviceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkSpec) DeepCopyInto(out *NetworkSpec) { + *out = *in + if in.Devices != nil { + in, out := &in.Devices, &out.Devices + *out = make([]NetworkDeviceSpec, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSpec. +func (in *NetworkSpec) DeepCopy() *NetworkSpec { + if in == nil { + return nil + } + out := new(NetworkSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSDisk) DeepCopyInto(out *OSDisk) { + *out = *in + in.ManagedDisk.DeepCopyInto(&out.ManagedDisk) + out.DiskSettings = in.DiskSettings + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSDisk. +func (in *OSDisk) DeepCopy() *OSDisk { + if in == nil { + return nil + } + out := new(OSDisk) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSDiskManagedDiskParameters) DeepCopyInto(out *OSDiskManagedDiskParameters) { + *out = *in + if in.DiskEncryptionSet != nil { + in, out := &in.DiskEncryptionSet, &out.DiskEncryptionSet + *out = new(DiskEncryptionSetParameters) + **out = **in + } + out.SecurityProfile = in.SecurityProfile + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSDiskManagedDiskParameters. +func (in *OSDiskManagedDiskParameters) DeepCopy() *OSDiskManagedDiskParameters { + if in == nil { + return nil + } + out := new(OSDiskManagedDiskParameters) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectMeta) DeepCopyInto(out *ObjectMeta) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.OwnerReferences != nil { + in, out := &in.OwnerReferences, &out.OwnerReferences + *out = make([]metav1.OwnerReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectMeta. +func (in *ObjectMeta) DeepCopy() *ObjectMeta { + if in == nil { + return nil + } + out := new(ObjectMeta) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Placement) DeepCopyInto(out *Placement) { + *out = *in + if in.Host != nil { + in, out := &in.Host, &out.Host + *out = new(HostPlacement) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Placement. +func (in *Placement) DeepCopy() *Placement { + if in == nil { + return nil + } + out := new(Placement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProviderSpec) DeepCopyInto(out *ProviderSpec) { + *out = *in + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(runtime.RawExtension) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderSpec. +func (in *ProviderSpec) DeepCopy() *ProviderSpec { + if in == nil { + return nil + } + out := new(ProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceManagerTag) DeepCopyInto(out *ResourceManagerTag) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceManagerTag. +func (in *ResourceManagerTag) DeepCopy() *ResourceManagerTag { + if in == nil { + return nil + } + out := new(ResourceManagerTag) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityProfile) DeepCopyInto(out *SecurityProfile) { + *out = *in + if in.EncryptionAtHost != nil { + in, out := &in.EncryptionAtHost, &out.EncryptionAtHost + *out = new(bool) + **out = **in + } + in.Settings.DeepCopyInto(&out.Settings) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityProfile. +func (in *SecurityProfile) DeepCopy() *SecurityProfile { + if in == nil { + return nil + } + out := new(SecurityProfile) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecuritySettings) DeepCopyInto(out *SecuritySettings) { + *out = *in + if in.ConfidentialVM != nil { + in, out := &in.ConfidentialVM, &out.ConfidentialVM + *out = new(ConfidentialVM) + **out = **in + } + if in.TrustedLaunch != nil { + in, out := &in.TrustedLaunch, &out.TrustedLaunch + *out = new(TrustedLaunch) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecuritySettings. +func (in *SecuritySettings) DeepCopy() *SecuritySettings { + if in == nil { + return nil + } + out := new(SecuritySettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SpotMarketOptions) DeepCopyInto(out *SpotMarketOptions) { + *out = *in + if in.MaxPrice != nil { + in, out := &in.MaxPrice, &out.MaxPrice + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SpotMarketOptions. +func (in *SpotMarketOptions) DeepCopy() *SpotMarketOptions { + if in == nil { + return nil + } + out := new(SpotMarketOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SpotVMOptions) DeepCopyInto(out *SpotVMOptions) { + *out = *in + if in.MaxPrice != nil { + in, out := &in.MaxPrice, &out.MaxPrice + x := (*in).DeepCopy() + *out = &x + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SpotVMOptions. +func (in *SpotVMOptions) DeepCopy() *SpotVMOptions { + if in == nil { + return nil + } + out := new(SpotVMOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TagSpecification) DeepCopyInto(out *TagSpecification) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TagSpecification. +func (in *TagSpecification) DeepCopy() *TagSpecification { + if in == nil { + return nil + } + out := new(TagSpecification) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrustedLaunch) DeepCopyInto(out *TrustedLaunch) { + *out = *in + out.UEFISettings = in.UEFISettings + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrustedLaunch. +func (in *TrustedLaunch) DeepCopy() *TrustedLaunch { + if in == nil { + return nil + } + out := new(TrustedLaunch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UEFISettings) DeepCopyInto(out *UEFISettings) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UEFISettings. +func (in *UEFISettings) DeepCopy() *UEFISettings { + if in == nil { + return nil + } + out := new(UEFISettings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UnhealthyCondition) DeepCopyInto(out *UnhealthyCondition) { + *out = *in + out.Timeout = in.Timeout + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UnhealthyCondition. +func (in *UnhealthyCondition) DeepCopy() *UnhealthyCondition { + if in == nil { + return nil + } + out := new(UnhealthyCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VMDiskSecurityProfile) DeepCopyInto(out *VMDiskSecurityProfile) { + *out = *in + out.DiskEncryptionSet = in.DiskEncryptionSet + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VMDiskSecurityProfile. +func (in *VMDiskSecurityProfile) DeepCopy() *VMDiskSecurityProfile { + if in == nil { + return nil + } + out := new(VMDiskSecurityProfile) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereDisk) DeepCopyInto(out *VSphereDisk) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereDisk. +func (in *VSphereDisk) DeepCopy() *VSphereDisk { + if in == nil { + return nil + } + out := new(VSphereDisk) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachineProviderSpec) DeepCopyInto(out *VSphereMachineProviderSpec) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + if in.UserDataSecret != nil { + in, out := &in.UserDataSecret, &out.UserDataSecret + *out = new(v1.LocalObjectReference) + **out = **in + } + if in.CredentialsSecret != nil { + in, out := &in.CredentialsSecret, &out.CredentialsSecret + *out = new(v1.LocalObjectReference) + **out = **in + } + if in.Workspace != nil { + in, out := &in.Workspace, &out.Workspace + *out = new(Workspace) + **out = **in + } + in.Network.DeepCopyInto(&out.Network) + if in.TagIDs != nil { + in, out := &in.TagIDs, &out.TagIDs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.DataDisks != nil { + in, out := &in.DataDisks, &out.DataDisks + *out = make([]VSphereDisk, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachineProviderSpec. +func (in *VSphereMachineProviderSpec) DeepCopy() *VSphereMachineProviderSpec { + if in == nil { + return nil + } + out := new(VSphereMachineProviderSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VSphereMachineProviderSpec) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VSphereMachineProviderStatus) DeepCopyInto(out *VSphereMachineProviderStatus) { + *out = *in + out.TypeMeta = in.TypeMeta + if in.InstanceID != nil { + in, out := &in.InstanceID, &out.InstanceID + *out = new(string) + **out = **in + } + if in.InstanceState != nil { + in, out := &in.InstanceState, &out.InstanceState + *out = new(string) + **out = **in + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VSphereMachineProviderStatus. +func (in *VSphereMachineProviderStatus) DeepCopy() *VSphereMachineProviderStatus { + if in == nil { + return nil + } + out := new(VSphereMachineProviderStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Workspace) DeepCopyInto(out *Workspace) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Workspace. +func (in *Workspace) DeepCopy() *Workspace { + if in == nil { + return nil + } + out := new(Workspace) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.featuregated-crd-manifests.yaml b/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.featuregated-crd-manifests.yaml new file mode 100644 index 000000000..ae6e6a8a5 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.featuregated-crd-manifests.yaml @@ -0,0 +1,140 @@ +machines.machine.openshift.io: + Annotations: + exclude.release.openshift.io/internal-openshift-hosted: "true" + include.release.openshift.io/self-managed-high-availability: "true" + ApprovedPRNumber: https://github.com/openshift/api/pull/948 + CRDName: machines.machine.openshift.io + Capability: MachineAPI + Category: "" + FeatureGates: + - MachineAPIMigration + FilenameOperatorName: machine-api + FilenameOperatorOrdering: "01" + FilenameRunLevel: "0000_10" + GroupName: machine.openshift.io + HasStatus: true + KindName: Machine + Labels: {} + PluralName: machines + PrinterColumns: + - description: Phase of machine + jsonPath: .status.phase + name: Phase + type: string + - description: Type of instance + jsonPath: .metadata.labels['machine\.openshift\.io/instance-type'] + name: Type + type: string + - description: Region associated with machine + jsonPath: .metadata.labels['machine\.openshift\.io/region'] + name: Region + type: string + - description: Zone associated with machine + jsonPath: .metadata.labels['machine\.openshift\.io/zone'] + name: Zone + type: string + - description: Machine age + jsonPath: .metadata.creationTimestamp + name: Age + type: date + - description: Node associated with machine + jsonPath: .status.nodeRef.name + name: Node + priority: 1 + type: string + - description: Provider ID of machine created in cloud provider + jsonPath: .spec.providerID + name: ProviderID + priority: 1 + type: string + - description: State of instance + jsonPath: .metadata.annotations['machine\.openshift\.io/instance-state'] + name: State + priority: 1 + type: string + Scope: Namespaced + ShortNames: null + TopLevelFeatureGates: [] + Version: v1beta1 + +machinehealthchecks.machine.openshift.io: + Annotations: + exclude.release.openshift.io/internal-openshift-hosted: "true" + include.release.openshift.io/self-managed-high-availability: "true" + ApprovedPRNumber: https://github.com/openshift/api/pull/1032 + CRDName: machinehealthchecks.machine.openshift.io + Capability: MachineAPI + Category: "" + FeatureGates: [] + FilenameOperatorName: machine-api + FilenameOperatorOrdering: "01" + FilenameRunLevel: "0000_10" + GroupName: machine.openshift.io + HasStatus: true + KindName: MachineHealthCheck + Labels: {} + PluralName: machinehealthchecks + PrinterColumns: + - description: Maximum number of unhealthy machines allowed + jsonPath: .spec.maxUnhealthy + name: MaxUnhealthy + type: string + - description: Number of machines currently monitored + jsonPath: .status.expectedMachines + name: ExpectedMachines + type: integer + - description: Current observed healthy machines + jsonPath: .status.currentHealthy + name: CurrentHealthy + type: integer + Scope: Namespaced + ShortNames: + - mhc + - mhcs + TopLevelFeatureGates: [] + Version: v1beta1 + +machinesets.machine.openshift.io: + Annotations: + exclude.release.openshift.io/internal-openshift-hosted: "true" + include.release.openshift.io/self-managed-high-availability: "true" + ApprovedPRNumber: https://github.com/openshift/api/pull/1032 + CRDName: machinesets.machine.openshift.io + Capability: MachineAPI + Category: "" + FeatureGates: + - MachineAPIMigration + FilenameOperatorName: machine-api + FilenameOperatorOrdering: "01" + FilenameRunLevel: "0000_10" + GroupName: machine.openshift.io + HasStatus: true + KindName: MachineSet + Labels: {} + PluralName: machinesets + PrinterColumns: + - description: Desired Replicas + jsonPath: .spec.replicas + name: Desired + type: integer + - description: Current Replicas + jsonPath: .status.replicas + name: Current + type: integer + - description: Ready Replicas + jsonPath: .status.readyReplicas + name: Ready + type: integer + - description: Observed number of available replicas + jsonPath: .status.availableReplicas + name: Available + type: string + - description: Machineset age + jsonPath: .metadata.creationTimestamp + name: Age + type: date + Scope: Namespaced + ShortNames: null + TopLevelFeatureGates: [] + Version: v1beta1 + 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 new file mode 100644 index 000000000..e686cad25 --- /dev/null +++ b/vendor/github.com/openshift/api/machine/v1beta1/zz_generated.swagger_doc_generated.go @@ -0,0 +1,901 @@ +package v1beta1 + +// This file contains a collection of methods that can be used from go-restful to +// generate Swagger API documentation for its models. Please read this PR for more +// information on the implementation: https://github.com/emicklei/go-restful/pull/215 +// +// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if +// they are on one line! For multiple line or blocks that you want to ignore use ---. +// Any context after a --- is ignored. +// +// Those methods can be generated by using hack/update-swagger-docs.sh + +// AUTO-GENERATED FUNCTIONS START HERE +var map_AWSMachineProviderConfig = map[string]string{ + "": "AWSMachineProviderConfig is the Schema for the awsmachineproviderconfigs API Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "ami": "ami is the reference to the AMI from which to create the machine instance.", + "instanceType": "instanceType is the type of instance to create. Example: m4.xlarge", + "cpuOptions": "cpuOptions defines CPU-related settings for the instance, including the confidential computing policy. When omitted, this means no opinion and the AWS platform is left to choose a reasonable default. More info: https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CpuOptionsRequest.html, https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/cpu-options-supported-instances-values.html", + "tags": "tags is the set of tags to add to apply to an instance, in addition to the ones added by default by the actuator. These tags are additive. The actuator will ensure these tags are present, but will not remove any other tags that may exist on the instance.", + "iamInstanceProfile": "iamInstanceProfile is a reference to an IAM role to assign to the instance", + "userDataSecret": "userDataSecret contains a local reference to a secret that contains the UserData to apply to the instance", + "credentialsSecret": "credentialsSecret is a reference to the secret with AWS credentials. Otherwise, defaults to permissions provided by attached IAM role where the actuator is running.", + "keyName": "keyName is the name of the KeyPair to use for SSH", + "deviceIndex": "deviceIndex is the index of the device on the instance for the network interface attachment. Defaults to 0.", + "publicIp": "publicIp specifies whether the instance should get a public IP. If not present, it should use the default of its subnet.", + "networkInterfaceType": "networkInterfaceType specifies the type of network interface to be used for the primary network interface. Valid values are \"ENA\", \"EFA\", and omitted, which means no opinion and the platform chooses a good default which may change over time. The current default value is \"ENA\". Please visit https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/efa.html to learn more about the AWS Elastic Fabric Adapter interface option.", + "securityGroups": "securityGroups is an array of references to security groups that should be applied to the instance.", + "subnet": "subnet is a reference to the subnet to use for this instance", + "placement": "placement specifies where to create the instance in AWS", + "loadBalancers": "loadBalancers is the set of load balancers to which the new instance should be added once it is created.", + "blockDevices": "blockDevices is the set of block device mapping associated to this instance, block device without a name will be used as a root device and only one device without a name is allowed https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/block-device-mapping-concepts.html", + "spotMarketOptions": "spotMarketOptions allows users to configure instances to be run using AWS Spot instances.", + "metadataServiceOptions": "metadataServiceOptions allows users to configure instance metadata service interaction options. If nothing specified, default AWS IMDS settings will be applied. https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InstanceMetadataOptionsRequest.html", + "placementGroupName": "placementGroupName specifies the name of the placement group in which to launch the instance. The placement group must already be created and may use any placement strategy. When omitted, no placement group is used when creating the EC2 instance.", + "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.", +} + +func (AWSMachineProviderConfig) SwaggerDoc() map[string]string { + return map_AWSMachineProviderConfig +} + +var map_AWSMachineProviderConfigList = map[string]string{ + "": "AWSMachineProviderConfigList contains a list of AWSMachineProviderConfig Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", +} + +func (AWSMachineProviderConfigList) SwaggerDoc() map[string]string { + return map_AWSMachineProviderConfigList +} + +var map_AWSMachineProviderStatus = map[string]string{ + "": "AWSMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. It contains AWS-specific status information. Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "instanceId": "instanceId is the instance ID of the machine created in AWS", + "instanceState": "instanceState is the state of the AWS instance for this machine", + "conditions": "conditions is a set of conditions associated with the Machine to indicate errors or other status", + "dedicatedHost": "dedicatedHost tracks the dynamically allocated dedicated host. This field is populated when allocationStrategy is Dynamic (with or without DynamicHostAllocation). When omitted, this indicates that the dedicated host has not yet been allocated, or allocation is in progress.", +} + +func (AWSMachineProviderStatus) SwaggerDoc() map[string]string { + return map_AWSMachineProviderStatus +} + +var map_AWSResourceReference = map[string]string{ + "": "AWSResourceReference is a reference to a specific AWS resource by ID, ARN, or filters. Only one of ID, ARN or Filters may be specified. Specifying more than one will result in a validation error.", + "id": "id of resource", + "arn": "arn of resource", + "filters": "filters is a set of filters used to identify a resource", +} + +func (AWSResourceReference) SwaggerDoc() map[string]string { + return map_AWSResourceReference +} + +var map_BlockDeviceMappingSpec = map[string]string{ + "": "BlockDeviceMappingSpec describes a block device mapping", + "deviceName": "The device name exposed to the machine (for example, /dev/sdh or xvdh).", + "ebs": "Parameters used to automatically set up EBS volumes when the machine is launched.", + "noDevice": "Suppresses the specified device included in the block device mapping of the AMI.", + "virtualName": "The virtual device name (ephemeralN). Machine store volumes are numbered starting from 0. An machine type with 2 available machine store volumes can specify mappings for ephemeral0 and ephemeral1.The number of available machine store volumes depends on the machine type. After you connect to the machine, you must mount the volume.\n\nConstraints: For M3 machines, you must specify machine store volumes in the block device mapping for the machine. When you launch an M3 machine, we ignore any machine store volumes specified in the block device mapping for the AMI.", +} + +func (BlockDeviceMappingSpec) SwaggerDoc() map[string]string { + return map_BlockDeviceMappingSpec +} + +var map_CPUOptions = map[string]string{ + "": "CPUOptions defines CPU-related settings for the instance, including the confidential computing policy. If provided, it must not be empty — at least one field must be set.", + "confidentialCompute": "confidentialCompute specifies whether confidential computing should be enabled for the instance, and, if so, which confidential computing technology to use. Valid values are: Disabled, AMDEncryptedVirtualizationNestedPaging and omitted. When set to Disabled, confidential computing will be disabled for the instance. When set to AMDEncryptedVirtualizationNestedPaging, AMD SEV-SNP will be used as the confidential computing technology for the instance. In this case, ensure the following conditions are met: 1) The selected instance type supports AMD SEV-SNP. 2) The selected AWS region supports AMD SEV-SNP. 3) The selected AMI supports AMD SEV-SNP. More details can be checked at https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sev-snp.html When omitted, this means no opinion and the AWS platform is left to choose a reasonable default, which is subject to change without notice. The current default is Disabled.", +} + +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.", + "allocationStrategy": "allocationStrategy specifies if the dedicated host will be provided by the admin through the id field or if the host will be dynamically allocated. Valid values are UserProvided and Dynamic. When omitted, the value defaults to \"UserProvided\", which requires the id field to be set. When allocationStrategy is set to UserProvided, an ID of the dedicated host to assign must be provided. When allocationStrategy is set to Dynamic, a dedicated host will be allocated and used to assign instances. When allocationStrategy is set to Dynamic, and dynamicHostAllocation is configured, a dedicated host will be allocated and the tags in dynamicHostAllocation will be assigned to that host.", + "id": "id identifies the AWS Dedicated Host on which the instance must run. The value must start with \"h-\" followed by either 8 or 17 lowercase hexadecimal characters (0-9 and a-f). The use of 8 lowercase hexadecimal characters is for older legacy hosts that may not have been migrated to newer format. Must be either 10 or 19 characters in length. This field is required when allocationStrategy is UserProvided, and forbidden otherwise. When omitted with allocationStrategy set to Dynamic, the platform will dynamically allocate a dedicated host.", + "dynamicHostAllocation": "dynamicHostAllocation specifies tags to apply to a dynamically allocated dedicated host. This field is only allowed when allocationStrategy is Dynamic, and is mutually exclusive with id. When specified, a dedicated host will be allocated with the provided tags applied. When omitted (and allocationStrategy is Dynamic), a dedicated host will be allocated without any additional tags.", +} + +func (DedicatedHost) SwaggerDoc() map[string]string { + return map_DedicatedHost +} + +var map_DedicatedHostStatus = map[string]string{ + "": "DedicatedHostStatus defines the observed state of a dynamically allocated dedicated host associated with an AWSMachine. This struct is used to track the ID of the dedicated host.", + "id": "id tracks the dynamically allocated dedicated host ID. This field is populated when allocationStrategy is Dynamic (with or without DynamicHostAllocation). The value must start with \"h-\" followed by either 8 or 17 lowercase hexadecimal characters (0-9 and a-f). The use of 8 lowercase hexadecimal characters is for older legacy hosts that may not have been migrated to newer format. Must be either 10 or 19 characters in length.", +} + +func (DedicatedHostStatus) SwaggerDoc() map[string]string { + return map_DedicatedHostStatus +} + +var map_DynamicHostAllocationSpec = map[string]string{ + "": "DynamicHostAllocationSpec defines the configuration for dynamic dedicated host allocation. This specification always allocates exactly one dedicated host per machine. At least one property must be specified when this struct is used. Currently only Tags are available for configuring, but in the future more configs may become available.", + "tags": "tags specifies a set of key-value pairs to apply to the allocated dedicated host. When omitted, no additional user-defined tags will be applied to the allocated host. A maximum of 50 tags can be specified.", +} + +func (DynamicHostAllocationSpec) SwaggerDoc() map[string]string { + return map_DynamicHostAllocationSpec +} + +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.", + "encrypted": "Indicates whether the EBS volume is encrypted. Encrypted Amazon EBS volumes may only be attached to machines that support Amazon EBS encryption.", + "kmsKey": "Indicates the KMS key that should be used to encrypt the Amazon EBS volume.", + "iops": "The number of I/O operations per second (IOPS) that the volume supports. For io1, this represents the number of IOPS that are provisioned for the volume. For gp2, this represents the baseline performance of the volume and the rate at which the volume accumulates I/O credits for bursting. For more information about General Purpose SSD baseline performance, I/O credits, and bursting, see Amazon EBS Volume Types (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html) in the Amazon Elastic Compute Cloud User Guide.\n\nMinimal and maximal IOPS for io1 and gp2 are constrained. Please, check https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html for precise boundaries for individual volumes.\n\nCondition: This parameter is required for requests to create io1 volumes; it is not used in requests to create gp2, st1, sc1, or standard volumes.", + "throughputMib": "throughputMib to provision in MiB/s supported for the volume type. Not applicable to all types.\n\nThis parameter is valid only for gp3 volumes. Valid Range: Minimum value of 125. Maximum value of 2000.\n\nWhen omitted, this means no opinion, and the platform is left to choose a reasonable default, which is subject to change over time. The current default is 125.", + "volumeSize": "The size of the volume, in GiB.\n\nConstraints: 1-16384 for General Purpose SSD (gp2), 4-16384 for Provisioned IOPS SSD (io1), 500-16384 for Throughput Optimized HDD (st1), 500-16384 for Cold HDD (sc1), and 1-1024 for Magnetic (standard) volumes. If you specify a snapshot, the volume size must be equal to or larger than the snapshot size.\n\nDefault: If you're creating the volume from a snapshot and don't specify a volume size, the default is the snapshot size.", + "volumeType": "volumeType can be of type gp2, gp3, io1, st1, sc1, or standard. Default: standard", +} + +func (EBSBlockDeviceSpec) SwaggerDoc() map[string]string { + return map_EBSBlockDeviceSpec +} + +var map_Filter = map[string]string{ + "": "Filter is a filter used to identify an AWS resource", + "name": "name of the filter. Filter names are case-sensitive.", + "values": "values includes one or more filter values. Filter values are case-sensitive.", +} + +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. When Affinity is set to AnyAvailable and the `dedicatedHost` field is defined, it runs on specified Dedicated Host, but may move if stopped.", + "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 optional 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.", +} + +func (LoadBalancerReference) SwaggerDoc() map[string]string { + return map_LoadBalancerReference +} + +var map_MetadataServiceOptions = map[string]string{ + "": "MetadataServiceOptions defines the options available to a user when configuring Instance Metadata Service (IMDS) Options.", + "authentication": "authentication determines whether or not the host requires the use of authentication when interacting with the metadata service. When using authentication, this enforces v2 interaction method (IMDSv2) with the metadata service. When omitted, this means the user has no opinion and the value is left to the platform to choose a good default, which is subject to change over time. The current default is optional. At this point this field represents `HttpTokens` parameter from `InstanceMetadataOptionsRequest` structure in AWS EC2 API https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InstanceMetadataOptionsRequest.html", +} + +func (MetadataServiceOptions) SwaggerDoc() map[string]string { + return map_MetadataServiceOptions +} + +var map_Placement = map[string]string{ + "": "Placement indicates where to create the instance in AWS", + "region": "region is the region to use to create the instance", + "availabilityZone": "availabilityZone is the availability zone of the instance", + "tenancy": "tenancy indicates if instance should run on shared or single-tenant hardware. There are supported 3 options: default, dedicated and host. When set to default Runs on shared multi-tenant hardware. When dedicated Runs on single-tenant hardware (any dedicated instance hardware). When host and the host object is not provided: Runs on Dedicated Host; best-effort restart on same host. When `host` and `host` object is provided with affinity `dedicatedHost` defined: Runs on specified Dedicated Host.", + "host": "host 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 (Placement) SwaggerDoc() map[string]string { + return map_Placement +} + +var map_SpotMarketOptions = map[string]string{ + "": "SpotMarketOptions defines the options available to a user when configuring Machines to run on Spot instances. Most users should provide an empty struct.", + "maxPrice": "The maximum price the user is willing to pay for their instances Default: On-Demand price", +} + +func (SpotMarketOptions) SwaggerDoc() map[string]string { + return map_SpotMarketOptions +} + +var map_TagSpecification = map[string]string{ + "": "TagSpecification is the name/value pair for a tag", + "name": "name of the tag. This field is required and must be a non-empty string. Must be between 1 and 128 characters in length.", + "value": "value of the tag. When omitted, this creates a tag with an empty string as the value.", +} + +func (TagSpecification) SwaggerDoc() map[string]string { + return map_TagSpecification +} + +var map_AzureBootDiagnostics = map[string]string{ + "": "AzureBootDiagnostics configures the boot diagnostics settings for the virtual machine. This allows you to configure capturing serial output from the virtual machine on boot. This is useful for debugging software based launch issues.", + "storageAccountType": "storageAccountType determines if the storage account for storing the diagnostics data should be provisioned by Azure (AzureManaged) or by the customer (CustomerManaged).", + "customerManaged": "customerManaged provides reference to the customer manager storage account.", +} + +func (AzureBootDiagnostics) SwaggerDoc() map[string]string { + return map_AzureBootDiagnostics +} + +var map_AzureCustomerManagedBootDiagnostics = map[string]string{ + "": "AzureCustomerManagedBootDiagnostics provides reference to a customer managed storage account.", + "storageAccountURI": "storageAccountURI is the URI of the customer managed storage account. The URI typically will be `https://.blob.core.windows.net/` but may differ if you are using Azure DNS zone endpoints. You can find the correct endpoint by looking for the Blob Primary Endpoint in the endpoints tab in the Azure console.", +} + +func (AzureCustomerManagedBootDiagnostics) SwaggerDoc() map[string]string { + return map_AzureCustomerManagedBootDiagnostics +} + +var map_AzureDiagnostics = map[string]string{ + "": "AzureDiagnostics is used to configure the diagnostic settings of the virtual machine.", + "boot": "AzureBootDiagnostics configures the boot diagnostics settings for the virtual machine. This allows you to configure capturing serial output from the virtual machine on boot. This is useful for debugging software based launch issues.", +} + +func (AzureDiagnostics) SwaggerDoc() map[string]string { + return map_AzureDiagnostics +} + +var map_AzureMachineProviderSpec = map[string]string{ + "": "AzureMachineProviderSpec is the type that will be embedded in a Machine.Spec.ProviderSpec field for an Azure virtual machine. It is used by the Azure machine actuator to create a single Machine. Required parameters such as location that are not specified by this configuration, will be defaulted by the actuator. Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "userDataSecret": "userDataSecret contains a local reference to a secret that contains the UserData to apply to the instance", + "credentialsSecret": "credentialsSecret is a reference to the secret with Azure credentials.", + "location": "location is the region to use to create the instance", + "vmSize": "vmSize is the size of the VM to create.", + "image": "image is the OS image to use to create the instance.", + "osDisk": "osDisk represents the parameters for creating the OS disk.", + "dataDisks": "DataDisk specifies the parameters that are used to add one or more data disks to the machine.", + "sshPublicKey": "sshPublicKey is the public key to use to SSH to the virtual machine.", + "publicIP": "publicIP if true a public IP will be used", + "tags": "tags is a list of tags to apply to the machine.", + "securityGroup": "Network Security Group that needs to be attached to the machine's interface. No security group will be attached if empty.", + "applicationSecurityGroups": "Application Security Groups that need to be attached to the machine's interface. No application security groups will be attached if zero-length.", + "subnet": "subnet to use for this instance", + "publicLoadBalancer": "publicLoadBalancer to use for this instance", + "internalLoadBalancer": "InternalLoadBalancerName to use for this instance", + "natRule": "natRule to set inbound NAT rule of the load balancer", + "managedIdentity": "managedIdentity to set managed identity name", + "vnet": "vnet to set virtual network name", + "zone": "Availability Zone for the virtual machine. If nil, the virtual machine should be deployed to no zone", + "networkResourceGroup": "networkResourceGroup is the resource group for the virtual machine's network", + "resourceGroup": "resourceGroup is the resource group for the virtual machine", + "spotVMOptions": "spotVMOptions allows the ability to specify the Machine should use a Spot VM", + "securityProfile": "securityProfile specifies the Security profile settings for a virtual machine.", + "ultraSSDCapability": "ultraSSDCapability enables or disables Azure UltraSSD capability for a virtual machine. This can be used to allow/disallow binding of Azure UltraSSD to the Machine both as Data Disks or via Persistent Volumes. This Azure feature is subject to a specific scope and certain limitations. More informations on this can be found in the official Azure documentation for Ultra Disks: (https://docs.microsoft.com/en-us/azure/virtual-machines/disks-enable-ultra-ssd?tabs=azure-portal#ga-scope-and-limitations).\n\nWhen omitted, if at least one Data Disk of type UltraSSD is specified, the platform will automatically enable the capability. If a Perisistent Volume backed by an UltraSSD is bound to a Pod on the Machine, when this field is ommitted, the platform will *not* automatically enable the capability (unless already enabled by the presence of an UltraSSD as Data Disk). This may manifest in the Pod being stuck in `ContainerCreating` phase. This defaulting behaviour may be subject to change in future.\n\nWhen set to \"Enabled\", if the capability is available for the Machine based on the scope and limitations described above, the capability will be set on the Machine. This will thus allow UltraSSD both as Data Disks and Persistent Volumes. If set to \"Enabled\" when the capability can't be available due to scope and limitations, the Machine will go into \"Failed\" state.\n\nWhen set to \"Disabled\", UltraSSDs will not be allowed either as Data Disks nor as Persistent Volumes. In this case if any UltraSSDs are specified as Data Disks on a Machine, the Machine will go into a \"Failed\" state. If instead any UltraSSDs are backing the volumes (via Persistent Volumes) of any Pods scheduled on a Node which is backed by the Machine, the Pod may get stuck in `ContainerCreating` phase.", + "acceleratedNetworking": "acceleratedNetworking enables or disables Azure accelerated networking feature. Set to false by default. If true, then this will depend on whether the requested VMSize is supported. If set to true with an unsupported VMSize, Azure will return an error.", + "availabilitySet": "availabilitySet specifies the availability set to use for this instance. Availability set should be precreated, before using this field.", + "diagnostics": "diagnostics configures the diagnostics settings for the virtual machine. This allows you to configure boot diagnostics such as capturing serial output from the virtual machine on boot. This is useful for debugging software based launch issues.", + "capacityReservationGroupID": "capacityReservationGroupID specifies the capacity reservation group resource id that should be used for allocating the virtual machine. The field size should be greater than 0 and the field input must start with '/'. The input for capacityReservationGroupID must be similar to '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/capacityReservationGroups/{capacityReservationGroupName}'. The keys which are used should be among 'subscriptions', 'providers' and 'resourcegroups' followed by valid ID or names respectively.", +} + +func (AzureMachineProviderSpec) SwaggerDoc() map[string]string { + return map_AzureMachineProviderSpec +} + +var map_AzureMachineProviderStatus = map[string]string{ + "": "AzureMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. It contains Azure-specific status information. Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "vmId": "vmId is the ID of the virtual machine created in Azure.", + "vmState": "vmState is the provisioning state of the Azure virtual machine.", + "conditions": "conditions is a set of conditions associated with the Machine to indicate errors or other status.", +} + +func (AzureMachineProviderStatus) SwaggerDoc() map[string]string { + return map_AzureMachineProviderStatus +} + +var map_ConfidentialVM = map[string]string{ + "": "ConfidentialVM defines the UEFI settings for the virtual machine.", + "uefiSettings": "uefiSettings specifies the security settings like secure boot and vTPM used while creating the virtual machine.", +} + +func (ConfidentialVM) SwaggerDoc() map[string]string { + return map_ConfidentialVM +} + +var map_DataDisk = map[string]string{ + "": "DataDisk specifies the parameters that are used to add one or more data disks to the machine. A Data Disk is a managed disk that's attached to a virtual machine to store application data. It differs from an OS Disk as it doesn't come with a pre-installed OS, and it cannot contain the boot volume. It is registered as SCSI drive and labeled with the chosen `lun`. e.g. for `lun: 0` the raw disk device will be available at `/dev/disk/azure/scsi1/lun0`.\n\nAs the Data Disk disk device is attached raw to the virtual machine, it will need to be partitioned, formatted with a filesystem and mounted, in order for it to be usable. This can be done by creating a custom userdata Secret with custom Ignition configuration to achieve the desired initialization. At this stage the previously defined `lun` is to be used as the \"device\" key for referencing the raw disk device to be initialized. Once the custom userdata Secret has been created, it can be referenced in the Machine's `.providerSpec.userDataSecret`. For further guidance and examples, please refer to the official OpenShift docs.", + "nameSuffix": "nameSuffix is the suffix to be appended to the machine name to generate the disk name. Each disk name will be in format _. NameSuffix name must start and finish with an alphanumeric character and can only contain letters, numbers, underscores, periods or hyphens. The overall disk name must not exceed 80 chars in length.", + "diskSizeGB": "diskSizeGB is the size in GB to assign to the data disk.", + "managedDisk": "managedDisk specifies the Managed Disk parameters for the data disk. Empty value means no opinion and the platform chooses a default, which is subject to change over time. Currently the default is a ManagedDisk with with storageAccountType: \"Premium_LRS\" and diskEncryptionSet.id: \"Default\".", + "lun": "lun Specifies the logical unit number of the data disk. This value is used to identify data disks within the VM and therefore must be unique for each data disk attached to a VM. This value is also needed for referencing the data disks devices within userdata to perform disk initialization through Ignition (e.g. partition/format/mount). The value must be between 0 and 63.", + "cachingType": "cachingType specifies the caching requirements. Empty value means no opinion and the platform chooses a default, which is subject to change over time. Currently the default is CachingTypeNone.", + "deletionPolicy": "deletionPolicy specifies the data disk deletion policy upon Machine deletion. Possible values are \"Delete\",\"Detach\". When \"Delete\" is used the data disk is deleted when the Machine is deleted. When \"Detach\" is used the data disk is detached from the Machine and retained when the Machine is deleted.", +} + +func (DataDisk) SwaggerDoc() map[string]string { + return map_DataDisk +} + +var map_DataDiskManagedDiskParameters = map[string]string{ + "": "DataDiskManagedDiskParameters is the parameters of a DataDisk managed disk.", + "storageAccountType": "storageAccountType is the storage account type to use. Possible values include \"Standard_LRS\", \"Premium_LRS\" and \"UltraSSD_LRS\".", + "diskEncryptionSet": "diskEncryptionSet is the disk encryption set properties. Empty value means no opinion and the platform chooses a default, which is subject to change over time. Currently the default is a DiskEncryptionSet with id: \"Default\".", +} + +func (DataDiskManagedDiskParameters) SwaggerDoc() map[string]string { + return map_DataDiskManagedDiskParameters +} + +var map_DiskEncryptionSetParameters = map[string]string{ + "": "DiskEncryptionSetParameters is the disk encryption set properties", + "id": "id is the disk encryption set ID Empty value means no opinion and the platform chooses a default, which is subject to change over time. Currently the default is: \"Default\".", +} + +func (DiskEncryptionSetParameters) SwaggerDoc() map[string]string { + return map_DiskEncryptionSetParameters +} + +var map_DiskSettings = map[string]string{ + "": "DiskSettings describe ephemeral disk settings for the os disk.", + "ephemeralStorageLocation": "ephemeralStorageLocation enables ephemeral OS when set to 'Local'. Possible values include: 'Local'. See https://docs.microsoft.com/en-us/azure/virtual-machines/ephemeral-os-disks for full details. Empty value means no opinion and the platform chooses a default, which is subject to change over time. Currently the default is that disks are saved to remote Azure storage.", +} + +func (DiskSettings) SwaggerDoc() map[string]string { + return map_DiskSettings +} + +var map_Image = map[string]string{ + "": "Image is a mirror of azure sdk compute.ImageReference", + "publisher": "publisher is the name of the organization that created the image", + "offer": "offer specifies the name of a group of related images created by the publisher. For example, UbuntuServer, WindowsServer", + "sku": "sku specifies an instance of an offer, such as a major release of a distribution. For example, 18.04-LTS, 2019-Datacenter", + "version": "version specifies the version of an image sku. The allowed formats are Major.Minor.Build or 'latest'. Major, Minor, and Build are decimal numbers. Specify 'latest' to use the latest version of an image available at deploy time. Even if you use 'latest', the VM image will not automatically update after deploy time even if a new version becomes available.", + "resourceID": "resourceID specifies an image to use by ID", + "type": "type identifies the source of the image and related information, such as purchase plans. Valid values are \"ID\", \"MarketplaceWithPlan\", \"MarketplaceNoPlan\", and omitted, which means no opinion and the platform chooses a good default which may change over time. Currently that default is \"MarketplaceNoPlan\" if publisher data is supplied, or \"ID\" if not. For more information about purchase plans, see: https://docs.microsoft.com/en-us/azure/virtual-machines/linux/cli-ps-findimage#check-the-purchase-plan-information", +} + +func (Image) SwaggerDoc() map[string]string { + return map_Image +} + +var map_OSDisk = map[string]string{ + "osType": "osType is the operating system type of the OS disk. Possible values include \"Linux\" and \"Windows\".", + "managedDisk": "managedDisk specifies the Managed Disk parameters for the OS disk.", + "diskSizeGB": "diskSizeGB is the size in GB to assign to the data disk.", + "diskSettings": "diskSettings describe ephemeral disk settings for the os disk.", + "cachingType": "cachingType specifies the caching requirements. Possible values include: 'None', 'ReadOnly', 'ReadWrite'. Empty value means no opinion and the platform chooses a default, which is subject to change over time. Currently the default is `None`.", +} + +func (OSDisk) SwaggerDoc() map[string]string { + return map_OSDisk +} + +var map_OSDiskManagedDiskParameters = map[string]string{ + "": "OSDiskManagedDiskParameters is the parameters of a OSDisk managed disk.", + "storageAccountType": "storageAccountType is the storage account type to use. Possible values include \"Standard_LRS\", \"Premium_LRS\".", + "diskEncryptionSet": "diskEncryptionSet is the disk encryption set properties", + "securityProfile": "securityProfile specifies the security profile for the managed disk.", +} + +func (OSDiskManagedDiskParameters) SwaggerDoc() map[string]string { + return map_OSDiskManagedDiskParameters +} + +var map_SecurityProfile = map[string]string{ + "": "SecurityProfile specifies the Security profile settings for a virtual machine or virtual machine scale set.", + "encryptionAtHost": "encryptionAtHost indicates whether Host Encryption should be enabled or disabled for a virtual machine or virtual machine scale set. This should be disabled when SecurityEncryptionType is set to DiskWithVMGuestState. Default is disabled.", + "settings": "settings specify the security type and the UEFI settings of the virtual machine. This field can be set for Confidential VMs and Trusted Launch for VMs.", +} + +func (SecurityProfile) SwaggerDoc() map[string]string { + return map_SecurityProfile +} + +var map_SecuritySettings = map[string]string{ + "": "SecuritySettings define the security type and the UEFI settings of the virtual machine.", + "securityType": "securityType specifies the SecurityType of the virtual machine. It has to be set to any specified value to enable UEFISettings. The default behavior is: UEFISettings will not be enabled unless this property is set.", + "confidentialVM": "confidentialVM specifies the security configuration of the virtual machine. For more information regarding Confidential VMs, please refer to: https://learn.microsoft.com/azure/confidential-computing/confidential-vm-overview", + "trustedLaunch": "trustedLaunch specifies the security configuration of the virtual machine. For more information regarding TrustedLaunch for VMs, please refer to: https://learn.microsoft.com/azure/virtual-machines/trusted-launch", +} + +func (SecuritySettings) SwaggerDoc() map[string]string { + return map_SecuritySettings +} + +var map_SpotVMOptions = map[string]string{ + "": "SpotVMOptions defines the options relevant to running the Machine on Spot VMs", + "maxPrice": "maxPrice defines the maximum price the user is willing to pay for Spot VM instances", +} + +func (SpotVMOptions) SwaggerDoc() map[string]string { + return map_SpotVMOptions +} + +var map_TrustedLaunch = map[string]string{ + "": "TrustedLaunch defines the UEFI settings for the virtual machine.", + "uefiSettings": "uefiSettings specifies the security settings like secure boot and vTPM used while creating the virtual machine.", +} + +func (TrustedLaunch) SwaggerDoc() map[string]string { + return map_TrustedLaunch +} + +var map_UEFISettings = map[string]string{ + "": "UEFISettings specifies the security settings like secure boot and vTPM used while creating the virtual machine.", + "secureBoot": "secureBoot specifies whether secure boot should be enabled on the virtual machine. Secure Boot verifies the digital signature of all boot components and halts the boot process if signature verification fails. If omitted, the platform chooses a default, which is subject to change over time, currently that default is disabled.", + "virtualizedTrustedPlatformModule": "virtualizedTrustedPlatformModule specifies whether vTPM should be enabled on the virtual machine. When enabled the virtualized trusted platform module measurements are used to create a known good boot integrity policy baseline. The integrity policy baseline is used for comparison with measurements from subsequent VM boots to determine if anything has changed. This is required to be enabled if SecurityEncryptionType is defined. If omitted, the platform chooses a default, which is subject to change over time, currently that default is disabled.", +} + +func (UEFISettings) SwaggerDoc() map[string]string { + return map_UEFISettings +} + +var map_VMDiskSecurityProfile = map[string]string{ + "": "VMDiskSecurityProfile specifies the security profile settings for the managed disk. It can be set only for Confidential VMs.", + "diskEncryptionSet": "diskEncryptionSet specifies the customer managed disk encryption set resource id for the managed disk that is used for Customer Managed Key encrypted ConfidentialVM OS Disk and VMGuest blob.", + "securityEncryptionType": "securityEncryptionType specifies the encryption type of the managed disk. It is set to DiskWithVMGuestState to encrypt the managed disk along with the VMGuestState blob, and to VMGuestStateOnly to encrypt the VMGuestState blob only. When set to VMGuestStateOnly, the vTPM should be enabled. When set to DiskWithVMGuestState, both SecureBoot and vTPM should be enabled. If the above conditions are not fulfilled, the VM will not be created and the respective error will be returned. It can be set only for Confidential VMs. Confidential VMs are defined by their SecurityProfile.SecurityType being set to ConfidentialVM, the SecurityEncryptionType of their OS disk being set to one of the allowed values and by enabling the respective SecurityProfile.UEFISettings of the VM (i.e. vTPM and SecureBoot), depending on the selected SecurityEncryptionType. For further details on Azure Confidential VMs, please refer to the respective documentation: https://learn.microsoft.com/azure/confidential-computing/confidential-vm-overview", +} + +func (VMDiskSecurityProfile) SwaggerDoc() map[string]string { + return map_VMDiskSecurityProfile +} + +var map_GCPDisk = map[string]string{ + "": "GCPDisk describes disks for GCP.", + "autoDelete": "autoDelete indicates if the disk will be auto-deleted when the instance is deleted (default false).", + "boot": "boot indicates if this is a boot disk (default false).", + "sizeGb": "sizeGb is the size of the disk (in GB).", + "type": "type is the type of the disk (eg: pd-standard).", + "image": "image is the source image to create this disk.", + "labels": "labels list of labels to apply to the disk.", + "encryptionKey": "encryptionKey is the customer-supplied encryption key of the disk.", +} + +func (GCPDisk) SwaggerDoc() map[string]string { + return map_GCPDisk +} + +var map_GCPEncryptionKeyReference = map[string]string{ + "": "GCPEncryptionKeyReference describes the encryptionKey to use for a disk's encryption.", + "kmsKey": "KMSKeyName is the reference KMS key, in the format", + "kmsKeyServiceAccount": "kmsKeyServiceAccount is the service account being used for the encryption request for the given KMS key. If absent, the Compute Engine default service account is used. See https://cloud.google.com/compute/docs/access/service-accounts#compute_engine_service_account for details on the default service account.", +} + +func (GCPEncryptionKeyReference) SwaggerDoc() map[string]string { + return map_GCPEncryptionKeyReference +} + +var map_GCPGPUConfig = map[string]string{ + "": "GCPGPUConfig describes type and count of GPUs attached to the instance on GCP.", + "count": "count is the number of GPUs to be attached to an instance.", + "type": "type is the type of GPU to be attached to an instance. Supported GPU types are: nvidia-tesla-k80, nvidia-tesla-p100, nvidia-tesla-v100, nvidia-tesla-p4, nvidia-tesla-t4", +} + +func (GCPGPUConfig) SwaggerDoc() map[string]string { + return map_GCPGPUConfig +} + +var map_GCPKMSKeyReference = map[string]string{ + "": "GCPKMSKeyReference gathers required fields for looking up a GCP KMS Key", + "name": "name is the name of the customer managed encryption key to be used for the disk encryption.", + "keyRing": "keyRing is the name of the KMS Key Ring which the KMS Key belongs to.", + "projectID": "projectID is the ID of the Project in which the KMS Key Ring exists. Defaults to the VM ProjectID if not set.", + "location": "location is the GCP location in which the Key Ring exists.", +} + +func (GCPKMSKeyReference) SwaggerDoc() map[string]string { + return map_GCPKMSKeyReference +} + +var map_GCPMachineProviderSpec = map[string]string{ + "": "GCPMachineProviderSpec is the type that will be embedded in a Machine.Spec.ProviderSpec field for an GCP virtual machine. It is used by the GCP machine actuator to create a single Machine. Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "userDataSecret": "userDataSecret contains a local reference to a secret that contains the UserData to apply to the instance", + "credentialsSecret": "credentialsSecret is a reference to the secret with GCP credentials.", + "canIPForward": "canIPForward Allows this instance to send and receive packets with non-matching destination or source IPs. This is required if you plan to use this instance to forward routes.", + "deletionProtection": "deletionProtection whether the resource should be protected against deletion.", + "disks": "disks is a list of disks to be attached to the VM.", + "labels": "labels list of labels to apply to the VM.", + "gcpMetadata": "Metadata key/value pairs to apply to the VM.", + "networkInterfaces": "networkInterfaces is a list of network interfaces to be attached to the VM.", + "serviceAccounts": "serviceAccounts is a list of GCP service accounts to be used by the VM.", + "tags": "tags list of network tags to apply to the VM.", + "targetPools": "targetPools are used for network TCP/UDP load balancing. A target pool references member instances, an associated legacy HttpHealthCheck resource, and, optionally, a backup target pool", + "machineType": "machineType is the machine type to use for the VM.", + "region": "region is the region in which the GCP machine provider will create the VM.", + "zone": "zone is the zone in which the GCP machine provider will create the VM.", + "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", + "confidentialCompute": "confidentialCompute is an optional field defining whether the instance should have confidential compute enabled or not, and the confidential computing technology of choice. Allowed values are omitted, Disabled, Enabled, AMDEncryptedVirtualization, AMDEncryptedVirtualizationNestedPaging, and IntelTrustedDomainExtensions When set to Disabled, the machine will not be configured to be a confidential computing instance. When set to Enabled, the machine will be configured as a confidential computing instance with no preference on the confidential compute policy used. In this mode, the platform chooses a default that is subject to change over time. Currently, the default is to use AMD Secure Encrypted Virtualization. When set to AMDEncryptedVirtualization, the machine will be configured as a confidential computing instance with AMD Secure Encrypted Virtualization (AMD SEV) as the confidential computing technology. When set to AMDEncryptedVirtualizationNestedPaging, the machine will be configured as a confidential computing instance with AMD Secure Encrypted Virtualization Secure Nested Paging (AMD SEV-SNP) as the confidential computing technology. When set to IntelTrustedDomainExtensions, the machine will be configured as a confidential computing instance with Intel Trusted Domain Extensions (Intel TDX) as the confidential computing technology. If any value other than Disabled is set the selected machine type must support that specific confidential computing technology. The machine series supporting confidential computing technologies can be checked at https://cloud.google.com/confidential-computing/confidential-vm/docs/supported-configurations#all-confidential-vm-instances Currently, AMDEncryptedVirtualization is supported in c2d, n2d, and c3d machines. AMDEncryptedVirtualizationNestedPaging is supported in n2d machines. IntelTrustedDomainExtensions is supported in c3 machines. If any value other than Disabled is set, the selected region must support that specific confidential computing technology. The list of regions supporting confidential computing technologies can be checked at https://cloud.google.com/confidential-computing/confidential-vm/docs/supported-configurations#supported-zones If any value other than Disabled is set onHostMaintenance is required to be set to \"Terminate\". If omitted, the platform chooses a default, which is subject to change over time, currently that default is Disabled.", + "resourceManagerTags": "resourceManagerTags is an optional list of tags to apply to the GCP resources created for the cluster. See https://cloud.google.com/resource-manager/docs/tags/tags-overview for information on tagging GCP resources. GCP supports a maximum of 50 tags per resource.", +} + +func (GCPMachineProviderSpec) SwaggerDoc() map[string]string { + return map_GCPMachineProviderSpec +} + +var map_GCPMachineProviderStatus = map[string]string{ + "": "GCPMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. It contains GCP-specific status information. Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "instanceId": "instanceId is the ID of the instance in GCP", + "instanceState": "instanceState is the provisioning state of the GCP Instance.", + "conditions": "conditions is a set of conditions associated with the Machine to indicate errors or other status", +} + +func (GCPMachineProviderStatus) SwaggerDoc() map[string]string { + return map_GCPMachineProviderStatus +} + +var map_GCPMetadata = map[string]string{ + "": "GCPMetadata describes metadata for GCP.", + "key": "key is the metadata key.", + "value": "value is the metadata value.", +} + +func (GCPMetadata) SwaggerDoc() map[string]string { + return map_GCPMetadata +} + +var map_GCPNetworkInterface = map[string]string{ + "": "GCPNetworkInterface describes network interfaces for GCP", + "publicIP": "publicIP indicates if true a public IP will be used", + "network": "network is the network name.", + "projectID": "projectID is the project in which the GCP machine provider will create the VM.", + "subnetwork": "subnetwork is the subnetwork name.", +} + +func (GCPNetworkInterface) SwaggerDoc() map[string]string { + return map_GCPNetworkInterface +} + +var map_GCPServiceAccount = map[string]string{ + "": "GCPServiceAccount describes service accounts for GCP.", + "email": "email is the service account email.", + "scopes": "scopes list of scopes to be assigned to the service account.", +} + +func (GCPServiceAccount) SwaggerDoc() map[string]string { + return map_GCPServiceAccount +} + +var map_GCPShieldedInstanceConfig = map[string]string{ + "": "GCPShieldedInstanceConfig describes the shielded VM configuration of the instance on GCP. Shielded VM configuration allow users to enable and disable Secure Boot, vTPM, and Integrity Monitoring.", + "secureBoot": "secureBoot Defines whether the instance should have secure boot enabled. Secure Boot verify the digital signature of all boot components, and halting the boot process if signature verification fails. If omitted, the platform chooses a default, which is subject to change over time, currently that default is Disabled.", + "virtualizedTrustedPlatformModule": "virtualizedTrustedPlatformModule enable virtualized trusted platform module measurements to create a known good boot integrity policy baseline. The integrity policy baseline is used for comparison with measurements from subsequent VM boots to determine if anything has changed. This is required to be set to \"Enabled\" if IntegrityMonitoring is enabled. If omitted, the platform chooses a default, which is subject to change over time, currently that default is Enabled.", + "integrityMonitoring": "integrityMonitoring determines whether the instance should have integrity monitoring that verify the runtime boot integrity. Compares the most recent boot measurements to the integrity policy baseline and return a pair of pass/fail results depending on whether they match or not. If omitted, the platform chooses a default, which is subject to change over time, currently that default is Enabled.", +} + +func (GCPShieldedInstanceConfig) SwaggerDoc() map[string]string { + return map_GCPShieldedInstanceConfig +} + +var map_ResourceManagerTag = map[string]string{ + "": "ResourceManagerTag is a tag to apply to GCP resources created for the cluster.", + "parentID": "parentID is the ID of the hierarchical resource where the tags are defined e.g. at the Organization or the Project level. To find the Organization or Project ID ref https://cloud.google.com/resource-manager/docs/creating-managing-organization#retrieving_your_organization_id https://cloud.google.com/resource-manager/docs/creating-managing-projects#identifying_projects An OrganizationID can have a maximum of 32 characters and must consist of decimal numbers, and cannot have leading zeroes. A ProjectID must be 6 to 30 characters in length, can only contain lowercase letters, numbers, and hyphens, and must start with a letter, and cannot end with a hyphen.", + "key": "key is the key part of the tag. A tag key can have a maximum of 63 characters and cannot be empty. Tag key must begin and end with an alphanumeric character, and must contain only uppercase, lowercase alphanumeric characters, and the following special characters `._-`.", + "value": "value is the value part of the tag. A tag value can have a maximum of 63 characters and cannot be empty. Tag value must begin and end with an alphanumeric character, and must contain only uppercase, lowercase alphanumeric characters, and the following special characters `_-.@%=+:,*#&(){}[]` and spaces.", +} + +func (ResourceManagerTag) SwaggerDoc() map[string]string { + return map_ResourceManagerTag +} + +var map_LastOperation = map[string]string{ + "": "LastOperation represents the detail of the last performed operation on the MachineObject.", + "description": "description is the human-readable description of the last operation.", + "lastUpdated": "lastUpdated is the timestamp at which LastOperation API was last-updated.", + "state": "state is the current status of the last performed operation. E.g. Processing, Failed, Successful etc", + "type": "type is the type of operation which was last performed. E.g. Create, Delete, Update etc", +} + +func (LastOperation) SwaggerDoc() map[string]string { + return map_LastOperation +} + +var map_LifecycleHook = map[string]string{ + "": "LifecycleHook represents a single instance of a lifecycle hook", + "name": "name defines a unique name for the lifcycle hook. The name should be unique and descriptive, ideally 1-3 words, in CamelCase or it may be namespaced, eg. foo.example.com/CamelCase. Names must be unique and should only be managed by a single entity.", + "owner": "owner defines the owner of the lifecycle hook. This should be descriptive enough so that users can identify who/what is responsible for blocking the lifecycle. This could be the name of a controller (e.g. clusteroperator/etcd) or an administrator managing the hook.", +} + +func (LifecycleHook) SwaggerDoc() map[string]string { + return map_LifecycleHook +} + +var map_LifecycleHooks = map[string]string{ + "": "LifecycleHooks allow users to pause operations on the machine at certain prefedined points within the machine lifecycle.", + "preDrain": "preDrain hooks prevent the machine from being drained. This also blocks further lifecycle events, such as termination.", + "preTerminate": "preTerminate hooks prevent the machine from being terminated. PreTerminate hooks be actioned after the Machine has been drained.", +} + +func (LifecycleHooks) SwaggerDoc() map[string]string { + return map_LifecycleHooks +} + +var map_Machine = map[string]string{ + "": "Machine is the Schema for the machines API Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", +} + +func (Machine) SwaggerDoc() map[string]string { + return map_Machine +} + +var map_MachineList = map[string]string{ + "": "MachineList contains a list of Machine Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard list's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", +} + +func (MachineList) SwaggerDoc() map[string]string { + return map_MachineList +} + +var map_MachineSpec = map[string]string{ + "": "MachineSpec defines the desired state of Machine", + "metadata": "ObjectMeta will autopopulate the Node created. Use this to indicate what labels, annotations, name prefix, etc., should be used when creating the Node.", + "lifecycleHooks": "lifecycleHooks allow users to pause operations on the machine at certain predefined points within the machine lifecycle.", + "taints": "The list of the taints to be applied to the corresponding Node in additive manner. This list will not overwrite any other taints added to the Node on an ongoing basis by other entities. These taints should be actively reconciled e.g. if you ask the machine controller to apply a taint and then manually remove the taint the machine controller will put it back) but not have the machine controller remove any taints", + "providerSpec": "providerSpec details Provider-specific configuration to use during node creation.", + "providerID": "providerID is the identification ID of the machine provided by the provider. This field must match the provider ID as seen on the node object corresponding to this machine. This field is required by higher level consumers of cluster-api. Example use case is cluster autoscaler with cluster-api as provider. Clean-up logic in the autoscaler compares machines to nodes to find out machines at provider which could not get registered as Kubernetes nodes. With cluster-api as a generic out-of-tree provider for autoscaler, this field is required by autoscaler to be able to have a provider view of the list of machines. Another list of nodes is queried from the k8s apiserver and then a comparison is done to find out unregistered machines and are marked for delete. This field will be set by the actuators and consumed by higher level entities like autoscaler that will be interfacing with cluster-api as generic provider.", + "authoritativeAPI": "authoritativeAPI is the API that is authoritative for this resource. Valid values are MachineAPI and ClusterAPI. When set to MachineAPI, writes to the spec of the machine.openshift.io copy of this resource will be reflected into the cluster.x-k8s.io copy. When set to ClusterAPI, writes to the spec of the cluster.x-k8s.io copy of this resource will be reflected into the machine.openshift.io copy. Updates to the status will be reflected in both copies of the resource, based on the controller implementing the functionality of the API. Currently the authoritative API determines which controller will manage the resource, this will change in a future release. To ensure the change has been accepted, please verify that the `status.authoritativeAPI` field has been updated to the desired value and that the `Synchronized` condition is present and set to `True`.", +} + +func (MachineSpec) SwaggerDoc() map[string]string { + return map_MachineSpec +} + +var map_MachineStatus = map[string]string{ + "": "MachineStatus defines the observed state of Machine", + "nodeRef": "nodeRef will point to the corresponding Node if it exists.", + "lastUpdated": "lastUpdated identifies when this status was last observed.", + "errorReason": "errorReason will be set in the event that there is a terminal problem reconciling the Machine and will contain a succinct value suitable for machine interpretation.\n\nThis field should not be set for transitive errors that a controller faces that are expected to be fixed automatically over time (like service outages), but instead indicate that something is fundamentally wrong with the Machine's spec or the configuration of the controller, and that manual intervention is required. Examples of terminal errors would be invalid combinations of settings in the spec, values that are unsupported by the controller, or the responsible controller itself being critically misconfigured.\n\nAny transient errors that occur during the reconciliation of Machines can be added as events to the Machine object and/or logged in the controller's output.", + "errorMessage": "errorMessage will be set in the event that there is a terminal problem reconciling the Machine and will contain a more verbose string suitable for logging and human consumption.\n\nThis field should not be set for transitive errors that a controller faces that are expected to be fixed automatically over time (like service outages), but instead indicate that something is fundamentally wrong with the Machine's spec or the configuration of the controller, and that manual intervention is required. Examples of terminal errors would be invalid combinations of settings in the spec, values that are unsupported by the controller, or the responsible controller itself being critically misconfigured.\n\nAny transient errors that occur during the reconciliation of Machines can be added as events to the Machine object and/or logged in the controller's output.", + "providerStatus": "providerStatus details a Provider-specific status. It is recommended that providers maintain their own versioned API types that should be serialized/deserialized from this field.", + "addresses": "addresses is a list of addresses assigned to the machine. Queried from cloud provider, if available.", + "lastOperation": "lastOperation describes the last-operation performed by the machine-controller. This API should be useful as a history in terms of the latest operation performed on the specific machine. It should also convey the state of the latest-operation for example if it is still on-going, failed or completed successfully.", + "phase": "phase represents the current phase of machine actuation. One of: Failed, Provisioning, Provisioned, Running, Deleting", + "conditions": "conditions defines the current state of the Machine", + "authoritativeAPI": "authoritativeAPI is the API that is authoritative for this resource. Valid values are MachineAPI, ClusterAPI and Migrating. This value is updated by the migration controller to reflect the authoritative API. Machine API and Cluster API controllers use this value to determine whether or not to reconcile the resource. When set to Migrating, the migration controller is currently performing the handover of authority from one API to the other.", + "synchronizedAPI": "synchronizedAPI holds the last stable value of authoritativeAPI. It is used to detect migration cancellation requests and to restore the resource to its previous state. Valid values are \"MachineAPI\" and \"ClusterAPI\". When omitted, the resource has not yet been reconciled by the migration controller.", + "synchronizedGeneration": "synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with. This field is set when the authoritative resource is updated and the sync controller has updated the non-authoritative resource to match.", +} + +func (MachineStatus) SwaggerDoc() map[string]string { + return map_MachineStatus +} + +var map_MachineHealthCheck = map[string]string{ + "": "MachineHealthCheck is the Schema for the machinehealthchecks API Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "spec": "Specification of machine health check policy", + "status": "Most recently observed status of MachineHealthCheck resource", +} + +func (MachineHealthCheck) SwaggerDoc() map[string]string { + return map_MachineHealthCheck +} + +var map_MachineHealthCheckList = map[string]string{ + "": "MachineHealthCheckList contains a list of MachineHealthCheck Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard list's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", +} + +func (MachineHealthCheckList) SwaggerDoc() map[string]string { + return map_MachineHealthCheckList +} + +var map_MachineHealthCheckSpec = map[string]string{ + "": "MachineHealthCheckSpec defines the desired state of MachineHealthCheck", + "selector": "Label selector to match machines whose health will be exercised. Note: An empty selector will match all machines.", + "unhealthyConditions": "unhealthyConditions contains a list of the conditions that determine whether a node is considered unhealthy. The conditions are combined in a logical OR, i.e. if any of the conditions is met, the node is unhealthy.", + "maxUnhealthy": "Any farther remediation is only allowed if at most \"MaxUnhealthy\" machines selected by \"selector\" are not healthy. Expects either a postive integer value or a percentage value. Percentage values must be positive whole numbers and are capped at 100%. Both 0 and 0% are valid and will block all remediation. Defaults to 100% if not set.", + "nodeStartupTimeout": "Machines older than this duration without a node will be considered to have failed and will be remediated. To prevent Machines without Nodes from being removed, disable startup checks by setting this value explicitly to \"0\". Expects an unsigned duration string of decimal numbers each with optional fraction and a unit suffix, eg \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".", + "remediationTemplate": "remediationTemplate is a reference to a remediation template provided by an infrastructure provider.\n\nThis field is completely optional, when filled, the MachineHealthCheck controller creates a new object from the template referenced and hands off remediation of the machine to a controller that lives outside of Machine API Operator.", +} + +func (MachineHealthCheckSpec) SwaggerDoc() map[string]string { + return map_MachineHealthCheckSpec +} + +var map_MachineHealthCheckStatus = map[string]string{ + "": "MachineHealthCheckStatus defines the observed state of MachineHealthCheck", + "expectedMachines": "total number of machines counted by this machine health check", + "currentHealthy": "total number of machines counted by this machine health check", + "remediationsAllowed": "remediationsAllowed is the number of further remediations allowed by this machine health check before maxUnhealthy short circuiting will be applied", + "conditions": "conditions defines the current state of the MachineHealthCheck", +} + +func (MachineHealthCheckStatus) SwaggerDoc() map[string]string { + return map_MachineHealthCheckStatus +} + +var map_UnhealthyCondition = map[string]string{ + "": "UnhealthyCondition represents a Node condition type and value with a timeout specified as a duration. When the named condition has been in the given status for at least the timeout value, a node is considered unhealthy.", + "timeout": "Expects an unsigned duration string of decimal numbers each with optional fraction and a unit suffix, eg \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".", +} + +func (UnhealthyCondition) SwaggerDoc() map[string]string { + return map_UnhealthyCondition +} + +var map_MachineSet = map[string]string{ + "": "MachineSet ensures that a specified number of machines replicas are running at any given time. Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", +} + +func (MachineSet) SwaggerDoc() map[string]string { + return map_MachineSet +} + +var map_MachineSetList = map[string]string{ + "": "MachineSetList contains a list of MachineSet Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "metadata": "metadata is the standard list's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", +} + +func (MachineSetList) SwaggerDoc() map[string]string { + return map_MachineSetList +} + +var map_MachineSetSpec = map[string]string{ + "": "MachineSetSpec defines the desired state of MachineSet", + "replicas": "replicas is the number of desired replicas. This is a pointer to distinguish between explicit zero and unspecified. Defaults to 1.", + "minReadySeconds": "minReadySeconds is the minimum number of seconds for which a newly created machine should be ready. Defaults to 0 (machine will be considered available as soon as it is ready)", + "deletePolicy": "deletePolicy defines the policy used to identify nodes to delete when downscaling. Defaults to \"Random\". Valid values are \"Random, \"Newest\", \"Oldest\"", + "selector": "selector is a label query over machines that should match the replica count. Label keys and values that must match in order to be controlled by this MachineSet. It must match the machine template's labels. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", + "template": "template is the object that describes the machine that will be created if insufficient replicas are detected.", + "authoritativeAPI": "authoritativeAPI is the API that is authoritative for this resource. Valid values are MachineAPI and ClusterAPI. When set to MachineAPI, writes to the spec of the machine.openshift.io copy of this resource will be reflected into the cluster.x-k8s.io copy. When set to ClusterAPI, writes to the spec of the cluster.x-k8s.io copy of this resource will be reflected into the machine.openshift.io copy. Updates to the status will be reflected in both copies of the resource, based on the controller implementing the functionality of the API. Currently the authoritative API determines which controller will manage the resource, this will change in a future release. To ensure the change has been accepted, please verify that the `status.authoritativeAPI` field has been updated to the desired value and that the `Synchronized` condition is present and set to `True`.", +} + +func (MachineSetSpec) SwaggerDoc() map[string]string { + return map_MachineSetSpec +} + +var map_MachineSetStatus = map[string]string{ + "": "MachineSetStatus defines the observed state of MachineSet", + "replicas": "replicas is the most recently observed number of replicas.", + "fullyLabeledReplicas": "The number of replicas that have labels matching the labels of the machine template of the MachineSet.", + "readyReplicas": "The number of ready replicas for this MachineSet. A machine is considered ready when the node has been created and is \"Ready\".", + "availableReplicas": "The number of available replicas (ready for at least minReadySeconds) for this MachineSet.", + "observedGeneration": "observedGeneration reflects the generation of the most recently observed MachineSet.", + "labelSelector": "labelSelector is a label selector, in string format, for Machines corresponding to the MachineSet. It is exposed via the scale subresource as status.selector. When omitted, the MachineSet controller has not yet reconciled spec.selector into status.labelSelector. When present, it must not be empty and must not exceed 4096 characters.", + "errorReason": "In the event that there is a terminal problem reconciling the replicas, both ErrorReason and ErrorMessage will be set. ErrorReason will be populated with a succinct value suitable for machine interpretation, while ErrorMessage will contain a more verbose string suitable for logging and human consumption.\n\nThese fields should not be set for transitive errors that a controller faces that are expected to be fixed automatically over time (like service outages), but instead indicate that something is fundamentally wrong with the MachineTemplate's spec or the configuration of the machine controller, and that manual intervention is required. Examples of terminal errors would be invalid combinations of settings in the spec, values that are unsupported by the machine controller, or the responsible machine controller itself being critically misconfigured.\n\nAny transient errors that occur during the reconciliation of Machines can be added as events to the MachineSet object and/or logged in the controller's output.", + "conditions": "conditions defines the current state of the MachineSet", + "authoritativeAPI": "authoritativeAPI is the API that is authoritative for this resource. Valid values are MachineAPI, ClusterAPI and Migrating. This value is updated by the migration controller to reflect the authoritative API. Machine API and Cluster API controllers use this value to determine whether or not to reconcile the resource. When set to Migrating, the migration controller is currently performing the handover of authority from one API to the other.", + "synchronizedAPI": "synchronizedAPI holds the last stable value of authoritativeAPI. It is used to detect migration cancellation requests and to restore the resource to its previous state. Valid values are \"MachineAPI\" and \"ClusterAPI\". When omitted, the resource has not yet been reconciled by the migration controller.", + "synchronizedGeneration": "synchronizedGeneration is the generation of the authoritative resource that the non-authoritative resource is synchronised with. This field is set when the authoritative resource is updated and the sync controller has updated the non-authoritative resource to match.", +} + +func (MachineSetStatus) SwaggerDoc() map[string]string { + return map_MachineSetStatus +} + +var map_MachineTemplateSpec = map[string]string{ + "": "MachineTemplateSpec describes the data needed to create a Machine from a template", + "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", + "spec": "Specification of the desired behavior of the machine. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status", +} + +func (MachineTemplateSpec) SwaggerDoc() map[string]string { + return map_MachineTemplateSpec +} + +var map_Condition = map[string]string{ + "": "Condition defines an observation of a Machine API resource operational state.", + "type": "type of condition in CamelCase or in foo.example.com/CamelCase. Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important.", + "status": "status of the condition, one of True, False, Unknown.", + "severity": "severity provides an explicit classification of Reason code, so the users or machines can immediately understand the current situation and act accordingly. The Severity field MUST be set only when Status=False.", + "lastTransitionTime": "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.", + "reason": "The reason for the condition's last transition in CamelCase. The specific API may choose whether or not this field is considered a guaranteed API. This field may not be empty.", + "message": "A human readable message indicating details about the transition. This field may be empty.", +} + +func (Condition) SwaggerDoc() map[string]string { + return map_Condition +} + +var map_ObjectMeta = map[string]string{ + "": "ObjectMeta is metadata that all persisted resources must have, which includes all objects users must create. This is a copy of customizable fields from metav1.ObjectMeta.\n\nObjectMeta is embedded in `Machine.Spec`, `MachineDeployment.Template` and `MachineSet.Template`, which are not top-level Kubernetes objects. Given that metav1.ObjectMeta has lots of special cases and read-only fields which end up in the generated CRD validation, having it as a subset simplifies the API and some issues that can impact user experience.\n\nDuring the [upgrade to controller-tools@v2](https://github.com/kubernetes-sigs/cluster-api/pull/1054) for v1alpha2, we noticed a failure would occur running Cluster API test suite against the new CRDs, specifically `spec.metadata.creationTimestamp in body must be of type string: \"null\"`. The investigation showed that `controller-tools@v2` behaves differently than its previous version when handling types from [metav1](k8s.io/apimachinery/pkg/apis/meta/v1) package.\n\nIn more details, we found that embedded (non-top level) types that embedded `metav1.ObjectMeta` had validation properties, including for `creationTimestamp` (metav1.Time). The `metav1.Time` type specifies a custom json marshaller that, when IsZero() is true, returns `null` which breaks validation because the field isn't marked as nullable.\n\nIn future versions, controller-tools@v2 might allow overriding the type and validation for embedded types. When that happens, this hack should be revisited.", + "name": "name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names", + "generateName": "generateName is an optional prefix, used by the server, to generate a unique name ONLY IF the Name field has not been provided. If this field is used, the name returned to the client will be different than the name passed. This value will also be combined with a unique suffix. The provided value has the same validation rules as the Name field, and may be truncated by the length of the suffix required to make the value unique on the server.\n\nIf this field is specified and the generated name exists, the server will NOT return a 409 - instead, it will either return 201 Created or 500 with Reason ServerTimeout indicating a unique name could not be found in the time allotted, and the client should retry (optionally after the time indicated in the Retry-After header).\n\nApplied only if Name is not specified. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency", + "namespace": "namespace defines the space within each name must be unique. An empty namespace is equivalent to the \"default\" namespace, but \"default\" is the canonical representation. Not all objects are required to be scoped to a namespace - the value of this field for those objects will be empty.\n\nMust be a DNS_LABEL. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/namespaces", + "labels": "Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels", + "annotations": "annotations is an unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. They are not queryable and should be preserved when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations", + "ownerReferences": "List of objects depended by this object. If ALL objects in the list have been deleted, this object will be garbage collected. If this object is managed by a controller, then an entry in this list will point to this controller, with the controller field set to true. There cannot be more than one managing controller.", +} + +func (ObjectMeta) SwaggerDoc() map[string]string { + return map_ObjectMeta +} + +var map_ProviderSpec = map[string]string{ + "": "ProviderSpec defines the configuration to use during node creation.", + "value": "value is an inlined, serialized representation of the resource configuration. It is recommended that providers maintain their own versioned API types that should be serialized/deserialized from this field, akin to component config.", +} + +func (ProviderSpec) SwaggerDoc() map[string]string { + return map_ProviderSpec +} + +var map_AddressesFromPool = map[string]string{ + "": "AddressesFromPool is an IPAddressPool that will be used to create IPAddressClaims for fulfillment by an external controller.", + "group": "group of the IP address pool type known to an external IPAM controller. This should be a fully qualified domain name, for example, externalipam.controller.io.", + "resource": "resource of the IP address pool type known to an external IPAM controller. It is normally the plural form of the resource kind in lowercase, for example, ippools.", + "name": "name of an IP address pool, for example, pool-config-1.", +} + +func (AddressesFromPool) SwaggerDoc() map[string]string { + return map_AddressesFromPool +} + +var map_NetworkDeviceSpec = map[string]string{ + "": "NetworkDeviceSpec defines the network configuration for a virtual machine's network device.", + "networkName": "networkName is the name of the vSphere network or port group to which the network device will be connected, for example, port-group-1. When not provided, the vCenter API will attempt to select a default network. The available networks (port groups) can be listed using `govc ls 'network/*'`", + "gateway": "gateway is an IPv4 or IPv6 address which represents the subnet gateway, for example, 192.168.1.1.", + "ipAddrs": "ipAddrs is a list of one or more IPv4 and/or IPv6 addresses and CIDR to assign to this device, for example, 192.168.1.100/24. IP addresses provided via ipAddrs are intended to allow explicit assignment of a machine's IP address. IP pool configurations provided via addressesFromPool, however, defer IP address assignment to an external controller. If both addressesFromPool and ipAddrs are empty or not defined, DHCP will be used to assign an IP address. If both ipAddrs and addressesFromPools are defined, the IP addresses associated with ipAddrs will be applied first followed by IP addresses from addressesFromPools.", + "nameservers": "nameservers is a list of IPv4 and/or IPv6 addresses used as DNS nameservers, for example, 8.8.8.8. a nameserver is not provided by a fulfilled IPAddressClaim. If DHCP is not the source of IP addresses for this network device, nameservers should include a valid nameserver.", + "addressesFromPools": "addressesFromPools is a list of references to IP pool types and instances which are handled by an external controller. addressesFromPool configurations provided via addressesFromPools defer IP address assignment to an external controller. IP addresses provided via ipAddrs, however, are intended to allow explicit assignment of a machine's IP address. If both addressesFromPool and ipAddrs are empty or not defined, DHCP will assign an IP address. If both ipAddrs and addressesFromPools are defined, the IP addresses associated with ipAddrs will be applied first followed by IP addresses from addressesFromPools.", +} + +func (NetworkDeviceSpec) SwaggerDoc() map[string]string { + return map_NetworkDeviceSpec +} + +var map_NetworkSpec = map[string]string{ + "": "NetworkSpec defines the virtual machine's network configuration.", + "devices": "devices defines the virtual machine's network interfaces.", +} + +func (NetworkSpec) SwaggerDoc() map[string]string { + return map_NetworkSpec +} + +var map_VSphereDisk = map[string]string{ + "": "VSphereDisk describes additional disks for vSphere.", + "name": "name is used to identify the disk definition. name is required needs to be unique so that it can be used to clearly identify purpose of the disk. It must be at most 80 characters in length and must consist only of alphanumeric characters, hyphens and underscores, and must start and end with an alphanumeric character.", + "sizeGiB": "sizeGiB is the size of the disk in GiB. The maximum supported size 16384 GiB.", + "provisioningMode": "provisioningMode is an optional field that specifies the provisioning type to be used by this vSphere data disk. Allowed values are \"Thin\", \"Thick\", \"EagerlyZeroed\", and omitted. When set to Thin, the disk will be made using thin provisioning allocating the bare minimum space. When set to Thick, the full disk size will be allocated when disk is created. When set to EagerlyZeroed, the disk will be created using eager zero provisioning. An eager zeroed thick disk has all space allocated and wiped clean of any previous contents on the physical media at creation time. Such disks may take longer time during creation compared to other disk formats. When omitted, no setting will be applied to the data disk and the provisioning mode for the disk will be determined by the default storage policy configured for the datastore in vSphere.", +} + +func (VSphereDisk) SwaggerDoc() map[string]string { + return map_VSphereDisk +} + +var map_VSphereMachineProviderSpec = map[string]string{ + "": "VSphereMachineProviderSpec is the type that will be embedded in a Machine.Spec.ProviderSpec field for an VSphere virtual machine. It is used by the vSphere machine actuator to create a single Machine. Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "userDataSecret": "userDataSecret contains a local reference to a secret that contains the UserData to apply to the instance", + "credentialsSecret": "credentialsSecret is a reference to the secret with vSphere credentials.", + "template": "template is the name, inventory path, or instance UUID of the template used to clone new machines.", + "workspace": "workspace describes the workspace to use for the machine.", + "network": "network is the network configuration for this machine's VM.", + "numCPUs": "numCPUs is the number of virtual processors in a virtual machine. Defaults to the analogue property value in the template from which this machine is cloned.", + "numCoresPerSocket": "NumCPUs is the number of cores among which to distribute CPUs in this virtual machine. Defaults to the analogue property value in the template from which this machine is cloned.", + "memoryMiB": "memoryMiB is the size of a virtual machine's memory, in MiB. Defaults to the analogue property value in the template from which this machine is cloned.", + "diskGiB": "diskGiB is the size of a virtual machine's disk, in GiB. Defaults to the analogue property value in the template from which this machine is cloned. This parameter will be ignored if 'LinkedClone' CloneMode is set.", + "tagIDs": "tagIDs is an optional set of tags to add to an instance. Specified tagIDs must use URN-notation instead of display names. A maximum of 10 tag IDs may be specified.", + "snapshot": "snapshot is the name of the snapshot from which the VM was cloned", + "cloneMode": "cloneMode specifies the type of clone operation. The LinkedClone mode is only support for templates that have at least one snapshot. If the template has no snapshots, then CloneMode defaults to FullClone. When LinkedClone mode is enabled the DiskGiB field is ignored as it is not possible to expand disks of linked clones. Defaults to FullClone. When using LinkedClone, if no snapshots exist for the source template, falls back to FullClone.", + "dataDisks": "dataDisks is a list of non OS disks to be created and attached to the VM. The max number of disk allowed to be attached is currently 29. The max number of disks for any controller is 30, but VM template will always have OS disk so that will leave 29 disks on any controller type.", +} + +func (VSphereMachineProviderSpec) SwaggerDoc() map[string]string { + return map_VSphereMachineProviderSpec +} + +var map_VSphereMachineProviderStatus = map[string]string{ + "": "VSphereMachineProviderStatus is the type that will be embedded in a Machine.Status.ProviderStatus field. It contains VSphere-specific status information. Compatibility level 2: Stable within a major release for a minimum of 9 months or 3 minor releases (whichever is longer).", + "instanceId": "instanceId is the ID of the instance in VSphere", + "instanceState": "instanceState is the provisioning state of the VSphere Instance.", + "conditions": "conditions is a set of conditions associated with the Machine to indicate errors or other status", + "taskRef": "taskRef is a managed object reference to a Task related to the machine. This value is set automatically at runtime and should not be set or modified by users.", +} + +func (VSphereMachineProviderStatus) SwaggerDoc() map[string]string { + return map_VSphereMachineProviderStatus +} + +var map_Workspace = map[string]string{ + "": "WorkspaceConfig defines a workspace configuration for the vSphere cloud provider.", + "server": "server is the IP address or FQDN of the vSphere endpoint.", + "datacenter": "datacenter is the datacenter in which VMs are created/located.", + "folder": "folder is the folder in which VMs are created/located.", + "datastore": "datastore is the datastore in which VMs are created/located.", + "resourcePool": "resourcePool is the resource pool in which VMs are created/located.", + "vmGroup": "vmGroup is the cluster vm group in which virtual machines will be added for vm host group based zonal.", +} + +func (Workspace) SwaggerDoc() map[string]string { + return map_Workspace +} + +// AUTO-GENERATED FUNCTIONS END HERE 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 53c71aabb..52f5db78d 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 @@ -163,7 +163,15 @@ type AWSCSIDriverConfigSpec struct { // kmsKeyARN sets the cluster default storage class to encrypt volumes with a user-defined KMS key, // rather than the default KMS key used by AWS. // The value may be either the ARN or Alias ARN of a KMS key. - // +kubebuilder:validation:Pattern:=`^arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b|aws-iso-e|aws-iso-f):kms:[a-z0-9-]+:[0-9]{12}:(key|alias)\/.*$` + // + // The ARN must follow the format: arn::kms:::(key|alias)/, where: + // is the AWS partition (aws, aws-cn, aws-us-gov, aws-iso, aws-iso-b, aws-iso-e, aws-iso-f, or aws-eusc), + // is the AWS region, + // is a 12-digit numeric identifier for the AWS account, + // is the KMS key ID or alias name. + // + // +openshift:validation:FeatureGateAwareXValidation:featureGate="",rule=`matches(self, '^arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b|aws-iso-e|aws-iso-f):kms:[a-z0-9-]+:[0-9]{12}:(key|alias)/.*$')`,message=`kmsKeyARN must be a valid AWS KMS key ARN in the format: arn::kms:::(key|alias)/` + // +openshift:validation:FeatureGateAwareXValidation:featureGate=AWSEuropeanSovereignCloudInstall,rule=`matches(self, '^arn:(aws|aws-cn|aws-us-gov|aws-iso|aws-iso-b|aws-iso-e|aws-iso-f|aws-eusc):kms:[a-z0-9-]+:[0-9]{12}:(key|alias)/.*$')`,message=`kmsKeyARN must be a valid AWS KMS key ARN in the format: arn::kms:::(key|alias)/` // +optional KMSKeyARN string `json:"kmsKeyARN,omitempty"` 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 d54352f2c..0c5cf919e 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_ingress.go +++ b/vendor/github.com/openshift/api/operator/v1/types_ingress.go @@ -2068,8 +2068,51 @@ type IngressControllerTuningOptions struct { // +kubebuilder:validation:Type:=string // +optional ReloadInterval metav1.Duration `json:"reloadInterval,omitempty"` + + // configurationManagement specifies how OpenShift router should update + // the HAProxy configuration. The following values are valid for this + // field: + // + // * "ForkAndReload". + // * "Dynamic". + // + // Omitting this field means that the user has no opinion and the + // platform may choose a reasonable default. This default is subject to + // change over time. The current default is "ForkAndReload". + // + // "ForkAndReload" means that OpenShift router should rewrite the + // HAProxy configuration file and instruct HAProxy to fork and reload. + // This is OpenShift router's traditional approach. + // + // "Dynamic" means that OpenShift router may use HAProxy's control + // socket for some configuration updates and fall back to fork and + // reload for other configuration updates. This is a newer approach, + // which may be less mature than ForkAndReload. This setting can + // improve load-balancing fairness and metrics accuracy and reduce CPU + // and memory usage if HAProxy has frequent configuration updates for + // route and endpoints updates. + // + // Note: The "Dynamic" option is currently experimental and should not + // be enabled on production clusters. + // + // +openshift:enable:FeatureGate=IngressControllerDynamicConfigurationManager + // +optional + ConfigurationManagement IngressControllerConfigurationManagement `json:"configurationManagement,omitempty"` } +// IngressControllerConfigurationManagement specifies whether always to use +// fork-and-reload to update the HAProxy configuration or whether to use +// HAProxy's control socket for some configuration updates. +// +// +enum +// +kubebuilder:validation:Enum=Dynamic;ForkAndReload +type IngressControllerConfigurationManagement string + +const ( + IngressControllerConfigurationManagementDynamic IngressControllerConfigurationManagement = "Dynamic" + IngressControllerConfigurationManagementForkAndReload IngressControllerConfigurationManagement = "ForkAndReload" +) + // HTTPEmptyRequestsPolicy indicates how HTTP connections for which no request // is received should be handled. // +kubebuilder:validation:Enum=Respond;Ignore diff --git a/vendor/github.com/openshift/api/operator/v1/types_machineconfiguration.go b/vendor/github.com/openshift/api/operator/v1/types_machineconfiguration.go index f5836af0f..f0c1e01c7 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_machineconfiguration.go +++ b/vendor/github.com/openshift/api/operator/v1/types_machineconfiguration.go @@ -47,7 +47,6 @@ type MachineConfigurationSpec struct { // and the platform is left to choose a reasonable default, which is subject to change over time. // The default for each machine manager mode is All for GCP and AWS platforms, and None for all // other platforms. - // +openshift:enable:FeatureGate=ManagedBootImages // +optional ManagedBootImages ManagedBootImages `json:"managedBootImages"` @@ -288,7 +287,6 @@ type MachineConfigurationStatus struct { // managedBootImagesStatus reflects what the latest cluster-validated boot image configuration is // and will be used by Machine Config Controller while performing boot image updates. - // +openshift:enable:FeatureGate=ManagedBootImages // +optional ManagedBootImagesStatus ManagedBootImages `json:"managedBootImagesStatus"` @@ -367,7 +365,7 @@ type ManagedBootImages struct { // MachineManager describes a target machine resource that is registered for boot image updates. It stores identifying information // such as the resource type and the API Group of the resource. It also provides granular control via the selection field. -// +openshift:validation:FeatureGateAwareXValidation:requiredFeatureGate=ManagedBootImages;ManagedBootImagesCPMS,rule="self.resource != 'controlplanemachinesets' || self.selection.mode == 'All' || self.selection.mode == 'None'", message="Only All or None selection mode is permitted for ControlPlaneMachineSets" +// +openshift:validation:FeatureGateAwareXValidation:requiredFeatureGate=ManagedBootImagesCPMS,rule="self.resource != 'controlplanemachinesets' || self.selection.mode == 'All' || self.selection.mode == 'None'", message="Only All or None selection mode is permitted for ControlPlaneMachineSets" type MachineManager struct { // resource is the machine management resource's type. // Valid values are machinesets and controlplanemachinesets. @@ -431,8 +429,8 @@ const ( // MachineManagerManagedResourceType is a string enum used in the MachineManager type to describe the resource // type to be registered. -// +openshift:validation:FeatureGateAwareEnum:requiredFeatureGate=ManagedBootImages,enum=machinesets -// +openshift:validation:FeatureGateAwareEnum:requiredFeatureGate=ManagedBootImages;ManagedBootImagesCPMS,enum=machinesets;controlplanemachinesets +// +openshift:validation:FeatureGateAwareEnum:featureGate="",enum=machinesets +// +openshift:validation:FeatureGateAwareEnum:featureGate=ManagedBootImagesCPMS,enum=machinesets;controlplanemachinesets type MachineManagerMachineSetsResourceType string const ( diff --git a/vendor/github.com/openshift/api/operator/v1/types_network.go b/vendor/github.com/openshift/api/operator/v1/types_network.go index 1cf56f549..cd2e2f9e3 100644 --- a/vendor/github.com/openshift/api/operator/v1/types_network.go +++ b/vendor/github.com/openshift/api/operator/v1/types_network.go @@ -398,6 +398,12 @@ type OpenShiftSDNConfig struct { // ovnKubernetesConfig contains the configuration parameters for networks // using the ovn-kubernetes network project +// +openshift:validation:FeatureGateAwareXValidation:featureGate=NoOverlayMode,rule="self.?transport.orValue('') == 'NoOverlay' ? self.?routeAdvertisements.orValue('') == 'Enabled' : true",message="routeAdvertisements must be Enabled when transport is NoOverlay" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=NoOverlayMode,rule="self.?transport.orValue('') == 'NoOverlay' ? has(self.noOverlayConfig) : !has(self.noOverlayConfig)",message="noOverlayConfig must be set if transport is NoOverlay, and is forbidden otherwise" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=NoOverlayMode,rule="self.?noOverlayConfig.routing.orValue('') == 'Managed' ? has(self.bgpManagedConfig) : true",message="bgpManagedConfig is required when noOverlayConfig.routing is Managed" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=NoOverlayMode,rule="!has(self.transport) || self.transport == 'Geneve' || has(oldSelf.transport)",message="transport can only be set to Geneve after installation" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=NoOverlayMode,rule="!has(oldSelf.transport) || has(self.transport)",message="transport may not be removed once set" +// +openshift:validation:FeatureGateAwareXValidation:featureGate=NoOverlayMode,rule="!has(oldSelf.noOverlayConfig) || has(self.noOverlayConfig)",message="noOverlayConfig may not be removed once set" type OVNKubernetesConfig struct { // mtu is the MTU to use for the tunnel interface. This must be 100 // bytes smaller than the uplink mtu. @@ -466,6 +472,38 @@ type OVNKubernetesConfig struct { // current default is "Disabled". // +optional RouteAdvertisements RouteAdvertisementsEnablement `json:"routeAdvertisements,omitempty"` + + // transport sets the transport mode for pods on the default network. + // Allowed values are "NoOverlay" and "Geneve". + // "NoOverlay" avoids tunnel encapsulation, routing pod traffic directly between nodes. + // "Geneve" encapsulates pod traffic using Geneve tunnels between nodes. + // When omitted, this means the user has no opinion and the platform chooses + // a reasonable default which is subject to change over time. + // The current default is "Geneve". + // "NoOverlay" can only be set at installation time and cannot be changed afterwards. + // "Geneve" may be set explicitly at any time to lock in the current default. + // +openshift:enable:FeatureGate=NoOverlayMode + // +kubebuilder:validation:Enum=NoOverlay;Geneve + // +openshift:validation:FeatureGateAwareXValidation:featureGate=NoOverlayMode,rule="self == oldSelf",message="transport is immutable once set" + // +optional + Transport TransportOption `json:"transport,omitempty"` + + // noOverlayConfig contains configuration for no-overlay mode. + // This configuration applies to the default network only. + // It is required when transport is "NoOverlay". + // When omitted, this means the user does not configure no-overlay mode options. + // +openshift:enable:FeatureGate=NoOverlayMode + // +optional + NoOverlayConfig NoOverlayConfig `json:"noOverlayConfig,omitzero,omitempty"` + + // bgpManagedConfig configures the BGP properties for networks (default network or CUDNs) + // in no-overlay mode that specify routing="Managed" in their noOverlayConfig. + // It is required when noOverlayConfig.routing is set to "Managed". + // When omitted, this means the user does not configure BGP for managed routing. + // This field can be set at installation time or on day 2, and can be modified at any time. + // +openshift:enable:FeatureGate=NoOverlayMode + // +optional + BGPManagedConfig BGPManagedConfig `json:"bgpManagedConfig,omitzero,omitempty"` } type IPv4OVNKubernetesConfig struct { @@ -896,3 +934,80 @@ type AdditionalRoutingCapabilities struct { // +kubebuilder:validation:XValidation:rule="self.all(x, self.exists_one(y, x == y))" Providers []RoutingCapabilitiesProvider `json:"providers"` } + +// TransportOption is the type for network transport options +type TransportOption string + +// SNATOption is the type for SNAT configuration options +type SNATOption string + +// RoutingOption is the type for routing configuration options +type RoutingOption string + +// BGPTopology is the type for BGP topology configuration +type BGPTopology string + +const ( + // TransportOptionNoOverlay indicates the network operates in no-overlay mode + TransportOptionNoOverlay TransportOption = "NoOverlay" + // TransportOptionGeneve indicates the network uses Geneve overlay + TransportOptionGeneve TransportOption = "Geneve" + + // SNATEnabled indicates outbound SNAT is enabled + SNATEnabled SNATOption = "Enabled" + // SNATDisabled indicates outbound SNAT is disabled + SNATDisabled SNATOption = "Disabled" + + // RoutingManaged indicates routing is managed by OVN-Kubernetes + RoutingManaged RoutingOption = "Managed" + // RoutingUnmanaged indicates routing is managed by users + RoutingUnmanaged RoutingOption = "Unmanaged" + + // BGPTopologyFullMesh indicates a full mesh BGP topology where every node peers directly with every other node + BGPTopologyFullMesh BGPTopology = "FullMesh" +) + +// NoOverlayConfig contains configuration options for networks operating in no-overlay mode. +type NoOverlayConfig struct { + // outboundSNAT defines the SNAT behavior for outbound traffic from pods. + // Allowed values are "Enabled" and "Disabled". + // When set to "Enabled", SNAT is performed on outbound traffic from pods. + // When set to "Disabled", SNAT is not performed and pod IPs are preserved in outbound traffic. + // This field is required when the network operates in no-overlay mode. + // This field can be set to any value at installation time and can be changed afterwards. + // +kubebuilder:validation:Enum=Enabled;Disabled + // +required + OutboundSNAT SNATOption `json:"outboundSNAT,omitempty"` + + // routing specifies whether the pod network routing is managed by OVN-Kubernetes or users. + // Allowed values are "Managed" and "Unmanaged". + // When set to "Managed", OVN-Kubernetes manages the pod network routing configuration through BGP. + // When set to "Unmanaged", users are responsible for configuring the pod network routing. + // This field is required when the network operates in no-overlay mode. + // This field is immutable once set. + // +kubebuilder:validation:Enum=Managed;Unmanaged + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="routing is immutable once set" + // +required + Routing RoutingOption `json:"routing,omitempty"` +} + +// BGPManagedConfig contains configuration options for BGP when routing is "Managed". +type BGPManagedConfig struct { + // asNumber is the 2-byte or 4-byte Autonomous System Number (ASN) + // to be used in the generated FRR configuration. + // Valid values are 1 to 4294967295. + // When omitted, this defaults to 64512. + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:validation:Maximum=4294967295 + // +default=64512 + // +optional + ASNumber int64 `json:"asNumber,omitempty"` + + // bgpTopology defines the BGP topology to be used. + // Allowed values are "FullMesh". + // When set to "FullMesh", every node peers directly with every other node via BGP. + // This field is required when BGPManagedConfig is specified. + // +kubebuilder:validation:Enum=FullMesh + // +required + BGPTopology BGPTopology `json:"bgpTopology,omitempty"` +} diff --git a/vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go index 3bc6b81de..3d3c8f4f8 100644 --- a/vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.go @@ -390,6 +390,22 @@ func (in *AzureDiskEncryptionSet) DeepCopy() *AzureDiskEncryptionSet { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *BGPManagedConfig) DeepCopyInto(out *BGPManagedConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BGPManagedConfig. +func (in *BGPManagedConfig) DeepCopy() *BGPManagedConfig { + if in == nil { + return nil + } + out := new(BGPManagedConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *BootImageSkewEnforcementConfig) DeepCopyInto(out *BootImageSkewEnforcementConfig) { *out = *in @@ -3665,6 +3681,22 @@ func (in *NetworkStatus) DeepCopy() *NetworkStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NoOverlayConfig) DeepCopyInto(out *NoOverlayConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NoOverlayConfig. +func (in *NoOverlayConfig) DeepCopy() *NoOverlayConfig { + if in == nil { + return nil + } + out := new(NoOverlayConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeDisruptionPolicyClusterStatus) DeepCopyInto(out *NodeDisruptionPolicyClusterStatus) { *out = *in @@ -4158,6 +4190,8 @@ func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = new(IPv6OVNKubernetesConfig) **out = **in } + out.NoOverlayConfig = in.NoOverlayConfig + out.BGPManagedConfig = in.BGPManagedConfig return } diff --git a/vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml b/vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml index 51a758804..aaf097290 100644 --- a/vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml +++ b/vendor/github.com/openshift/api/operator/v1/zz_generated.featuregated-crd-manifests.yaml @@ -69,6 +69,7 @@ clustercsidrivers.operator.openshift.io: Capability: "" Category: "" FeatureGates: + - AWSEuropeanSovereignCloudInstall - VSphereConfigurableMaxAllowedBlockVolumesPerNode FilenameOperatorName: csi-driver FilenameOperatorOrdering: "01" @@ -175,7 +176,8 @@ ingresscontrollers.operator.openshift.io: CRDName: ingresscontrollers.operator.openshift.io Capability: Ingress Category: "" - FeatureGates: [] + FeatureGates: + - IngressControllerDynamicConfigurationManager FilenameOperatorName: ingress FilenameOperatorOrdering: "00" FilenameRunLevel: "0000_50" @@ -305,8 +307,7 @@ machineconfigurations.operator.openshift.io: FeatureGates: - BootImageSkewEnforcement - IrreconcilableMachineConfig - - ManagedBootImages - - ManagedBootImages+ManagedBootImagesCPMS + - ManagedBootImagesCPMS FilenameOperatorName: machine-config FilenameOperatorOrdering: "01" FilenameRunLevel: "0000_80" @@ -327,7 +328,8 @@ networks.operator.openshift.io: CRDName: networks.operator.openshift.io Capability: "" Category: "" - FeatureGates: [] + FeatureGates: + - NoOverlayMode FilenameOperatorName: network FilenameOperatorOrdering: "01" FilenameRunLevel: "0000_70" 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 64aac26eb..c3ed72602 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 @@ -466,7 +466,7 @@ func (Theme) SwaggerDoc() map[string]string { var map_AWSCSIDriverConfigSpec = map[string]string{ "": "AWSCSIDriverConfigSpec defines properties that can be configured for the AWS CSI driver.", - "kmsKeyARN": "kmsKeyARN sets the cluster default storage class to encrypt volumes with a user-defined KMS key, rather than the default KMS key used by AWS. The value may be either the ARN or Alias ARN of a KMS key.", + "kmsKeyARN": "kmsKeyARN sets the cluster default storage class to encrypt volumes with a user-defined KMS key, rather than the default KMS key used by AWS. The value may be either the ARN or Alias ARN of a KMS key.\n\nThe ARN must follow the format: arn::kms:::(key|alias)/, where: is the AWS partition (aws, aws-cn, aws-us-gov, aws-iso, aws-iso-b, aws-iso-e, aws-iso-f, or aws-eusc), is the AWS region, is a 12-digit numeric identifier for the AWS account, is the KMS key ID or alias name.", "efsVolumeMetrics": "efsVolumeMetrics sets the configuration for collecting metrics from EFS volumes used by the EFS CSI Driver.", } @@ -1121,6 +1121,7 @@ var map_IngressControllerTuningOptions = map[string]string{ "healthCheckInterval": "healthCheckInterval defines how long the router waits between two consecutive health checks on its configured backends. This value is applied globally as a default for all routes, but may be overridden per-route by the route annotation \"router.openshift.io/haproxy.health.check.interval\".\n\nExpects an unsigned duration string of decimal numbers, each with optional fraction and a unit suffix, eg \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\" U+00B5 or \"μs\" U+03BC), \"ms\", \"s\", \"m\", \"h\".\n\nSetting this to less than 5s can cause excess traffic due to too frequent TCP health checks and accompanying SYN packet storms. Alternatively, setting this too high can result in increased latency, due to backend servers that are no longer available, but haven't yet been detected as such.\n\nAn empty or zero healthCheckInterval means no opinion and IngressController chooses a default, which is subject to change over time. Currently the default healthCheckInterval value is 5s.\n\nCurrently the minimum allowed value is 1s and the maximum allowed value is 2147483647ms (24.85 days). Both are subject to change over time.", "maxConnections": "maxConnections defines the maximum number of simultaneous connections that can be established per HAProxy process. Increasing this value allows each ingress controller pod to handle more connections but at the cost of additional system resources being consumed.\n\nPermitted values are: empty, 0, -1, and the range 2000-2000000.\n\nIf this field is empty or 0, the IngressController will use the default value of 50000, but the default is subject to change in future releases.\n\nIf the value is -1 then HAProxy will dynamically compute a maximum value based on the available ulimits in the running container. Selecting -1 (i.e., auto) will result in a large value being computed (~520000 on OpenShift >=4.10 clusters) and therefore each HAProxy process will incur significant memory usage compared to the current default of 50000.\n\nSetting a value that is greater than the current operating system limit will prevent the HAProxy process from starting.\n\nIf you choose a discrete value (e.g., 750000) and the router pod is migrated to a new node, there's no guarantee that that new node has identical ulimits configured. In such a scenario the pod would fail to start. If you have nodes with different ulimits configured (e.g., different tuned profiles) and you choose a discrete value then the guidance is to use -1 and let the value be computed dynamically at runtime.\n\nYou can monitor memory usage for router containers with the following metric: 'container_memory_working_set_bytes{container=\"router\",namespace=\"openshift-ingress\"}'.\n\nYou can monitor memory usage of individual HAProxy processes in router containers with the following metric: 'container_memory_working_set_bytes{container=\"router\",namespace=\"openshift-ingress\"}/container_processes{container=\"router\",namespace=\"openshift-ingress\"}'.", "reloadInterval": "reloadInterval defines the minimum interval at which the router is allowed to reload to accept new changes. Increasing this value can prevent the accumulation of HAProxy processes, depending on the scenario. Increasing this interval can also lessen load imbalance on a backend's servers when using the roundrobin balancing algorithm. Alternatively, decreasing this value may decrease latency since updates to HAProxy's configuration can take effect more quickly.\n\nThe value must be a time duration value; see . Currently, the minimum value allowed is 1s, and the maximum allowed value is 120s. Minimum and maximum allowed values may change in future versions of OpenShift. Note that if a duration outside of these bounds is provided, the value of reloadInterval will be capped/floored and not rejected (e.g. a duration of over 120s will be capped to 120s; the IngressController will not reject and replace this disallowed value with the default).\n\nA zero value for reloadInterval tells the IngressController to choose the default, which is currently 5s and subject to change without notice.\n\nThis field expects an unsigned duration string of decimal numbers, each with optional fraction and a unit suffix, e.g. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\" U+00B5 or \"μs\" U+03BC), \"ms\", \"s\", \"m\", \"h\".\n\nNote: Setting a value significantly larger than the default of 5s can cause latency in observing updates to routes and their endpoints. HAProxy's configuration will be reloaded less frequently, and newly created routes will not be served until the subsequent reload.", + "configurationManagement": "configurationManagement specifies how OpenShift router should update the HAProxy configuration. The following values are valid for this field:\n\n* \"ForkAndReload\". * \"Dynamic\".\n\nOmitting this field means that the user has no opinion and the platform may choose a reasonable default. This default is subject to change over time. The current default is \"ForkAndReload\".\n\n\"ForkAndReload\" means that OpenShift router should rewrite the HAProxy configuration file and instruct HAProxy to fork and reload. This is OpenShift router's traditional approach.\n\n\"Dynamic\" means that OpenShift router may use HAProxy's control socket for some configuration updates and fall back to fork and reload for other configuration updates. This is a newer approach, which may be less mature than ForkAndReload. This setting can improve load-balancing fairness and metrics accuracy and reduce CPU and memory usage if HAProxy has frequent configuration updates for route and endpoints updates.\n\nNote: The \"Dynamic\" option is currently experimental and should not be enabled on production clusters.", } func (IngressControllerTuningOptions) SwaggerDoc() map[string]string { @@ -1669,6 +1670,16 @@ func (AdditionalRoutingCapabilities) SwaggerDoc() map[string]string { return map_AdditionalRoutingCapabilities } +var map_BGPManagedConfig = map[string]string{ + "": "BGPManagedConfig contains configuration options for BGP when routing is \"Managed\".", + "asNumber": "asNumber is the 2-byte or 4-byte Autonomous System Number (ASN) to be used in the generated FRR configuration. Valid values are 1 to 4294967295. When omitted, this defaults to 64512.", + "bgpTopology": "bgpTopology defines the BGP topology to be used. Allowed values are \"FullMesh\". When set to \"FullMesh\", every node peers directly with every other node via BGP. This field is required when BGPManagedConfig is specified.", +} + +func (BGPManagedConfig) SwaggerDoc() map[string]string { + return map_BGPManagedConfig +} + var map_ClusterNetworkEntry = map[string]string{ "": "ClusterNetworkEntry is a subnet from which to allocate PodIPs. A network of size HostPrefix (in CIDR notation) will be allocated when nodes join the cluster. If the HostPrefix field is not used by the plugin, it can be left unset. Not all network providers support multiple ClusterNetworks", } @@ -1896,6 +1907,16 @@ func (NetworkStatus) SwaggerDoc() map[string]string { return map_NetworkStatus } +var map_NoOverlayConfig = map[string]string{ + "": "NoOverlayConfig contains configuration options for networks operating in no-overlay mode.", + "outboundSNAT": "outboundSNAT defines the SNAT behavior for outbound traffic from pods. Allowed values are \"Enabled\" and \"Disabled\". When set to \"Enabled\", SNAT is performed on outbound traffic from pods. When set to \"Disabled\", SNAT is not performed and pod IPs are preserved in outbound traffic. This field is required when the network operates in no-overlay mode. This field can be set to any value at installation time and can be changed afterwards.", + "routing": "routing specifies whether the pod network routing is managed by OVN-Kubernetes or users. Allowed values are \"Managed\" and \"Unmanaged\". When set to \"Managed\", OVN-Kubernetes manages the pod network routing configuration through BGP. When set to \"Unmanaged\", users are responsible for configuring the pod network routing. This field is required when the network operates in no-overlay mode. This field is immutable once set.", +} + +func (NoOverlayConfig) SwaggerDoc() map[string]string { + return map_NoOverlayConfig +} + var map_OVNKubernetesConfig = map[string]string{ "": "ovnKubernetesConfig contains the configuration parameters for networks using the ovn-kubernetes network project", "mtu": "mtu is the MTU to use for the tunnel interface. This must be 100 bytes smaller than the uplink mtu. Default is 1400", @@ -1910,6 +1931,9 @@ var map_OVNKubernetesConfig = map[string]string{ "ipv4": "ipv4 allows users to configure IP settings for IPv4 connections. When ommitted, this means no opinions and the default configuration is used. Check individual fields within ipv4 for details of default values.", "ipv6": "ipv6 allows users to configure IP settings for IPv6 connections. When ommitted, this means no opinions and the default configuration is used. Check individual fields within ipv4 for details of default values.", "routeAdvertisements": "routeAdvertisements determines if the functionality to advertise cluster network routes through a dynamic routing protocol, such as BGP, is enabled or not. This functionality is configured through the ovn-kubernetes RouteAdvertisements CRD. Requires the 'FRR' routing capability provider to be enabled as an additional routing capability. Allowed values are \"Enabled\", \"Disabled\" and ommited. 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 \"Disabled\".", + "transport": "transport sets the transport mode for pods on the default network. Allowed values are \"NoOverlay\" and \"Geneve\". \"NoOverlay\" avoids tunnel encapsulation, routing pod traffic directly between nodes. \"Geneve\" encapsulates pod traffic using Geneve tunnels between nodes. When omitted, this means the user has no opinion and the platform chooses a reasonable default which is subject to change over time. The current default is \"Geneve\". \"NoOverlay\" can only be set at installation time and cannot be changed afterwards. \"Geneve\" may be set explicitly at any time to lock in the current default.", + "noOverlayConfig": "noOverlayConfig contains configuration for no-overlay mode. This configuration applies to the default network only. It is required when transport is \"NoOverlay\". When omitted, this means the user does not configure no-overlay mode options.", + "bgpManagedConfig": "bgpManagedConfig configures the BGP properties for networks (default network or CUDNs) in no-overlay mode that specify routing=\"Managed\" in their noOverlayConfig. It is required when noOverlayConfig.routing is set to \"Managed\". When omitted, this means the user does not configure BGP for managed routing. This field can be set at installation time or on day 2, and can be modified at any time.", } func (OVNKubernetesConfig) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go b/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go deleted file mode 100644 index 7f98c60a0..000000000 --- a/vendor/github.com/openshift/custom-resource-status/conditions/v1/conditions.go +++ /dev/null @@ -1,114 +0,0 @@ -package v1 - -import ( - "time" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// SetStatusCondition sets the corresponding condition in conditions to newCondition. -// The return value indicates if this resulted in any changes *other than* LastHeartbeatTime. -func SetStatusCondition(conditions *[]Condition, newCondition Condition) bool { - if conditions == nil { - conditions = &[]Condition{} - } - existingCondition := FindStatusCondition(*conditions, newCondition.Type) - if existingCondition == nil { - newCondition.LastTransitionTime = metav1.NewTime(time.Now()) - newCondition.LastHeartbeatTime = metav1.NewTime(time.Now()) - *conditions = append(*conditions, newCondition) - return true - } - - changed := updateCondition(existingCondition, newCondition) - existingCondition.LastHeartbeatTime = metav1.NewTime(time.Now()) - return changed -} - -// SetStatusConditionNoHearbeat sets the corresponding condition in conditions to newCondition -// without setting lastHeartbeatTime. -// The return value indicates if this resulted in any changes. -func SetStatusConditionNoHeartbeat(conditions *[]Condition, newCondition Condition) bool { - if conditions == nil { - conditions = &[]Condition{} - } - existingCondition := FindStatusCondition(*conditions, newCondition.Type) - if existingCondition == nil { - newCondition.LastTransitionTime = metav1.NewTime(time.Now()) - *conditions = append(*conditions, newCondition) - return true - } - - return updateCondition(existingCondition, newCondition) -} - -// RemoveStatusCondition removes the corresponding conditionType from conditions. -func RemoveStatusCondition(conditions *[]Condition, conditionType ConditionType) { - if conditions == nil { - return - } - newConditions := []Condition{} - for _, condition := range *conditions { - if condition.Type != conditionType { - newConditions = append(newConditions, condition) - } - } - - *conditions = newConditions -} - -func updateCondition(existingCondition *Condition, newCondition Condition) bool { - changed := false - if existingCondition.Status != newCondition.Status { - changed = true - existingCondition.Status = newCondition.Status - existingCondition.LastTransitionTime = metav1.NewTime(time.Now()) - } - - if existingCondition.Reason != newCondition.Reason { - changed = true - existingCondition.Reason = newCondition.Reason - } - if existingCondition.Message != newCondition.Message { - changed = true - existingCondition.Message = newCondition.Message - } - return changed -} - -// FindStatusCondition finds the conditionType in conditions. -func FindStatusCondition(conditions []Condition, conditionType ConditionType) *Condition { - for i := range conditions { - if conditions[i].Type == conditionType { - return &conditions[i] - } - } - - return nil -} - -// IsStatusConditionTrue returns true when the conditionType is present and set to `corev1.ConditionTrue` -func IsStatusConditionTrue(conditions []Condition, conditionType ConditionType) bool { - return IsStatusConditionPresentAndEqual(conditions, conditionType, corev1.ConditionTrue) -} - -// IsStatusConditionFalse returns true when the conditionType is present and set to `corev1.ConditionFalse` -func IsStatusConditionFalse(conditions []Condition, conditionType ConditionType) bool { - return IsStatusConditionPresentAndEqual(conditions, conditionType, corev1.ConditionFalse) -} - -// IsStatusConditionUnknown returns true when the conditionType is present and set to `corev1.ConditionUnknown` -func IsStatusConditionUnknown(conditions []Condition, conditionType ConditionType) bool { - return IsStatusConditionPresentAndEqual(conditions, conditionType, corev1.ConditionUnknown) -} - -// IsStatusConditionPresentAndEqual returns true when conditionType is present and equal to status. -func IsStatusConditionPresentAndEqual(conditions []Condition, conditionType ConditionType, status corev1.ConditionStatus) bool { - for _, condition := range conditions { - if condition.Type == conditionType { - return condition.Status == status - } - } - return false -} diff --git a/vendor/github.com/openshift/custom-resource-status/conditions/v1/doc.go b/vendor/github.com/openshift/custom-resource-status/conditions/v1/doc.go deleted file mode 100644 index b657efeaa..000000000 --- a/vendor/github.com/openshift/custom-resource-status/conditions/v1/doc.go +++ /dev/null @@ -1,9 +0,0 @@ -// +k8s:deepcopy-gen=package,register -// +k8s:defaulter-gen=TypeMeta -// +k8s:openapi-gen=true - -// Package v1 provides version v1 of the types and functions necessary to -// manage and inspect a slice of conditions. It is opinionated in the -// condition types provided but leaves it to the user to define additional -// types as necessary. -package v1 diff --git a/vendor/github.com/openshift/custom-resource-status/conditions/v1/types.go b/vendor/github.com/openshift/custom-resource-status/conditions/v1/types.go deleted file mode 100644 index 950678fb9..000000000 --- a/vendor/github.com/openshift/custom-resource-status/conditions/v1/types.go +++ /dev/null @@ -1,51 +0,0 @@ -package v1 - -import ( - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// Condition represents the state of the operator's -// reconciliation functionality. -// +k8s:deepcopy-gen=true -type Condition struct { - Type ConditionType `json:"type" description:"type of condition ie. Available|Progressing|Degraded."` - - Status corev1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"` - - // +optional - Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"` - - // +optional - Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"` - - // +optional - LastHeartbeatTime metav1.Time `json:"lastHeartbeatTime" description:"last time we got an update on a given condition"` - - // +optional - LastTransitionTime metav1.Time `json:"lastTransitionTime" description:"last time the condition transit from one status to another"` -} - -// ConditionType is the state of the operator's reconciliation functionality. -type ConditionType string - -const ( - // ConditionAvailable indicates that the resources maintained by the operator, - // is functional and available in the cluster. - ConditionAvailable ConditionType = "Available" - - // ConditionProgressing indicates that the operator is actively making changes to the resources maintained by the - // operator - ConditionProgressing ConditionType = "Progressing" - - // ConditionDegraded indicates that the resources maintained by the operator are not functioning completely. - // An example of a degraded state would be if not all pods in a deployment were running. - // It may still be available, but it is degraded - ConditionDegraded ConditionType = "Degraded" - - // ConditionUpgradeable indicates whether the resources maintained by the operator are in a state that is safe to upgrade. - // When `False`, the resources maintained by the operator should not be upgraded and the - // message field should contain a human readable description of what the administrator should do to - // allow the operator to successfully update the resources maintained by the operator. - ConditionUpgradeable ConditionType = "Upgradeable" -) diff --git a/vendor/github.com/openshift/custom-resource-status/conditions/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/custom-resource-status/conditions/v1/zz_generated.deepcopy.go deleted file mode 100644 index bbbbf863d..000000000 --- a/vendor/github.com/openshift/custom-resource-status/conditions/v1/zz_generated.deepcopy.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build !ignore_autogenerated - -// Code generated by deepcopy-gen. DO NOT EDIT. - -package v1 - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Condition) DeepCopyInto(out *Condition) { - *out = *in - in.LastHeartbeatTime.DeepCopyInto(&out.LastHeartbeatTime) - in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. -func (in *Condition) DeepCopy() *Condition { - if in == nil { - return nil - } - out := new(Condition) - in.DeepCopyInto(out) - return out -} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/agent/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/agent/doc.go index c3f1e406f..b1bc157c4 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/agent/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/agent/doc.go @@ -1,4 +1,3 @@ // Package agent contains API Schema definitions for assisted agent based installations. -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +// +k8s:deepcopy-gen=package package agent diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/aws/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/aws/doc.go index fbeefb46c..deb275bb2 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/aws/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/aws/doc.go @@ -1,3 +1,3 @@ // Package aws contains API Schema definitions for AWS clusters. -// +k8s:deepcopy-gen=package,register +// +k8s:deepcopy-gen=package package aws diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/aws/metadata.go b/vendor/github.com/openshift/hive/apis/hive/v1/aws/metadata.go index efbb50e5d..acab47a3e 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/aws/metadata.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/aws/metadata.go @@ -4,5 +4,7 @@ package aws type Metadata struct { // HostedZoneRole is the role to assume when performing operations // on a hosted zone owned by another account. + // Deprecated. Use the Secret referenced by ClusterMetadata.MetadataJSONSecretRef instead. We + // may stop populating this section in the future. HostedZoneRole *string `json:"hostedZoneRole,omitempty"` } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/azure/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/azure/doc.go index 9514fdf6e..b418c3337 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/azure/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/azure/doc.go @@ -1,4 +1,3 @@ // Package azure contains API Schema definitions for Azure cluster. -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +// +k8s:deepcopy-gen=package package azure diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/azure/machinepool.go b/vendor/github.com/openshift/hive/apis/hive/v1/azure/machinepool.go index 1fb9f51cc..dba630479 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/azure/machinepool.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/azure/machinepool.go @@ -17,10 +17,53 @@ type MachinePool struct { // OSImage defines the image to use for the OS. // +optional OSImage *OSImage `json:"osImage,omitempty"` + + // NetworkResourceGroupName specifies the network resource group that contains an existing VNet. + // Ignored unless VirtualNetwork is also specified. + // +optional + NetworkResourceGroupName string `json:"networkResourceGroupName,omitempty"` + + // ComputeSubnet specifies an existing subnet for use by compute nodes. + // If omitted, the default (${infraID}-worker-subnet) will be used. + // +optional + ComputeSubnet string `json:"computeSubnet,omitempty"` + + // VirtualNetwork specifies the name of an existing VNet for the Machines to use + // If omitted, the default (${infraID}-vnet) will be used. + // +optional + VirtualNetwork string `json:"virtualNetwork,omitempty"` + + // VMNetworkingType specifies whether to enable accelerated networking. + // Accelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its + // networking performance. + // eg. values: "Accelerated", "Basic" + // + // +kubebuilder:validation:Enum="Accelerated"; "Basic" + // +optional + VMNetworkingType string `json:"vmNetworkingType,omitempty"` + + // OutboundType is a strategy for how egress from cluster is achieved. When not specified default is "Loadbalancer". + // +optional + OutboundType string `json:"outboundType"` } +// ImagePurchasePlan defines the purchase plan of a Marketplace image. +// +kubebuilder:validation:Enum=WithPurchasePlan;NoPurchasePlan +type ImagePurchasePlan string + +const ( + // ImageWithPurchasePlan enum attribute which is the default setting. + ImageWithPurchasePlan ImagePurchasePlan = "WithPurchasePlan" + // ImageNoPurchasePlan enum attribute which speficies the image does not need a purchase plan. + ImageNoPurchasePlan ImagePurchasePlan = "NoPurchasePlan" +) + // OSImage is the image to use for the OS of a machine. type OSImage struct { + // Plan is the purchase plan of the image. + // If omitted, it defaults to "WithPurchasePlan". + // +optional + Plan ImagePurchasePlan `json:"plan"` // Publisher is the publisher of the image. Publisher string `json:"publisher"` // Offer is the offer of the image. diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/azure/metadata.go b/vendor/github.com/openshift/hive/apis/hive/v1/azure/metadata.go index 65552358d..c989b6d69 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/azure/metadata.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/azure/metadata.go @@ -3,5 +3,7 @@ package azure // Metadata contains Azure metadata (e.g. for uninstalling the cluster). type Metadata struct { // ResourceGroupName is the name of the resource group in which the cluster resources were created. + // Deprecated. Use the Secret referenced by ClusterMetadata.MetadataJSONSecretRef instead. We + // may stop populating this section in the future. ResourceGroupName *string `json:"resourceGroupName"` } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/baremetal/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/baremetal/doc.go index e9f9c8339..127cd666b 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/baremetal/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/baremetal/doc.go @@ -1,4 +1,3 @@ // Package baremetal contains API Schema definitions for bare metal clusters. -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +// +k8s:deepcopy-gen=package package baremetal diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeployment_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeployment_types.go index f76cf2c1c..c0b4ca49d 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeployment_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeployment_types.go @@ -2,6 +2,7 @@ package v1 import ( configv1 "github.com/openshift/api/config/v1" + operatorv1 "github.com/openshift/api/operator/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -12,8 +13,8 @@ import ( "github.com/openshift/hive/apis/hive/v1/gcp" "github.com/openshift/hive/apis/hive/v1/ibmcloud" "github.com/openshift/hive/apis/hive/v1/none" + "github.com/openshift/hive/apis/hive/v1/nutanix" "github.com/openshift/hive/apis/hive/v1/openstack" - "github.com/openshift/hive/apis/hive/v1/ovirt" "github.com/openshift/hive/apis/hive/v1/vsphere" ) @@ -133,6 +134,7 @@ type ClusterDeploymentSpec struct { ControlPlaneConfig ControlPlaneConfigSpec `json:"controlPlaneConfig,omitempty"` // Ingress allows defining desired clusteringress/shards to be configured on the cluster. + // +kubebuilder:validation:MaxItems=16 // +optional Ingress []ClusterIngress `json:"ingress,omitempty"` @@ -218,6 +220,13 @@ type Provisioning struct { // +optional InstallConfigSecretRef *corev1.LocalObjectReference `json:"installConfigSecretRef,omitempty"` + // CustomizationRef is a reference to a ClusterDeploymentCustomization containing + // InstallerManifestPatches to be applied to the manifests generated by openshift-install prior + // to starting the installation. (InstallConfigPatches will be ignored -- those changes should + // be made directly to the install-config.yaml referenced by InstallConfigSecretRef.) + // +optional + CustomizationRef *corev1.LocalObjectReference `json:"customizationRef,omitempty"` + // ReleaseImage is the image containing metadata for all components that run in the cluster, and // is the primary and best way to specify what specific version of OpenShift you wish to install. ReleaseImage string `json:"releaseImage,omitempty"` @@ -300,7 +309,13 @@ type ClusterMetadata struct { // +optional AdminPasswordSecretRef *corev1.LocalObjectReference `json:"adminPasswordSecretRef,omitempty"` - // Platform holds platform-specific cluster metadata + // MetadataJSONSecretRef references the secret containing the metadata.json emitted by the + // installer, potentially scrubbed for sensitive data. + MetadataJSONSecretRef *corev1.LocalObjectReference `json:"metadataJSONSecretRef,omitempty"` + + // Platform holds platform-specific cluster metadata. + // Deprecated. Use the Secret referenced by MetadataJSONSecretRef instead. We may stop + // populating this section in the future. // +optional Platform *ClusterPlatformMetadata `json:"platform,omitempty"` } @@ -373,6 +388,12 @@ type ClusterDeploymentStatus struct { // perform the installation. // +optional Platform *PlatformStatus `json:"platformStatus,omitempty"` + + // ClusterVersionStatus is a wholesale copy of the Status section of the spoke cluster's + // `clusterversion version` object. This is not officially supported, and is only populated + // on request. + // +optional + ClusterVersionStatus *configv1.ClusterVersionStatus `json:"clusterVersionStatus,omitempty"` } // ClusterDeploymentCondition contains details for the current condition of a cluster deployment @@ -484,6 +505,14 @@ const ( // for the cluster. AWSPrivateLinkFailedClusterDeploymentCondition ClusterDeploymentConditionType = "AWSPrivateLinkFailed" + // PrivateLinkReadyClusterDeploymentCondition is true when private link access has been + // setup for the cluster. + PrivateLinkReadyClusterDeploymentCondition ClusterDeploymentConditionType = "PrivateLinkReady" + + // PrivateLinkFailedClusterDeploymentCondition is true controller fails to setup private link access + // for the cluster. + PrivateLinkFailedClusterDeploymentCondition ClusterDeploymentConditionType = "PrivateLinkFailed" + // These are conditions that are copied from ClusterInstall on to the ClusterDeployment object. ClusterInstallFailedClusterDeploymentCondition ClusterDeploymentConditionType = "ClusterInstallFailed" ClusterInstallCompletedClusterDeploymentCondition ClusterDeploymentConditionType = "ClusterInstallCompleted" @@ -645,9 +674,6 @@ type Platform struct { // VSphere is the configuration used when installing on vSphere VSphere *vsphere.Platform `json:"vsphere,omitempty"` - // Ovirt is the configuration used when installing on oVirt - Ovirt *ovirt.Platform `json:"ovirt,omitempty"` - // AgentBareMetal is the configuration used when performing an Assisted Agent based installation // to bare metal. AgentBareMetal *agent.BareMetalPlatform `json:"agentBareMetal,omitempty"` @@ -658,6 +684,9 @@ type Platform struct { // None indicates platform-agnostic install. // https://docs.openshift.com/container-platform/4.7/installing/installing_platform_agnostic/installing-platform-agnostic.html None *none.Platform `json:"none,omitempty"` + + // Nutanix is the configuration used when installing on Nutanix Prism Central. + Nutanix *nutanix.Platform `json:"nutanix,omitempty"` } // PlatformStatus contains the observed state for the specific platform upon which to @@ -665,6 +694,9 @@ type Platform struct { type PlatformStatus struct { // AWS is the observed state on AWS. AWS *aws.PlatformStatus `json:"aws,omitempty"` + + // GCP is the observed state on GCP + GCP *gcp.PlatformStatus `json:"gcp,omitempty"` } // ClusterIngress contains the configurable pieces for any ClusterIngress objects @@ -696,6 +728,10 @@ type ClusterIngress struct { // HttpErrorCodePages allows configuring custom HTTP error pages using the IngressController object // +optional HttpErrorCodePages *configv1.ConfigMapNameReference `json:"httpErrorCodePages,omitempty"` + + // TuningOptions allows configuring the tuning options of the ingress controller + // +optional + TuningOptions *operatorv1.IngressControllerTuningOptions `json:"tuningOptions,omitempty"` } // ControlPlaneConfigSpec contains additional configuration settings for a target diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeploymentcustomization_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeploymentcustomization_types.go index 8917e756c..1692d8089 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeploymentcustomization_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeploymentcustomization_types.go @@ -1,7 +1,8 @@ package v1 import ( - conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" + "fmt" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -28,7 +29,7 @@ const ( // ClusterDeploymentCustomization is the Schema for clusterdeploymentcustomizations API. // +kubebuilder:subresource:status // +k8s:openapi-gen=true -// +kubebuilder:resource:scope=Namespaced +// +kubebuilder:resource:shortName=cdc,scope=Namespaced type ClusterDeploymentCustomization struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -41,11 +42,33 @@ type ClusterDeploymentCustomization struct { type ClusterDeploymentCustomizationSpec struct { // InstallConfigPatches is a list of patches to be applied to the install-config. InstallConfigPatches []PatchEntity `json:"installConfigPatches,omitempty"` + + // InstallerManifestPatches is a list of patches to be applied to installer-generated manifests. + InstallerManifestPatches []InstallerManifestPatch `json:"installerManifestPatches,omitempty"` +} + +type InstallerManifestPatch struct { + // ManifestSelector identifies one or more manifests to patch + ManifestSelector ManifestSelector `json:"manifestSelector"` + + // Patches is a list of RFC6902 patches to apply to manifests identified by manifestSelector. + Patches []PatchEntity `json:"patches"` +} + +type ManifestSelector struct { + // Glob is a file glob (per https://pkg.go.dev/path/filepath#Glob) identifying one or more + // manifests. Paths should be relative to the installer's working directory. Examples: + // - openshift/99_role-cloud-creds-secret-reader.yaml + // - openshift/99_openshift-cluster-api_worker-machineset-*.yaml + // - */*secret* + // It is an error if a glob matches zero manifests. + Glob string `json:"glob"` } -// PatchEntity represent a json patch (RFC 6902) to be applied to the install-config +// PatchEntity represents a json patch (RFC 6902) to be applied type PatchEntity struct { - // Op is the operation to perform: add, remove, replace, move, copy, test + // Op is the operation to perform. + // +kubebuilder:validation:Enum=add;remove;replace;move;copy;test // +required Op string `json:"op"` // Path is the json path to the value to be modified @@ -54,9 +77,50 @@ type PatchEntity struct { // From is the json path to copy or move the value from // +optional From string `json:"from,omitempty"` - // Value is the value to be used in the operation - // +required - Value string `json:"value"` + // Value is the *string* value to be used in the operation. For more complex values, use + // ValueJSON. + // +optional + Value string `json:"value,omitempty"` + // ValueJSON is a string representing a JSON object to be used in the operation. As such, + // internal quotes must be escaped. If nonempty, Value is ignored. + // +optional + ValueJSON string `json:"valueJSON,omitempty"` +} + +// Encode returns a string representation of the RFC6902 patching operation represented by the +// PatchEntity. +func (pe *PatchEntity) Encode() string { + var val string + // Prefer ValueJSON + if len(pe.ValueJSON) != 0 { + // ValueJSON will be a raw JSON object in the patch; don't quote it. + val = pe.ValueJSON + } else { + // Value will be a JSON string value in the patch; quote it. + val = fmt.Sprintf("%q", pe.Value) + } + // Is this overkill? Should we just assemble the whole thing and let jsonpatch figure it out? + switch pe.Op { + case "copy", "move": + return fmt.Sprintf( + `{"op": %q, "from": %q, "path": %q}`, + pe.Op, pe.From, pe.Path) + case "remove": + return fmt.Sprintf( + `{"op": %q, "path": %q}`, + pe.Op, pe.Path) + case "test", "replace", "add": + return fmt.Sprintf( + // val is already quoted iff necessary + `{"op": %q, "path": %q, "value": %s}`, + pe.Op, pe.Path, val) + default: + // This should never happen, but... + return fmt.Sprintf( + // val is already quoted iff necessary + `{"op": %q, "path": %q, "from", %q, "value": %s}`, + pe.Op, pe.Path, pe.From, val) + } } // ClusterDeploymentCustomizationStatus defines the observed state of ClusterDeploymentCustomization. @@ -78,11 +142,11 @@ type ClusterDeploymentCustomizationStatus struct { // +patchMergeKey=type // +patchStrategy=merge // +optional - Conditions []conditionsv1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` + Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` } const ( - ApplySucceededCondition conditionsv1.ConditionType = "ApplySucceeded" + ApplySucceededCondition = "ApplySucceeded" ) // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeprovision_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeprovision_types.go index 61b47a0cc..8519b549b 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeprovision_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterdeprovision_types.go @@ -3,6 +3,7 @@ package v1 import ( "github.com/openshift/hive/apis/hive/v1/aws" "github.com/openshift/hive/apis/hive/v1/azure" + "github.com/openshift/hive/apis/hive/v1/nutanix" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -23,6 +24,10 @@ type ClusterDeprovisionSpec struct { // BaseDomain is the DNS base domain. BaseDomain string `json:"baseDomain,omitempty"` + // MetadataJSONSecretRef references the secret containing the metadata.json emitted by the + // installer, potentially scrubbed for sensitive data. + MetadataJSONSecretRef *corev1.LocalObjectReference `json:"metadataJSONSecretRef,omitempty"` + // Platform contains platform-specific configuration for a ClusterDeprovision Platform ClusterDeprovisionPlatform `json:"platform,omitempty"` } @@ -50,10 +55,10 @@ type ClusterDeprovisionPlatform struct { OpenStack *OpenStackClusterDeprovision `json:"openstack,omitempty"` // VSphere contains VMWare vSphere-specific deprovision settings VSphere *VSphereClusterDeprovision `json:"vsphere,omitempty"` - // Ovirt contains oVirt-specific deprovision settings - Ovirt *OvirtClusterDeprovision `json:"ovirt,omitempty"` // IBMCloud contains IBM Cloud specific deprovision settings IBMCloud *IBMClusterDeprovision `json:"ibmcloud,omitempty"` + // Nutanix contains Nutanix-specific deprovision settings + Nutanix *NutanixClusterDeprovision `json:"nutanix,omitempty"` } // AWSClusterDeprovision contains AWS-specific configuration for a ClusterDeprovision @@ -89,6 +94,10 @@ type AzureClusterDeprovision struct { // Required for new deprovisions (schema notwithstanding). // +optional ResourceGroupName *string `json:"resourceGroupName,omitempty"` + // BaseDomainResourceGroupName is the name of the resource group where the cluster's DNS records + // were created, if different from the default or the custom ResourceGroupName. + // +optional + BaseDomainResourceGroupName *string `json:"baseDomainResourceGroupName,omitempty"` } // GCPClusterDeprovision contains GCP-specific configuration for a ClusterDeprovision @@ -127,18 +136,6 @@ type VSphereClusterDeprovision struct { VCenter string `json:"vCenter"` } -// OvirtClusterDeprovision contains oVirt-specific configuration for a ClusterDeprovision -type OvirtClusterDeprovision struct { - // The oVirt cluster ID - ClusterID string `json:"clusterID"` - // CredentialsSecretRef is the oVirt account credentials to use for deprovisioning the cluster - // secret fields: ovirt_url, ovirt_username, ovirt_password, ovirt_ca_bundle - CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` - // CertificatesSecretRef refers to a secret that contains the oVirt CA certificates - // necessary for communicating with the oVirt. - CertificatesSecretRef corev1.LocalObjectReference `json:"certificatesSecretRef"` -} - // IBMClusterDeprovision contains IBM Cloud specific configuration for a ClusterDeprovision type IBMClusterDeprovision struct { // CredentialsSecretRef is the IBM Cloud credentials to use for deprovisioning the cluster @@ -150,6 +147,22 @@ type IBMClusterDeprovision struct { BaseDomain string `json:"baseDomain"` } +// NutanixClusterDeprovision contains Nutanix-specific configuration for a ClusterDeprovision +type NutanixClusterDeprovision struct { + // PrismCentral is the endpoint (address and port) to connect to the Prism Central. + // This serves as the default Prism-Central. + PrismCentral nutanix.PrismEndpoint `json:"prismCentral"` + + // CredentialsSecretRef refers to a secret that contains the Nutanix account access + // credentials. + CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` + + // CertificatesSecretRef refers to a secret that contains the Nutanix CA certificates + // necessary for communicating with the Prism Central. + // +optional + CertificatesSecretRef corev1.LocalObjectReference `json:"certificatesSecretRef"` +} + // +genclient // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/clusterpool_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/clusterpool_types.go index 577a00861..eca37072a 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/clusterpool_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/clusterpool_types.go @@ -97,6 +97,18 @@ type ClusterPoolSpec struct { // to customize the default ClusterDeployment. // +optional Inventory []InventoryEntry `json:"inventory,omitempty"` + + // InstallerEnv are extra environment variables to pass through to the installer. This may be used to enable + // additional features of the installer. + // +optional + InstallerEnv []corev1.EnvVar `json:"installerEnv,omitempty"` + + // CustomizationRef refers to a ClusterDeploymentCustomization object whose InstallerManifestPatches should + // be applied to *all* ClusterDeployments created by this ClusterPool. This is in addition to any CDC from + // Inventory. The CDC must exist in the ClusterPool's namespace. It will be copied to the namespace of each + // ClusterDeployment generated by the ClusterPool. + // +optional + CustomizationRef *corev1.LocalObjectReference `json:"customizationRef,omitempty"` } type HibernationConfig struct { diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/doc.go index 4a7aad498..616a2a115 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/doc.go @@ -1,7 +1,5 @@ // Package v1 contains API Schema definitions for the hive v1 API group // +k8s:openapi-gen=true -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/hive/apis/hive -// +k8s:defaulter-gen=TypeMeta +// +k8s:deepcopy-gen=package // +groupName=hive.openshift.io package v1 diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/doc.go index 84aa74408..73cd6f070 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/doc.go @@ -1,4 +1,3 @@ // Package gcp contains API Schema definitions for GCP clusters. -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +// +k8s:deepcopy-gen=package package gcp diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/machinepools.go b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/machinepools.go index 779563dca..e5c789ef4 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/machinepools.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/machinepools.go @@ -34,19 +34,32 @@ type MachinePool struct { // +optional OnHostMaintenance string `json:"onHostMaintenance,omitempty"` + // ServiceAccount is the email of a gcp service account to be attached to worker nodes + // in order to provide the permissions required by the cloud provider. For the default + // worker MachinePool, it is the user's responsibility to match this to the value + // provided in the install-config. + // + // +optional + ServiceAccount string `json:"serviceAccount,omitempty"` + // userTags has additional keys and values that we will add as tags to the providerSpec of // MachineSets that we creates on GCP. Tag key and tag value should be the shortnames of the // tag key and tag value resource. Consumer is responsible for using this only for spokes // where custom tags are supported. UserTags []UserTag `json:"userTags,omitempty"` + + // Tags defines a set of network tags which will be added to instances in the machineset. + // Not to be confused with UserTags. + // + // +optional + Tags []string `json:"tags,omitempty"` } // OSDisk defines the disk for machines on GCP. type OSDisk struct { // DiskType defines the type of disk. - // The valid values are pd-standard and pd-ssd. + // The valid values at this time are: pd-standard, pd-ssd, local-ssd, pd-balanced, hyperdisk-balanced. // Defaulted internally to pd-ssd. - // +kubebuilder:validation:Enum=pd-ssd;pd-standard // +optional DiskType string `json:"diskType,omitempty"` diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/metadata.go b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/metadata.go index 556783130..7e7054241 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/metadata.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/metadata.go @@ -3,6 +3,8 @@ package gcp // Metadata contains GCP metadata (e.g. for uninstalling the cluster). type Metadata struct { // NetworkProjectID is used for shared VPC setups + // Deprecated. Use the Secret referenced by ClusterMetadata.MetadataJSONSecretRef instead. We + // may stop populating this section in the future. // +optional NetworkProjectID *string `json:"networkProjectID,omitempty"` } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/platform.go b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/platform.go index 252caff3c..b49fc57bc 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/platform.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/platform.go @@ -4,13 +4,100 @@ import ( corev1 "k8s.io/api/core/v1" ) -// Platform stores all the global configuration that all machinesets -// use. +// Platform stores all the global configuration that all machinesets use. type Platform struct { - // CredentialsSecretRef refers to a secret that contains the GCP account access - // credentials. + // CredentialsSecretRef refers to a secret that contains the GCP account access credentials. + // +optional CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` // Region specifies the GCP region where the cluster will be created. Region string `json:"region"` + + // PrivateSericeConnect allows users to enable access to the cluster's API server using GCP + // Private Service Connect. It includes a forwarding rule paired with a Service Attachment + // across GCP accounts and allows clients to connect to services using GCP internal networking + // of using public load balancers. + // +optional + PrivateServiceConnect *PrivateServiceConnect `json:"privateServiceConnect,omitempty"` + + // DiscardLocalSsdOnHibernate passes the specified value through to the GCP API to indicate + // whether the content of any local SSDs should be preserved or discarded. See + // https://cloud.google.com/compute/docs/disks/local-ssd#stop_instance + // This field is required when attempting to hibernate clusters with instances possessing + // SSDs -- e.g. those with GPUs. + // +optional + DiscardLocalSsdOnHibernate *bool `json:"discardLocalSsdOnHibernate,omitempty"` +} + +// PrivateServiceConnectAccess configures access to the cluster API using GCP Private Service Connect +type PrivateServiceConnect struct { + // Enabled specifies if Private Service Connect is to be enabled on the cluster. + Enabled bool `json:"enabled"` + + // ServiceAttachment configures the service attachment to be used by the cluster. + // +optional + ServiceAttachment *ServiceAttachment `json:"serviceAttachment,omitempty"` +} + +// ServiceAttachment configures the service attachment to be used by the cluster +type ServiceAttachment struct { + // Subnet configures the subnetwork that contains the service attachment. + // +optional + Subnet *ServiceAttachmentSubnet `json:"subnet,omitempty"` +} + +// ServiceAttachmentSubnet configures the subnetwork used by the service attachment +type ServiceAttachmentSubnet struct { + // Cidr specifies the cidr to use when creating a service attachment subnet. + // +optional + Cidr string `json:"cidr,omitempty"` + + // Existing specifies a pre-existing subnet to use instead of creating a new service attachment subnet. + // This is required when using BYO VPCs. It must be in the same region as the api-int load balancer, be + // configured with a purpose of "Private Service Connect", and have sufficient routing and firewall rules + // to access the api-int load balancer. + // +optional + Existing *ServiceAttachmentSubnetExisting `json:"existing,omitempty"` +} + +// ServiceAttachmentSubnetExisting describes the existing subnet. +type ServiceAttachmentSubnetExisting struct { + // Name specifies the name of the existing subnet. + Name string `json:"name"` + + // Project specifies the project the subnet exists in. + // This is required for Shared VPC. + // +optional + Project string `json:"project,omitempty"` +} + +// PlatformStatus contains the observed state on GCP platform. +type PlatformStatus struct { + // PrivateServiceConnect contains the private service connect resource references + // +optional + PrivateServiceConnect *PrivateServiceConnectStatus `json:"privateServiceConnect,omitempty"` +} + +// PrivateServiceConnectStatus contains the observed state for PrivateServiceConnect resources. +type PrivateServiceConnectStatus struct { + // Endpoint is the selfLink of the endpoint created for the cluster. + // +optional + Endpoint string `json:"endpoint,omitempty"` + + // EndpointAddress is the selfLink of the address created for the cluster endpoint. + // +optional + EndpointAddress string `json:"endpointAddress,omitempty"` + + // ServiceAttachment is the selfLink of the service attachment created for the clsuter. + // +optional + ServiceAttachment string `json:"serviceAttachment,omitempty"` + + // ServiceAttachmentFirewall is the selfLink of the firewall that allows traffic between + // the service attachment and the cluster's internal api load balancer. + // +optional + ServiceAttachmentFirewall string `json:"serviceAttachmentFirewall,omitempty"` + + // ServiceAttachmentSubnet is the selfLink of the subnet that will contain the service attachment. + // +optional + ServiceAttachmentSubnet string `json:"serviceAttachmentSubnet,omitempty"` } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/zz_generated.deepcopy.go index 2472f1af6..9c78d64b8 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/gcp/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/gcp/zz_generated.deepcopy.go @@ -56,6 +56,11 @@ func (in *MachinePool) DeepCopyInto(out *MachinePool) { *out = make([]UserTag, len(*in)) copy(*out, *in) } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -115,6 +120,16 @@ func (in *OSDisk) DeepCopy() *OSDisk { func (in *Platform) DeepCopyInto(out *Platform) { *out = *in out.CredentialsSecretRef = in.CredentialsSecretRef + if in.PrivateServiceConnect != nil { + in, out := &in.PrivateServiceConnect, &out.PrivateServiceConnect + *out = new(PrivateServiceConnect) + (*in).DeepCopyInto(*out) + } + if in.DiscardLocalSsdOnHibernate != nil { + in, out := &in.DiscardLocalSsdOnHibernate, &out.DiscardLocalSsdOnHibernate + *out = new(bool) + **out = **in + } return } @@ -128,6 +143,122 @@ func (in *Platform) DeepCopy() *Platform { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PlatformStatus) DeepCopyInto(out *PlatformStatus) { + *out = *in + if in.PrivateServiceConnect != nil { + in, out := &in.PrivateServiceConnect, &out.PrivateServiceConnect + *out = new(PrivateServiceConnectStatus) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PlatformStatus. +func (in *PlatformStatus) DeepCopy() *PlatformStatus { + if in == nil { + return nil + } + out := new(PlatformStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateServiceConnect) DeepCopyInto(out *PrivateServiceConnect) { + *out = *in + if in.ServiceAttachment != nil { + in, out := &in.ServiceAttachment, &out.ServiceAttachment + *out = new(ServiceAttachment) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateServiceConnect. +func (in *PrivateServiceConnect) DeepCopy() *PrivateServiceConnect { + if in == nil { + return nil + } + out := new(PrivateServiceConnect) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateServiceConnectStatus) DeepCopyInto(out *PrivateServiceConnectStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateServiceConnectStatus. +func (in *PrivateServiceConnectStatus) DeepCopy() *PrivateServiceConnectStatus { + if in == nil { + return nil + } + out := new(PrivateServiceConnectStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAttachment) DeepCopyInto(out *ServiceAttachment) { + *out = *in + if in.Subnet != nil { + in, out := &in.Subnet, &out.Subnet + *out = new(ServiceAttachmentSubnet) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAttachment. +func (in *ServiceAttachment) DeepCopy() *ServiceAttachment { + if in == nil { + return nil + } + out := new(ServiceAttachment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAttachmentSubnet) DeepCopyInto(out *ServiceAttachmentSubnet) { + *out = *in + if in.Existing != nil { + in, out := &in.Existing, &out.Existing + *out = new(ServiceAttachmentSubnetExisting) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAttachmentSubnet. +func (in *ServiceAttachmentSubnet) DeepCopy() *ServiceAttachmentSubnet { + if in == nil { + return nil + } + out := new(ServiceAttachmentSubnet) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceAttachmentSubnetExisting) DeepCopyInto(out *ServiceAttachmentSubnetExisting) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceAttachmentSubnetExisting. +func (in *ServiceAttachmentSubnetExisting) DeepCopy() *ServiceAttachmentSubnetExisting { + if in == nil { + return nil + } + out := new(ServiceAttachmentSubnetExisting) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *UserTag) DeepCopyInto(out *UserTag) { *out = *in diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/hiveconfig_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/hiveconfig_types.go index 08f121344..e830cc3a6 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/hiveconfig_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/hiveconfig_types.go @@ -41,6 +41,14 @@ type HiveConfigSpec struct { // +optional GlobalPullSecretRef *corev1.LocalObjectReference `json:"globalPullSecretRef,omitempty"` + // HiveImagePullSecretRef is used to specify a pull secret that can be used to pull Hive's own image. + // If hive has been deployed from a private registry, cluster installations will not succeed unless + // this reference is specified. This secret must live in the same namespace as the Hive operator's deployment. + // NOTE: This secret will be copied into Hive's TargetNamespace (if it is different than the namespace + // that the Hive operator is deployed in), as well as the namespace of every ClusterDeployment. + // +optional + HiveImagePullSecretRef *corev1.LocalObjectReference `json:"hiveImagePullSecretRef,omitempty"` + // Backup specifies configuration for backup integration. // If absent, backup integration will be disabled. // +optional @@ -64,8 +72,43 @@ type HiveConfigSpec struct { // SyncSetReapplyInterval is a string duration indicating how much time must pass before SyncSet resources // will be reapplied. // The default reapply interval is two hours. + // This is a Duration value; see https://pkg.go.dev/time#ParseDuration for accepted formats. + // Note: due to discrepancies in validation vs parsing, we use a Pattern instead of `Format=duration`. See + // https://bugzilla.redhat.com/show_bug.cgi?id=2050332 + // https://github.com/kubernetes/apimachinery/issues/131 + // https://github.com/kubernetes/apiextensions-apiserver/issues/56 + // +optional + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" SyncSetReapplyInterval string `json:"syncSetReapplyInterval,omitempty"` + // MachinePoolPollInterval is a string duration indicating how much time must pass before checking whether + // remote resources related to MachinePools need to be reapplied. Set to zero to disable polling -- we'll + // only reconcile when hub objects change. + // The default interval is 30m. + // This is a Duration value; see https://pkg.go.dev/time#ParseDuration for accepted formats. + // Note: due to discrepancies in validation vs parsing, we use a Pattern instead of `Format=duration`. See + // https://bugzilla.redhat.com/show_bug.cgi?id=2050332 + // https://github.com/kubernetes/apimachinery/issues/131 + // https://github.com/kubernetes/apiextensions-apiserver/issues/56 + // +optional + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" + MachinePoolPollInterval string `json:"machinePoolPollInterval,omitempty"` + + // ClusterVersionPollInterval is a string duration indicating how much time must pass before checking + // whether we need to update the hive.openshift.io/version* labels on ClusterDeployment. If zero or unset, + // we'll only reconcile when the ClusterDeployment changes. + // This is a Duration value; see https://pkg.go.dev/time#ParseDuration for accepted formats. + // Note: due to discrepancies in validation vs parsing, we use a Pattern instead of `Format=duration`. See + // https://bugzilla.redhat.com/show_bug.cgi?id=2050332 + // https://github.com/kubernetes/apimachinery/issues/131 + // https://github.com/kubernetes/apiextensions-apiserver/issues/56 + // +optional + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$" + ClusterVersionPollInterval string `json:"clusterVersionPollInterval,omitempty"` + // MaintenanceMode can be set to true to disable the hive controllers in situations where we need to ensure // nothing is running that will add or act upon finalizers on Hive types. This should rarely be needed. // Sets replicas to 0 for the hive-controllers deployment to accomplish this. @@ -94,6 +137,10 @@ type HiveConfigSpec struct { // +optional DeploymentConfig *[]DeploymentConfig `json:"deploymentConfig,omitempty"` + // PrivateLink is used to configure the privatelink controller. + // +optional + PrivateLink *PrivateLinkConfig `json:"privateLink,omitempty"` + // AWSPrivateLink defines the configuration for the aws-private-link controller. // It provides 3 major pieces of information required by the controller, // 1. The Credentials that should be used to create AWS PrivateLink resources other than @@ -167,6 +214,13 @@ type ReleaseImageVerificationConfigMapReference struct { Name string `json:"name"` } +// PrivateLinkConfig defines the configuration for the privatelink controller. +type PrivateLinkConfig struct { + // GCP is the configuration for GCP hub and link resources. + // +optional + GCP *GCPPrivateServiceConnectConfig `json:"gcp,omitempty"` +} + // AWSPrivateLinkConfig defines the configuration for the aws-private-link controller. type AWSPrivateLinkConfig struct { // CredentialsSecretRef references a secret in the TargetNamespace that will be used to authenticate with @@ -262,6 +316,34 @@ type AWSServiceProviderCredentials struct { CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef,omitempty"` } +// GCPPrivateServiceConnectConfig defines the gcp private service connect config for the private-link controller. +type GCPPrivateServiceConnectConfig struct { + // CredentialsSecretRef references a secret in the TargetNamespace that will be used to authenticate with + // GCP for creating the resources for GCP Private Service Connect + CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` + + // EndpointVPCInventory is a list of VPCs and the corresponding subnets in various GCP regions. + // The controller uses this list to choose a VPC for creating GCP Endpoints. Since the VPC Endpoints + // must be in the same region as the ClusterDeployment, we must have VPCs in that region to be able + // to setup Private Service Connect. + // +optional + EndpointVPCInventory []GCPPrivateServiceConnectInventory `json:"endpointVPCInventory,omitempty"` +} + +// GCPPrivateServiceConnectInventory is a VPC and its corresponding subnets. +// This VPC will be used to create a GCP Endpoint whenever there is a Private Service Connect +// service created for a ClusterDeployment. +type GCPPrivateServiceConnectInventory struct { + Network string `json:"network"` + Subnets []GCPPrivateServiceConnectSubnet `json:"subnets"` +} + +// GCPPrivateServiceConnectSubnet defines subnet and the corresponding GCP region. +type GCPPrivateServiceConnectSubnet struct { + Subnet string `json:"subnet"` + Region string `json:"region"` +} + // FeatureSet defines the set of feature gates that should be used. // +kubebuilder:validation:Enum="";Custom type FeatureSet string @@ -581,6 +663,7 @@ const ( MetricsControllerName ControllerName = "metrics" ClustersyncControllerName ControllerName = "clustersync" AWSPrivateLinkControllerName ControllerName = "awsprivatelink" + PrivateLinkControllerName ControllerName = "privatelink" HiveControllerName ControllerName = "hive" // DeprecatedRemoteMachinesetControllerName was deprecated but can be used to disable the @@ -617,6 +700,7 @@ type DeploymentName string const ( DeploymentNameControllers DeploymentName = "hive-controllers" DeploymentNameClustersync DeploymentName = "hive-clustersync" + DeploymentNameMachinepool DeploymentName = "hive-machinepool" DeploymentNameAdmission DeploymentName = "hiveadmission" ) diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/ibmcloud/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/ibmcloud/doc.go index 14a0db4b9..14fb7a960 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/ibmcloud/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/ibmcloud/doc.go @@ -1,6 +1,5 @@ // Package ibmcloud contains API Schema definitions for IBM Cloud clusters. -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +// +k8s:deepcopy-gen=package package ibmcloud // Name is name for the ibmcloud platform. diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/machinepool_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/machinepool_types.go index e971a4022..707536c05 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/machinepool_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/machinepool_types.go @@ -8,8 +8,8 @@ import ( "github.com/openshift/hive/apis/hive/v1/azure" "github.com/openshift/hive/apis/hive/v1/gcp" "github.com/openshift/hive/apis/hive/v1/ibmcloud" + "github.com/openshift/hive/apis/hive/v1/nutanix" "github.com/openshift/hive/apis/hive/v1/openstack" - "github.com/openshift/hive/apis/hive/v1/ovirt" "github.com/openshift/hive/apis/hive/v1/vsphere" ) @@ -43,14 +43,26 @@ type MachinePoolSpec struct { Autoscaling *MachinePoolAutoscaling `json:"autoscaling,omitempty"` // Platform is configuration for machine pool specific to the platform. + // When using a MachinePool to control the default worker machines + // created by installer, these must match the values provided in the + // install-config. Platform MachinePoolPlatform `json:"platform"` // Map of label string keys and values that will be applied to the created MachineSet's - // MachineSpec. This list will overwrite any modifications made to Node labels on an - // ongoing basis. + // MachineSpec. This affects the labels that will end up on the *Nodes* (in contrast with + // the MachineLabels field). This list will overwrite any modifications made to Node labels + // on an ongoing basis. // +optional Labels map[string]string `json:"labels,omitempty"` + // Map of label string keys and values that will be applied to the created MachineSet's + // MachineTemplateSpec. This affects the labels that will end up on the *Machines* (in + // contrast with the Labels field). This list will overwrite any modifications made to + // Machine labels on an ongoing basis. Note: We ignore entries that conflict with + // generated labels. + // +optional + MachineLabels map[string]string `json:"machineLabels,omitempty"` + // List of taints that will be applied to the created MachineSet's MachineSpec. // This list will overwrite any modifications made to Node taints on an ongoing basis. // In case of duplicate entries, first encountered taint Value will be preserved, @@ -82,10 +94,10 @@ type MachinePoolPlatform struct { OpenStack *openstack.MachinePool `json:"openstack,omitempty"` // VSphere is the configuration used when installing on vSphere VSphere *vsphere.MachinePool `json:"vsphere,omitempty"` - // Ovirt is the configuration used when installing on oVirt. - Ovirt *ovirt.MachinePool `json:"ovirt,omitempty"` // IBMCloud is the configuration used when installing on IBM Cloud. IBMCloud *ibmcloud.MachinePool `json:"ibmcloud,omitempty"` + // Nutanix is the configuration used when installing on Nutanix prism central. + Nutanix *nutanix.MachinePool `json:"nutanix,omitempty"` } // MachinePoolStatus defines the observed state of MachinePool @@ -101,16 +113,31 @@ type MachinePoolStatus struct { // +optional Conditions []MachinePoolCondition `json:"conditions,omitempty"` - // OwnedLabels lists the keys of labels this MachinePool created on the remote MachineSet. + // OwnedLabels lists the keys of labels this MachinePool created on the remote MachineSet's + // MachineSpec. (In contrast with OwnedMachineLabels.) // Used to identify labels to remove from the remote MachineSet when they are absent from // the MachinePool's spec.labels. // +optional OwnedLabels []string `json:"ownedLabels,omitempty"` + + // OwnedMachineLabels lists the keys of labels this MachinePool created on the remote + // MachineSet's MachineTemplateSpec. (In contrast with OwnedLabels.) + // Used to identify labels to remove from the remote MachineSet when they are absent from + // the MachinePool's spec.machineLabels. + // +optional + OwnedMachineLabels []string `json:"ownedMachineLabels,omitempty"` + // OwnedTaints lists identifiers of taints this MachinePool created on the remote MachineSet. // Used to identify taints to remove from the remote MachineSet when they are absent from // the MachinePool's spec.taints. // +optional OwnedTaints []TaintIdentifier `json:"ownedTaints,omitempty"` + + // ControlledByReplica indicates which replica of the hive-machinepool StatefulSet is responsible + // for this MachinePool. Note that this value indicates the replica that most recently handled the + // MachinePool. If the hive-machinepool statefulset is scaled up or down, the controlling replica + // can change, potentially causing logs to be spread across multiple pods. + ControlledByReplica *int64 `json:"controlledByReplica,omitempty"` } // TaintIdentifier uniquely identifies a Taint. (It turns out taints are mutually exclusive by @@ -201,6 +228,14 @@ const ( // UnsupportedConfigurationMachinePoolCondition is true when the configuration of the MachinePool is unsupported // by the cluster. UnsupportedConfigurationMachinePoolCondition MachinePoolConditionType = "UnsupportedConfiguration" + + // MachineSetsGeneratedMachinePoolCondition is true when the most recent pass of the controller successfully + // generated MachineSet manifests to sync to the spoke cluster, false if it failed. + MachineSetsGeneratedMachinePoolCondition MachinePoolConditionType = "MachineSetsGenerated" + + // SyncedMachinePoolCondition indicates whether the most recent pass of the controller successfully synced + // objects (MachineSets, and {Machine|Cluster}Autoscaler(s) if appropriate) to the spoke cluster. + SyncedMachinePoolCondition MachinePoolConditionType = "Synced" ) // +genclient diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/doc.go index 422f98a2f..7941acf06 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/metricsconfig/doc.go @@ -1,4 +1,3 @@ // Package metricsconfig contains API Schema definitions for configurations specific to metrics controller. -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +// +k8s:deepcopy-gen=package package metricsconfig diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/none/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/none/doc.go index f2bb8992e..6ddcfcb6b 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/none/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/none/doc.go @@ -1,4 +1,3 @@ // Package none contains API Schema definitions for platform-agnostic installations. -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +// +k8s:deepcopy-gen=package package none diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/doc.go new file mode 100644 index 000000000..7665f1280 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/doc.go @@ -0,0 +1,3 @@ +// Package nutanix contains API Schema definitions for nutanix clusters. +// +k8s:deepcopy-gen=package +package nutanix diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/machinepools.go b/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/machinepools.go new file mode 100644 index 000000000..c5fd40c11 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/machinepools.go @@ -0,0 +1,78 @@ +package nutanix + +import ( + machinev1 "github.com/openshift/api/machine/v1" +) + +// MachinePool stores the configuration for a machine pool installed +// on Nutanix. +type MachinePool struct { + // NumCPUs is the total number of virtual processor cores to assign a vm. + // + // +optional + NumCPUs int64 `json:"cpus,omitempty"` + + // NumCoresPerSocket is the number of cores per socket in a vm. The number + // of vCPUs on the vm will be NumCPUs times NumCoresPerSocket. + // For example: 4 CPUs and 4 Cores per socket will result in 16 VPUs. + // The AHV scheduler treats socket and core allocation exactly the same + // so there is no benefit to configuring cores over CPUs. + // + // +optional + NumCoresPerSocket int64 `json:"coresPerSocket,omitempty"` + + // Memory is the size of a VM's memory in MiB. + // + // +optional + MemoryMiB int64 `json:"memoryMiB,omitempty"` + + // OSDisk defines the storage for instance. + // + // +optional + OSDisk `json:"osDisk,omitempty"` + + // BootType indicates the boot type (Legacy, UEFI or SecureBoot) the Machine's VM uses to boot. + // If this field is empty or omitted, the VM will use the default boot type "Legacy" to boot. + // "SecureBoot" depends on "UEFI" boot, i.e., enabling "SecureBoot" means that "UEFI" boot is also enabled. + // +kubebuilder:validation:Enum="";Legacy;UEFI;SecureBoot + // +optional + BootType machinev1.NutanixBootType `json:"bootType,omitempty"` + + // Project optionally identifies a Prism project for the Machine's VM to associate with. + // +optional + Project *machinev1.NutanixResourceIdentifier `json:"project,omitempty"` + + // Categories optionally adds one or more prism categories (each with key and value) for + // the Machine's VM to associate with. All the category key and value pairs specified must + // already exist in the prism central. + // +listType=map + // +listMapKey=key + // +optional + Categories []machinev1.NutanixCategory `json:"categories,omitempty"` + + // GPUs is a list of GPU devices to attach to the machine's VM. + // +kubebuilder:validation:X-KubernetesListType=set + // +kubebuilder:validation:X-KubernetesMapType=atomic + // +optional + GPUs []machinev1.NutanixGPU `json:"gpus,omitempty"` + + // DataDisks holds information of the data disks to attach to the Machine's VM + // +kubebuilder:validation:X-KubernetesListType=set + // +optional + DataDisks []machinev1.NutanixVMDisk `json:"dataDisks,omitempty"` + + // FailureDomains optionally configures a list of failure domain names + // that will be applied to the MachinePool. These names must correspond + // to failure domains configured in `CD.Spec.Platform.Nutanix`. + // +listType=set + // +optional + FailureDomains []string `json:"failureDomains,omitempty"` +} + +// OSDisk defines the system disk for a Machine VM. +type OSDisk struct { + // DiskSizeGiB defines the size of disk in GiB. + // + // +optional + DiskSizeGiB int64 `json:"diskSizeGiB,omitempty"` +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/platform.go b/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/platform.go new file mode 100644 index 000000000..e1a3ac5a8 --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/platform.go @@ -0,0 +1,95 @@ +package nutanix + +import ( + corev1 "k8s.io/api/core/v1" +) + +// Platform stores any global configuration used for Nutanix platform +type Platform struct { + // PrismCentral is the endpoint (address and port) to connect to the Prism Central. + // This serves as the default Prism-Central. + PrismCentral PrismEndpoint `json:"prismCentral"` + + // CredentialsSecretRef refers to a secret that contains the Nutanix account access + // credentials. + CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` + + // CertificatesSecretRef refers to a secret that contains the Prism Central CA certificates + // necessary for communicating with the Prism Central. + // +optional + CertificatesSecretRef corev1.LocalObjectReference `json:"certificatesSecretRef"` + + // FailureDomains configures failure domains for the Nutanix platform. + // Required for using MachinePools + FailureDomains []FailureDomain `json:"failureDomains,omitempty"` +} + +// PrismEndpoint holds the endpoint address and port to access the Nutanix Prism Central or Element (cluster) +type PrismEndpoint struct { + // address is the endpoint address (DNS name or IP address) of the Nutanix Prism Central or Element (cluster) + Address string `json:"address"` + + // port is the port number to access the Nutanix Prism Central or Element (cluster) + Port int32 `json:"port"` +} + +// PrismElement holds the uuid, endpoint of the Prism Element (cluster) +type PrismElement struct { + // UUID is the UUID of the Prism Element (cluster) + UUID string `json:"uuid"` + + // Endpoint holds the address and port of the Prism Element + // +optional + Endpoint PrismEndpoint `json:"endpoint,omitempty"` + + // Name is the Prism Element (cluster) name. + Name string `json:"name,omitempty"` +} + +// FailureDomain configures failure domain information for the Nutanix platform. +type FailureDomain struct { + // Name defines the unique name of a failure domain. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=64 + // +kubebuilder:validation:Pattern=`^[0-9A-Za-z_.-@/]+$` + Name string `json:"name"` + + // PrismElement holds the identification (name, UUID) and the optional endpoint address and + // port of the Nutanix Prism Element. When a cluster-wide proxy is installed, this endpoint will, + // by default, be accessed through the cluster-wide proxy configured for the platform. + // If communication with this endpoint should bypass the proxy, add the endpoint to the install-config + // `spec.noProxy` list in the proxy configuration. + // +kubebuilder:validation:Required + PrismElement PrismElement `json:"prismElement"` + + // SubnetUUIDs identifies the network subnets of the Prism Element. + // Currently we only support one subnet for a failure domain. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinItems=1 + // +listType=set + SubnetUUIDs []string `json:"subnetUUIDs"` + + // StorageContainers identifies the storage containers in the Prism Element. + // +optional + StorageContainers []StorageResourceReference `json:"storageContainers,omitempty"` + + // DataSourceImages identifies the datasource images in the Prism Element. + // +optional + DataSourceImages []StorageResourceReference `json:"dataSourceImages,omitempty"` +} + +// StorageResourceReference holds reference information of a storage resource (storage container, data source image, etc.) +type StorageResourceReference struct { + // ReferenceName is the identifier of the storage resource configured in the FailureDomain. + // +optional + ReferenceName string `json:"referenceName,omitempty"` + + // UUID is the UUID of the storage container resource in the Prism Element. + // +kubebuilder:validation:Required + UUID string `json:"uuid"` + + // Name is the name of the storage container resource in the Prism Element. + // +optional + Name string `json:"name,omitempty"` +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/zz_generated.deepcopy.go new file mode 100644 index 000000000..1a03a562f --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/nutanix/zz_generated.deepcopy.go @@ -0,0 +1,179 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package nutanix + +import ( + v1 "github.com/openshift/api/machine/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *FailureDomain) DeepCopyInto(out *FailureDomain) { + *out = *in + out.PrismElement = in.PrismElement + if in.SubnetUUIDs != nil { + in, out := &in.SubnetUUIDs, &out.SubnetUUIDs + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.StorageContainers != nil { + in, out := &in.StorageContainers, &out.StorageContainers + *out = make([]StorageResourceReference, len(*in)) + copy(*out, *in) + } + if in.DataSourceImages != nil { + in, out := &in.DataSourceImages, &out.DataSourceImages + *out = make([]StorageResourceReference, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FailureDomain. +func (in *FailureDomain) DeepCopy() *FailureDomain { + if in == nil { + return nil + } + out := new(FailureDomain) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MachinePool) DeepCopyInto(out *MachinePool) { + *out = *in + out.OSDisk = in.OSDisk + if in.Project != nil { + in, out := &in.Project, &out.Project + *out = new(v1.NutanixResourceIdentifier) + (*in).DeepCopyInto(*out) + } + if in.Categories != nil { + in, out := &in.Categories, &out.Categories + *out = make([]v1.NutanixCategory, len(*in)) + copy(*out, *in) + } + if in.GPUs != nil { + in, out := &in.GPUs, &out.GPUs + *out = make([]v1.NutanixGPU, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.DataDisks != nil { + in, out := &in.DataDisks, &out.DataDisks + *out = make([]v1.NutanixVMDisk, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.FailureDomains != nil { + in, out := &in.FailureDomains, &out.FailureDomains + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachinePool. +func (in *MachinePool) DeepCopy() *MachinePool { + if in == nil { + return nil + } + out := new(MachinePool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OSDisk) DeepCopyInto(out *OSDisk) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSDisk. +func (in *OSDisk) DeepCopy() *OSDisk { + if in == nil { + return nil + } + out := new(OSDisk) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Platform) DeepCopyInto(out *Platform) { + *out = *in + out.PrismCentral = in.PrismCentral + out.CredentialsSecretRef = in.CredentialsSecretRef + out.CertificatesSecretRef = in.CertificatesSecretRef + if in.FailureDomains != nil { + in, out := &in.FailureDomains, &out.FailureDomains + *out = make([]FailureDomain, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Platform. +func (in *Platform) DeepCopy() *Platform { + if in == nil { + return nil + } + out := new(Platform) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrismElement) DeepCopyInto(out *PrismElement) { + *out = *in + out.Endpoint = in.Endpoint + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrismElement. +func (in *PrismElement) DeepCopy() *PrismElement { + if in == nil { + return nil + } + out := new(PrismElement) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrismEndpoint) DeepCopyInto(out *PrismEndpoint) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrismEndpoint. +func (in *PrismEndpoint) DeepCopy() *PrismEndpoint { + if in == nil { + return nil + } + out := new(PrismEndpoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageResourceReference) DeepCopyInto(out *StorageResourceReference) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageResourceReference. +func (in *StorageResourceReference) DeepCopy() *StorageResourceReference { + if in == nil { + return nil + } + out := new(StorageResourceReference) + in.DeepCopyInto(out) + return out +} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/openstack/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/openstack/doc.go index 5233b0d39..a6a9192b1 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/openstack/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/openstack/doc.go @@ -1,4 +1,3 @@ // Package openstack contains API Schema definitions for OpenStack clusters. -// +k8s:deepcopy-gen=package,register -// +k8s:conversion-gen=github.com/openshift/hive/apis/hive +// +k8s:deepcopy-gen=package package openstack diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/openstack/machinepools.go b/vendor/github.com/openshift/hive/apis/hive/v1/openstack/machinepools.go index 2853c7ffa..dd92da0c7 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/openstack/machinepools.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/openstack/machinepools.go @@ -14,6 +14,12 @@ type MachinePool struct { // The instances use ephemeral disks if not set. // +optional RootVolume *RootVolume `json:"rootVolume,omitempty"` + + // AdditionalSecurityGroupIDs contains IDs of additional security groups for machines, where each ID + // is presented in the UUID format. + // + // +optional + AdditionalSecurityGroupIDs []string `json:"additionalSecurityGroupIDs,omitempty"` } // Set sets the values from `required` to `a`. diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/openstack/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/openstack/zz_generated.deepcopy.go index 8033e1c99..3adcd77d9 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/openstack/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/openstack/zz_generated.deepcopy.go @@ -17,6 +17,11 @@ func (in *MachinePool) DeepCopyInto(out *MachinePool) { *out = new(RootVolume) **out = **in } + if in.AdditionalSecurityGroupIDs != nil { + in, out := &in.AdditionalSecurityGroupIDs, &out.AdditionalSecurityGroupIDs + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/doc.go deleted file mode 100644 index 9fbf9dd5b..000000000 --- a/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package ovirt contains ovirt-specific structures for -// installer configuration and management. -// +k8s:deepcopy-gen=package,register -package ovirt diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/machinepool.go b/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/machinepool.go deleted file mode 100644 index 5670b4647..000000000 --- a/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/machinepool.go +++ /dev/null @@ -1,61 +0,0 @@ -package ovirt - -// MachinePool stores the configuration for a machine pool installed -// on ovirt. -type MachinePool struct { - // CPU defines the VM CPU. - // +optional - CPU *CPU `json:"cpu,omitempty"` - - // MemoryMB is the size of a VM's memory in MiBs. - // +optional - MemoryMB int32 `json:"memoryMB,omitempty"` - - // OSDisk is the the root disk of the node. - // +optional - OSDisk *Disk `json:"osDisk,omitempty"` - - // VMType defines the workload type of the VM. - // +kubebuilder:validation:Enum="";desktop;server;high_performance - // +optional - VMType VMType `json:"vmType,omitempty"` -} - -// CPU defines the VM cpu, made of (Sockets * Cores). -type CPU struct { - // Sockets is the number of sockets for a VM. - // Total CPUs is (Sockets * Cores) - Sockets int32 `json:"sockets"` - - // Cores is the number of cores per socket. - // Total CPUs is (Sockets * Cores) - Cores int32 `json:"cores"` -} - -// Disk defines a VM disk -type Disk struct { - // SizeGB size of the bootable disk in GiB. - SizeGB int64 `json:"sizeGB"` -} - -// VMType defines the type of the VM, which will change the VM configuration, -// like including or excluding devices (like excluding sound-card), -// device configuration (like using multi-queues for vNic), and several other -// configuration tweaks. This doesn't effect properties like CPU count and amount of memory. -type VMType string - -const ( - // VMTypeDesktop set the VM type to desktop. Virtual machines optimized to act - // as desktop machines do have a sound card, use an image (thin allocation), - // and are stateless. - VMTypeDesktop VMType = "desktop" - // VMTypeServer sets the VM type to server. Virtual machines optimized to act - // as servers have no sound card, use a cloned disk image, and are not stateless. - VMTypeServer VMType = "server" - // VMTypeHighPerformance sets a VM type to high_performance which sets various - // properties of a VM to optimize for performance, like enabling headless mode, - // disabling usb, smart-card, and sound devices, enabling host cpu pass-through, - // multi-queues for vNics and several more items. - // See https://www.ovirt.org/develop/release-management/features/virt/high-performance-vm.html. - VMTypeHighPerformance VMType = "high_performance" -) diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/platform.go b/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/platform.go deleted file mode 100644 index fc3b8b276..000000000 --- a/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/platform.go +++ /dev/null @@ -1,22 +0,0 @@ -package ovirt - -import ( - corev1 "k8s.io/api/core/v1" -) - -// Platform stores all the global oVirt configuration -type Platform struct { - // The target cluster under which all VMs will run - ClusterID string `json:"ovirt_cluster_id"` - // CredentialsSecretRef refers to a secret that contains the oVirt account access - // credentials with fields: ovirt_url, ovirt_username, ovirt_password, ovirt_ca_bundle - CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"` - // CertificatesSecretRef refers to a secret that contains the oVirt CA certificates - // necessary for communicating with oVirt. - CertificatesSecretRef corev1.LocalObjectReference `json:"certificatesSecretRef"` - // The target storage domain under which all VM disk would be created. - StorageDomainID string `json:"storage_domain_id"` - // The target network of all the network interfaces of the nodes. Omitting defaults to ovirtmgmt - // network which is a default network for evert ovirt cluster. - NetworkName string `json:"ovirt_network_name,omitempty"` -} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/zz_generated.deepcopy.go deleted file mode 100644 index b2fe4f994..000000000 --- a/vendor/github.com/openshift/hive/apis/hive/v1/ovirt/zz_generated.deepcopy.go +++ /dev/null @@ -1,82 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -// Code generated by deepcopy-gen. DO NOT EDIT. - -package ovirt - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CPU) DeepCopyInto(out *CPU) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CPU. -func (in *CPU) DeepCopy() *CPU { - if in == nil { - return nil - } - out := new(CPU) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Disk) DeepCopyInto(out *Disk) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Disk. -func (in *Disk) DeepCopy() *Disk { - if in == nil { - return nil - } - out := new(Disk) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *MachinePool) DeepCopyInto(out *MachinePool) { - *out = *in - if in.CPU != nil { - in, out := &in.CPU, &out.CPU - *out = new(CPU) - **out = **in - } - if in.OSDisk != nil { - in, out := &in.OSDisk, &out.OSDisk - *out = new(Disk) - **out = **in - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MachinePool. -func (in *MachinePool) DeepCopy() *MachinePool { - if in == nil { - return nil - } - out := new(MachinePool) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Platform) DeepCopyInto(out *Platform) { - *out = *in - out.CredentialsSecretRef = in.CredentialsSecretRef - out.CertificatesSecretRef = in.CertificatesSecretRef - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Platform. -func (in *Platform) DeepCopy() *Platform { - if in == nil { - return nil - } - out := new(Platform) - in.DeepCopyInto(out) - return out -} diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/syncidentityprovider_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/syncidentityprovider_types.go index af1b03f13..50b71003f 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/syncidentityprovider_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/syncidentityprovider_types.go @@ -19,7 +19,7 @@ type SyncIdentityProviderCommonSpec struct { type SelectorSyncIdentityProviderSpec struct { SyncIdentityProviderCommonSpec `json:",inline"` - // ClusterDeploymentSelector is a LabelSelector indicating which clusters the SelectorIdentityProvider + // ClusterDeploymentSelector is a LabelSelector indicating which clusters the SelectorSyncIdentityProvider // applies to in any namespace. // +optional ClusterDeploymentSelector metav1.LabelSelector `json:"clusterDeploymentSelector,omitempty"` @@ -32,12 +32,12 @@ type SyncIdentityProviderSpec struct { SyncIdentityProviderCommonSpec `json:",inline"` // ClusterDeploymentRefs is the list of LocalObjectReference indicating which clusters the - // SyncSet applies to in the SyncSet's namespace. + // SyncIdentityProvider applies to in the SyncIdentityProvider's namespace. // +required ClusterDeploymentRefs []corev1.LocalObjectReference `json:"clusterDeploymentRefs"` } -// IdentityProviderStatus defines the observed state of SyncSet +// IdentityProviderStatus defines the observed state of the SyncIdentityProvider type IdentityProviderStatus struct { } @@ -45,7 +45,7 @@ type IdentityProviderStatus struct { // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object -// SelectorSyncIdentityProvider is the Schema for the SelectorSyncSet API +// SelectorSyncIdentityProvider is the Schema for the SelectorSyncIdentityProvider API // +k8s:openapi-gen=true // +kubebuilder:resource:scope=Cluster type SelectorSyncIdentityProvider struct { diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/syncset_types.go b/vendor/github.com/openshift/hive/apis/hive/v1/syncset_types.go index 09b237e7d..de7e2077c 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/syncset_types.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/syncset_types.go @@ -44,20 +44,6 @@ const ( CreateOrUpdateSyncSetApplyBehavior SyncSetApplyBehavior = "CreateOrUpdate" ) -// SyncSetPatchApplyMode is a string representing the mode with which to apply -// SyncSet Patches. -type SyncSetPatchApplyMode string - -const ( - // ApplyOncePatchApplyMode indicates that the patch should be applied - // only once. - ApplyOncePatchApplyMode SyncSetPatchApplyMode = "ApplyOnce" - - // AlwaysApplyPatchApplyMode indicates that the patch should be - // continuously applied. - AlwaysApplyPatchApplyMode SyncSetPatchApplyMode = "AlwaysApply" -) - // SyncObjectPatch represents a patch to be applied to a specific object type SyncObjectPatch struct { // APIVersion is the Group and Version of the object to be patched. @@ -252,6 +238,16 @@ type SyncSetCommonSpec struct { // empty string is interpolated if there are no labels, or if the indicated key does not exist. // Note that this only works in values (not e.g. map keys) that are of type string. EnableResourceTemplates bool `json:"enableResourceTemplates,omitempty"` + + // EnablePatchTemplates, if True, causes hive to honor golang text/templates in Patches[].Patch + // strings. While the standard syntax is supported, it won't do you a whole lot of good as the + // parser does not pass a data object (i.e. there is no "dot" for you to use). This currently + // exists to expose a single function: {{ fromCDLabel "some.label/key" }} will be substituted + // with the string value of ClusterDeployment.Labels["some.label/key"]. The empty string is + // interpolated if there are no labels, or if the indicated key does not exist. Note that the + // patch string must be valid JSON after interpolation. This may make for odd-looking quoting + // in the uninterpolated string. + EnablePatchTemplates bool `json:"enablePatchTemplates,omitempty"` } // SelectorSyncSetSpec defines the SyncSetCommonSpec resources and patches to sync along diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/doc.go b/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/doc.go index d37553ddc..ee79f2ba6 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/doc.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/doc.go @@ -1,3 +1,3 @@ // Package vsphere contains contains API Schema definitions for vSphere clusters. -// +k8s:deepcopy-gen=package,register +// +k8s:deepcopy-gen=package package vsphere diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/machinepools.go b/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/machinepools.go index 71e67294b..e08c4fab7 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/machinepools.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/machinepools.go @@ -20,6 +20,10 @@ type MachinePool struct { // OSDisk defines the storage for instance. OSDisk `json:"osDisk"` + + // TagIDs is a list of up to 10 tags to add to the VMs that this machine set provisions in vSphere. + // +kubebuilder:validation:MaxItems:=10 + TagIDs []string `json:"tagIDs,omitempty"` } // OSDisk defines the disk for a virtual machine. diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/zz_generated.deepcopy.go index 153ab3f92..6108b1415 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/vsphere/zz_generated.deepcopy.go @@ -9,6 +9,11 @@ package vsphere func (in *MachinePool) DeepCopyInto(out *MachinePool) { *out = *in out.OSDisk = in.OSDisk + if in.TagIDs != nil { + in, out := &in.TagIDs, &out.TagIDs + *out = make([]string, len(*in)) + copy(*out, *in) + } return } diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.deepcopy.go index c6398e840..56dcc627c 100644 --- a/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.deepcopy.go @@ -7,7 +7,7 @@ package v1 import ( configv1 "github.com/openshift/api/config/v1" - conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" + operatorv1 "github.com/openshift/api/operator/v1" agent "github.com/openshift/hive/apis/hive/v1/agent" aws "github.com/openshift/hive/apis/hive/v1/aws" azure "github.com/openshift/hive/apis/hive/v1/azure" @@ -16,8 +16,8 @@ import ( ibmcloud "github.com/openshift/hive/apis/hive/v1/ibmcloud" metricsconfig "github.com/openshift/hive/apis/hive/v1/metricsconfig" none "github.com/openshift/hive/apis/hive/v1/none" + nutanix "github.com/openshift/hive/apis/hive/v1/nutanix" openstack "github.com/openshift/hive/apis/hive/v1/openstack" - ovirt "github.com/openshift/hive/apis/hive/v1/ovirt" vsphere "github.com/openshift/hive/apis/hive/v1/vsphere" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" @@ -278,6 +278,11 @@ func (in *AzureClusterDeprovision) DeepCopyInto(out *AzureClusterDeprovision) { *out = new(string) **out = **in } + if in.BaseDomainResourceGroupName != nil { + in, out := &in.BaseDomainResourceGroupName, &out.BaseDomainResourceGroupName + *out = new(string) + **out = **in + } return } @@ -738,6 +743,13 @@ func (in *ClusterDeploymentCustomizationSpec) DeepCopyInto(out *ClusterDeploymen *out = make([]PatchEntity, len(*in)) copy(*out, *in) } + if in.InstallerManifestPatches != nil { + in, out := &in.InstallerManifestPatches, &out.InstallerManifestPatches + *out = make([]InstallerManifestPatch, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } @@ -766,7 +778,7 @@ func (in *ClusterDeploymentCustomizationStatus) DeepCopyInto(out *ClusterDeploym } if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]conditionsv1.Condition, len(*in)) + *out = make([]metav1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } @@ -935,6 +947,11 @@ func (in *ClusterDeploymentStatus) DeepCopyInto(out *ClusterDeploymentStatus) { *out = new(PlatformStatus) (*in).DeepCopyInto(*out) } + if in.ClusterVersionStatus != nil { + in, out := &in.ClusterVersionStatus, &out.ClusterVersionStatus + *out = new(configv1.ClusterVersionStatus) + (*in).DeepCopyInto(*out) + } return } @@ -1055,16 +1072,16 @@ func (in *ClusterDeprovisionPlatform) DeepCopyInto(out *ClusterDeprovisionPlatfo *out = new(VSphereClusterDeprovision) **out = **in } - if in.Ovirt != nil { - in, out := &in.Ovirt, &out.Ovirt - *out = new(OvirtClusterDeprovision) - **out = **in - } if in.IBMCloud != nil { in, out := &in.IBMCloud, &out.IBMCloud *out = new(IBMClusterDeprovision) **out = **in } + if in.Nutanix != nil { + in, out := &in.Nutanix, &out.Nutanix + *out = new(NutanixClusterDeprovision) + **out = **in + } return } @@ -1081,6 +1098,11 @@ func (in *ClusterDeprovisionPlatform) DeepCopy() *ClusterDeprovisionPlatform { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ClusterDeprovisionSpec) DeepCopyInto(out *ClusterDeprovisionSpec) { *out = *in + if in.MetadataJSONSecretRef != nil { + in, out := &in.MetadataJSONSecretRef, &out.MetadataJSONSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } in.Platform.DeepCopyInto(&out.Platform) return } @@ -1245,6 +1267,11 @@ func (in *ClusterIngress) DeepCopyInto(out *ClusterIngress) { *out = new(configv1.ConfigMapNameReference) **out = **in } + if in.TuningOptions != nil { + in, out := &in.TuningOptions, &out.TuningOptions + *out = new(operatorv1.IngressControllerTuningOptions) + (*in).DeepCopyInto(*out) + } return } @@ -1301,6 +1328,11 @@ func (in *ClusterMetadata) DeepCopyInto(out *ClusterMetadata) { *out = new(corev1.LocalObjectReference) **out = **in } + if in.MetadataJSONSecretRef != nil { + in, out := &in.MetadataJSONSecretRef, &out.MetadataJSONSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } if in.Platform != nil { in, out := &in.Platform, &out.Platform *out = new(ClusterPlatformMetadata) @@ -1567,6 +1599,18 @@ func (in *ClusterPoolSpec) DeepCopyInto(out *ClusterPoolSpec) { *out = make([]InventoryEntry, len(*in)) copy(*out, *in) } + if in.InstallerEnv != nil { + in, out := &in.InstallerEnv, &out.InstallerEnv + *out = make([]corev1.EnvVar, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.CustomizationRef != nil { + in, out := &in.CustomizationRef, &out.CustomizationRef + *out = new(corev1.LocalObjectReference) + **out = **in + } return } @@ -2461,6 +2505,67 @@ func (in *GCPDNSZoneStatus) DeepCopy() *GCPDNSZoneStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPPrivateServiceConnectConfig) DeepCopyInto(out *GCPPrivateServiceConnectConfig) { + *out = *in + out.CredentialsSecretRef = in.CredentialsSecretRef + if in.EndpointVPCInventory != nil { + in, out := &in.EndpointVPCInventory, &out.EndpointVPCInventory + *out = make([]GCPPrivateServiceConnectInventory, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPPrivateServiceConnectConfig. +func (in *GCPPrivateServiceConnectConfig) DeepCopy() *GCPPrivateServiceConnectConfig { + if in == nil { + return nil + } + out := new(GCPPrivateServiceConnectConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPPrivateServiceConnectInventory) DeepCopyInto(out *GCPPrivateServiceConnectInventory) { + *out = *in + if in.Subnets != nil { + in, out := &in.Subnets, &out.Subnets + *out = make([]GCPPrivateServiceConnectSubnet, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPPrivateServiceConnectInventory. +func (in *GCPPrivateServiceConnectInventory) DeepCopy() *GCPPrivateServiceConnectInventory { + if in == nil { + return nil + } + out := new(GCPPrivateServiceConnectInventory) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GCPPrivateServiceConnectSubnet) DeepCopyInto(out *GCPPrivateServiceConnectSubnet) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GCPPrivateServiceConnectSubnet. +func (in *GCPPrivateServiceConnectSubnet) DeepCopy() *GCPPrivateServiceConnectSubnet { + if in == nil { + return nil + } + out := new(GCPPrivateServiceConnectSubnet) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *HibernationConfig) DeepCopyInto(out *HibernationConfig) { *out = *in @@ -2577,6 +2682,11 @@ func (in *HiveConfigSpec) DeepCopyInto(out *HiveConfigSpec) { *out = new(corev1.LocalObjectReference) **out = **in } + if in.HiveImagePullSecretRef != nil { + in, out := &in.HiveImagePullSecretRef, &out.HiveImagePullSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } in.Backup.DeepCopyInto(&out.Backup) in.FailedProvisionConfig.DeepCopyInto(&out.FailedProvisionConfig) in.ServiceProviderCredentialsConfig.DeepCopyInto(&out.ServiceProviderCredentialsConfig) @@ -2611,6 +2721,11 @@ func (in *HiveConfigSpec) DeepCopyInto(out *HiveConfigSpec) { } } } + if in.PrivateLink != nil { + in, out := &in.PrivateLink, &out.PrivateLink + *out = new(PrivateLinkConfig) + (*in).DeepCopyInto(*out) + } if in.AWSPrivateLink != nil { in, out := &in.AWSPrivateLink, &out.AWSPrivateLink *out = new(AWSPrivateLinkConfig) @@ -2701,6 +2816,28 @@ func (in *IdentityProviderStatus) DeepCopy() *IdentityProviderStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *InstallerManifestPatch) DeepCopyInto(out *InstallerManifestPatch) { + *out = *in + out.ManifestSelector = in.ManifestSelector + if in.Patches != nil { + in, out := &in.Patches, &out.Patches + *out = make([]PatchEntity, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallerManifestPatch. +func (in *InstallerManifestPatch) DeepCopy() *InstallerManifestPatch { + if in == nil { + return nil + } + out := new(InstallerManifestPatch) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *InventoryEntry) DeepCopyInto(out *InventoryEntry) { *out = *in @@ -2947,11 +3084,6 @@ func (in *MachinePoolPlatform) DeepCopyInto(out *MachinePoolPlatform) { if in.VSphere != nil { in, out := &in.VSphere, &out.VSphere *out = new(vsphere.MachinePool) - **out = **in - } - if in.Ovirt != nil { - in, out := &in.Ovirt, &out.Ovirt - *out = new(ovirt.MachinePool) (*in).DeepCopyInto(*out) } if in.IBMCloud != nil { @@ -2959,6 +3091,11 @@ func (in *MachinePoolPlatform) DeepCopyInto(out *MachinePoolPlatform) { *out = new(ibmcloud.MachinePool) (*in).DeepCopyInto(*out) } + if in.Nutanix != nil { + in, out := &in.Nutanix, &out.Nutanix + *out = new(nutanix.MachinePool) + (*in).DeepCopyInto(*out) + } return } @@ -2994,6 +3131,13 @@ func (in *MachinePoolSpec) DeepCopyInto(out *MachinePoolSpec) { (*out)[key] = val } } + if in.MachineLabels != nil { + in, out := &in.MachineLabels, &out.MachineLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } if in.Taints != nil { in, out := &in.Taints, &out.Taints *out = make([]corev1.Taint, len(*in)) @@ -3036,11 +3180,21 @@ func (in *MachinePoolStatus) DeepCopyInto(out *MachinePoolStatus) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.OwnedMachineLabels != nil { + in, out := &in.OwnedMachineLabels, &out.OwnedMachineLabels + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.OwnedTaints != nil { in, out := &in.OwnedTaints, &out.OwnedTaints *out = make([]TaintIdentifier, len(*in)) copy(*out, *in) } + if in.ControlledByReplica != nil { + in, out := &in.ControlledByReplica, &out.ControlledByReplica + *out = new(int64) + **out = **in + } return } @@ -3168,45 +3322,62 @@ func (in *ManageDNSGCPConfig) DeepCopy() *ManageDNSGCPConfig { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *OpenStackClusterDeprovision) DeepCopyInto(out *OpenStackClusterDeprovision) { +func (in *ManifestSelector) DeepCopyInto(out *ManifestSelector) { *out = *in - if in.CredentialsSecretRef != nil { - in, out := &in.CredentialsSecretRef, &out.CredentialsSecretRef - *out = new(corev1.LocalObjectReference) - **out = **in - } - if in.CertificatesSecretRef != nil { - in, out := &in.CertificatesSecretRef, &out.CertificatesSecretRef - *out = new(corev1.LocalObjectReference) - **out = **in - } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterDeprovision. -func (in *OpenStackClusterDeprovision) DeepCopy() *OpenStackClusterDeprovision { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManifestSelector. +func (in *ManifestSelector) DeepCopy() *ManifestSelector { if in == nil { return nil } - out := new(OpenStackClusterDeprovision) + out := new(ManifestSelector) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *OvirtClusterDeprovision) DeepCopyInto(out *OvirtClusterDeprovision) { +func (in *NutanixClusterDeprovision) DeepCopyInto(out *NutanixClusterDeprovision) { *out = *in + out.PrismCentral = in.PrismCentral out.CredentialsSecretRef = in.CredentialsSecretRef out.CertificatesSecretRef = in.CertificatesSecretRef return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OvirtClusterDeprovision. -func (in *OvirtClusterDeprovision) DeepCopy() *OvirtClusterDeprovision { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NutanixClusterDeprovision. +func (in *NutanixClusterDeprovision) DeepCopy() *NutanixClusterDeprovision { + if in == nil { + return nil + } + out := new(NutanixClusterDeprovision) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OpenStackClusterDeprovision) DeepCopyInto(out *OpenStackClusterDeprovision) { + *out = *in + if in.CredentialsSecretRef != nil { + in, out := &in.CredentialsSecretRef, &out.CredentialsSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } + if in.CertificatesSecretRef != nil { + in, out := &in.CertificatesSecretRef, &out.CertificatesSecretRef + *out = new(corev1.LocalObjectReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackClusterDeprovision. +func (in *OpenStackClusterDeprovision) DeepCopy() *OpenStackClusterDeprovision { if in == nil { return nil } - out := new(OvirtClusterDeprovision) + out := new(OpenStackClusterDeprovision) in.DeepCopyInto(out) return out } @@ -3248,7 +3419,7 @@ func (in *Platform) DeepCopyInto(out *Platform) { if in.GCP != nil { in, out := &in.GCP, &out.GCP *out = new(gcp.Platform) - **out = **in + (*in).DeepCopyInto(*out) } if in.OpenStack != nil { in, out := &in.OpenStack, &out.OpenStack @@ -3260,11 +3431,6 @@ func (in *Platform) DeepCopyInto(out *Platform) { *out = new(vsphere.Platform) **out = **in } - if in.Ovirt != nil { - in, out := &in.Ovirt, &out.Ovirt - *out = new(ovirt.Platform) - **out = **in - } if in.AgentBareMetal != nil { in, out := &in.AgentBareMetal, &out.AgentBareMetal *out = new(agent.BareMetalPlatform) @@ -3280,6 +3446,11 @@ func (in *Platform) DeepCopyInto(out *Platform) { *out = new(none.Platform) **out = **in } + if in.Nutanix != nil { + in, out := &in.Nutanix, &out.Nutanix + *out = new(nutanix.Platform) + (*in).DeepCopyInto(*out) + } return } @@ -3301,6 +3472,11 @@ func (in *PlatformStatus) DeepCopyInto(out *PlatformStatus) { *out = new(aws.PlatformStatus) (*in).DeepCopyInto(*out) } + if in.GCP != nil { + in, out := &in.GCP, &out.GCP + *out = new(gcp.PlatformStatus) + (*in).DeepCopyInto(*out) + } return } @@ -3314,6 +3490,27 @@ func (in *PlatformStatus) DeepCopy() *PlatformStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrivateLinkConfig) DeepCopyInto(out *PrivateLinkConfig) { + *out = *in + if in.GCP != nil { + in, out := &in.GCP, &out.GCP + *out = new(GCPPrivateServiceConnectConfig) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrivateLinkConfig. +func (in *PrivateLinkConfig) DeepCopy() *PrivateLinkConfig { + if in == nil { + return nil + } + out := new(PrivateLinkConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Provisioning) DeepCopyInto(out *Provisioning) { *out = *in @@ -3322,6 +3519,11 @@ func (in *Provisioning) DeepCopyInto(out *Provisioning) { *out = new(corev1.LocalObjectReference) **out = **in } + if in.CustomizationRef != nil { + in, out := &in.CustomizationRef, &out.CustomizationRef + *out = new(corev1.LocalObjectReference) + **out = **in + } if in.ImageSetRef != nil { in, out := &in.ImageSetRef, &out.ImageSetRef *out = new(ClusterImageSetReference) diff --git a/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.defaults.go b/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.defaults.go new file mode 100644 index 000000000..88694caac --- /dev/null +++ b/vendor/github.com/openshift/hive/apis/hive/v1/zz_generated.defaults.go @@ -0,0 +1,17 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Code generated by defaulter-gen. DO NOT EDIT. + +package v1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// RegisterDefaults adds defaulters functions to the given scheme. +// Public to allow building arbitrary schemes. +// All generated defaulters are covering - they call all nested defaulters. +func RegisterDefaults(scheme *runtime.Scheme) error { + return nil +} diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.go b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.go index e4ec6cac9..ea22d5ea4 100644 --- a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.go +++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/gcp.go @@ -105,6 +105,7 @@ type GCPNetworkConfig struct { // +kubebuilder:validation:XValidation:rule="self.workloadIdentity.serviceAccountsEmails.cloudController.contains('@') && self.workloadIdentity.serviceAccountsEmails.cloudController.endsWith('@' + self.project + '.iam.gserviceaccount.com')",message="cloudController service account must belong to the same project" // +kubebuilder:validation:XValidation:rule="self.workloadIdentity.serviceAccountsEmails.storage.contains('@') && self.workloadIdentity.serviceAccountsEmails.storage.endsWith('@' + self.project + '.iam.gserviceaccount.com')",message="storage service account must belong to the same project" // +kubebuilder:validation:XValidation:rule="self.workloadIdentity.serviceAccountsEmails.imageRegistry.contains('@') && self.workloadIdentity.serviceAccountsEmails.imageRegistry.endsWith('@' + self.project + '.iam.gserviceaccount.com')",message="imageRegistry service account must belong to the same project" +// +kubebuilder:validation:XValidation:rule="self.workloadIdentity.serviceAccountsEmails.network.endsWith('@' + self.project + '.iam.gserviceaccount.com')",message="network service account must belong to the same project" type GCPPlatformSpec struct { // project is the GCP project ID. // A valid project ID must satisfy the following rules: @@ -357,6 +358,22 @@ type GCPServiceAccountsEmails struct { // +immutable // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="ImageRegistry is immutable" ImageRegistry GCPServiceAccountEmail `json:"imageRegistry,omitempty"` + + // network is the Google Service Account email for the Cloud Network Config Controller + // that manages cloud-level network configurations (egress IPs, subnets). + // This GSA requires the following IAM roles: + // - roles/compute.instanceAdmin.v1 (Compute Instance Admin - for managing network interfaces) + // - roles/compute.networkUser (Compute Network User - for using subnets) + // See cmd/infra/gcp/iam-bindings.json for the authoritative role definitions. + // Format: service-account-name@project-id.iam.gserviceaccount.com + // + // This is a user-provided value referencing a pre-created Google Service Account. + // Typically obtained from the output of `hypershift infra create gcp` which creates + // the required service accounts with appropriate IAM roles and WIF bindings. + // + // +required + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Network is immutable" + Network GCPServiceAccountEmail `json:"network,omitempty"` } // GCPOnHostMaintenance defines the behavior when a host maintenance event occurs. diff --git a/vendor/github.com/prometheus/procfs/.golangci.yml b/vendor/github.com/prometheus/procfs/.golangci.yml index 3c3bf910f..eac920ba8 100644 --- a/vendor/github.com/prometheus/procfs/.golangci.yml +++ b/vendor/github.com/prometheus/procfs/.golangci.yml @@ -1,7 +1,9 @@ version: "2" linters: enable: + - errorlint - forbidigo + - gocritic - godot - misspell - revive @@ -11,6 +13,20 @@ linters: forbid: - pattern: ^fmt\.Print.*$ msg: Do not commit print statements. + gocritic: + enable-all: true + disabled-checks: + - commentFormatting + - commentedOutCode + - deferInLoop + - filepathJoin + - hugeParam + - importShadow + - paramTypeCombine + - rangeValCopy + - tooManyResultsChecker + - unnamedResult + - whyNoLint godot: exclude: # Ignore "See: URL". @@ -18,17 +34,21 @@ linters: capital: true misspell: locale: US + revive: + rules: + - name: var-naming + # TODO(SuperQ): See: https://github.com/prometheus/prometheus/issues/17766 + arguments: + - [] + - [] + - - skip-package-name-checks: true exclusions: - generated: lax presets: - comments - common-false-positives - legacy - std-error-handling - paths: - - third_party$ - - builtin$ - - examples$ + warn-unused: true formatters: enable: - gofmt @@ -37,9 +57,3 @@ formatters: goimports: local-prefixes: - github.com/prometheus/procfs - exclusions: - generated: lax - paths: - - third_party$ - - builtin$ - - examples$ diff --git a/vendor/github.com/prometheus/procfs/Makefile b/vendor/github.com/prometheus/procfs/Makefile index 7edfe4d09..bce50a19c 100644 --- a/vendor/github.com/prometheus/procfs/Makefile +++ b/vendor/github.com/prometheus/procfs/Makefile @@ -1,4 +1,4 @@ -# Copyright 2018 The Prometheus Authors +# Copyright The Prometheus Authors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/Makefile.common b/vendor/github.com/prometheus/procfs/Makefile.common index 0ed55c2ba..cce3ef1d1 100644 --- a/vendor/github.com/prometheus/procfs/Makefile.common +++ b/vendor/github.com/prometheus/procfs/Makefile.common @@ -1,4 +1,4 @@ -# Copyright 2018 The Prometheus Authors +# Copyright The Prometheus Authors # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -33,7 +33,7 @@ GOHOSTOS ?= $(shell $(GO) env GOHOSTOS) GOHOSTARCH ?= $(shell $(GO) env GOHOSTARCH) GO_VERSION ?= $(shell $(GO) version) -GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION))Error Parsing File +GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') PROMU := $(FIRST_GOPATH)/bin/promu @@ -55,13 +55,14 @@ ifneq ($(shell command -v gotestsum 2> /dev/null),) endif endif -PROMU_VERSION ?= 0.17.0 +PROMU_VERSION ?= 0.18.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= -GOLANGCI_LINT_VERSION ?= v2.0.2 +GOLANGCI_LINT_VERSION ?= v2.10.1 +GOLANGCI_FMT_OPTS ?= # golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) @@ -81,11 +82,50 @@ endif PREFIX ?= $(shell pwd) BIN_DIR ?= $(shell pwd) DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD)) -DOCKERFILE_PATH ?= ./Dockerfile DOCKERBUILD_CONTEXT ?= ./ DOCKER_REPO ?= prom +# Check if deprecated DOCKERFILE_PATH is set +ifdef DOCKERFILE_PATH +$(error DOCKERFILE_PATH is deprecated. Use DOCKERFILE_VARIANTS ?= $(DOCKERFILE_PATH) in the Makefile) +endif + DOCKER_ARCHS ?= amd64 +DOCKERFILE_VARIANTS ?= Dockerfile $(wildcard Dockerfile.*) + +# Function to extract variant from Dockerfile label. +# Returns the variant name from io.prometheus.image.variant label, or "default" if not found. +define dockerfile_variant +$(strip $(or $(shell sed -n 's/.*io\.prometheus\.image\.variant="\([^"]*\)".*/\1/p' $(1)),default)) +endef + +# Check for duplicate variant names (including default for Dockerfiles without labels). +DOCKERFILE_VARIANT_NAMES := $(foreach df,$(DOCKERFILE_VARIANTS),$(call dockerfile_variant,$(df))) +DOCKERFILE_VARIANT_NAMES_SORTED := $(sort $(DOCKERFILE_VARIANT_NAMES)) +ifneq ($(words $(DOCKERFILE_VARIANT_NAMES)),$(words $(DOCKERFILE_VARIANT_NAMES_SORTED))) +$(error Duplicate variant names found. Each Dockerfile must have a unique io.prometheus.image.variant label, and only one can be without a label (default)) +endif + +# Build variant:dockerfile pairs for shell iteration. +DOCKERFILE_VARIANTS_WITH_NAMES := $(foreach df,$(DOCKERFILE_VARIANTS),$(call dockerfile_variant,$(df)):$(df)) + +# Shell helper to check whether a dockerfile/arch pair is excluded. +define dockerfile_arch_is_excluded +case " $(DOCKERFILE_ARCH_EXCLUSIONS) " in \ + *" $$dockerfile:$(1) "*) true ;; \ + *) false ;; \ +esac +endef + +# Shell helper to check whether a registry/arch pair is excluded. +# Extracts registry from DOCKER_REPO (e.g., quay.io/prometheus -> quay.io) +define registry_arch_is_excluded +registry=$$(echo "$(DOCKER_REPO)" | cut -d'/' -f1); \ +case " $(DOCKER_REGISTRY_ARCH_EXCLUSIONS) " in \ + *" $$registry:$(1) "*) true ;; \ + *) false ;; \ +esac +endef BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS)) PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS)) @@ -111,7 +151,7 @@ common-all: precheck style check_license lint yamllint unused build test .PHONY: common-style common-style: @echo ">> checking code style" - @fmtRes=$$($(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print)); \ + @fmtRes=$$($(GOFMT) -d $$(git ls-files '*.go' ':!:vendor/*' || find . -path ./vendor -prune -o -name '*.go' -print)); \ if [ -n "$${fmtRes}" ]; then \ echo "gofmt checking failed!"; echo "$${fmtRes}"; echo; \ echo "Please ensure you are using $$($(GO) version) for formatting code."; \ @@ -121,13 +161,19 @@ common-style: .PHONY: common-check_license common-check_license: @echo ">> checking license header" - @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ + @licRes=$$(for file in $$(git ls-files '*.go' ':!:vendor/*' || find . -path ./vendor -prune -o -type f -iname '*.go' -print) ; do \ awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \ done); \ if [ -n "$${licRes}" ]; then \ echo "license header checking failed:"; echo "$${licRes}"; \ exit 1; \ fi + @echo ">> checking for copyright years 2026 or later" + @futureYearRes=$$(git grep -E 'Copyright (202[6-9]|20[3-9][0-9])' -- '*.go' ':!:vendor/*' || true); \ + if [ -n "$${futureYearRes}" ]; then \ + echo "Files with copyright year 2026 or later found (should use 'Copyright The Prometheus Authors'):"; echo "$${futureYearRes}"; \ + exit 1; \ + fi .PHONY: common-deps common-deps: @@ -138,7 +184,7 @@ common-deps: update-go-deps: @echo ">> updating Go dependencies" @for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \ - $(GO) get -d $$m; \ + $(GO) get $$m; \ done $(GO) mod tidy @@ -156,9 +202,13 @@ $(GOTEST_DIR): @mkdir -p $@ .PHONY: common-format -common-format: +common-format: $(GOLANGCI_LINT) @echo ">> formatting code" $(GO) fmt $(pkgs) +ifdef GOLANGCI_LINT + @echo ">> formatting code with golangci-lint" + $(GOLANGCI_LINT) fmt $(GOLANGCI_FMT_OPTS) +endif .PHONY: common-vet common-vet: @@ -215,28 +265,194 @@ common-docker-repo-name: .PHONY: common-docker $(BUILD_DOCKER_ARCHS) common-docker: $(BUILD_DOCKER_ARCHS) $(BUILD_DOCKER_ARCHS): common-docker-%: - docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \ - -f $(DOCKERFILE_PATH) \ - --build-arg ARCH="$*" \ - --build-arg OS="linux" \ - $(DOCKERBUILD_CONTEXT) + @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \ + dockerfile=$${variant#*:}; \ + variant_name=$${variant%%:*}; \ + if $(call dockerfile_arch_is_excluded,$*); then \ + echo "Skipping $$variant_name variant for linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + distroless_arch="$*"; \ + if [ "$*" = "armv7" ]; then \ + distroless_arch="arm"; \ + fi; \ + if [ "$$dockerfile" = "Dockerfile" ]; then \ + echo "Building default variant ($$variant_name) for linux-$* using $$dockerfile"; \ + docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \ + -f $$dockerfile \ + --build-arg ARCH="$*" \ + --build-arg OS="linux" \ + --build-arg DISTROLESS_ARCH="$$distroless_arch" \ + $(DOCKERBUILD_CONTEXT); \ + if [ "$$variant_name" != "default" ]; then \ + echo "Tagging default variant with $$variant_name suffix"; \ + docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \ + "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \ + fi; \ + else \ + echo "Building $$variant_name variant for linux-$* using $$dockerfile"; \ + docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" \ + -f $$dockerfile \ + --build-arg ARCH="$*" \ + --build-arg OS="linux" \ + --build-arg DISTROLESS_ARCH="$$distroless_arch" \ + $(DOCKERBUILD_CONTEXT); \ + fi; \ + done .PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS) common-docker-publish: $(PUBLISH_DOCKER_ARCHS) $(PUBLISH_DOCKER_ARCHS): common-docker-publish-%: - docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" + @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \ + dockerfile=$${variant#*:}; \ + variant_name=$${variant%%:*}; \ + if $(call dockerfile_arch_is_excluded,$*); then \ + echo "Skipping push for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + if $(call registry_arch_is_excluded,$*); then \ + echo "Skipping push for $$variant_name variant on linux-$* to $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \ + echo "Pushing $$variant_name variant for linux-$*"; \ + docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \ + fi; \ + if [ "$$dockerfile" = "Dockerfile" ]; then \ + echo "Pushing default variant ($$variant_name) for linux-$*"; \ + docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)"; \ + fi; \ + if [ "$(DOCKER_IMAGE_TAG)" = "latest" ]; then \ + if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \ + echo "Pushing $$variant_name variant version tags for linux-$*"; \ + docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \ + fi; \ + if [ "$$dockerfile" = "Dockerfile" ]; then \ + echo "Pushing default variant version tag for linux-$*"; \ + docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"; \ + fi; \ + fi; \ + done DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION))) .PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS) common-docker-tag-latest: $(TAG_DOCKER_ARCHS) $(TAG_DOCKER_ARCHS): common-docker-tag-latest-%: - docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" - docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)" + @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \ + dockerfile=$${variant#*:}; \ + variant_name=$${variant%%:*}; \ + if $(call dockerfile_arch_is_excluded,$*); then \ + echo "Skipping tag for $$variant_name variant on linux-$* (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + if $(call registry_arch_is_excluded,$*); then \ + echo "Skipping tag for $$variant_name variant on linux-$* for $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \ + echo "Tagging $$variant_name variant for linux-$* as latest"; \ + docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest-$$variant_name"; \ + docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \ + fi; \ + if [ "$$dockerfile" = "Dockerfile" ]; then \ + echo "Tagging default variant ($$variant_name) for linux-$* as latest"; \ + docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest"; \ + docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"; \ + fi; \ + done .PHONY: common-docker-manifest common-docker-manifest: - DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(SANITIZED_DOCKER_IMAGE_TAG)) - DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" + @for variant in $(DOCKERFILE_VARIANTS_WITH_NAMES); do \ + dockerfile=$${variant#*:}; \ + variant_name=$${variant%%:*}; \ + if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \ + echo "Creating manifest for $$variant_name variant"; \ + refs=""; \ + for arch in $(DOCKER_ARCHS); do \ + if $(call dockerfile_arch_is_excluded,$$arch); then \ + echo " Skipping $$arch for $$variant_name (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + if $(call registry_arch_is_excluded,$$arch); then \ + echo " Skipping $$arch for $$variant_name on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \ + done; \ + if [ -z "$$refs" ]; then \ + echo "Skipping manifest for $$variant_name variant (no supported architectures)"; \ + continue; \ + fi; \ + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name" $$refs; \ + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)-$$variant_name"; \ + fi; \ + if [ "$$dockerfile" = "Dockerfile" ]; then \ + echo "Creating default variant ($$variant_name) manifest"; \ + refs=""; \ + for arch in $(DOCKER_ARCHS); do \ + if $(call dockerfile_arch_is_excluded,$$arch); then \ + echo " Skipping $$arch for default variant (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + if $(call registry_arch_is_excluded,$$arch); then \ + echo " Skipping $$arch for default variant on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:$(SANITIZED_DOCKER_IMAGE_TAG)"; \ + done; \ + if [ -z "$$refs" ]; then \ + echo "Skipping default variant manifest (no supported architectures)"; \ + continue; \ + fi; \ + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $$refs; \ + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)"; \ + fi; \ + if [ "$(DOCKER_IMAGE_TAG)" = "latest" ]; then \ + if [ "$$dockerfile" != "Dockerfile" ] || [ "$$variant_name" != "default" ]; then \ + echo "Creating manifest for $$variant_name variant version tag"; \ + refs=""; \ + for arch in $(DOCKER_ARCHS); do \ + if $(call dockerfile_arch_is_excluded,$$arch); then \ + echo " Skipping $$arch for $$variant_name version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + if $(call registry_arch_is_excluded,$$arch); then \ + echo " Skipping $$arch for $$variant_name version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \ + done; \ + if [ -z "$$refs" ]; then \ + echo "Skipping version-tag manifest for $$variant_name variant (no supported architectures)"; \ + continue; \ + fi; \ + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name" $$refs; \ + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)-$$variant_name"; \ + fi; \ + if [ "$$dockerfile" = "Dockerfile" ]; then \ + echo "Creating default variant version tag manifest"; \ + refs=""; \ + for arch in $(DOCKER_ARCHS); do \ + if $(call dockerfile_arch_is_excluded,$$arch); then \ + echo " Skipping $$arch for default variant version tag (excluded by DOCKERFILE_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + if $(call registry_arch_is_excluded,$$arch); then \ + echo " Skipping $$arch for default variant version tag on $(DOCKER_REPO) (excluded by DOCKER_REGISTRY_ARCH_EXCLUSIONS)"; \ + continue; \ + fi; \ + refs="$$refs $(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$$arch:v$(DOCKER_MAJOR_VERSION_TAG)"; \ + done; \ + if [ -z "$$refs" ]; then \ + echo "Skipping default variant version-tag manifest (no supported architectures)"; \ + continue; \ + fi; \ + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)" $$refs; \ + DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):v$(DOCKER_MAJOR_VERSION_TAG)"; \ + fi; \ + fi; \ + done .PHONY: promu promu: $(PROMU) @@ -248,8 +464,8 @@ $(PROMU): cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu rm -r $(PROMU_TMP) -.PHONY: proto -proto: +.PHONY: common-proto +common-proto: @echo ">> generating code from proto files" @./scripts/genproto.sh @@ -261,6 +477,10 @@ $(GOLANGCI_LINT): | sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION) endif +.PHONY: common-print-golangci-lint-version +common-print-golangci-lint-version: + @echo $(GOLANGCI_LINT_VERSION) + .PHONY: precheck precheck:: diff --git a/vendor/github.com/prometheus/procfs/arp.go b/vendor/github.com/prometheus/procfs/arp.go index 2e5334415..716bdef10 100644 --- a/vendor/github.com/prometheus/procfs/arp.go +++ b/vendor/github.com/prometheus/procfs/arp.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -73,15 +73,16 @@ func parseARPEntries(data []byte) ([]ARPEntry, error) { columns := strings.Fields(line) width := len(columns) - if width == expectedHeaderWidth || width == 0 { + switch width { + case expectedHeaderWidth, 0: continue - } else if width == expectedDataWidth { + case expectedDataWidth: entry, err := parseARPEntry(columns) if err != nil { return []ARPEntry{}, fmt.Errorf("%w: Failed to parse ARP entry: %v: %w", ErrFileParse, entry, err) } entries = append(entries, entry) - } else { + default: return []ARPEntry{}, fmt.Errorf("%w: %d columns found, but expected %d: %w", ErrFileParse, width, expectedDataWidth, err) } diff --git a/vendor/github.com/prometheus/procfs/buddyinfo.go b/vendor/github.com/prometheus/procfs/buddyinfo.go index 838075009..53243e687 100644 --- a/vendor/github.com/prometheus/procfs/buddyinfo.go +++ b/vendor/github.com/prometheus/procfs/buddyinfo.go @@ -1,4 +1,4 @@ -// Copyright 2017 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -64,14 +64,12 @@ func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { if bucketCount == -1 { bucketCount = arraySize - } else { - if bucketCount != arraySize { - return nil, fmt.Errorf("%w: mismatch in number of buddyinfo buckets, previous count %d, new count %d", ErrFileParse, bucketCount, arraySize) - } + } else if bucketCount != arraySize { + return nil, fmt.Errorf("%w: mismatch in number of buddyinfo buckets, previous count %d, new count %d", ErrFileParse, bucketCount, arraySize) } sizes := make([]float64, arraySize) - for i := 0; i < arraySize; i++ { + for i := range arraySize { sizes[i], err = strconv.ParseFloat(parts[i+4], 64) if err != nil { return nil, fmt.Errorf("%w: Invalid valid in buddyinfo: %f: %w", ErrFileParse, sizes[i], err) diff --git a/vendor/github.com/prometheus/procfs/cmdline.go b/vendor/github.com/prometheus/procfs/cmdline.go index bf4f3b48c..4f1cac1f0 100644 --- a/vendor/github.com/prometheus/procfs/cmdline.go +++ b/vendor/github.com/prometheus/procfs/cmdline.go @@ -1,4 +1,4 @@ -// Copyright 2021 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/cpuinfo.go b/vendor/github.com/prometheus/procfs/cpuinfo.go index f0950bb49..4b23d8d6b 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build linux -// +build linux package procfs @@ -502,7 +501,7 @@ func parseCPUInfoRISCV(info []byte) ([]CPUInfo, error) { return cpuinfo, nil } -func parseCPUInfoDummy(_ []byte) ([]CPUInfo, error) { // nolint:unused,deadcode +func parseCPUInfoDummy(_ []byte) ([]CPUInfo, error) { //nolint:unused return nil, errors.New("not implemented") } diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_armx.go b/vendor/github.com/prometheus/procfs/cpuinfo_armx.go index 64cfd534c..b09035ff3 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_armx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_armx.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,8 +12,6 @@ // limitations under the License. //go:build linux && (arm || arm64) -// +build linux -// +build arm arm64 package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_loong64.go b/vendor/github.com/prometheus/procfs/cpuinfo_loong64.go index d88442f0e..7bb20211f 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_loong64.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_loong64.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build linux -// +build linux package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go b/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go index c11207f3a..fd75d0f79 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_mipsx.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,8 +12,6 @@ // limitations under the License. //go:build linux && (mips || mipsle || mips64 || mips64le) -// +build linux -// +build mips mipsle mips64 mips64le package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_others.go b/vendor/github.com/prometheus/procfs/cpuinfo_others.go index a6b2b3127..3d36ba0e6 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_others.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_others.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build linux && !386 && !amd64 && !arm && !arm64 && !loong64 && !mips && !mips64 && !mips64le && !mipsle && !ppc64 && !ppc64le && !riscv64 && !s390x -// +build linux,!386,!amd64,!arm,!arm64,!loong64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go b/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go index 003bc2ad4..b3425051e 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_ppcx.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,8 +12,6 @@ // limitations under the License. //go:build linux && (ppc64 || ppc64le) -// +build linux -// +build ppc64 ppc64le package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go b/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go index 1c9b7313b..72598230c 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_riscvx.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,8 +12,6 @@ // limitations under the License. //go:build linux && (riscv || riscv64) -// +build linux -// +build riscv riscv64 package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go b/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go index fa3686bc0..50a8239cb 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_s390x.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build linux -// +build linux package procfs diff --git a/vendor/github.com/prometheus/procfs/cpuinfo_x86.go b/vendor/github.com/prometheus/procfs/cpuinfo_x86.go index a0ef55562..00edb30a5 100644 --- a/vendor/github.com/prometheus/procfs/cpuinfo_x86.go +++ b/vendor/github.com/prometheus/procfs/cpuinfo_x86.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,8 +12,6 @@ // limitations under the License. //go:build linux && (386 || amd64) -// +build linux -// +build 386 amd64 package procfs diff --git a/vendor/github.com/prometheus/procfs/crypto.go b/vendor/github.com/prometheus/procfs/crypto.go index 5f2a37a78..e4a5876ea 100644 --- a/vendor/github.com/prometheus/procfs/crypto.go +++ b/vendor/github.com/prometheus/procfs/crypto.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/doc.go b/vendor/github.com/prometheus/procfs/doc.go index f9d961e44..26bfea071 100644 --- a/vendor/github.com/prometheus/procfs/doc.go +++ b/vendor/github.com/prometheus/procfs/doc.go @@ -1,4 +1,4 @@ -// Copyright 2014 Prometheus Team +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/fs.go b/vendor/github.com/prometheus/procfs/fs.go index 9bdaccc7c..8f27912a1 100644 --- a/vendor/github.com/prometheus/procfs/fs.go +++ b/vendor/github.com/prometheus/procfs/fs.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/fs_statfs_notype.go b/vendor/github.com/prometheus/procfs/fs_statfs_notype.go index 1b5bdbdf8..0bef25bdd 100644 --- a/vendor/github.com/prometheus/procfs/fs_statfs_notype.go +++ b/vendor/github.com/prometheus/procfs/fs_statfs_notype.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build !freebsd && !linux -// +build !freebsd,!linux package procfs diff --git a/vendor/github.com/prometheus/procfs/fs_statfs_type.go b/vendor/github.com/prometheus/procfs/fs_statfs_type.go index 80df79c31..d18333039 100644 --- a/vendor/github.com/prometheus/procfs/fs_statfs_type.go +++ b/vendor/github.com/prometheus/procfs/fs_statfs_type.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build freebsd || linux -// +build freebsd linux package procfs diff --git a/vendor/github.com/prometheus/procfs/fscache.go b/vendor/github.com/prometheus/procfs/fscache.go index 7db863307..9dde85707 100644 --- a/vendor/github.com/prometheus/procfs/fscache.go +++ b/vendor/github.com/prometheus/procfs/fscache.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -388,20 +388,21 @@ func parseFscacheinfo(r io.Reader) (*Fscacheinfo, error) { } } case "CacheOp:": - if strings.Split(fields[1], "=")[0] == "alo" { + switch strings.Split(fields[1], "=")[0] { + case "alo": err := setFSCacheFields(fields[1:], &m.CacheopAllocationsinProgress, &m.CacheopLookupObjectInProgress, &m.CacheopLookupCompleteInPorgress, &m.CacheopGrabObjectInProgress) if err != nil { return &m, err } - } else if strings.Split(fields[1], "=")[0] == "inv" { + case "inv": err := setFSCacheFields(fields[1:], &m.CacheopInvalidations, &m.CacheopUpdateObjectInProgress, &m.CacheopDropObjectInProgress, &m.CacheopPutObjectInProgress, &m.CacheopAttributeChangeInProgress, &m.CacheopSyncCacheInProgress) if err != nil { return &m, err } - } else { + default: err := setFSCacheFields(fields[1:], &m.CacheopReadOrAllocPageInProgress, &m.CacheopReadOrAllocPagesInProgress, &m.CacheopAllocatePageInProgress, &m.CacheopAllocatePagesInProgress, &m.CacheopWritePagesInProgress, &m.CacheopUncachePagesInProgress, &m.CacheopDissociatePagesInProgress) diff --git a/vendor/github.com/prometheus/procfs/internal/fs/fs.go b/vendor/github.com/prometheus/procfs/internal/fs/fs.go index 3a43e8391..e7ccad66b 100644 --- a/vendor/github.com/prometheus/procfs/internal/fs/fs.go +++ b/vendor/github.com/prometheus/procfs/internal/fs/fs.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/internal/util/parse.go b/vendor/github.com/prometheus/procfs/internal/util/parse.go index 5a7d2df06..30c587201 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/parse.go +++ b/vendor/github.com/prometheus/procfs/internal/util/parse.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/internal/util/readfile.go b/vendor/github.com/prometheus/procfs/internal/util/readfile.go index 71b7a70eb..0e41f71af 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/readfile.go +++ b/vendor/github.com/prometheus/procfs/internal/util/readfile.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go index d5404a6d7..f6a4a4de6 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go +++ b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,8 +12,6 @@ // limitations under the License. //go:build (linux || darwin) && !appengine -// +build linux darwin -// +build !appengine package util diff --git a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go index 1d86f5e63..c80e082cb 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go +++ b/vendor/github.com/prometheus/procfs/internal/util/sysreadfile_compat.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build (linux && appengine) || (!linux && !darwin) -// +build linux,appengine !linux,!darwin package util diff --git a/vendor/github.com/prometheus/procfs/internal/util/valueparser.go b/vendor/github.com/prometheus/procfs/internal/util/valueparser.go index fe2355d3c..e0ed671ea 100644 --- a/vendor/github.com/prometheus/procfs/internal/util/valueparser.go +++ b/vendor/github.com/prometheus/procfs/internal/util/valueparser.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/ipvs.go b/vendor/github.com/prometheus/procfs/ipvs.go index bc3a20c93..5374da9fa 100644 --- a/vendor/github.com/prometheus/procfs/ipvs.go +++ b/vendor/github.com/prometheus/procfs/ipvs.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/kernel_hung.go b/vendor/github.com/prometheus/procfs/kernel_hung.go new file mode 100644 index 000000000..0c7a69f99 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/kernel_hung.go @@ -0,0 +1,44 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build !windows + +package procfs + +import ( + "os" + "strconv" + "strings" +) + +// KernelHung contains information about to the kernel's hung_task_detect_count number. +type KernelHung struct { + // Indicates the total number of tasks that have been detected as hung since the system boot. + // This file shows up if `CONFIG_DETECT_HUNG_TASK` is enabled. + HungTaskDetectCount *uint64 +} + +// KernelHung returns values from /proc/sys/kernel/hung_task_detect_count. +func (fs FS) KernelHung() (KernelHung, error) { + data, err := os.ReadFile(fs.proc.Path("sys", "kernel", "hung_task_detect_count")) + if err != nil { + return KernelHung{}, err + } + val, err := strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) + if err != nil { + return KernelHung{}, err + } + return KernelHung{ + HungTaskDetectCount: &val, + }, nil +} diff --git a/vendor/github.com/prometheus/procfs/kernel_random.go b/vendor/github.com/prometheus/procfs/kernel_random.go index db88566bd..e7c5b8cf2 100644 --- a/vendor/github.com/prometheus/procfs/kernel_random.go +++ b/vendor/github.com/prometheus/procfs/kernel_random.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build !windows -// +build !windows package procfs diff --git a/vendor/github.com/prometheus/procfs/loadavg.go b/vendor/github.com/prometheus/procfs/loadavg.go index 332e76c17..c8c78a65e 100644 --- a/vendor/github.com/prometheus/procfs/loadavg.go +++ b/vendor/github.com/prometheus/procfs/loadavg.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/mdstat.go b/vendor/github.com/prometheus/procfs/mdstat.go index 67a9d2b44..d66eeda82 100644 --- a/vendor/github.com/prometheus/procfs/mdstat.go +++ b/vendor/github.com/prometheus/procfs/mdstat.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -27,13 +27,34 @@ var ( recoveryLinePctRE = regexp.MustCompile(`= (.+)%`) recoveryLineFinishRE = regexp.MustCompile(`finish=(.+)min`) recoveryLineSpeedRE = regexp.MustCompile(`speed=(.+)[A-Z]`) - componentDeviceRE = regexp.MustCompile(`(.*)\[\d+\]`) + componentDeviceRE = regexp.MustCompile(`(.*)\[(\d+)\](\([SF]+\))?`) + personalitiesPrefix = "Personalities : " ) +type MDStatComponent struct { + // Name of the component device. + Name string + // DescriptorIndex number of component device, e.g. the order in the superblock. + DescriptorIndex int32 + // Flags per Linux drivers/md/md.[ch] as of v6.12-rc1 + // Subset that are exposed in mdstat + WriteMostly bool + Journal bool + Faulty bool // "Faulty" is what kernel source uses for "(F)" + Spare bool + Replacement bool + // Some additional flags that are NOT exposed in procfs today; they may + // be available via sysfs. + // In_sync, Bitmap_sync, Blocked, WriteErrorSeen, FaultRecorded, + // BlockedBadBlocks, WantReplacement, Candidate, ... +} + // MDStat holds info parsed from /proc/mdstat. type MDStat struct { // Name of the device. Name string + // raid type of the device. + Type string // activity-state of the device. ActivityState string // Number of active disks. @@ -58,8 +79,8 @@ type MDStat struct { BlocksSyncedFinishTime float64 // current sync speed (in Kilobytes/sec) BlocksSyncedSpeed float64 - // Name of md component devices - Devices []string + // component devices + Devices []MDStatComponent } // MDStat parses an mdstat-file (/proc/mdstat) and returns a slice of @@ -80,28 +101,52 @@ func (fs FS) MDStat() ([]MDStat, error) { // parseMDStat parses data from mdstat file (/proc/mdstat) and returns a slice of // structs containing the relevant info. func parseMDStat(mdStatData []byte) ([]MDStat, error) { + // TODO: + // - parse global hotspares from the "unused devices" line. mdStats := []MDStat{} lines := strings.Split(string(mdStatData), "\n") + knownRaidTypes := make(map[string]bool) for i, line := range lines { if strings.TrimSpace(line) == "" || line[0] == ' ' || - strings.HasPrefix(line, "Personalities") || strings.HasPrefix(line, "unused") { continue } + // Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] + if len(knownRaidTypes) == 0 && strings.HasPrefix(line, personalitiesPrefix) { + personalities := strings.Fields(line[len(personalitiesPrefix):]) + for _, word := range personalities { + word := word[1 : len(word)-1] + knownRaidTypes[word] = true + } + continue + } deviceFields := strings.Fields(line) if len(deviceFields) < 3 { return nil, fmt.Errorf("%w: Expected 3+ lines, got %q", ErrFileParse, line) } mdName := deviceFields[0] // mdx - state := deviceFields[2] // active or inactive + state := deviceFields[2] // active, inactive, broken + + mdType := "unknown" // raid1, raid5, etc. + var deviceStartIndex int + if len(deviceFields) > 3 { // mdType may be in the 3rd or 4th field + if isRaidType(deviceFields[3], knownRaidTypes) { + mdType = deviceFields[3] + deviceStartIndex = 4 + } else if len(deviceFields) > 4 && isRaidType(deviceFields[4], knownRaidTypes) { + // if the 3rd field is (...), the 4th field is the mdType + mdType = deviceFields[4] + deviceStartIndex = 5 + } + } if len(lines) <= i+3 { return nil, fmt.Errorf("%w: Too few lines for md device: %q", ErrFileParse, mdName) } - // Failed disks have the suffix (F) & Spare disks have the suffix (S). + // Failed (Faulty) disks have the suffix (F) & Spare disks have the suffix (S). fail := int64(strings.Count(line, "(F)")) spare := int64(strings.Count(line, "(S)")) active, total, down, size, err := evalStatusLine(lines[i], lines[i+1]) @@ -123,16 +168,20 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { finish := float64(0) pct := float64(0) recovering := strings.Contains(lines[syncLineIdx], "recovery") + reshaping := strings.Contains(lines[syncLineIdx], "reshape") resyncing := strings.Contains(lines[syncLineIdx], "resync") checking := strings.Contains(lines[syncLineIdx], "check") // Append recovery and resyncing state info. - if recovering || resyncing || checking { - if recovering { + if recovering || resyncing || checking || reshaping { + switch { + case recovering: state = "recovering" - } else if checking { + case reshaping: + state = "reshaping" + case checking: state = "checking" - } else { + default: state = "resyncing" } @@ -148,8 +197,14 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { } } + devices, err := evalComponentDevices(deviceFields[deviceStartIndex:]) + if err != nil { + return nil, fmt.Errorf("error parsing components in md device %q: %w", mdName, err) + } + mdStats = append(mdStats, MDStat{ Name: mdName, + Type: mdType, ActivityState: state, DisksActive: active, DisksFailed: fail, @@ -162,14 +217,24 @@ func parseMDStat(mdStatData []byte) ([]MDStat, error) { BlocksSyncedPct: pct, BlocksSyncedFinishTime: finish, BlocksSyncedSpeed: speed, - Devices: evalComponentDevices(deviceFields), + Devices: devices, }) } return mdStats, nil } +// check if a string's format is like the mdType +// Rule 1: mdType should not be like (...) +// Rule 2: mdType should not be like sda[0] +// . +func isRaidType(mdType string, knownRaidTypes map[string]bool) bool { + _, ok := knownRaidTypes[mdType] + return !strings.ContainsAny(mdType, "([") && ok +} + func evalStatusLine(deviceLine, statusLine string) (active, total, down, size int64, err error) { + // e.g. 523968 blocks super 1.2 [4/4] [UUUU] statusFields := strings.Fields(statusLine) if len(statusFields) < 1 { return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) @@ -260,17 +325,29 @@ func evalRecoveryLine(recoveryLine string) (blocksSynced int64, blocksToBeSynced return blocksSynced, blocksToBeSynced, pct, finish, speed, nil } -func evalComponentDevices(deviceFields []string) []string { - mdComponentDevices := make([]string, 0) - if len(deviceFields) > 3 { - for _, field := range deviceFields[4:] { - match := componentDeviceRE.FindStringSubmatch(field) - if match == nil { - continue - } - mdComponentDevices = append(mdComponentDevices, match[1]) +func evalComponentDevices(deviceFields []string) ([]MDStatComponent, error) { + mdComponentDevices := make([]MDStatComponent, 0) + for _, field := range deviceFields { + match := componentDeviceRE.FindStringSubmatch(field) + if match == nil { + continue + } + descriptorIndex, err := strconv.ParseInt(match[2], 10, 32) + if err != nil { + return mdComponentDevices, fmt.Errorf("error parsing int from device %q: %w", match[2], err) } + mdComponentDevices = append(mdComponentDevices, MDStatComponent{ + Name: match[1], + DescriptorIndex: int32(descriptorIndex), + // match may contain one or more of these + // https://github.com/torvalds/linux/blob/7ec462100ef9142344ddbf86f2c3008b97acddbe/drivers/md/md.c#L8376-L8392 + Faulty: strings.Contains(match[3], "(F)"), + Spare: strings.Contains(match[3], "(S)"), + Journal: strings.Contains(match[3], "(J)"), + Replacement: strings.Contains(match[3], "(R)"), + WriteMostly: strings.Contains(match[3], "(W)"), + }) } - return mdComponentDevices + return mdComponentDevices, nil } diff --git a/vendor/github.com/prometheus/procfs/meminfo.go b/vendor/github.com/prometheus/procfs/meminfo.go index 4b2c4050a..342038318 100644 --- a/vendor/github.com/prometheus/procfs/meminfo.go +++ b/vendor/github.com/prometheus/procfs/meminfo.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -66,6 +66,10 @@ type Meminfo struct { // Memory which has been evicted from RAM, and is temporarily // on the disk SwapFree *uint64 + // Memory consumed by the zswap backend (compressed size) + Zswap *uint64 + // Amount of anonymous memory stored in zswap (original size) + Zswapped *uint64 // Memory which is waiting to get written back to the disk Dirty *uint64 // Memory which is actively being written back to the disk @@ -85,6 +89,8 @@ type Meminfo struct { // amount of memory dedicated to the lowest level of page // tables. PageTables *uint64 + // secondary page tables. + SecPageTables *uint64 // NFS pages sent to the server, but not yet committed to // stable storage NFSUnstable *uint64 @@ -129,15 +135,18 @@ type Meminfo struct { Percpu *uint64 HardwareCorrupted *uint64 AnonHugePages *uint64 + FileHugePages *uint64 ShmemHugePages *uint64 ShmemPmdMapped *uint64 CmaTotal *uint64 CmaFree *uint64 + Unaccepted *uint64 HugePagesTotal *uint64 HugePagesFree *uint64 HugePagesRsvd *uint64 HugePagesSurp *uint64 Hugepagesize *uint64 + Hugetlb *uint64 DirectMap4k *uint64 DirectMap2M *uint64 DirectMap1G *uint64 @@ -161,6 +170,8 @@ type Meminfo struct { MlockedBytes *uint64 SwapTotalBytes *uint64 SwapFreeBytes *uint64 + ZswapBytes *uint64 + ZswappedBytes *uint64 DirtyBytes *uint64 WritebackBytes *uint64 AnonPagesBytes *uint64 @@ -171,6 +182,7 @@ type Meminfo struct { SUnreclaimBytes *uint64 KernelStackBytes *uint64 PageTablesBytes *uint64 + SecPageTablesBytes *uint64 NFSUnstableBytes *uint64 BounceBytes *uint64 WritebackTmpBytes *uint64 @@ -182,11 +194,14 @@ type Meminfo struct { PercpuBytes *uint64 HardwareCorruptedBytes *uint64 AnonHugePagesBytes *uint64 + FileHugePagesBytes *uint64 ShmemHugePagesBytes *uint64 ShmemPmdMappedBytes *uint64 CmaTotalBytes *uint64 CmaFreeBytes *uint64 + UnacceptedBytes *uint64 HugepagesizeBytes *uint64 + HugetlbBytes *uint64 DirectMap4kBytes *uint64 DirectMap2MBytes *uint64 DirectMap1GBytes *uint64 @@ -287,6 +302,12 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "SwapFree:": m.SwapFree = &val m.SwapFreeBytes = &valBytes + case "Zswap:": + m.Zswap = &val + m.ZswapBytes = &valBytes + case "Zswapped:": + m.Zswapped = &val + m.ZswappedBytes = &valBytes case "Dirty:": m.Dirty = &val m.DirtyBytes = &valBytes @@ -317,6 +338,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "PageTables:": m.PageTables = &val m.PageTablesBytes = &valBytes + case "SecPageTables:": + m.SecPageTables = &val + m.SecPageTablesBytes = &valBytes case "NFS_Unstable:": m.NFSUnstable = &val m.NFSUnstableBytes = &valBytes @@ -350,6 +374,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "AnonHugePages:": m.AnonHugePages = &val m.AnonHugePagesBytes = &valBytes + case "FileHugePages:": + m.FileHugePages = &val + m.FileHugePagesBytes = &valBytes case "ShmemHugePages:": m.ShmemHugePages = &val m.ShmemHugePagesBytes = &valBytes @@ -362,6 +389,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "CmaFree:": m.CmaFree = &val m.CmaFreeBytes = &valBytes + case "Unaccepted:": + m.Unaccepted = &val + m.UnacceptedBytes = &valBytes case "HugePages_Total:": m.HugePagesTotal = &val case "HugePages_Free:": @@ -373,6 +403,9 @@ func parseMemInfo(r io.Reader) (*Meminfo, error) { case "Hugepagesize:": m.Hugepagesize = &val m.HugepagesizeBytes = &valBytes + case "Hugetlb:": + m.Hugetlb = &val + m.HugetlbBytes = &valBytes case "DirectMap4k:": m.DirectMap4k = &val m.DirectMap4kBytes = &valBytes diff --git a/vendor/github.com/prometheus/procfs/mountinfo.go b/vendor/github.com/prometheus/procfs/mountinfo.go index a704c5e73..9414a12f4 100644 --- a/vendor/github.com/prometheus/procfs/mountinfo.go +++ b/vendor/github.com/prometheus/procfs/mountinfo.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -147,8 +147,7 @@ func mountOptionsParseOptionalFields(o []string) (map[string]string, error) { // mountOptionsParser parses the mount options, superblock options. func mountOptionsParser(mountOptions string) map[string]string { opts := make(map[string]string) - options := strings.Split(mountOptions, ",") - for _, opt := range options { + for opt := range strings.SplitSeq(mountOptions, ",") { splitOption := strings.Split(opt, "=") if len(splitOption) < 2 { key := splitOption[0] @@ -178,3 +177,21 @@ func GetProcMounts(pid int) ([]*MountInfo, error) { } return parseMountInfo(data) } + +// GetMounts retrieves mountinfo information from `/proc/self/mountinfo`. +func (fs FS) GetMounts() ([]*MountInfo, error) { + data, err := util.ReadFileNoStat(fs.proc.Path("self/mountinfo")) + if err != nil { + return nil, err + } + return parseMountInfo(data) +} + +// GetProcMounts retrieves mountinfo information from a processes' `/proc//mountinfo`. +func (fs FS) GetProcMounts(pid int) ([]*MountInfo, error) { + data, err := util.ReadFileNoStat(fs.proc.Path(fmt.Sprintf("%d/mountinfo", pid))) + if err != nil { + return nil, err + } + return parseMountInfo(data) +} diff --git a/vendor/github.com/prometheus/procfs/mountstats.go b/vendor/github.com/prometheus/procfs/mountstats.go index 50caa7327..e503cb3a6 100644 --- a/vendor/github.com/prometheus/procfs/mountstats.go +++ b/vendor/github.com/prometheus/procfs/mountstats.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -383,7 +383,7 @@ func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, e if stats.Opts == nil { stats.Opts = map[string]string{} } - for _, opt := range strings.Split(ss[1], ",") { + for opt := range strings.SplitSeq(ss[1], ",") { split := strings.Split(opt, "=") if len(split) == 2 { stats.Opts[split[0]] = split[1] diff --git a/vendor/github.com/prometheus/procfs/net_conntrackstat.go b/vendor/github.com/prometheus/procfs/net_conntrackstat.go index 316df5fbb..e9ca35707 100644 --- a/vendor/github.com/prometheus/procfs/net_conntrackstat.go +++ b/vendor/github.com/prometheus/procfs/net_conntrackstat.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/net_dev.go b/vendor/github.com/prometheus/procfs/net_dev.go index e66208aa0..7b3e1d61c 100644 --- a/vendor/github.com/prometheus/procfs/net_dev.go +++ b/vendor/github.com/prometheus/procfs/net_dev.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/net_dev_snmp6.go b/vendor/github.com/prometheus/procfs/net_dev_snmp6.go index f50b38e35..2a0f60f29 100644 --- a/vendor/github.com/prometheus/procfs/net_dev_snmp6.go +++ b/vendor/github.com/prometheus/procfs/net_dev_snmp6.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -18,6 +18,7 @@ import ( "errors" "io" "os" + "path/filepath" "strconv" "strings" ) @@ -56,7 +57,9 @@ func newNetDevSNMP6(dir string) (NetDevSNMP6, error) { } for _, iFaceFile := range ifaceFiles { - f, err := os.Open(dir + "/" + iFaceFile.Name()) + filePath := filepath.Join(dir, iFaceFile.Name()) + + f, err := os.Open(filePath) if err != nil { return netDevSNMP6, err } diff --git a/vendor/github.com/prometheus/procfs/net_ip_socket.go b/vendor/github.com/prometheus/procfs/net_ip_socket.go index 19e3378f7..9291f8cd4 100644 --- a/vendor/github.com/prometheus/procfs/net_ip_socket.go +++ b/vendor/github.com/prometheus/procfs/net_ip_socket.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/net_protocols.go b/vendor/github.com/prometheus/procfs/net_protocols.go index 8d4b1ac05..eaa996cbc 100644 --- a/vendor/github.com/prometheus/procfs/net_protocols.go +++ b/vendor/github.com/prometheus/procfs/net_protocols.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -169,7 +169,7 @@ func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) erro &pc.EnterMemoryPressure, } - for i := 0; i < len(capabilities); i++ { + for i := range capabilities { switch capabilities[i] { case "y": *capabilityFields[i] = true diff --git a/vendor/github.com/prometheus/procfs/net_route.go b/vendor/github.com/prometheus/procfs/net_route.go index deb7029fe..fa3812d9d 100644 --- a/vendor/github.com/prometheus/procfs/net_route.go +++ b/vendor/github.com/prometheus/procfs/net_route.go @@ -1,4 +1,4 @@ -// Copyright 2023 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/net_sockstat.go b/vendor/github.com/prometheus/procfs/net_sockstat.go index fae62b13d..8b221ebff 100644 --- a/vendor/github.com/prometheus/procfs/net_sockstat.go +++ b/vendor/github.com/prometheus/procfs/net_sockstat.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -139,9 +139,6 @@ func parseSockstatKVs(kvs []string) (map[string]int, error) { func parseSockstatProtocol(kvs map[string]int) NetSockstatProtocol { var nsp NetSockstatProtocol for k, v := range kvs { - // Capture the range variable to ensure we get unique pointers for - // each of the optional fields. - v := v switch k { case "inuse": nsp.InUse = v diff --git a/vendor/github.com/prometheus/procfs/net_softnet.go b/vendor/github.com/prometheus/procfs/net_softnet.go index 71c8059f4..4a2dfa18f 100644 --- a/vendor/github.com/prometheus/procfs/net_softnet.go +++ b/vendor/github.com/prometheus/procfs/net_softnet.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/net_tcp.go b/vendor/github.com/prometheus/procfs/net_tcp.go index 0396d7201..2c7f9bc7c 100644 --- a/vendor/github.com/prometheus/procfs/net_tcp.go +++ b/vendor/github.com/prometheus/procfs/net_tcp.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -25,6 +25,7 @@ type ( // NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp. +// // Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead. func (fs FS) NetTCP() (NetTCP, error) { return newNetTCP(fs.proc.Path("net/tcp")) @@ -32,6 +33,7 @@ func (fs FS) NetTCP() (NetTCP, error) { // NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp6. +// // Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead. func (fs FS) NetTCP6() (NetTCP, error) { return newNetTCP(fs.proc.Path("net/tcp6")) @@ -39,6 +41,7 @@ func (fs FS) NetTCP6() (NetTCP, error) { // NetTCPSummary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp. +// // Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET) instead. func (fs FS) NetTCPSummary() (*NetTCPSummary, error) { return newNetTCPSummary(fs.proc.Path("net/tcp")) @@ -46,6 +49,7 @@ func (fs FS) NetTCPSummary() (*NetTCPSummary, error) { // NetTCP6Summary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp6. +// // Deprecated: Use github.com/mdlayher/netlink#Conn (with syscall.AF_INET6) instead. func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) { return newNetTCPSummary(fs.proc.Path("net/tcp6")) diff --git a/vendor/github.com/prometheus/procfs/net_tls_stat.go b/vendor/github.com/prometheus/procfs/net_tls_stat.go index 13994c178..b1b3f6a6a 100644 --- a/vendor/github.com/prometheus/procfs/net_tls_stat.go +++ b/vendor/github.com/prometheus/procfs/net_tls_stat.go @@ -1,4 +1,4 @@ -// Copyright 2023 Prometheus Team +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/net_udp.go b/vendor/github.com/prometheus/procfs/net_udp.go index 9ac3daf2d..8a3277910 100644 --- a/vendor/github.com/prometheus/procfs/net_udp.go +++ b/vendor/github.com/prometheus/procfs/net_udp.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/net_unix.go b/vendor/github.com/prometheus/procfs/net_unix.go index d7e0cacb4..e4d635923 100644 --- a/vendor/github.com/prometheus/procfs/net_unix.go +++ b/vendor/github.com/prometheus/procfs/net_unix.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/net_wireless.go b/vendor/github.com/prometheus/procfs/net_wireless.go index 7c597bc87..69d079445 100644 --- a/vendor/github.com/prometheus/procfs/net_wireless.go +++ b/vendor/github.com/prometheus/procfs/net_wireless.go @@ -1,4 +1,4 @@ -// Copyright 2023 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/net_xfrm.go b/vendor/github.com/prometheus/procfs/net_xfrm.go index 932ef2046..5a9f497d1 100644 --- a/vendor/github.com/prometheus/procfs/net_xfrm.go +++ b/vendor/github.com/prometheus/procfs/net_xfrm.go @@ -1,4 +1,4 @@ -// Copyright 2017 Prometheus Team +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/netstat.go b/vendor/github.com/prometheus/procfs/netstat.go index 742dff453..dbdae4739 100644 --- a/vendor/github.com/prometheus/procfs/netstat.go +++ b/vendor/github.com/prometheus/procfs/netstat.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/nfnetlink_queue.go b/vendor/github.com/prometheus/procfs/nfnetlink_queue.go new file mode 100644 index 000000000..b0a73b11e --- /dev/null +++ b/vendor/github.com/prometheus/procfs/nfnetlink_queue.go @@ -0,0 +1,85 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "bufio" + "bytes" + "fmt" + + "github.com/prometheus/procfs/internal/util" +) + +const nfNetLinkQueueFormat = "%d %d %d %d %d %d %d %d %d" + +// NFNetLinkQueue contains general information about netfilter queues found in /proc/net/netfilter/nfnetlink_queue. +type NFNetLinkQueue struct { + // id of the queue + QueueID uint + // pid of process handling the queue + PeerPID uint + // number of packets waiting for a decision + QueueTotal uint + // indicate how userspace receive packets + CopyMode uint + // size of copy + CopyRange uint + // number of items dropped by the kernel because too many packets were waiting a decision. + // It queue_total is superior to queue_max_len (1024 per default) the packets are dropped. + QueueDropped uint + // number of packets dropped by userspace (due to kernel send failure on the netlink socket) + QueueUserDropped uint + // sequence number of packets queued. It gives a correct approximation of the number of queued packets. + SequenceID uint + // internal value (number of entity using the queue) + Use uint +} + +// NFNetLinkQueue returns information about current state of netfilter queues. +func (fs FS) NFNetLinkQueue() ([]NFNetLinkQueue, error) { + data, err := util.ReadFileNoStat(fs.proc.Path("net/netfilter/nfnetlink_queue")) + if err != nil { + return nil, err + } + + queue := []NFNetLinkQueue{} + if len(data) == 0 { + return queue, nil + } + + scanner := bufio.NewScanner(bytes.NewReader(data)) + for scanner.Scan() { + line := scanner.Text() + nFNetLinkQueue, err := parseNFNetLinkQueueLine(line) + if err != nil { + return nil, err + } + queue = append(queue, *nFNetLinkQueue) + } + return queue, nil +} + +// parseNFNetLinkQueueLine parses each line of the /proc/net/netfilter/nfnetlink_queue file. +func parseNFNetLinkQueueLine(line string) (*NFNetLinkQueue, error) { + nFNetLinkQueue := NFNetLinkQueue{} + _, err := fmt.Sscanf( + line, nfNetLinkQueueFormat, + &nFNetLinkQueue.QueueID, &nFNetLinkQueue.PeerPID, &nFNetLinkQueue.QueueTotal, &nFNetLinkQueue.CopyMode, + &nFNetLinkQueue.CopyRange, &nFNetLinkQueue.QueueDropped, &nFNetLinkQueue.QueueUserDropped, &nFNetLinkQueue.SequenceID, &nFNetLinkQueue.Use, + ) + if err != nil { + return nil, err + } + return &nFNetLinkQueue, nil +} diff --git a/vendor/github.com/prometheus/procfs/proc.go b/vendor/github.com/prometheus/procfs/proc.go index 368187fa8..39c14aa55 100644 --- a/vendor/github.com/prometheus/procfs/proc.go +++ b/vendor/github.com/prometheus/procfs/proc.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -49,7 +49,7 @@ func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID } // Self returns a process for the current process read via /proc/self. func Self() (Proc, error) { fs, err := NewFS(DefaultMountPoint) - if err != nil || errors.Unwrap(err) == ErrMountPoint { + if err != nil || errors.Is(err, ErrMountPoint) { return Proc{}, err } return fs.Self() diff --git a/vendor/github.com/prometheus/procfs/proc_cgroup.go b/vendor/github.com/prometheus/procfs/proc_cgroup.go index 4a64347c0..535c08d6f 100644 --- a/vendor/github.com/prometheus/procfs/proc_cgroup.go +++ b/vendor/github.com/prometheus/procfs/proc_cgroup.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/proc_cgroups.go b/vendor/github.com/prometheus/procfs/proc_cgroups.go index 5dd493899..0b275c3b1 100644 --- a/vendor/github.com/prometheus/procfs/proc_cgroups.go +++ b/vendor/github.com/prometheus/procfs/proc_cgroups.go @@ -1,4 +1,4 @@ -// Copyright 2021 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -40,13 +40,13 @@ type CgroupSummary struct { // parseCgroupSummary parses each line of the /proc/cgroup file // Line format is `subsys_name hierarchy num_cgroups enabled`. -func parseCgroupSummaryString(CgroupSummaryStr string) (*CgroupSummary, error) { +func parseCgroupSummaryString(cgroupSummaryStr string) (*CgroupSummary, error) { var err error - fields := strings.Fields(CgroupSummaryStr) + fields := strings.Fields(cgroupSummaryStr) // require at least 4 fields if len(fields) < 4 { - return nil, fmt.Errorf("%w: 4+ fields required, found %d fields in cgroup info string: %s", ErrFileParse, len(fields), CgroupSummaryStr) + return nil, fmt.Errorf("%w: 4+ fields required, found %d fields in cgroup info string: %s", ErrFileParse, len(fields), cgroupSummaryStr) } CgroupSummary := &CgroupSummary{ diff --git a/vendor/github.com/prometheus/procfs/proc_environ.go b/vendor/github.com/prometheus/procfs/proc_environ.go index 57a89895d..5b941de04 100644 --- a/vendor/github.com/prometheus/procfs/proc_environ.go +++ b/vendor/github.com/prometheus/procfs/proc_environ.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/proc_fdinfo.go b/vendor/github.com/prometheus/procfs/proc_fdinfo.go index fa761b352..fa57761db 100644 --- a/vendor/github.com/prometheus/procfs/proc_fdinfo.go +++ b/vendor/github.com/prometheus/procfs/proc_fdinfo.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -60,15 +60,16 @@ func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(data)) for scanner.Scan() { text = scanner.Text() - if rPos.MatchString(text) { + switch { + case rPos.MatchString(text): pos = rPos.FindStringSubmatch(text)[1] - } else if rFlags.MatchString(text) { + case rFlags.MatchString(text): flags = rFlags.FindStringSubmatch(text)[1] - } else if rMntID.MatchString(text) { + case rMntID.MatchString(text): mntid = rMntID.FindStringSubmatch(text)[1] - } else if rIno.MatchString(text) { + case rIno.MatchString(text): ino = rIno.FindStringSubmatch(text)[1] - } else if rInotify.MatchString(text) { + case rInotify.MatchString(text): newInotify, err := parseInotifyInfo(text) if err != nil { return nil, err diff --git a/vendor/github.com/prometheus/procfs/proc_interrupts.go b/vendor/github.com/prometheus/procfs/proc_interrupts.go index 86b4b4524..643b500d5 100644 --- a/vendor/github.com/prometheus/procfs/proc_interrupts.go +++ b/vendor/github.com/prometheus/procfs/proc_interrupts.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -42,7 +42,7 @@ type Interrupts map[string]Interrupt // Interrupts creates a new instance from a given Proc instance. func (p Proc) Interrupts() (Interrupts, error) { - data, err := util.ReadFileNoStat(p.path("interrupts")) + data, err := util.ReadFileNoStat(p.fs.proc.Path("interrupts")) if err != nil { return nil, err } diff --git a/vendor/github.com/prometheus/procfs/proc_io.go b/vendor/github.com/prometheus/procfs/proc_io.go index d15b66ddb..dd8086ba2 100644 --- a/vendor/github.com/prometheus/procfs/proc_io.go +++ b/vendor/github.com/prometheus/procfs/proc_io.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/proc_limits.go b/vendor/github.com/prometheus/procfs/proc_limits.go index 9530b14bc..4b7d33784 100644 --- a/vendor/github.com/prometheus/procfs/proc_limits.go +++ b/vendor/github.com/prometheus/procfs/proc_limits.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -19,6 +19,7 @@ import ( "os" "regexp" "strconv" + "strings" ) // ProcLimits represents the soft limits for each of the process's resource @@ -74,7 +75,7 @@ const ( ) var ( - limitsMatch = regexp.MustCompile(`(Max \w+\s{0,1}?\w*\s{0,1}\w*)\s{2,}(\w+)\s+(\w+)`) + limitsMatch = regexp.MustCompile(`(Max \w+\s??\w*\s?\w*)\s{2,}(\w+)\s+(\w+)`) ) // NewLimits returns the current soft limits of the process. @@ -106,7 +107,7 @@ func (p Proc) Limits() (ProcLimits, error) { return ProcLimits{}, fmt.Errorf("%w: couldn't parse %q line %q", ErrFileParse, f.Name(), s.Text()) } - switch fields[1] { + switch strings.TrimSpace(fields[1]) { case "Max cpu time": l.CPUTime, err = parseUint(fields[2]) case "Max file size": diff --git a/vendor/github.com/prometheus/procfs/proc_maps.go b/vendor/github.com/prometheus/procfs/proc_maps.go index 7e75c286b..08b89a6eb 100644 --- a/vendor/github.com/prometheus/procfs/proc_maps.go +++ b/vendor/github.com/prometheus/procfs/proc_maps.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,8 +12,6 @@ // limitations under the License. //go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) && !js -// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris -// +build !js package procfs diff --git a/vendor/github.com/prometheus/procfs/proc_netstat.go b/vendor/github.com/prometheus/procfs/proc_netstat.go index 4248c1716..7f94cc891 100644 --- a/vendor/github.com/prometheus/procfs/proc_netstat.go +++ b/vendor/github.com/prometheus/procfs/proc_netstat.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/proc_ns.go b/vendor/github.com/prometheus/procfs/proc_ns.go index 0f8f847f9..5fc0eb9e2 100644 --- a/vendor/github.com/prometheus/procfs/proc_ns.go +++ b/vendor/github.com/prometheus/procfs/proc_ns.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/proc_psi.go b/vendor/github.com/prometheus/procfs/proc_psi.go index ccd35f153..cc2c5de87 100644 --- a/vendor/github.com/prometheus/procfs/proc_psi.go +++ b/vendor/github.com/prometheus/procfs/proc_psi.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/proc_smaps.go b/vendor/github.com/prometheus/procfs/proc_smaps.go index 9a297afcf..f637309b3 100644 --- a/vendor/github.com/prometheus/procfs/proc_smaps.go +++ b/vendor/github.com/prometheus/procfs/proc_smaps.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build !windows -// +build !windows package procfs diff --git a/vendor/github.com/prometheus/procfs/proc_snmp.go b/vendor/github.com/prometheus/procfs/proc_snmp.go index 4bdc90b07..8d9a9bcd6 100644 --- a/vendor/github.com/prometheus/procfs/proc_snmp.go +++ b/vendor/github.com/prometheus/procfs/proc_snmp.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/proc_snmp6.go b/vendor/github.com/prometheus/procfs/proc_snmp6.go index fb7fd3995..841fef464 100644 --- a/vendor/github.com/prometheus/procfs/proc_snmp6.go +++ b/vendor/github.com/prometheus/procfs/proc_snmp6.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/proc_stat.go b/vendor/github.com/prometheus/procfs/proc_stat.go index 06a8d931c..02e3f9e31 100644 --- a/vendor/github.com/prometheus/procfs/proc_stat.go +++ b/vendor/github.com/prometheus/procfs/proc_stat.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -101,6 +101,12 @@ type ProcStat struct { RSS int // Soft limit in bytes on the rss of the process. RSSLimit uint64 + // The address above which program text can run. + StartCode uint64 + // The address below which program text can run. + EndCode uint64 + // The address of the start (i.e., bottom) of the stack. + StartStack uint64 // CPU number last executed on. Processor uint // Real-time scheduling priority, a number in the range 1 to 99 for processes @@ -177,9 +183,9 @@ func (p Proc) Stat() (ProcStat, error) { &s.VSize, &s.RSS, &s.RSSLimit, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, + &s.StartCode, + &s.EndCode, + &s.StartStack, &ignoreUint64, &ignoreUint64, &ignoreUint64, diff --git a/vendor/github.com/prometheus/procfs/proc_statm.go b/vendor/github.com/prometheus/procfs/proc_statm.go new file mode 100644 index 000000000..6bcc97ec9 --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_statm.go @@ -0,0 +1,117 @@ +// Copyright The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package procfs + +import ( + "os" + "strconv" + "strings" + + "github.com/prometheus/procfs/internal/util" +) + +// - https://man7.org/linux/man-pages/man5/proc_pid_statm.5.html + +// ProcStatm Provides memory usage information for a process, measured in memory pages. +// Read from /proc/[pid]/statm. +type ProcStatm struct { + // The process ID. + PID int + // total program size (same as VmSize in status) + Size uint64 + // resident set size (same as VmRSS in status) + Resident uint64 + // number of resident shared pages (i.e., backed by a file) + Shared uint64 + // text (code) + Text uint64 + // library (unused since Linux 2.6; always 0) + Lib uint64 + // data + stack + Data uint64 + // dirty pages (unused since Linux 2.6; always 0) + Dt uint64 +} + +// NewStatm returns the current status information of the process. +// +// Deprecated: Use p.Statm() instead. +func (p Proc) NewStatm() (ProcStatm, error) { + return p.Statm() +} + +// Statm returns the current memory usage information of the process. +func (p Proc) Statm() (ProcStatm, error) { + data, err := util.ReadFileNoStat(p.path("statm")) + if err != nil { + return ProcStatm{}, err + } + + statmSlice, err := parseStatm(data) + if err != nil { + return ProcStatm{}, err + } + + procStatm := ProcStatm{ + PID: p.PID, + Size: statmSlice[0], + Resident: statmSlice[1], + Shared: statmSlice[2], + Text: statmSlice[3], + Lib: statmSlice[4], + Data: statmSlice[5], + Dt: statmSlice[6], + } + + return procStatm, nil +} + +// parseStatm return /proc/[pid]/statm data to uint64 slice. +func parseStatm(data []byte) ([]uint64, error) { + var statmSlice []uint64 + statmItems := strings.Fields(string(data)) + for i := range statmItems { + statmItem, err := strconv.ParseUint(statmItems[i], 10, 64) + if err != nil { + return nil, err + } + statmSlice = append(statmSlice, statmItem) + } + return statmSlice, nil +} + +// SizeBytes returns the process of total program size in bytes. +func (s ProcStatm) SizeBytes() uint64 { + return s.Size * uint64(os.Getpagesize()) +} + +// ResidentBytes returns the process of resident set size in bytes. +func (s ProcStatm) ResidentBytes() uint64 { + return s.Resident * uint64(os.Getpagesize()) +} + +// SHRBytes returns the process of share memory size in bytes. +func (s ProcStatm) SHRBytes() uint64 { + return s.Shared * uint64(os.Getpagesize()) +} + +// TextBytes returns the process of text (code) size in bytes. +func (s ProcStatm) TextBytes() uint64 { + return s.Text * uint64(os.Getpagesize()) +} + +// DataBytes returns the process of data + stack size in bytes. +func (s ProcStatm) DataBytes() uint64 { + return s.Data * uint64(os.Getpagesize()) +} diff --git a/vendor/github.com/prometheus/procfs/proc_status.go b/vendor/github.com/prometheus/procfs/proc_status.go index dd8aa5688..12d65581c 100644 --- a/vendor/github.com/prometheus/procfs/proc_status.go +++ b/vendor/github.com/prometheus/procfs/proc_status.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -16,7 +16,7 @@ package procfs import ( "bytes" "math/bits" - "sort" + "slices" "strconv" "strings" @@ -83,6 +83,19 @@ type ProcStatus struct { // CpusAllowedList: List of cpu cores processes are allowed to run on. CpusAllowedList []uint64 + + // CapInh is the bitmap of inheritable capabilities + // + // See: https://www.kernel.org/doc/man-pages/online/pages/man7/capabilities.7.html + CapInh uint64 + // CapPrm is the bitmap of permitted capabilities + CapPrm uint64 + // CapEff is the bitmap of effective capabilities + CapEff uint64 + // CapBnd is the bitmap of bounding capabilities + CapBnd uint64 + // CapAmb is the bitmap of ambient capabilities + CapAmb uint64 } // NewStatus returns the current status information of the process. @@ -94,8 +107,7 @@ func (p Proc) NewStatus() (ProcStatus, error) { s := ProcStatus{PID: p.PID} - lines := strings.Split(string(data), "\n") - for _, line := range lines { + for line := range strings.SplitSeq(string(data), "\n") { if !bytes.Contains([]byte(line), []byte(":")) { continue } @@ -191,6 +203,36 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt s.NonVoluntaryCtxtSwitches = vUint case "Cpus_allowed_list": s.CpusAllowedList = calcCpusAllowedList(vString) + case "CapInh": + var err error + s.CapInh, err = strconv.ParseUint(vString, 16, 64) + if err != nil { + return err + } + case "CapPrm": + var err error + s.CapPrm, err = strconv.ParseUint(vString, 16, 64) + if err != nil { + return err + } + case "CapEff": + var err error + s.CapEff, err = strconv.ParseUint(vString, 16, 64) + if err != nil { + return err + } + case "CapBnd": + var err error + s.CapBnd, err = strconv.ParseUint(vString, 16, 64) + if err != nil { + return err + } + case "CapAmb": + var err error + s.CapAmb, err = strconv.ParseUint(vString, 16, 64) + if err != nil { + return err + } } return nil @@ -222,7 +264,7 @@ func calcCpusAllowedList(cpuString string) []uint64 { } - sort.Slice(g, func(i, j int) bool { return g[i] < g[j] }) + slices.Sort(g) return g } diff --git a/vendor/github.com/prometheus/procfs/proc_sys.go b/vendor/github.com/prometheus/procfs/proc_sys.go index 3810d1ac9..52658a4d5 100644 --- a/vendor/github.com/prometheus/procfs/proc_sys.go +++ b/vendor/github.com/prometheus/procfs/proc_sys.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/schedstat.go b/vendor/github.com/prometheus/procfs/schedstat.go index 5f7f32dc8..fafd8dff7 100644 --- a/vendor/github.com/prometheus/procfs/schedstat.go +++ b/vendor/github.com/prometheus/procfs/schedstat.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/slab.go b/vendor/github.com/prometheus/procfs/slab.go index 8611c9017..32a04678a 100644 --- a/vendor/github.com/prometheus/procfs/slab.go +++ b/vendor/github.com/prometheus/procfs/slab.go @@ -1,4 +1,4 @@ -// Copyright 2020 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/softirqs.go b/vendor/github.com/prometheus/procfs/softirqs.go index 403e6ae70..47b73a729 100644 --- a/vendor/github.com/prometheus/procfs/softirqs.go +++ b/vendor/github.com/prometheus/procfs/softirqs.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/stat.go b/vendor/github.com/prometheus/procfs/stat.go index e36b41c18..593ad0f62 100644 --- a/vendor/github.com/prometheus/procfs/stat.go +++ b/vendor/github.com/prometheus/procfs/stat.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -16,6 +16,7 @@ package procfs import ( "bufio" "bytes" + "errors" "fmt" "io" "strconv" @@ -92,7 +93,7 @@ func parseCPUStat(line string) (CPUStat, int64, error) { &cpuStat.Iowait, &cpuStat.IRQ, &cpuStat.SoftIRQ, &cpuStat.Steal, &cpuStat.Guest, &cpuStat.GuestNice) - if err != nil && err != io.EOF { + if err != nil && !errors.Is(err, io.EOF) { return CPUStat{}, -1, fmt.Errorf("%w: couldn't parse %q (cpu): %w", ErrFileParse, line, err) } if count == 0 { diff --git a/vendor/github.com/prometheus/procfs/swaps.go b/vendor/github.com/prometheus/procfs/swaps.go index 65fec834b..ee17bf488 100644 --- a/vendor/github.com/prometheus/procfs/swaps.go +++ b/vendor/github.com/prometheus/procfs/swaps.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/thread.go b/vendor/github.com/prometheus/procfs/thread.go index 80e0e947b..0cfbb5418 100644 --- a/vendor/github.com/prometheus/procfs/thread.go +++ b/vendor/github.com/prometheus/procfs/thread.go @@ -1,4 +1,4 @@ -// Copyright 2022 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at diff --git a/vendor/github.com/prometheus/procfs/vm.go b/vendor/github.com/prometheus/procfs/vm.go index 51c49d89e..52180c03e 100644 --- a/vendor/github.com/prometheus/procfs/vm.go +++ b/vendor/github.com/prometheus/procfs/vm.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build !windows -// +build !windows package procfs diff --git a/vendor/github.com/prometheus/procfs/zoneinfo.go b/vendor/github.com/prometheus/procfs/zoneinfo.go index e54d94b09..63d1898bc 100644 --- a/vendor/github.com/prometheus/procfs/zoneinfo.go +++ b/vendor/github.com/prometheus/procfs/zoneinfo.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Prometheus Authors +// Copyright The Prometheus Authors // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -12,7 +12,6 @@ // limitations under the License. //go:build !windows -// +build !windows package procfs @@ -88,11 +87,9 @@ func parseZoneinfo(zoneinfoData []byte) ([]Zoneinfo, error) { zoneinfo := []Zoneinfo{} - zoneinfoBlocks := bytes.Split(zoneinfoData, []byte("\nNode")) - for _, block := range zoneinfoBlocks { + for block := range bytes.SplitSeq(zoneinfoData, []byte("\nNode")) { var zoneinfoElement Zoneinfo - lines := strings.Split(string(block), "\n") - for _, line := range lines { + for line := range strings.SplitSeq(string(block), "\n") { if nodeZone := nodeZoneRE.FindStringSubmatch(line); nodeZone != nil { zoneinfoElement.Node = nodeZone[1] diff --git a/vendor/golang.org/x/net/http2/hpack/tables.go b/vendor/golang.org/x/net/http2/hpack/tables.go index 8cbdf3f01..803fe5178 100644 --- a/vendor/golang.org/x/net/http2/hpack/tables.go +++ b/vendor/golang.org/x/net/http2/hpack/tables.go @@ -6,6 +6,7 @@ package hpack import ( "fmt" + "strings" ) // headerFieldTable implements a list of HeaderFields. @@ -54,10 +55,16 @@ func (t *headerFieldTable) len() int { // addEntry adds a new entry. func (t *headerFieldTable) addEntry(f HeaderField) { + // Prevent f from escaping to the heap. + f2 := HeaderField{ + Name: strings.Clone(f.Name), + Value: strings.Clone(f.Value), + Sensitive: f.Sensitive, + } id := uint64(t.len()) + t.evictCount + 1 - t.byName[f.Name] = id - t.byNameValue[pairNameValue{f.Name, f.Value}] = id - t.ents = append(t.ents, f) + t.byName[f2.Name] = id + t.byNameValue[pairNameValue{f2.Name, f2.Value}] = id + t.ents = append(t.ents, f2) } // evictOldest evicts the n oldest entries in the table. diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go index 2e9c2f6a5..19553f10c 100644 --- a/vendor/golang.org/x/net/http2/transport.go +++ b/vendor/golang.org/x/net/http2/transport.go @@ -718,9 +718,6 @@ func canRetryError(err error) bool { } func (t *Transport) dialClientConn(ctx context.Context, addr string, singleUse bool) (*ClientConn, error) { - if t.transportTestHooks != nil { - return t.newClientConn(nil, singleUse, nil) - } host, _, err := net.SplitHostPort(addr) if err != nil { return nil, err @@ -2861,6 +2858,9 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error { var seenMaxConcurrentStreams bool err := f.ForeachSetting(func(s Setting) error { + if err := s.Valid(); err != nil { + return err + } switch s.ID { case SettingMaxFrameSize: cc.maxFrameSize = s.Val @@ -2892,9 +2892,6 @@ func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error { cc.henc.SetMaxDynamicTableSize(s.Val) cc.peerMaxHeaderTableSize = s.Val case SettingEnableConnectProtocol: - if err := s.Valid(); err != nil { - return err - } // If the peer wants to send us SETTINGS_ENABLE_CONNECT_PROTOCOL, // we require that it do so in the first SETTINGS frame. // diff --git a/vendor/golang.org/x/sys/windows/dll_windows.go b/vendor/golang.org/x/sys/windows/dll_windows.go index 3ca814f54..1157b06d8 100644 --- a/vendor/golang.org/x/sys/windows/dll_windows.go +++ b/vendor/golang.org/x/sys/windows/dll_windows.go @@ -163,42 +163,7 @@ func (p *Proc) Addr() uintptr { // (according to the semantics of the specific function being called) before consulting // the error. The error will be guaranteed to contain windows.Errno. func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error) { - switch len(a) { - case 0: - return syscall.Syscall(p.Addr(), uintptr(len(a)), 0, 0, 0) - case 1: - return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], 0, 0) - case 2: - return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], 0) - case 3: - return syscall.Syscall(p.Addr(), uintptr(len(a)), a[0], a[1], a[2]) - case 4: - return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], 0, 0) - case 5: - return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], 0) - case 6: - return syscall.Syscall6(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5]) - case 7: - return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], 0, 0) - case 8: - return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], 0) - case 9: - return syscall.Syscall9(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]) - case 10: - return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], 0, 0) - case 11: - return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], 0) - case 12: - return syscall.Syscall12(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11]) - case 13: - return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], 0, 0) - case 14: - return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], 0) - case 15: - return syscall.Syscall15(p.Addr(), uintptr(len(a)), a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14]) - default: - panic("Call " + p.Name + " with too many arguments " + itoa(len(a)) + ".") - } + return syscall.SyscallN(p.Addr(), a...) } // A LazyDLL implements access to a single DLL. diff --git a/vendor/golang.org/x/sys/windows/security_windows.go b/vendor/golang.org/x/sys/windows/security_windows.go index a8b0364c7..6c955cea1 100644 --- a/vendor/golang.org/x/sys/windows/security_windows.go +++ b/vendor/golang.org/x/sys/windows/security_windows.go @@ -1438,13 +1438,17 @@ func GetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformati } // GetNamedSecurityInfo queries the security information for a given named object and returns the self-relative security -// descriptor result on the Go heap. +// descriptor result on the Go heap. The security descriptor might be nil, even when err is nil, if the object exists +// but has no security descriptor. func GetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION) (sd *SECURITY_DESCRIPTOR, err error) { var winHeapSD *SECURITY_DESCRIPTOR err = getNamedSecurityInfo(objectName, objectType, securityInformation, nil, nil, nil, nil, &winHeapSD) if err != nil { return } + if winHeapSD == nil { + return nil, nil + } defer LocalFree(Handle(unsafe.Pointer(winHeapSD))) return winHeapSD.copySelfRelativeSecurityDescriptor(), nil } diff --git a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go index 06a3f7106..f25a7bcc7 100644 --- a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go +++ b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go @@ -1,4 +1,4 @@ -// Copyright 2025 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -127,14 +127,13 @@ var file_google_rpc_status_proto_rawDesc = []byte{ 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, - 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x42, 0x61, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, + 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x42, 0x5e, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x42, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x37, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x65, 0x6e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x03, 0x52, 0x50, 0x43, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x75, 0x73, 0xa2, 0x02, 0x03, 0x52, 0x50, 0x43, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/vendor/google.golang.org/grpc/attributes/attributes.go b/vendor/google.golang.org/grpc/attributes/attributes.go index 52d530d7a..4c60518c7 100644 --- a/vendor/google.golang.org/grpc/attributes/attributes.go +++ b/vendor/google.golang.org/grpc/attributes/attributes.go @@ -27,6 +27,8 @@ package attributes import ( "fmt" + "iter" + "maps" "strings" ) @@ -37,37 +39,46 @@ import ( // any) bool', it will be called by (*Attributes).Equal to determine whether // two values with the same key should be considered equal. type Attributes struct { - m map[any]any + parent *Attributes + key, value any } // New returns a new Attributes containing the key/value pair. func New(key, value any) *Attributes { - return &Attributes{m: map[any]any{key: value}} + return &Attributes{ + key: key, + value: value, + } } // WithValue returns a new Attributes containing the previous keys and values // and the new key/value pair. If the same key appears multiple times, the -// last value overwrites all previous values for that key. To remove an -// existing key, use a nil value. value should not be modified later. +// last value overwrites all previous values for that key. value should not be +// modified later. +// +// Note that Attributes do not support deletion. Avoid using untyped nil values. +// Since the Value method returns an untyped nil when a key is absent, it is +// impossible to distinguish between a missing key and a key explicitly set to +// an untyped nil. If you need to represent a value being unset, consider +// storing a specific sentinel type or a wrapper struct with a boolean field +// indicating presence. func (a *Attributes) WithValue(key, value any) *Attributes { - if a == nil { - return New(key, value) + return &Attributes{ + parent: a, + key: key, + value: value, } - n := &Attributes{m: make(map[any]any, len(a.m)+1)} - for k, v := range a.m { - n.m[k] = v - } - n.m[key] = value - return n } // Value returns the value associated with these attributes for key, or nil if // no value is associated with key. The returned value should not be modified. func (a *Attributes) Value(key any) any { - if a == nil { - return nil + for cur := a; cur != nil; cur = cur.parent { + if cur.key == key { + return cur.value + } } - return a.m[key] + return nil } // Equal returns whether a and o are equivalent. If 'Equal(o any) bool' is @@ -83,11 +94,15 @@ func (a *Attributes) Equal(o *Attributes) bool { if a == nil || o == nil { return false } - if len(a.m) != len(o.m) { - return false + if a == o { + return true } - for k, v := range a.m { - ov, ok := o.m[k] + m := maps.Collect(o.all()) + lenA := 0 + + for k, v := range a.all() { + lenA++ + ov, ok := m[k] if !ok { // o missing element of a return false @@ -101,7 +116,7 @@ func (a *Attributes) Equal(o *Attributes) bool { return false } } - return true + return lenA == len(m) } // String prints the attribute map. If any key or values throughout the map @@ -110,11 +125,11 @@ func (a *Attributes) String() string { var sb strings.Builder sb.WriteString("{") first := true - for k, v := range a.m { + for k, v := range a.all() { if !first { sb.WriteString(", ") } - sb.WriteString(fmt.Sprintf("%q: %q ", str(k), str(v))) + fmt.Fprintf(&sb, "%q: %q ", str(k), str(v)) first = false } sb.WriteString("}") @@ -139,3 +154,21 @@ func str(x any) (s string) { func (a *Attributes) MarshalJSON() ([]byte, error) { return []byte(a.String()), nil } + +// all returns an iterator that yields all key-value pairs in the Attributes +// chain. If a key appears multiple times, only the most recently added value +// is yielded. +func (a *Attributes) all() iter.Seq2[any, any] { + return func(yield func(any, any) bool) { + seen := map[any]bool{} + for cur := a; cur != nil; cur = cur.parent { + if seen[cur.key] { + continue + } + if !yield(cur.key, cur.value) { + return + } + seen[cur.key] = true + } + } +} diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go index b1264017d..326888ae3 100644 --- a/vendor/google.golang.org/grpc/balancer/balancer.go +++ b/vendor/google.golang.org/grpc/balancer/balancer.go @@ -33,6 +33,7 @@ import ( estats "google.golang.org/grpc/experimental/stats" "google.golang.org/grpc/grpclog" "google.golang.org/grpc/internal" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/metadata" "google.golang.org/grpc/resolver" "google.golang.org/grpc/serviceconfig" @@ -46,8 +47,8 @@ var ( ) // Register registers the balancer builder to the balancer map. b.Name -// (lowercased) will be used as the name registered with this builder. If the -// Builder implements ConfigParser, ParseConfig will be called when new service +// will be used as the name registered with this builder. If the Builder +// implements ConfigParser, ParseConfig will be called when new service // configs are received by the resolver, and the result will be provided to the // Balancer in UpdateClientConnState. // @@ -55,12 +56,12 @@ var ( // an init() function), and is not thread-safe. If multiple Balancers are // registered with the same name, the one registered last will take effect. func Register(b Builder) { - name := strings.ToLower(b.Name()) - if name != b.Name() { - // TODO: Skip the use of strings.ToLower() to index the map after v1.59 - // is released to switch to case sensitive balancer registry. Also, - // remove this warning and update the docstrings for Register and Get. - logger.Warningf("Balancer registered with name %q. grpc-go will be switching to case sensitive balancer registries soon", b.Name()) + name := b.Name() + if !envconfig.CaseSensitiveBalancerRegistries { + name = strings.ToLower(name) + if name != b.Name() { + logger.Warningf("Balancer registered with name %q. grpc-go will be switching to case sensitive balancer registries soon. After 2 releases, we will enable the env var by default.", b.Name()) + } } m[name] = b } @@ -75,21 +76,20 @@ func unregisterForTesting(name string) { func init() { internal.BalancerUnregister = unregisterForTesting - internal.ConnectedAddress = connectedAddress - internal.SetConnectedAddress = setConnectedAddress } // Get returns the resolver builder registered with the given name. -// Note that the compare is done in a case-insensitive fashion. +// Note that the compare is done in a case-sensitive fashion. // If no builder is register with the name, nil will be returned. func Get(name string) Builder { - if strings.ToLower(name) != name { - // TODO: Skip the use of strings.ToLower() to index the map after v1.59 - // is released to switch to case sensitive balancer registry. Also, - // remove this warning and update the docstrings for Register and Get. - logger.Warningf("Balancer retrieved for name %q. grpc-go will be switching to case sensitive balancer registries soon", name) + if !envconfig.CaseSensitiveBalancerRegistries { + lowerName := strings.ToLower(name) + if lowerName != name { + logger.Warningf("Balancer retrieved for name %q. grpc-go will be switching to case sensitive balancer registries soon. After 2 releases, we will enable the env var by default.", name) + } + name = lowerName } - if b, ok := m[strings.ToLower(name)]; ok { + if b, ok := m[name]; ok { return b } return nil diff --git a/vendor/google.golang.org/grpc/balancer/base/balancer.go b/vendor/google.golang.org/grpc/balancer/base/balancer.go index 4d576876d..4399ba014 100644 --- a/vendor/google.golang.org/grpc/balancer/base/balancer.go +++ b/vendor/google.golang.org/grpc/balancer/base/balancer.go @@ -121,8 +121,7 @@ func (b *baseBalancer) UpdateClientConnState(s balancer.ClientConnState) error { sc.Connect() } } - for _, a := range b.subConns.Keys() { - sc, _ := b.subConns.Get(a) + for a, sc := range b.subConns.All() { // a was removed by resolver. if _, ok := addrsSet.Get(a); !ok { sc.Shutdown() @@ -171,8 +170,7 @@ func (b *baseBalancer) regeneratePicker() { readySCs := make(map[balancer.SubConn]SubConnInfo) // Filter out all ready SCs from full subConn map. - for _, addr := range b.subConns.Keys() { - sc, _ := b.subConns.Get(addr) + for addr, sc := range b.subConns.All() { if st, ok := b.scStates[sc]; ok && st == connectivity.Ready { readySCs[sc] = SubConnInfo{Address: addr} } diff --git a/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go b/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go index 360db08eb..12479f698 100644 --- a/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go +++ b/vendor/google.golang.org/grpc/balancer/endpointsharding/endpointsharding.go @@ -187,8 +187,7 @@ func (es *endpointSharding) UpdateClientConnState(state balancer.ClientConnState } } // Delete old children that are no longer present. - for _, e := range children.Keys() { - child, _ := children.Get(e) + for e, child := range children.All() { if _, ok := newChildren.Get(e); !ok { child.closeLocked() } @@ -212,7 +211,7 @@ func (es *endpointSharding) ResolverError(err error) { es.updateState() }() children := es.children.Load() - for _, child := range children.Values() { + for _, child := range children.All() { child.resolverErrorLocked(err) } } @@ -225,7 +224,7 @@ func (es *endpointSharding) Close() { es.childMu.Lock() defer es.childMu.Unlock() children := es.children.Load() - for _, child := range children.Values() { + for _, child := range children.All() { child.closeLocked() } } @@ -233,7 +232,7 @@ func (es *endpointSharding) Close() { func (es *endpointSharding) ExitIdle() { es.childMu.Lock() defer es.childMu.Unlock() - for _, bw := range es.children.Load().Values() { + for _, bw := range es.children.Load().All() { if !bw.isClosed { bw.child.ExitIdle() } @@ -255,7 +254,7 @@ func (es *endpointSharding) updateState() { children := es.children.Load() childStates := make([]ChildState, 0, children.Len()) - for _, child := range children.Values() { + for _, child := range children.All() { childState := child.childState childStates = append(childStates, childState) childPicker := childState.State.Picker diff --git a/vendor/google.golang.org/grpc/balancer/pickfirst/internal/internal.go b/vendor/google.golang.org/grpc/balancer/pickfirst/internal/internal.go index 7d66cb491..cc902a4de 100644 --- a/vendor/google.golang.org/grpc/balancer/pickfirst/internal/internal.go +++ b/vendor/google.golang.org/grpc/balancer/pickfirst/internal/internal.go @@ -26,6 +26,8 @@ import ( var ( // RandShuffle pseudo-randomizes the order of addresses. RandShuffle = rand.Shuffle + // RandFloat64 returns, as a float64, a pseudo-random number in [0.0,1.0). + RandFloat64 = rand.Float64 // TimeAfterFunc allows mocking the timer for testing connection delay // related functionality. TimeAfterFunc = func(d time.Duration, f func()) func() { diff --git a/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go index b4bc3a2bf..518a69d57 100644 --- a/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go +++ b/vendor/google.golang.org/grpc/balancer/pickfirst/pickfirst.go @@ -21,11 +21,14 @@ package pickfirst import ( + "cmp" "encoding/json" "errors" "fmt" + "math" "net" "net/netip" + "slices" "sync" "time" @@ -34,6 +37,8 @@ import ( "google.golang.org/grpc/connectivity" expstats "google.golang.org/grpc/experimental/stats" "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/internal/balancer/weight" + "google.golang.org/grpc/internal/envconfig" internalgrpclog "google.golang.org/grpc/internal/grpclog" "google.golang.org/grpc/internal/pretty" "google.golang.org/grpc/resolver" @@ -258,8 +263,42 @@ func (b *pickfirstBalancer) UpdateClientConnState(state balancer.ClientConnState // will change the order of endpoints but not touch the order of the // addresses within each endpoint. - A61 if cfg.ShuffleAddressList { - endpoints = append([]resolver.Endpoint{}, endpoints...) - internal.RandShuffle(len(endpoints), func(i, j int) { endpoints[i], endpoints[j] = endpoints[j], endpoints[i] }) + if envconfig.PickFirstWeightedShuffling { + type weightedEndpoint struct { + endpoint resolver.Endpoint + weight float64 + } + + // For each endpoint, compute a key as described in A113 and + // https://utopia.duth.gr/~pefraimi/research/data/2007EncOfAlg.pdf: + var weightedEndpoints []weightedEndpoint + for _, endpoint := range endpoints { + u := internal.RandFloat64() // Random number in [0.0, 1.0) + weight := weightAttribute(endpoint) + weightedEndpoints = append(weightedEndpoints, weightedEndpoint{ + endpoint: endpoint, + weight: math.Pow(u, 1.0/float64(weight)), + }) + } + // Sort endpoints by key in descending order and reconstruct the + // endpoints slice. + slices.SortFunc(weightedEndpoints, func(a, b weightedEndpoint) int { + return cmp.Compare(b.weight, a.weight) + }) + + // Here, and in the "else" block below, we clone the endpoints + // slice to avoid mutating the resolver state. Doing the latter + // would lead to data races if the caller is accessing the same + // slice concurrently. + sortedEndpoints := make([]resolver.Endpoint, len(endpoints)) + for i, we := range weightedEndpoints { + sortedEndpoints[i] = we.endpoint + } + endpoints = sortedEndpoints + } else { + endpoints = slices.Clone(endpoints) + internal.RandShuffle(len(endpoints), func(i, j int) { endpoints[i], endpoints[j] = endpoints[j], endpoints[i] }) + } } // "Flatten the list by concatenating the ordered list of addresses for @@ -360,14 +399,14 @@ func (b *pickfirstBalancer) startFirstPassLocked() { b.firstPass = true b.numTF = 0 // Reset the connection attempt record for existing SubConns. - for _, sd := range b.subConns.Values() { + for _, sd := range b.subConns.All() { sd.connectionFailedInFirstPass = false } b.requestConnectionLocked() } func (b *pickfirstBalancer) closeSubConnsLocked() { - for _, sd := range b.subConns.Values() { + for _, sd := range b.subConns.All() { sd.subConn.Shutdown() } b.subConns = resolver.NewAddressMapV2[*scData]() @@ -467,7 +506,7 @@ func (b *pickfirstBalancer) reconcileSubConnsLocked(newAddrs []resolver.Address) newAddrsMap.Set(addr, true) } - for _, oldAddr := range b.subConns.Keys() { + for oldAddr := range b.subConns.All() { if _, ok := newAddrsMap.Get(oldAddr); ok { continue } @@ -481,7 +520,7 @@ func (b *pickfirstBalancer) reconcileSubConnsLocked(newAddrs []resolver.Address) // becomes ready, which means that all other subConn must be shutdown. func (b *pickfirstBalancer) shutdownRemainingLocked(selected *scData) { b.cancelConnectionTimer() - for _, sd := range b.subConns.Values() { + for _, sd := range b.subConns.All() { if sd.subConn != selected.subConn { sd.subConn.Shutdown() } @@ -732,7 +771,7 @@ func (b *pickfirstBalancer) endFirstPassIfPossibleLocked(lastErr error) { } // Connect() has been called on all the SubConns. The first pass can be // ended if all the SubConns have reported a failure. - for _, sd := range b.subConns.Values() { + for _, sd := range b.subConns.All() { if !sd.connectionFailedInFirstPass { return } @@ -743,7 +782,7 @@ func (b *pickfirstBalancer) endFirstPassIfPossibleLocked(lastErr error) { Picker: &picker{err: lastErr}, }) // Start re-connecting all the SubConns that are already in IDLE. - for _, sd := range b.subConns.Values() { + for _, sd := range b.subConns.All() { if sd.rawConnectivityState == connectivity.Idle { sd.subConn.Connect() } @@ -906,3 +945,17 @@ func equalAddressIgnoringBalAttributes(a, b *resolver.Address) bool { return a.Addr == b.Addr && a.ServerName == b.ServerName && a.Attributes.Equal(b.Attributes) } + +// weightAttribute is a convenience function which returns the value of the +// weight endpoint Attribute. +// +// When used in the xDS context, the weight attribute is guaranteed to be +// non-zero. But, when used in a non-xDS context, the weight attribute could be +// unset. A Default of 1 is used in the latter case. +func weightAttribute(e resolver.Endpoint) uint32 { + w := weight.FromEndpoint(e).Weight + if w == 0 { + return 1 + } + return w +} diff --git a/vendor/google.golang.org/grpc/balancer/subconn.go b/vendor/google.golang.org/grpc/balancer/subconn.go index 9ee44d4af..c1ca7c92e 100644 --- a/vendor/google.golang.org/grpc/balancer/subconn.go +++ b/vendor/google.golang.org/grpc/balancer/subconn.go @@ -111,20 +111,6 @@ type SubConnState struct { // ConnectionError is set if the ConnectivityState is TransientFailure, // describing the reason the SubConn failed. Otherwise, it is nil. ConnectionError error - // connectedAddr contains the connected address when ConnectivityState is - // Ready. Otherwise, it is indeterminate. - connectedAddress resolver.Address -} - -// connectedAddress returns the connected address for a SubConnState. The -// address is only valid if the state is READY. -func connectedAddress(scs SubConnState) resolver.Address { - return scs.connectedAddress -} - -// setConnectedAddress sets the connected address for a SubConnState. -func setConnectedAddress(scs *SubConnState, addr resolver.Address) { - scs.connectedAddress = addr } // A Producer is a type shared among potentially many consumers. It is diff --git a/vendor/google.golang.org/grpc/balancer_wrapper.go b/vendor/google.golang.org/grpc/balancer_wrapper.go index 2c760e623..a1e56a389 100644 --- a/vendor/google.golang.org/grpc/balancer_wrapper.go +++ b/vendor/google.golang.org/grpc/balancer_wrapper.go @@ -36,7 +36,6 @@ import ( ) var ( - setConnectedAddress = internal.SetConnectedAddress.(func(*balancer.SubConnState, resolver.Address)) // noOpRegisterHealthListenerFn is used when client side health checking is // disabled. It sends a single READY update on the registered listener. noOpRegisterHealthListenerFn = func(_ context.Context, listener func(balancer.SubConnState)) func() { @@ -305,7 +304,7 @@ func newHealthData(s connectivity.State) *healthData { // updateState is invoked by grpc to push a subConn state update to the // underlying balancer. -func (acbw *acBalancerWrapper) updateState(s connectivity.State, curAddr resolver.Address, err error) { +func (acbw *acBalancerWrapper) updateState(s connectivity.State, err error) { acbw.ccb.serializer.TrySchedule(func(ctx context.Context) { if ctx.Err() != nil || acbw.ccb.balancer == nil { return @@ -317,9 +316,6 @@ func (acbw *acBalancerWrapper) updateState(s connectivity.State, curAddr resolve // opts.StateListener is set, so this cannot ever be nil. // TODO: delete this comment when UpdateSubConnState is removed. scs := balancer.SubConnState{ConnectivityState: s, ConnectionError: err} - if s == connectivity.Ready { - setConnectedAddress(&scs, curAddr) - } // Invalidate the health listener by updating the healthData. acbw.healthMu.Lock() // A race may occur if a health listener is registered soon after the diff --git a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go index 42c61cf9f..296123e20 100644 --- a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go +++ b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go @@ -18,7 +18,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.10 +// protoc-gen-go v1.36.11 // protoc v5.27.1 // source: grpc/binlog/v1/binarylog.proto diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go index c0c2c9a76..5dec2dacc 100644 --- a/vendor/google.golang.org/grpc/clientconn.go +++ b/vendor/google.golang.org/grpc/clientconn.go @@ -35,6 +35,8 @@ import ( "google.golang.org/grpc/balancer/pickfirst" "google.golang.org/grpc/codes" "google.golang.org/grpc/connectivity" + "google.golang.org/grpc/credentials" + expstats "google.golang.org/grpc/experimental/stats" "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/channelz" "google.golang.org/grpc/internal/grpcsync" @@ -98,6 +100,41 @@ var ( errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)") ) +var ( + disconnectionsMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{ + Name: "grpc.subchannel.disconnections", + Description: "EXPERIMENTAL. Number of times the selected subchannel becomes disconnected.", + Unit: "{disconnection}", + Labels: []string{"grpc.target"}, + OptionalLabels: []string{"grpc.lb.backend_service", "grpc.lb.locality", "grpc.disconnect_error"}, + Default: false, + }) + connectionAttemptsSucceededMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{ + Name: "grpc.subchannel.connection_attempts_succeeded", + Description: "EXPERIMENTAL. Number of successful connection attempts.", + Unit: "{attempt}", + Labels: []string{"grpc.target"}, + OptionalLabels: []string{"grpc.lb.backend_service", "grpc.lb.locality"}, + Default: false, + }) + connectionAttemptsFailedMetric = expstats.RegisterInt64Count(expstats.MetricDescriptor{ + Name: "grpc.subchannel.connection_attempts_failed", + Description: "EXPERIMENTAL. Number of failed connection attempts.", + Unit: "{attempt}", + Labels: []string{"grpc.target"}, + OptionalLabels: []string{"grpc.lb.backend_service", "grpc.lb.locality"}, + Default: false, + }) + openConnectionsMetric = expstats.RegisterInt64UpDownCount(expstats.MetricDescriptor{ + Name: "grpc.subchannel.open_connections", + Description: "EXPERIMENTAL. Number of open connections.", + Unit: "{attempt}", + Labels: []string{"grpc.target"}, + OptionalLabels: []string{"grpc.lb.backend_service", "grpc.security_level", "grpc.lb.locality"}, + Default: false, + }) +) + const ( defaultClientMaxReceiveMessageSize = 1024 * 1024 * 4 defaultClientMaxSendMessageSize = math.MaxInt32 @@ -262,9 +299,10 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn * }() // This creates the name resolver, load balancer, etc. - if err := cc.idlenessMgr.ExitIdleMode(); err != nil { - return nil, err + if err := cc.exitIdleMode(); err != nil { + return nil, fmt.Errorf("failed to exit idle mode: %w", err) } + cc.idlenessMgr.UnsafeSetNotIdle() // Return now for non-blocking dials. if !cc.dopts.block { @@ -332,7 +370,7 @@ func (cc *ClientConn) addTraceEvent(msg string) { Severity: channelz.CtInfo, } } - channelz.AddTraceEvent(logger, cc.channelz, 0, ted) + channelz.AddTraceEvent(logger, cc.channelz, 1, ted) } type idler ClientConn @@ -341,14 +379,17 @@ func (i *idler) EnterIdleMode() { (*ClientConn)(i).enterIdleMode() } -func (i *idler) ExitIdleMode() error { - return (*ClientConn)(i).exitIdleMode() +func (i *idler) ExitIdleMode() { + // Ignore the error returned from this method, because from the perspective + // of the caller (idleness manager), the channel would have always moved out + // of IDLE by the time this method returns. + (*ClientConn)(i).exitIdleMode() } // exitIdleMode moves the channel out of idle mode by recreating the name // resolver and load balancer. This should never be called directly; use // cc.idlenessMgr.ExitIdleMode instead. -func (cc *ClientConn) exitIdleMode() (err error) { +func (cc *ClientConn) exitIdleMode() error { cc.mu.Lock() if cc.conns == nil { cc.mu.Unlock() @@ -356,11 +397,23 @@ func (cc *ClientConn) exitIdleMode() (err error) { } cc.mu.Unlock() + // Set state to CONNECTING before building the name resolver + // so the channel does not remain in IDLE. + cc.csMgr.updateState(connectivity.Connecting) + // This needs to be called without cc.mu because this builds a new resolver // which might update state or report error inline, which would then need to // acquire cc.mu. if err := cc.resolverWrapper.start(); err != nil { - return err + // If resolver creation fails, treat it like an error reported by the + // resolver before any valid updates. Set channel's state to + // TransientFailure, and set an erroring picker with the resolver build + // error, which will returned as part of any subsequent RPCs. + logger.Warningf("Failed to start resolver: %v", err) + cc.csMgr.updateState(connectivity.TransientFailure) + cc.mu.Lock() + cc.updateResolverStateAndUnlock(resolver.State{}, err) + return fmt.Errorf("failed to start resolver: %w", err) } cc.addTraceEvent("exiting idle mode") @@ -681,10 +734,8 @@ func (cc *ClientConn) GetState() connectivity.State { // Notice: This API is EXPERIMENTAL and may be changed or removed in a later // release. func (cc *ClientConn) Connect() { - if err := cc.idlenessMgr.ExitIdleMode(); err != nil { - cc.addTraceEvent(err.Error()) - return - } + cc.idlenessMgr.ExitIdleMode() + // If the ClientConn was not in idle mode, we need to call ExitIdle on the // LB policy so that connections can be created. cc.mu.Lock() @@ -735,8 +786,8 @@ func init() { internal.EnterIdleModeForTesting = func(cc *ClientConn) { cc.idlenessMgr.EnterIdleModeForTesting() } - internal.ExitIdleModeForTesting = func(cc *ClientConn) error { - return cc.idlenessMgr.ExitIdleMode() + internal.ExitIdleModeForTesting = func(cc *ClientConn) { + cc.idlenessMgr.ExitIdleMode() } } @@ -861,6 +912,7 @@ func (cc *ClientConn) newAddrConnLocked(addrs []resolver.Address, opts balancer. channelz: channelz.RegisterSubChannel(cc.channelz, ""), resetBackoff: make(chan struct{}), } + ac.updateTelemetryLabelsLocked() ac.ctx, ac.cancel = context.WithCancel(cc.ctx) // Start with our address set to the first address; this may be updated if // we connect to different addresses. @@ -925,25 +977,24 @@ func (cc *ClientConn) incrCallsFailed() { // connect starts creating a transport. // It does nothing if the ac is not IDLE. // TODO(bar) Move this to the addrConn section. -func (ac *addrConn) connect() error { +func (ac *addrConn) connect() { ac.mu.Lock() if ac.state == connectivity.Shutdown { if logger.V(2) { logger.Infof("connect called on shutdown addrConn; ignoring.") } ac.mu.Unlock() - return errConnClosing + return } if ac.state != connectivity.Idle { if logger.V(2) { logger.Infof("connect called on addrConn in non-idle state (%v); ignoring.", ac.state) } ac.mu.Unlock() - return nil + return } ac.resetTransportAndUnlock() - return nil } // equalAddressIgnoringBalAttributes returns true is a and b are considered equal. @@ -977,7 +1028,7 @@ func (ac *addrConn) updateAddrs(addrs []resolver.Address) { } ac.addrs = addrs - + ac.updateTelemetryLabelsLocked() if ac.state == connectivity.Shutdown || ac.state == connectivity.TransientFailure || ac.state == connectivity.Idle { @@ -1216,6 +1267,9 @@ type addrConn struct { resetBackoff chan struct{} channelz *channelz.SubChannel + + localityLabel string + backendServiceLabel string } // Note: this requires a lock on ac.mu. @@ -1223,6 +1277,18 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error) if ac.state == s { return } + + // If we are transitioning out of Ready, it means there is a disconnection. + // A SubConn can also transition from CONNECTING directly to IDLE when + // a transport is successfully created, but the connection fails + // before the SubConn can send the notification for READY. We treat + // this as a successful connection and transition to IDLE. + // TODO: https://github.com/grpc/grpc-go/issues/7862 - Remove the second + // part of the if condition below once the issue is fixed. + if ac.state == connectivity.Ready || (ac.state == connectivity.Connecting && s == connectivity.Idle) { + disconnectionsMetric.Record(ac.cc.metricsRecorderList, 1, ac.cc.target, ac.backendServiceLabel, ac.localityLabel, "unknown") + openConnectionsMetric.Record(ac.cc.metricsRecorderList, -1, ac.cc.target, ac.backendServiceLabel, ac.securityLevelLocked(), ac.localityLabel) + } ac.state = s ac.channelz.ChannelMetrics.State.Store(&s) if lastErr == nil { @@ -1230,7 +1296,7 @@ func (ac *addrConn) updateConnectivityState(s connectivity.State, lastErr error) } else { channelz.Infof(logger, ac.channelz, "Subchannel Connectivity change to %v, last error: %s", s, lastErr) } - ac.acbw.updateState(s, ac.curAddr, lastErr) + ac.acbw.updateState(s, lastErr) } // adjustParams updates parameters used to create transports upon @@ -1280,6 +1346,15 @@ func (ac *addrConn) resetTransportAndUnlock() { ac.mu.Unlock() if err := ac.tryAllAddrs(acCtx, addrs, connectDeadline); err != nil { + if !errors.Is(err, context.Canceled) { + connectionAttemptsFailedMetric.Record(ac.cc.metricsRecorderList, 1, ac.cc.target, ac.backendServiceLabel, ac.localityLabel) + } else { + if logger.V(2) { + // This records cancelled connection attempts which can be later + // replaced by a metric. + logger.Infof("Context cancellation detected; not recording this as a failed connection attempt.") + } + } // TODO: #7534 - Move re-resolution requests into the pick_first LB policy // to ensure one resolution request per pass instead of per subconn failure. ac.cc.resolveNow(resolver.ResolveNowOptions{}) @@ -1319,10 +1394,50 @@ func (ac *addrConn) resetTransportAndUnlock() { } // Success; reset backoff. ac.mu.Lock() + connectionAttemptsSucceededMetric.Record(ac.cc.metricsRecorderList, 1, ac.cc.target, ac.backendServiceLabel, ac.localityLabel) + openConnectionsMetric.Record(ac.cc.metricsRecorderList, 1, ac.cc.target, ac.backendServiceLabel, ac.securityLevelLocked(), ac.localityLabel) ac.backoffIdx = 0 ac.mu.Unlock() } +// updateTelemetryLabelsLocked calculates and caches the telemetry labels based on the +// first address in addrConn. +func (ac *addrConn) updateTelemetryLabelsLocked() { + labelsFunc, ok := internal.AddressToTelemetryLabels.(func(resolver.Address) map[string]string) + if !ok || len(ac.addrs) == 0 { + // Reset defaults + ac.localityLabel = "" + ac.backendServiceLabel = "" + return + } + labels := labelsFunc(ac.addrs[0]) + ac.localityLabel = labels["grpc.lb.locality"] + ac.backendServiceLabel = labels["grpc.lb.backend_service"] +} + +type securityLevelKey struct{} + +func (ac *addrConn) securityLevelLocked() string { + var secLevel string + // During disconnection, ac.transport is nil. Fall back to the security level + // stored in the current address during connection. + if ac.transport == nil { + secLevel, _ = ac.curAddr.Attributes.Value(securityLevelKey{}).(string) + return secLevel + } + authInfo := ac.transport.Peer().AuthInfo + if ci, ok := authInfo.(interface { + GetCommonAuthInfo() credentials.CommonAuthInfo + }); ok { + secLevel = ci.GetCommonAuthInfo().SecurityLevel.String() + // Store the security level in the current address' attributes so + // that it remains available for disconnection metrics after the + // transport is closed. + ac.curAddr.Attributes = ac.curAddr.Attributes.WithValue(securityLevelKey{}, secLevel) + } + return secLevel +} + // tryAllAddrs tries to create a connection to the addresses, and stop when at // the first successful one. It returns an error if no address was successfully // connected, or updates ac appropriately with the new transport. @@ -1412,25 +1527,26 @@ func (ac *addrConn) createTransport(ctx context.Context, addr resolver.Address, } ac.mu.Lock() - defer ac.mu.Unlock() if ctx.Err() != nil { // This can happen if the subConn was removed while in `Connecting` // state. tearDown() would have set the state to `Shutdown`, but // would not have closed the transport since ac.transport would not // have been set at that point. - // - // We run this in a goroutine because newTr.Close() calls onClose() + + // We unlock ac.mu because newTr.Close() calls onClose() // inline, which requires locking ac.mu. - // + ac.mu.Unlock() + // The error we pass to Close() is immaterial since there are no open // streams at this point, so no trailers with error details will be sent // out. We just need to pass a non-nil error. // // This can also happen when updateAddrs is called during a connection // attempt. - go newTr.Close(transport.ErrConnClosing) + newTr.Close(transport.ErrConnClosing) return nil } + defer ac.mu.Unlock() if hctx.Err() != nil { // onClose was already called for this connection, but the connection // was successfully established first. Consider it a success and set diff --git a/vendor/google.golang.org/grpc/credentials/tls.go b/vendor/google.golang.org/grpc/credentials/tls.go index 8277be7d6..a6083c3b0 100644 --- a/vendor/google.golang.org/grpc/credentials/tls.go +++ b/vendor/google.golang.org/grpc/credentials/tls.go @@ -22,7 +22,6 @@ import ( "context" "crypto/tls" "crypto/x509" - "errors" "fmt" "net" "net/url" @@ -52,18 +51,21 @@ func (t TLSInfo) AuthType() string { } // ValidateAuthority validates the provided authority being used to override the -// :authority header by verifying it against the peer certificates. It returns a +// :authority header by verifying it against the peer certificate. It returns a // non-nil error if the validation fails. func (t TLSInfo) ValidateAuthority(authority string) error { - var errs []error - for _, cert := range t.State.PeerCertificates { - var err error - if err = cert.VerifyHostname(authority); err == nil { - return nil - } - errs = append(errs, err) + host, _, err := net.SplitHostPort(authority) + if err != nil { + host = authority + } + + // Verify authority against the leaf certificate. + if len(t.State.PeerCertificates) == 0 { + // This is not expected to happen as the TLS handshake has already + // completed and should have populated PeerCertificates. + return fmt.Errorf("credentials: no peer certificates found to verify authority %q", host) } - return fmt.Errorf("credentials: invalid authority %q: %v", authority, errors.Join(errs...)) + return t.State.PeerCertificates[0].VerifyHostname(host) } // cipherSuiteLookup returns the string version of a TLS cipher suite ID. diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go index 7a5ac2e7c..4ec5f9cd0 100644 --- a/vendor/google.golang.org/grpc/dialoptions.go +++ b/vendor/google.golang.org/grpc/dialoptions.go @@ -705,10 +705,11 @@ func WithDisableHealthCheck() DialOption { func defaultDialOptions() dialOptions { return dialOptions{ copts: transport.ConnectOptions{ - ReadBufferSize: defaultReadBufSize, - WriteBufferSize: defaultWriteBufSize, - UserAgent: grpcUA, - BufferPool: mem.DefaultBufferPool(), + ReadBufferSize: defaultReadBufSize, + WriteBufferSize: defaultWriteBufSize, + SharedWriteBuffer: true, + UserAgent: grpcUA, + BufferPool: mem.DefaultBufferPool(), }, bs: internalbackoff.DefaultExponential, idleTimeout: 30 * time.Minute, diff --git a/vendor/google.golang.org/grpc/encoding/encoding.go b/vendor/google.golang.org/grpc/encoding/encoding.go index dadd21e40..296f38c3a 100644 --- a/vendor/google.golang.org/grpc/encoding/encoding.go +++ b/vendor/google.golang.org/grpc/encoding/encoding.go @@ -58,10 +58,6 @@ func init() { // Compressor is used for compressing and decompressing when sending or // receiving messages. -// -// If a Compressor implements `DecompressedSize(compressedBytes []byte) int`, -// gRPC will invoke it to determine the size of the buffer allocated for the -// result of decompression. A return value of -1 indicates unknown size. type Compressor interface { // Compress writes the data written to wc to w after compressing it. If an // error occurs while initializing the compressor, that error is returned diff --git a/vendor/google.golang.org/grpc/experimental/stats/metricregistry.go b/vendor/google.golang.org/grpc/experimental/stats/metricregistry.go index 2b57ba65a..472813f58 100644 --- a/vendor/google.golang.org/grpc/experimental/stats/metricregistry.go +++ b/vendor/google.golang.org/grpc/experimental/stats/metricregistry.go @@ -76,6 +76,7 @@ const ( MetricTypeFloatHisto MetricTypeIntGauge MetricTypeIntUpDownCount + MetricTypeIntAsyncGauge ) // Int64CountHandle is a typed handle for a int count metric. This handle @@ -172,6 +173,30 @@ func (h *Int64GaugeHandle) Record(recorder MetricsRecorder, incr int64, labels . recorder.RecordInt64Gauge(h, incr, labels...) } +// AsyncMetric is a marker interface for asynchronous metric types. +type AsyncMetric interface { + isAsync() + Descriptor() *MetricDescriptor +} + +// Int64AsyncGaugeHandle is a typed handle for an int gauge metric. This handle is +// passed at the recording point in order to know which metric to record on. +type Int64AsyncGaugeHandle MetricDescriptor + +// isAsync implements the AsyncMetric interface. +func (h *Int64AsyncGaugeHandle) isAsync() {} + +// Descriptor returns the int64 gauge handle typecast to a pointer to a +// MetricDescriptor. +func (h *Int64AsyncGaugeHandle) Descriptor() *MetricDescriptor { + return (*MetricDescriptor)(h) +} + +// Record records the int64 gauge value on the metrics recorder provided. +func (h *Int64AsyncGaugeHandle) Record(recorder AsyncMetricsRecorder, value int64, labels ...string) { + recorder.RecordInt64AsyncGauge(h, value, labels...) +} + // registeredMetrics are the registered metric descriptor names. var registeredMetrics = make(map[string]bool) @@ -282,6 +307,20 @@ func RegisterInt64UpDownCount(descriptor MetricDescriptor) *Int64UpDownCountHand return (*Int64UpDownCountHandle)(descPtr) } +// RegisterInt64AsyncGauge registers the metric description onto the global registry. +// It returns a typed handle to use for recording data. +// +// NOTE: this function must only be called during initialization time (i.e. in +// an init() function), and is not thread-safe. If multiple metrics are +// registered with the same name, this function will panic. +func RegisterInt64AsyncGauge(descriptor MetricDescriptor) *Int64AsyncGaugeHandle { + registerMetric(descriptor.Name, descriptor.Default) + descriptor.Type = MetricTypeIntAsyncGauge + descPtr := &descriptor + metricsRegistry[descriptor.Name] = descPtr + return (*Int64AsyncGaugeHandle)(descPtr) +} + // snapshotMetricsRegistryForTesting snapshots the global data of the metrics // registry. Returns a cleanup function that sets the metrics registry to its // original state. diff --git a/vendor/google.golang.org/grpc/experimental/stats/metrics.go b/vendor/google.golang.org/grpc/experimental/stats/metrics.go index cb57f1a74..88742724a 100644 --- a/vendor/google.golang.org/grpc/experimental/stats/metrics.go +++ b/vendor/google.golang.org/grpc/experimental/stats/metrics.go @@ -19,9 +19,13 @@ // Package stats contains experimental metrics/stats API's. package stats -import "google.golang.org/grpc/stats" +import ( + "google.golang.org/grpc/internal" + "google.golang.org/grpc/stats" +) // MetricsRecorder records on metrics derived from metric registry. +// Implementors must embed UnimplementedMetricsRecorder. type MetricsRecorder interface { // RecordInt64Count records the measurement alongside labels on the int // count associated with the provided handle. @@ -41,6 +45,46 @@ type MetricsRecorder interface { // RecordInt64UpDownCounter records the measurement alongside labels on the int // count associated with the provided handle. RecordInt64UpDownCount(handle *Int64UpDownCountHandle, incr int64, labels ...string) + // RegisterAsyncReporter registers a reporter to produce metric values for + // only the listed descriptors. The returned function must be called when + // the metrics are no longer needed, which will remove the reporter. The + // returned method needs to be idempotent and concurrent safe. + RegisterAsyncReporter(reporter AsyncMetricReporter, descriptors ...AsyncMetric) func() + + // EnforceMetricsRecorderEmbedding is included to force implementers to embed + // another implementation of this interface, allowing gRPC to add methods + // without breaking users. + internal.EnforceMetricsRecorderEmbedding +} + +// AsyncMetricReporter is an interface for types that record metrics asynchronously +// for the set of descriptors they are registered with. The AsyncMetricsRecorder +// parameter is used to record values for these metrics. +// +// Implementations must make unique recordings across all registered +// AsyncMetricReporters. Meaning, they should not report values for a metric with +// the same attributes as another AsyncMetricReporter will report. +// +// Implementations must be concurrent-safe. +type AsyncMetricReporter interface { + // Report records metric values using the provided recorder. + Report(AsyncMetricsRecorder) error +} + +// AsyncMetricReporterFunc is an adapter to allow the use of ordinary functions as +// AsyncMetricReporters. +type AsyncMetricReporterFunc func(AsyncMetricsRecorder) error + +// Report calls f(r). +func (f AsyncMetricReporterFunc) Report(r AsyncMetricsRecorder) error { + return f(r) +} + +// AsyncMetricsRecorder records on asynchronous metrics derived from metric registry. +type AsyncMetricsRecorder interface { + // RecordInt64AsyncGauge records the measurement alongside labels on the int + // count associated with the provided handle asynchronously + RecordInt64AsyncGauge(handle *Int64AsyncGaugeHandle, incr int64, labels ...string) } // Metrics is an experimental legacy alias of the now-stable stats.MetricSet. @@ -55,3 +99,33 @@ type Metric = string func NewMetrics(metrics ...Metric) *Metrics { return stats.NewMetricSet(metrics...) } + +// UnimplementedMetricsRecorder must be embedded to have forward compatible implementations. +type UnimplementedMetricsRecorder struct { + internal.EnforceMetricsRecorderEmbedding +} + +// RecordInt64Count provides a no-op implementation. +func (UnimplementedMetricsRecorder) RecordInt64Count(*Int64CountHandle, int64, ...string) {} + +// RecordFloat64Count provides a no-op implementation. +func (UnimplementedMetricsRecorder) RecordFloat64Count(*Float64CountHandle, float64, ...string) {} + +// RecordInt64Histo provides a no-op implementation. +func (UnimplementedMetricsRecorder) RecordInt64Histo(*Int64HistoHandle, int64, ...string) {} + +// RecordFloat64Histo provides a no-op implementation. +func (UnimplementedMetricsRecorder) RecordFloat64Histo(*Float64HistoHandle, float64, ...string) {} + +// RecordInt64Gauge provides a no-op implementation. +func (UnimplementedMetricsRecorder) RecordInt64Gauge(*Int64GaugeHandle, int64, ...string) {} + +// RecordInt64UpDownCount provides a no-op implementation. +func (UnimplementedMetricsRecorder) RecordInt64UpDownCount(*Int64UpDownCountHandle, int64, ...string) { +} + +// RegisterAsyncReporter provides a no-op implementation. +func (UnimplementedMetricsRecorder) RegisterAsyncReporter(AsyncMetricReporter, ...AsyncMetric) func() { + // No-op: Return an empty function to ensure caller doesn't panic on nil function call + return func() {} +} diff --git a/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go b/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go index 8f7d9f6bb..dcb98cdbc 100644 --- a/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go +++ b/vendor/google.golang.org/grpc/health/grpc_health_v1/health.pb.go @@ -17,7 +17,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.10 +// protoc-gen-go v1.36.11 // protoc v5.27.1 // source: grpc/health/v1/health.proto diff --git a/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go b/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go index f2c01f296..9e10fdd2e 100644 --- a/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go +++ b/vendor/google.golang.org/grpc/health/grpc_health_v1/health_grpc.pb.go @@ -17,7 +17,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.1 // - protoc v5.27.1 // source: grpc/health/v1/health.proto diff --git a/vendor/google.golang.org/grpc/interceptor.go b/vendor/google.golang.org/grpc/interceptor.go index 877d78fc3..099e3d093 100644 --- a/vendor/google.golang.org/grpc/interceptor.go +++ b/vendor/google.golang.org/grpc/interceptor.go @@ -97,8 +97,12 @@ type StreamServerInfo struct { IsServerStream bool } -// StreamServerInterceptor provides a hook to intercept the execution of a streaming RPC on the server. -// info contains all the information of this RPC the interceptor can operate on. And handler is the -// service method implementation. It is the responsibility of the interceptor to invoke handler to -// complete the RPC. +// StreamServerInterceptor provides a hook to intercept the execution of a +// streaming RPC on the server. +// +// srv is the service implementation on which the RPC was invoked, and needs to +// be passed to handler, and not used otherwise. ss is the server side of the +// stream. info contains all the information of this RPC the interceptor can +// operate on. And handler is the service method implementation. It is the +// responsibility of the interceptor to invoke handler to complete the RPC. type StreamServerInterceptor func(srv any, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error diff --git a/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go b/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go index ba25b8988..f38de74a4 100644 --- a/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go +++ b/vendor/google.golang.org/grpc/internal/balancer/gracefulswitch/gracefulswitch.go @@ -67,6 +67,10 @@ type Balancer struct { // balancerCurrent before the UpdateSubConnState is called on the // balancerCurrent. currentMu sync.Mutex + + // activeGoroutines tracks all the goroutines that this balancer has started + // and that should be waited on when the balancer closes. + activeGoroutines sync.WaitGroup } // swap swaps out the current lb with the pending lb and updates the ClientConn. @@ -76,7 +80,9 @@ func (gsb *Balancer) swap() { cur := gsb.balancerCurrent gsb.balancerCurrent = gsb.balancerPending gsb.balancerPending = nil + gsb.activeGoroutines.Add(1) go func() { + defer gsb.activeGoroutines.Done() gsb.currentMu.Lock() defer gsb.currentMu.Unlock() cur.Close() @@ -274,6 +280,7 @@ func (gsb *Balancer) Close() { currentBalancerToClose.Close() pendingBalancerToClose.Close() + gsb.activeGoroutines.Wait() } // balancerWrapper wraps a balancer.Balancer, and overrides some Balancer @@ -324,7 +331,12 @@ func (bw *balancerWrapper) UpdateState(state balancer.State) { defer bw.gsb.mu.Unlock() bw.lastState = state + // If Close() acquires the mutex before UpdateState(), the balancer + // will already have been removed from the current or pending state when + // reaching this point. if !bw.gsb.balancerCurrentOrPending(bw) { + // Returning here ensures that (*Balancer).swap() is not invoked after + // (*Balancer).Close() and therefore prevents "use after close". return } diff --git a/vendor/google.golang.org/grpc/internal/balancer/weight/weight.go b/vendor/google.golang.org/grpc/internal/balancer/weight/weight.go new file mode 100644 index 000000000..11beb07d1 --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/balancer/weight/weight.go @@ -0,0 +1,66 @@ +/* + * + * Copyright 2025 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 weight contains utilities to manage endpoint weights. Weights are +// used by LB policies such as ringhash to distribute load across multiple +// endpoints. +package weight + +import ( + "fmt" + + "google.golang.org/grpc/resolver" +) + +// attributeKey is the type used as the key to store EndpointInfo in the +// Attributes field of resolver.Endpoint. +type attributeKey struct{} + +// EndpointInfo will be stored in the Attributes field of Endpoints in order to +// use the ringhash balancer. +type EndpointInfo struct { + Weight uint32 +} + +// Equal allows the values to be compared by Attributes.Equal. +func (a EndpointInfo) Equal(o any) bool { + oa, ok := o.(EndpointInfo) + return ok && oa.Weight == a.Weight +} + +// Set returns a copy of endpoint in which the Attributes field is updated with +// EndpointInfo. +func Set(endpoint resolver.Endpoint, epInfo EndpointInfo) resolver.Endpoint { + endpoint.Attributes = endpoint.Attributes.WithValue(attributeKey{}, epInfo) + return endpoint +} + +// String returns a human-readable representation of EndpointInfo. +// This method is intended for logging, testing, and debugging purposes only. +// Do not rely on the output format, as it is not guaranteed to remain stable. +func (a EndpointInfo) String() string { + return fmt.Sprintf("Weight: %d", a.Weight) +} + +// FromEndpoint returns the EndpointInfo stored in the Attributes field of an +// endpoint. It returns an empty EndpointInfo if attribute is not found. +func FromEndpoint(endpoint resolver.Endpoint) EndpointInfo { + v := endpoint.Attributes.Value(attributeKey{}) + ei, _ := v.(EndpointInfo) + return ei +} diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go index 91f760936..3ae45faa4 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go @@ -54,17 +54,16 @@ var ( // XDSEndpointHashKeyBackwardCompat controls the parsing of the endpoint hash // key from EDS LbEndpoint metadata. Endpoint hash keys can be disabled by - // setting "GRPC_XDS_ENDPOINT_HASH_KEY_BACKWARD_COMPAT" to "true". When the - // implementation of A76 is stable, we will flip the default value to false - // in a subsequent release. A final release will remove this environment - // variable, enabling the new behavior unconditionally. - XDSEndpointHashKeyBackwardCompat = boolFromEnv("GRPC_XDS_ENDPOINT_HASH_KEY_BACKWARD_COMPAT", true) + // setting "GRPC_XDS_ENDPOINT_HASH_KEY_BACKWARD_COMPAT" to "true". A future + // release will remove this environment variable, enabling the new behavior + // unconditionally. + XDSEndpointHashKeyBackwardCompat = boolFromEnv("GRPC_XDS_ENDPOINT_HASH_KEY_BACKWARD_COMPAT", false) // RingHashSetRequestHashKey is set if the ring hash balancer can get the // request hash header by setting the "requestHashHeader" field, according - // to gRFC A76. It can be enabled by setting the environment variable - // "GRPC_EXPERIMENTAL_RING_HASH_SET_REQUEST_HASH_KEY" to "true". - RingHashSetRequestHashKey = boolFromEnv("GRPC_EXPERIMENTAL_RING_HASH_SET_REQUEST_HASH_KEY", false) + // to gRFC A76. It can be disabled by setting the environment variable + // "GRPC_EXPERIMENTAL_RING_HASH_SET_REQUEST_HASH_KEY" to "false". + RingHashSetRequestHashKey = boolFromEnv("GRPC_EXPERIMENTAL_RING_HASH_SET_REQUEST_HASH_KEY", true) // ALTSHandshakerKeepaliveParams is set if we should add the // KeepaliveParams when dial the ALTS handshaker service. @@ -77,6 +76,56 @@ var ( // - Target resolution is disabled. // - The DNS resolver is being used. EnableDefaultPortForProxyTarget = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_DEFAULT_PORT_FOR_PROXY_TARGET", true) + + // CaseSensitiveBalancerRegistries is set if the balancer registry should be + // case-sensitive. This is disabled by default, but can be enabled by setting + // the env variable "GRPC_GO_EXPERIMENTAL_CASE_SENSITIVE_BALANCER_REGISTRIES" + // to "true". + // + // TODO: After 2 releases, we will enable the env var by default. + CaseSensitiveBalancerRegistries = boolFromEnv("GRPC_GO_EXPERIMENTAL_CASE_SENSITIVE_BALANCER_REGISTRIES", false) + + // XDSAuthorityRewrite indicates whether xDS authority rewriting is enabled. + // This feature is defined in gRFC A81 and is enabled by setting the + // environment variable GRPC_EXPERIMENTAL_XDS_AUTHORITY_REWRITE to "true". + XDSAuthorityRewrite = boolFromEnv("GRPC_EXPERIMENTAL_XDS_AUTHORITY_REWRITE", false) + + // PickFirstWeightedShuffling indicates whether weighted endpoint shuffling + // is enabled in the pick_first LB policy, as defined in gRFC A113. This + // feature can be disabled by setting the environment variable + // GRPC_EXPERIMENTAL_PF_WEIGHTED_SHUFFLING to "false". + PickFirstWeightedShuffling = boolFromEnv("GRPC_EXPERIMENTAL_PF_WEIGHTED_SHUFFLING", true) + + // XDSRecoverPanicInResourceParsing indicates whether the xdsclient should + // recover from panics while parsing xDS resources. + // + // This feature can be disabled (e.g. for fuzz testing) by setting the + // environment variable "GRPC_GO_EXPERIMENTAL_XDS_RESOURCE_PANIC_RECOVERY" + // to "false". + XDSRecoverPanicInResourceParsing = boolFromEnv("GRPC_GO_EXPERIMENTAL_XDS_RESOURCE_PANIC_RECOVERY", true) + + // DisableStrictPathChecking indicates whether strict path checking is + // disabled. This feature can be disabled by setting the environment + // variable GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING to "true". + // + // When strict path checking is enabled, gRPC will reject requests with + // paths that do not conform to the gRPC over HTTP/2 specification found at + // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md. + // + // When disabled, gRPC will allow paths that do not contain a leading slash. + // Enabling strict path checking is recommended for security reasons, as it + // prevents potential path traversal vulnerabilities. + // + // A future release will remove this environment variable, enabling strict + // path checking behavior unconditionally. + DisableStrictPathChecking = boolFromEnv("GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING", false) + + // EnablePriorityLBChildPolicyCache controls whether the priority balancer + // should cache child balancers that are removed from the LB policy config, + // for a period of 15 minutes. This is disabled by default, but can be + // enabled by setting the env variable + // GRPC_EXPERIMENTAL_ENABLE_PRIORITY_LB_CHILD_POLICY_CACHE to true. + EnablePriorityLBChildPolicyCache = boolFromEnv("GRPC_EXPERIMENTAL_ENABLE_PRIORITY_LB_CHILD_POLICY_CACHE", false) ) func boolFromEnv(envVar string, def bool) bool { diff --git a/vendor/google.golang.org/grpc/internal/experimental.go b/vendor/google.golang.org/grpc/internal/experimental.go index 7617be215..8a999917d 100644 --- a/vendor/google.golang.org/grpc/internal/experimental.go +++ b/vendor/google.golang.org/grpc/internal/experimental.go @@ -25,4 +25,11 @@ var ( // BufferPool is implemented by the grpc package and returns a server // option to configure a shared buffer pool for a grpc.Server. BufferPool any // func (grpc.SharedBufferPool) grpc.ServerOption + + // SetDefaultBufferPool updates the default buffer pool. + SetDefaultBufferPool any // func(mem.BufferPool) + + // AcceptCompressors is implemented by the grpc package and returns + // a call option that restricts the grpc-accept-encoding header for a call. + AcceptCompressors any // func(...string) grpc.CallOption ) diff --git a/vendor/google.golang.org/grpc/internal/idle/idle.go b/vendor/google.golang.org/grpc/internal/idle/idle.go index 2c13ee9da..d3cd24f80 100644 --- a/vendor/google.golang.org/grpc/internal/idle/idle.go +++ b/vendor/google.golang.org/grpc/internal/idle/idle.go @@ -21,7 +21,6 @@ package idle import ( - "fmt" "math" "sync" "sync/atomic" @@ -33,15 +32,15 @@ var timeAfterFunc = func(d time.Duration, f func()) *time.Timer { return time.AfterFunc(d, f) } -// Enforcer is the functionality provided by grpc.ClientConn to enter -// and exit from idle mode. -type Enforcer interface { - ExitIdleMode() error +// ClientConn is the functionality provided by grpc.ClientConn to enter and exit +// from idle mode. +type ClientConn interface { + ExitIdleMode() EnterIdleMode() } -// Manager implements idleness detection and calls the configured Enforcer to -// enter/exit idle mode when appropriate. Must be created by NewManager. +// Manager implements idleness detection and calls the ClientConn to enter/exit +// idle mode when appropriate. Must be created by NewManager. type Manager struct { // State accessed atomically. lastCallEndTime int64 // Unix timestamp in nanos; time when the most recent RPC completed. @@ -51,8 +50,8 @@ type Manager struct { // Can be accessed without atomics or mutex since these are set at creation // time and read-only after that. - enforcer Enforcer // Functionality provided by grpc.ClientConn. - timeout time.Duration + cc ClientConn // Functionality provided by grpc.ClientConn. + timeout time.Duration // idleMu is used to guarantee mutual exclusion in two scenarios: // - Opposing intentions: @@ -72,9 +71,9 @@ type Manager struct { // NewManager creates a new idleness manager implementation for the // given idle timeout. It begins in idle mode. -func NewManager(enforcer Enforcer, timeout time.Duration) *Manager { +func NewManager(cc ClientConn, timeout time.Duration) *Manager { return &Manager{ - enforcer: enforcer, + cc: cc, timeout: timeout, actuallyIdle: true, activeCallsCount: -math.MaxInt32, @@ -127,7 +126,7 @@ func (m *Manager) handleIdleTimeout() { // Now that we've checked that there has been no activity, attempt to enter // idle mode, which is very likely to succeed. - if m.tryEnterIdleMode() { + if m.tryEnterIdleMode(true) { // Successfully entered idle mode. No timer needed until we exit idle. return } @@ -142,10 +141,13 @@ func (m *Manager) handleIdleTimeout() { // that, it performs a last minute check to ensure that no new RPC has come in, // making the channel active. // +// checkActivity controls if a check for RPC activity, since the last time the +// idle_timeout fired, is made. + // Return value indicates whether or not the channel moved to idle mode. // // Holds idleMu which ensures mutual exclusion with exitIdleMode. -func (m *Manager) tryEnterIdleMode() bool { +func (m *Manager) tryEnterIdleMode(checkActivity bool) bool { // Setting the activeCallsCount to -math.MaxInt32 indicates to OnCallBegin() // that the channel is either in idle mode or is trying to get there. if !atomic.CompareAndSwapInt32(&m.activeCallsCount, 0, -math.MaxInt32) { @@ -166,7 +168,7 @@ func (m *Manager) tryEnterIdleMode() bool { atomic.AddInt32(&m.activeCallsCount, math.MaxInt32) return false } - if atomic.LoadInt32(&m.activeSinceLastTimerCheck) == 1 { + if checkActivity && atomic.LoadInt32(&m.activeSinceLastTimerCheck) == 1 { // A very short RPC could have come in (and also finished) after we // checked for calls count and activity in handleIdleTimeout(), but // before the CAS operation. So, we need to check for activity again. @@ -177,44 +179,37 @@ func (m *Manager) tryEnterIdleMode() bool { // No new RPCs have come in since we set the active calls count value to // -math.MaxInt32. And since we have the lock, it is safe to enter idle mode // unconditionally now. - m.enforcer.EnterIdleMode() + m.cc.EnterIdleMode() m.actuallyIdle = true return true } // EnterIdleModeForTesting instructs the channel to enter idle mode. func (m *Manager) EnterIdleModeForTesting() { - m.tryEnterIdleMode() + m.tryEnterIdleMode(false) } // OnCallBegin is invoked at the start of every RPC. -func (m *Manager) OnCallBegin() error { +func (m *Manager) OnCallBegin() { if m.isClosed() { - return nil + return } if atomic.AddInt32(&m.activeCallsCount, 1) > 0 { // Channel is not idle now. Set the activity bit and allow the call. atomic.StoreInt32(&m.activeSinceLastTimerCheck, 1) - return nil + return } // Channel is either in idle mode or is in the process of moving to idle // mode. Attempt to exit idle mode to allow this RPC. - if err := m.ExitIdleMode(); err != nil { - // Undo the increment to calls count, and return an error causing the - // RPC to fail. - atomic.AddInt32(&m.activeCallsCount, -1) - return err - } - + m.ExitIdleMode() atomic.StoreInt32(&m.activeSinceLastTimerCheck, 1) - return nil } -// ExitIdleMode instructs m to call the enforcer's ExitIdleMode and update m's +// ExitIdleMode instructs m to call the ClientConn's ExitIdleMode and update its // internal state. -func (m *Manager) ExitIdleMode() error { +func (m *Manager) ExitIdleMode() { // Holds idleMu which ensures mutual exclusion with tryEnterIdleMode. m.idleMu.Lock() defer m.idleMu.Unlock() @@ -231,12 +226,10 @@ func (m *Manager) ExitIdleMode() error { // m.ExitIdleMode. // // In any case, there is nothing to do here. - return nil + return } - if err := m.enforcer.ExitIdleMode(); err != nil { - return fmt.Errorf("failed to exit idle mode: %w", err) - } + m.cc.ExitIdleMode() // Undo the idle entry process. This also respects any new RPC attempts. atomic.AddInt32(&m.activeCallsCount, math.MaxInt32) @@ -244,7 +237,23 @@ func (m *Manager) ExitIdleMode() error { // Start a new timer to fire after the configured idle timeout. m.resetIdleTimerLocked(m.timeout) - return nil +} + +// UnsafeSetNotIdle instructs the Manager to update its internal state to +// reflect the reality that the channel is no longer in IDLE mode. +// +// N.B. This method is intended only for internal use by the gRPC client +// when it exits IDLE mode **manually** from `Dial`. The callsite must ensure: +// - The channel was **actually in IDLE mode** immediately prior to the call. +// - There is **no concurrent activity** that could cause the channel to exit +// IDLE mode *naturally* at the same time. +func (m *Manager) UnsafeSetNotIdle() { + m.idleMu.Lock() + defer m.idleMu.Unlock() + + atomic.AddInt32(&m.activeCallsCount, math.MaxInt32) + m.actuallyIdle = false + m.resetIdleTimerLocked(m.timeout) } // OnCallEnd is invoked at the end of every RPC. diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go index 2699223a2..4b3d563f8 100644 --- a/vendor/google.golang.org/grpc/internal/internal.go +++ b/vendor/google.golang.org/grpc/internal/internal.go @@ -211,22 +211,11 @@ var ( // default resolver scheme. UserSetDefaultScheme = false - // ConnectedAddress returns the connected address for a SubConnState. The - // address is only valid if the state is READY. - ConnectedAddress any // func (scs SubConnState) resolver.Address - - // SetConnectedAddress sets the connected address for a SubConnState. - SetConnectedAddress any // func(scs *SubConnState, addr resolver.Address) - // SnapshotMetricRegistryForTesting snapshots the global data of the metric // registry. Returns a cleanup function that sets the metric registry to its // original state. Only called in testing functions. SnapshotMetricRegistryForTesting func() func() - // SetDefaultBufferPoolForTesting updates the default buffer pool, for - // testing purposes. - SetDefaultBufferPoolForTesting any // func(mem.BufferPool) - // SetBufferPoolingThresholdForTesting updates the buffer pooling threshold, for // testing purposes. SetBufferPoolingThresholdForTesting any // func(int) @@ -244,6 +233,18 @@ var ( // When set, the function will be called before the stream enters // the blocking state. NewStreamWaitingForResolver = func() {} + + // AddressToTelemetryLabels is an xDS-provided function to extract telemetry + // labels from a resolver.Address. Callers must assert its type before calling. + AddressToTelemetryLabels any // func(addr resolver.Address) map[string]string + + // AsyncReporterCleanupDelegate is initialized to a pass-through function by + // default (production behavior), allowing tests to swap it with an + // implementation which tracks registration of async reporter and its + // corresponding cleanup. + AsyncReporterCleanupDelegate = func(cleanup func()) func() { + return cleanup + } ) // HealthChecker defines the signature of the client-side LB channel health @@ -291,3 +292,9 @@ type EnforceClientConnEmbedding interface { type Timer interface { Stop() bool } + +// EnforceMetricsRecorderEmbedding is used to enforce proper MetricsRecorder +// implementation embedding. +type EnforceMetricsRecorderEmbedding interface { + enforceMetricsRecorderEmbedding() +} diff --git a/vendor/google.golang.org/grpc/internal/mem/buffer_pool.go b/vendor/google.golang.org/grpc/internal/mem/buffer_pool.go new file mode 100644 index 000000000..c2348a82e --- /dev/null +++ b/vendor/google.golang.org/grpc/internal/mem/buffer_pool.go @@ -0,0 +1,338 @@ +/* + * + * Copyright 2026 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 mem provides utilities that facilitate memory reuse in byte slices +// that are used as buffers. +package mem + +import ( + "fmt" + "math/bits" + "slices" + "sort" + "sync" +) + +const ( + goPageSize = 4 * 1024 // 4KiB. N.B. this must be a power of 2. +) + +var uintSize = bits.UintSize // use a variable for mocking during tests. + +// bufferPool is a copy of the public bufferPool interface used to avoid +// circular dependencies. +type bufferPool interface { + // Get returns a buffer with specified length from the pool. + Get(length int) *[]byte + + // Put returns a buffer to the pool. + // + // The provided pointer must hold a prefix of the buffer obtained via + // BufferPool.Get to ensure the buffer's entire capacity can be re-used. + Put(*[]byte) +} + +// BinaryTieredBufferPool is a buffer pool that uses multiple sub-pools with +// power-of-two sizes. +type BinaryTieredBufferPool struct { + // exponentToNextLargestPoolMap maps a power-of-two exponent (e.g., 12 for + // 4KB) to the index of the next largest sizedBufferPool. This is used by + // Get() to find the smallest pool that can satisfy a request for a given + // size. + exponentToNextLargestPoolMap []int + // exponentToPreviousLargestPoolMap maps a power-of-two exponent to the + // index of the previous largest sizedBufferPool. This is used by Put() + // to return a buffer to the most appropriate pool based on its capacity. + exponentToPreviousLargestPoolMap []int + sizedPools []bufferPool + fallbackPool bufferPool + maxPoolCap int // Optimization: Cache max capacity +} + +// NewBinaryTieredBufferPool returns a BufferPool backed by multiple sub-pools. +// This structure enables O(1) lookup time for Get and Put operations. +// +// The arguments provided are the exponents for the buffer capacities (powers +// of 2), not the raw byte sizes. For example, to create a pool of 16KB buffers +// (2^14 bytes), pass 14 as the argument. +func NewBinaryTieredBufferPool(powerOfTwoExponents ...uint8) (*BinaryTieredBufferPool, error) { + return newBinaryTiered(func(size int) bufferPool { + return newSizedBufferPool(size, true) + }, &simpleBufferPool{shouldZero: true}, powerOfTwoExponents...) +} + +// NewDirtyBinaryTieredBufferPool returns a BufferPool backed by multiple +// sub-pools. It is similar to NewBinaryTieredBufferPool but it does not +// initialize the buffers before returning them. +func NewDirtyBinaryTieredBufferPool(powerOfTwoExponents ...uint8) (*BinaryTieredBufferPool, error) { + return newBinaryTiered(func(size int) bufferPool { + return newSizedBufferPool(size, false) + }, &simpleBufferPool{shouldZero: false}, powerOfTwoExponents...) +} + +func newBinaryTiered(sizedPoolFactory func(int) bufferPool, fallbackPool bufferPool, powerOfTwoExponents ...uint8) (*BinaryTieredBufferPool, error) { + slices.Sort(powerOfTwoExponents) + powerOfTwoExponents = slices.Compact(powerOfTwoExponents) + + // Determine the maximum exponent we need to support. This depends on the + // word size (32-bit vs 64-bit). + maxExponent := uintSize - 2 + indexOfNextLargestBit := slices.Repeat([]int{-1}, maxExponent+1) + indexOfPreviousLargestBit := slices.Repeat([]int{-1}, maxExponent+1) + + maxTier := 0 + pools := make([]bufferPool, 0, len(powerOfTwoExponents)) + + for i, exp := range powerOfTwoExponents { + // Allocating slices of size > 2^maxExponent isn't possible on + // maxExponent-bit machines. + if int(exp) > maxExponent { + return nil, fmt.Errorf("mem: allocating slice of size 2^%d is not possible", exp) + } + tierSize := 1 << exp + pools = append(pools, sizedPoolFactory(tierSize)) + maxTier = max(maxTier, tierSize) + + // Map the exact power of 2 to this pool index. + indexOfNextLargestBit[exp] = i + indexOfPreviousLargestBit[exp] = i + } + + // Fill gaps for Get() (Next Largest) + // We iterate backwards. If current is empty, take the value from the right (larger). + for i := maxExponent - 1; i >= 0; i-- { + if indexOfNextLargestBit[i] == -1 { + indexOfNextLargestBit[i] = indexOfNextLargestBit[i+1] + } + } + + // Fill gaps for Put() (Previous Largest) + // We iterate forwards. If current is empty, take the value from the left (smaller). + for i := 1; i <= maxExponent; i++ { + if indexOfPreviousLargestBit[i] == -1 { + indexOfPreviousLargestBit[i] = indexOfPreviousLargestBit[i-1] + } + } + + return &BinaryTieredBufferPool{ + exponentToNextLargestPoolMap: indexOfNextLargestBit, + exponentToPreviousLargestPoolMap: indexOfPreviousLargestBit, + sizedPools: pools, + maxPoolCap: maxTier, + fallbackPool: fallbackPool, + }, nil +} + +// Get returns a buffer with specified length from the pool. +func (b *BinaryTieredBufferPool) Get(size int) *[]byte { + return b.poolForGet(size).Get(size) +} + +func (b *BinaryTieredBufferPool) poolForGet(size int) bufferPool { + if size == 0 || size > b.maxPoolCap { + return b.fallbackPool + } + + // Calculate the exponent of the smallest power of 2 >= size. + // We subtract 1 from size to handle exact powers of 2 correctly. + // + // Examples: + // size=16 (0b10000) -> size-1=15 (0b01111) -> bits.Len=4 -> Pool for 2^4 + // size=17 (0b10001) -> size-1=16 (0b10000) -> bits.Len=5 -> Pool for 2^5 + querySize := uint(size - 1) + poolIdx := b.exponentToNextLargestPoolMap[bits.Len(querySize)] + + return b.sizedPools[poolIdx] +} + +// Put returns a buffer to the pool. +func (b *BinaryTieredBufferPool) Put(buf *[]byte) { + // We pass the capacity of the buffer, and not the size of the buffer here. + // If we did the latter, all buffers would eventually move to the smallest + // pool. + b.poolForPut(cap(*buf)).Put(buf) +} + +func (b *BinaryTieredBufferPool) poolForPut(bCap int) bufferPool { + if bCap == 0 { + return NopBufferPool{} + } + if bCap > b.maxPoolCap { + return b.fallbackPool + } + // Find the pool with the largest capacity <= bCap. + // + // We calculate the exponent of the largest power of 2 <= bCap. + // bits.Len(x) returns the minimum number of bits required to represent x; + // i.e. the number of bits up to and including the most significant bit. + // Subtracting 1 gives the 0-based index of the most significant bit, + // which is the exponent of the largest power of 2 <= bCap. + // + // Examples: + // cap=16 (0b10000) -> Len=5 -> 5-1=4 -> 2^4 + // cap=15 (0b01111) -> Len=4 -> 4-1=3 -> 2^3 + largestPowerOfTwo := bits.Len(uint(bCap)) - 1 + poolIdx := b.exponentToPreviousLargestPoolMap[largestPowerOfTwo] + // The buffer is smaller than the smallest power of 2, discard it. + if poolIdx == -1 { + // Buffer is smaller than our smallest pool bucket. + return NopBufferPool{} + } + return b.sizedPools[poolIdx] +} + +// NopBufferPool is a buffer pool that returns new buffers without pooling. +type NopBufferPool struct{} + +// Get returns a buffer with specified length from the pool. +func (NopBufferPool) Get(length int) *[]byte { + b := make([]byte, length) + return &b +} + +// Put returns a buffer to the pool. +func (NopBufferPool) Put(*[]byte) { +} + +// sizedBufferPool is a BufferPool implementation that is optimized for specific +// buffer sizes. For example, HTTP/2 frames within gRPC have a default max size +// of 16kb and a sizedBufferPool can be configured to only return buffers with a +// capacity of 16kb. Note that however it does not support returning larger +// buffers and in fact panics if such a buffer is requested. Because of this, +// this BufferPool implementation is not meant to be used on its own and rather +// is intended to be embedded in a TieredBufferPool such that Get is only +// invoked when the required size is smaller than or equal to defaultSize. +type sizedBufferPool struct { + pool sync.Pool + defaultSize int + shouldZero bool +} + +func (p *sizedBufferPool) Get(size int) *[]byte { + buf, ok := p.pool.Get().(*[]byte) + if !ok { + buf := make([]byte, size, p.defaultSize) + return &buf + } + b := *buf + if p.shouldZero { + clear(b[:cap(b)]) + } + *buf = b[:size] + return buf +} + +func (p *sizedBufferPool) Put(buf *[]byte) { + if cap(*buf) < p.defaultSize { + // Ignore buffers that are too small to fit in the pool. Otherwise, when + // Get is called it will panic as it tries to index outside the bounds + // of the buffer. + return + } + p.pool.Put(buf) +} + +func newSizedBufferPool(size int, zero bool) *sizedBufferPool { + return &sizedBufferPool{ + defaultSize: size, + shouldZero: zero, + } +} + +// TieredBufferPool implements the BufferPool interface with multiple tiers of +// buffer pools for different sizes of buffers. +type TieredBufferPool struct { + sizedPools []*sizedBufferPool + fallbackPool simpleBufferPool +} + +// NewTieredBufferPool returns a BufferPool implementation that uses multiple +// underlying pools of the given pool sizes. +func NewTieredBufferPool(poolSizes ...int) *TieredBufferPool { + sort.Ints(poolSizes) + pools := make([]*sizedBufferPool, len(poolSizes)) + for i, s := range poolSizes { + pools[i] = newSizedBufferPool(s, true) + } + return &TieredBufferPool{ + sizedPools: pools, + fallbackPool: simpleBufferPool{shouldZero: true}, + } +} + +// Get returns a buffer with specified length from the pool. +func (p *TieredBufferPool) Get(size int) *[]byte { + return p.getPool(size).Get(size) +} + +// Put returns a buffer to the pool. +func (p *TieredBufferPool) Put(buf *[]byte) { + p.getPool(cap(*buf)).Put(buf) +} + +func (p *TieredBufferPool) getPool(size int) bufferPool { + poolIdx := sort.Search(len(p.sizedPools), func(i int) bool { + return p.sizedPools[i].defaultSize >= size + }) + + if poolIdx == len(p.sizedPools) { + return &p.fallbackPool + } + + return p.sizedPools[poolIdx] +} + +// simpleBufferPool is an implementation of the BufferPool interface that +// attempts to pool buffers with a sync.Pool. When Get is invoked, it tries to +// acquire a buffer from the pool but if that buffer is too small, it returns it +// to the pool and creates a new one. +type simpleBufferPool struct { + pool sync.Pool + shouldZero bool +} + +func (p *simpleBufferPool) Get(size int) *[]byte { + bs, ok := p.pool.Get().(*[]byte) + if ok && cap(*bs) >= size { + if p.shouldZero { + clear((*bs)[:cap(*bs)]) + } + *bs = (*bs)[:size] + return bs + } + + // A buffer was pulled from the pool, but it is too small. Put it back in + // the pool and create one large enough. + if ok { + p.pool.Put(bs) + } + + // If we're going to allocate, round up to the nearest page. This way if + // requests frequently arrive with small variation we don't allocate + // repeatedly if we get unlucky and they increase over time. By default we + // only allocate here if size > 1MiB. Because goPageSize is a power of 2, we + // can round up efficiently. + allocSize := (size + goPageSize - 1) & ^(goPageSize - 1) + + b := make([]byte, size, allocSize) + return &b +} + +func (p *simpleBufferPool) Put(buf *[]byte) { + p.pool.Put(buf) +} diff --git a/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go b/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go index ada5251cf..70b89e4d7 100644 --- a/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go +++ b/vendor/google.golang.org/grpc/internal/resolver/dns/dns_resolver.go @@ -125,7 +125,10 @@ func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts // IP address. if ipAddr, err := formatIP(host); err == nil { addr := []resolver.Address{{Addr: ipAddr + ":" + port}} - cc.UpdateState(resolver.State{Addresses: addr}) + cc.UpdateState(resolver.State{ + Addresses: addr, + Endpoints: []resolver.Endpoint{{Addresses: addr}}, + }) return deadResolver{}, nil } @@ -342,7 +345,15 @@ func (d *dnsResolver) lookup() (*resolver.State, error) { return nil, hostErr } - state := resolver.State{Addresses: addrs} + eps := make([]resolver.Endpoint, 0, len(addrs)) + for _, addr := range addrs { + eps = append(eps, resolver.Endpoint{Addresses: []resolver.Address{addr}}) + } + + state := resolver.State{ + Addresses: addrs, + Endpoints: eps, + } if len(srv) > 0 { state = grpclbstate.Set(state, &grpclbstate.State{BalancerAddresses: srv}) } diff --git a/vendor/google.golang.org/grpc/internal/stats/metrics_recorder_list.go b/vendor/google.golang.org/grpc/internal/stats/metrics_recorder_list.go index d5f7e4d62..1c8c2ab30 100644 --- a/vendor/google.golang.org/grpc/internal/stats/metrics_recorder_list.go +++ b/vendor/google.golang.org/grpc/internal/stats/metrics_recorder_list.go @@ -20,6 +20,7 @@ import ( "fmt" estats "google.golang.org/grpc/experimental/stats" + "google.golang.org/grpc/internal" "google.golang.org/grpc/stats" ) @@ -28,6 +29,7 @@ import ( // It eats any record calls where the label values provided do not match the // number of label keys. type MetricsRecorderList struct { + internal.EnforceMetricsRecorderEmbedding // metricsRecorders are the metrics recorders this list will forward to. metricsRecorders []estats.MetricsRecorder } @@ -113,3 +115,61 @@ func (l *MetricsRecorderList) RecordInt64Gauge(handle *estats.Int64GaugeHandle, metricRecorder.RecordInt64Gauge(handle, incr, labels...) } } + +// RegisterAsyncReporter forwards the registration to all underlying metrics +// recorders. +// +// It returns a cleanup function that, when called, invokes the cleanup function +// returned by each underlying recorder, ensuring the reporter is unregistered +// from all of them. +func (l *MetricsRecorderList) RegisterAsyncReporter(reporter estats.AsyncMetricReporter, metrics ...estats.AsyncMetric) func() { + descriptorsMap := make(map[*estats.MetricDescriptor]bool, len(metrics)) + for _, m := range metrics { + descriptorsMap[m.Descriptor()] = true + } + unregisterFns := make([]func(), 0, len(l.metricsRecorders)) + for _, mr := range l.metricsRecorders { + // Wrap the AsyncMetricsRecorder to intercept calls to RecordInt64Gauge + // and validate the labels. + wrappedCallback := func(recorder estats.AsyncMetricsRecorder) error { + wrappedRecorder := &asyncRecorderWrapper{ + delegate: recorder, + descriptors: descriptorsMap, + } + return reporter.Report(wrappedRecorder) + } + unregisterFns = append(unregisterFns, mr.RegisterAsyncReporter(estats.AsyncMetricReporterFunc(wrappedCallback), metrics...)) + } + + // Wrap the cleanup function using the internal delegate. + // In production, this returns realCleanup as-is. + // In tests, the leak checker can swap this to track the registration lifetime. + return internal.AsyncReporterCleanupDelegate(defaultCleanUp(unregisterFns)) +} + +func defaultCleanUp(unregisterFns []func()) func() { + return func() { + for _, unregister := range unregisterFns { + unregister() + } + } +} + +type asyncRecorderWrapper struct { + delegate estats.AsyncMetricsRecorder + descriptors map[*estats.MetricDescriptor]bool +} + +// RecordIntAsync64Gauge records the measurement alongside labels on the int +// gauge associated with the provided handle. +func (w *asyncRecorderWrapper) RecordInt64AsyncGauge(handle *estats.Int64AsyncGaugeHandle, value int64, labels ...string) { + // Ensure only metrics for descriptors passed during callback registration + // are emitted. + d := handle.Descriptor() + if _, ok := w.descriptors[d]; !ok { + return + } + // Validate labels and delegate. + verifyLabels(d, labels...) + w.delegate.RecordInt64AsyncGauge(handle, value, labels...) +} diff --git a/vendor/google.golang.org/grpc/internal/transport/client_stream.go b/vendor/google.golang.org/grpc/internal/transport/client_stream.go index 980452519..cd8152ef1 100644 --- a/vendor/google.golang.org/grpc/internal/transport/client_stream.go +++ b/vendor/google.golang.org/grpc/internal/transport/client_stream.go @@ -24,6 +24,7 @@ import ( "golang.org/x/net/http2" "google.golang.org/grpc/mem" "google.golang.org/grpc/metadata" + "google.golang.org/grpc/stats" "google.golang.org/grpc/status" ) @@ -46,10 +47,11 @@ type ClientStream struct { // meaningful after headerChan is closed (always call waitOnHeader() before // reading its value). headerValid bool - noHeaders bool // set if the client never received headers (set only after the stream is done). - headerChanClosed uint32 // set when headerChan is closed. Used to avoid closing headerChan multiple times. - bytesReceived atomic.Bool // indicates whether any bytes have been received on this stream - unprocessed atomic.Bool // set if the server sends a refused stream or GOAWAY including this stream + noHeaders bool // set if the client never received headers (set only after the stream is done). + headerChanClosed uint32 // set when headerChan is closed. Used to avoid closing headerChan multiple times. + bytesReceived atomic.Bool // indicates whether any bytes have been received on this stream + unprocessed atomic.Bool // set if the server sends a refused stream or GOAWAY including this stream + statsHandler stats.Handler // nil for internal streams (e.g., health check, ORCA) where telemetry is not supported. } // Read reads an n byte message from the input stream. diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go index 2dcd1e63b..7efa52478 100644 --- a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go +++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go @@ -24,16 +24,13 @@ import ( "fmt" "net" "runtime" - "strconv" "sync" "sync/atomic" "golang.org/x/net/http2" "golang.org/x/net/http2/hpack" "google.golang.org/grpc/internal/grpclog" - "google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/mem" - "google.golang.org/grpc/status" ) var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) { @@ -147,11 +144,9 @@ type cleanupStream struct { func (c *cleanupStream) isTransportResponseFrame() bool { return c.rst } // Results in a RST_STREAM type earlyAbortStream struct { - httpStatus uint32 - streamID uint32 - contentSubtype string - status *status.Status - rst bool + streamID uint32 + rst bool + hf []hpack.HeaderField // Pre-built header fields } func (*earlyAbortStream) isTransportResponseFrame() bool { return false } @@ -843,18 +838,7 @@ func (l *loopyWriter) earlyAbortStreamHandler(eas *earlyAbortStream) error { if l.side == clientSide { return errors.New("earlyAbortStream not handled on client") } - // In case the caller forgets to set the http status, default to 200. - if eas.httpStatus == 0 { - eas.httpStatus = 200 - } - headerFields := []hpack.HeaderField{ - {Name: ":status", Value: strconv.Itoa(int(eas.httpStatus))}, - {Name: "content-type", Value: grpcutil.ContentType(eas.contentSubtype)}, - {Name: "grpc-status", Value: strconv.Itoa(int(eas.status.Code()))}, - {Name: "grpc-message", Value: encodeGrpcMessage(eas.status.Message())}, - } - - if err := l.writeHeader(eas.streamID, true, headerFields, nil); err != nil { + if err := l.writeHeader(eas.streamID, true, eas.hf, nil); err != nil { return err } if eas.rst { diff --git a/vendor/google.golang.org/grpc/internal/transport/defaults.go b/vendor/google.golang.org/grpc/internal/transport/defaults.go index bc8ee0747..0b2269a50 100644 --- a/vendor/google.golang.org/grpc/internal/transport/defaults.go +++ b/vendor/google.golang.org/grpc/internal/transport/defaults.go @@ -46,6 +46,7 @@ const ( defaultWriteQuota = 64 * 1024 defaultClientMaxHeaderListSize = uint32(16 << 20) defaultServerMaxHeaderListSize = uint32(16 << 20) + upcomingDefaultHeaderListSize = uint32(8 << 10) ) // MaxStreamID is the upper bound for the stream ID before the current diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go index 65b4ab243..c943503f3 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go @@ -370,7 +370,7 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts }) t.logger = prefixLoggerForClientTransport(t) // Add peer information to the http2client context. - t.ctx = peer.NewContext(t.ctx, t.getPeer()) + t.ctx = peer.NewContext(t.ctx, t.Peer()) if md, ok := addr.Metadata.(*metadata.MD); ok { t.md = *md @@ -478,7 +478,7 @@ func NewHTTP2Client(connectCtx, ctx context.Context, addr resolver.Address, opts return t, nil } -func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *ClientStream { +func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr, handler stats.Handler) *ClientStream { // TODO(zhaoq): Handle uint32 overflow of Stream.id. s := &ClientStream{ Stream: Stream{ @@ -486,10 +486,11 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *ClientSt sendCompress: callHdr.SendCompress, contentSubtype: callHdr.ContentSubtype, }, - ct: t, - done: make(chan struct{}), - headerChan: make(chan struct{}), - doneFunc: callHdr.DoneFunc, + ct: t, + done: make(chan struct{}), + headerChan: make(chan struct{}), + doneFunc: callHdr.DoneFunc, + statsHandler: handler, } s.Stream.buf.init() s.Stream.wq.init(defaultWriteQuota, s.done) @@ -510,7 +511,7 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *ClientSt return s } -func (t *http2Client) getPeer() *peer.Peer { +func (t *http2Client) Peer() *peer.Peer { return &peer.Peer{ Addr: t.remoteAddr, AuthInfo: t.authInfo, // Can be nil @@ -551,6 +552,9 @@ func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr) hfLen := 7 // :method, :scheme, :path, :authority, content-type, user-agent, te hfLen += len(authData) + len(callAuthData) registeredCompressors := t.registeredCompressors + if callHdr.AcceptedCompressors != nil { + registeredCompressors = *callHdr.AcceptedCompressors + } if callHdr.PreviousAttempts > 0 { hfLen++ } @@ -741,8 +745,8 @@ func (e NewStreamError) Error() string { // NewStream creates a stream and registers it into the transport as "active" // streams. All non-nil errors returned will be *NewStreamError. -func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*ClientStream, error) { - ctx = peer.NewContext(ctx, t.getPeer()) +func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr, handler stats.Handler) (*ClientStream, error) { + ctx = peer.NewContext(ctx, t.Peer()) // ServerName field of the resolver returned address takes precedence over // Host field of CallHdr to determine the :authority header. This is because, @@ -778,7 +782,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*ClientS if err != nil { return nil, &NewStreamError{Err: err, AllowTransparentRetry: false} } - s := t.newStream(ctx, callHdr) + s := t.newStream(ctx, callHdr, handler) cleanup := func(err error) { if s.swapState(streamDone) == streamDone { // If it was already done, return. @@ -867,11 +871,15 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*ClientS } var sz int64 for _, f := range hdr.hf { - if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) { + sz += int64(f.Size()) + if sz > int64(*t.maxSendHeaderListSize) { hdrListSizeErr = status.Errorf(codes.Internal, "header list size to send violates the maximum size (%d bytes) set by server", *t.maxSendHeaderListSize) return false } } + if sz > int64(upcomingDefaultHeaderListSize) { + t.logger.Warningf("Header list size to send (%d bytes) is larger than the upcoming default limit (%d bytes). In a future release, this will be restricted to %d bytes.", sz, upcomingDefaultHeaderListSize, upcomingDefaultHeaderListSize) + } return true } for { @@ -899,7 +907,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*ClientS return nil, &NewStreamError{Err: ErrConnClosing, AllowTransparentRetry: true} } } - if t.statsHandler != nil { + if s.statsHandler != nil { header, ok := metadata.FromOutgoingContext(ctx) if ok { header.Set("user-agent", t.userAgent) @@ -908,7 +916,7 @@ func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (*ClientS } // Note: The header fields are compressed with hpack after this call returns. // No WireLength field is set here. - t.statsHandler.HandleRPC(s.ctx, &stats.OutHeader{ + s.statsHandler.HandleRPC(s.ctx, &stats.OutHeader{ Client: true, FullMethod: callHdr.Method, RemoteAddr: t.remoteAddr, @@ -1485,7 +1493,7 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { case "grpc-status": code, err := strconv.ParseInt(hf.Value, 10, 32) if err != nil { - se := status.New(codes.Internal, fmt.Sprintf("transport: malformed grpc-status: %v", err)) + se := status.New(codes.Unknown, fmt.Sprintf("transport: malformed grpc-status: %v", err)) t.closeStream(s, se.Err(), true, http2.ErrCodeProtocol, se, nil, endStream) return } @@ -1584,16 +1592,16 @@ func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) { } } - if t.statsHandler != nil { + if s.statsHandler != nil { if !endStream { - t.statsHandler.HandleRPC(s.ctx, &stats.InHeader{ + s.statsHandler.HandleRPC(s.ctx, &stats.InHeader{ Client: true, WireLength: int(frame.Header().Length), Header: metadata.MD(mdata).Copy(), Compression: s.recvCompress, }) } else { - t.statsHandler.HandleRPC(s.ctx, &stats.InTrailer{ + s.statsHandler.HandleRPC(s.ctx, &stats.InTrailer{ Client: true, WireLength: int(frame.Header().Length), Trailer: metadata.MD(mdata).Copy(), @@ -1807,8 +1815,6 @@ func (t *http2Client) socketMetrics() *channelz.EphemeralSocketMetrics { } } -func (t *http2Client) RemoteAddr() net.Addr { return t.remoteAddr } - func (t *http2Client) incrMsgSent() { if channelz.IsOn() { t.channelz.SocketMetrics.MessagesSent.Add(1) diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go index 6f78a6b0c..3a8c36e4f 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go @@ -479,13 +479,7 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade if t.logger.V(logLevel) { t.logger.Infof("Aborting the stream early: %v", errMsg) } - t.controlBuf.put(&earlyAbortStream{ - httpStatus: http.StatusBadRequest, - streamID: streamID, - contentSubtype: s.contentSubtype, - status: status.New(codes.Internal, errMsg), - rst: !frame.StreamEnded(), - }) + t.writeEarlyAbort(streamID, s.contentSubtype, status.New(codes.Internal, errMsg), http.StatusBadRequest, !frame.StreamEnded()) return nil } @@ -499,23 +493,11 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade return nil } if !isGRPC { - t.controlBuf.put(&earlyAbortStream{ - httpStatus: http.StatusUnsupportedMediaType, - streamID: streamID, - contentSubtype: s.contentSubtype, - status: status.Newf(codes.InvalidArgument, "invalid gRPC request content-type %q", contentType), - rst: !frame.StreamEnded(), - }) + t.writeEarlyAbort(streamID, s.contentSubtype, status.Newf(codes.InvalidArgument, "invalid gRPC request content-type %q", contentType), http.StatusUnsupportedMediaType, !frame.StreamEnded()) return nil } if headerError != nil { - t.controlBuf.put(&earlyAbortStream{ - httpStatus: http.StatusBadRequest, - streamID: streamID, - contentSubtype: s.contentSubtype, - status: headerError, - rst: !frame.StreamEnded(), - }) + t.writeEarlyAbort(streamID, s.contentSubtype, headerError, http.StatusBadRequest, !frame.StreamEnded()) return nil } @@ -569,13 +551,7 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade if t.logger.V(logLevel) { t.logger.Infof("Aborting the stream early: %v", errMsg) } - t.controlBuf.put(&earlyAbortStream{ - httpStatus: http.StatusMethodNotAllowed, - streamID: streamID, - contentSubtype: s.contentSubtype, - status: status.New(codes.Internal, errMsg), - rst: !frame.StreamEnded(), - }) + t.writeEarlyAbort(streamID, s.contentSubtype, status.New(codes.Internal, errMsg), http.StatusMethodNotAllowed, !frame.StreamEnded()) s.cancel() return nil } @@ -590,27 +566,16 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade if !ok { stat = status.New(codes.PermissionDenied, err.Error()) } - t.controlBuf.put(&earlyAbortStream{ - httpStatus: http.StatusOK, - streamID: s.id, - contentSubtype: s.contentSubtype, - status: stat, - rst: !frame.StreamEnded(), - }) + t.writeEarlyAbort(s.id, s.contentSubtype, stat, http.StatusOK, !frame.StreamEnded()) return nil } } if s.ctx.Err() != nil { t.mu.Unlock() + st := status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()) // Early abort in case the timeout was zero or so low it already fired. - t.controlBuf.put(&earlyAbortStream{ - httpStatus: http.StatusOK, - streamID: s.id, - contentSubtype: s.contentSubtype, - status: status.New(codes.DeadlineExceeded, context.DeadlineExceeded.Error()), - rst: !frame.StreamEnded(), - }) + t.writeEarlyAbort(s.id, s.contentSubtype, st, http.StatusOK, !frame.StreamEnded()) return nil } @@ -969,23 +934,62 @@ func appendHeaderFieldsFromMD(headerFields []hpack.HeaderField, md metadata.MD) return headerFields } -func (t *http2Server) checkForHeaderListSize(it any) bool { +func (t *http2Server) checkForHeaderListSize(hf []hpack.HeaderField) bool { if t.maxSendHeaderListSize == nil { return true } - hdrFrame := it.(*headerFrame) var sz int64 - for _, f := range hdrFrame.hf { - if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) { + for _, f := range hf { + sz += int64(f.Size()) + if sz > int64(*t.maxSendHeaderListSize) { if t.logger.V(logLevel) { t.logger.Infof("Header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize) } return false } } + if sz > int64(upcomingDefaultHeaderListSize) { + t.logger.Warningf("Header list size to send (%d bytes) is larger than the upcoming default limit (%d bytes). In a future release, this will be restricted to %d bytes.", sz, upcomingDefaultHeaderListSize, upcomingDefaultHeaderListSize) + } return true } +// writeEarlyAbort sends an early abort response with the given HTTP status and +// gRPC status. If the header list size exceeds the peer's limit, it sends a +// RST_STREAM instead. +func (t *http2Server) writeEarlyAbort(streamID uint32, contentSubtype string, stat *status.Status, httpStatus uint32, rst bool) { + hf := []hpack.HeaderField{ + {Name: ":status", Value: strconv.Itoa(int(httpStatus))}, + {Name: "content-type", Value: grpcutil.ContentType(contentSubtype)}, + {Name: "grpc-status", Value: strconv.Itoa(int(stat.Code()))}, + {Name: "grpc-message", Value: encodeGrpcMessage(stat.Message())}, + } + if p := istatus.RawStatusProto(stat); len(p.GetDetails()) > 0 { + stBytes, err := proto.Marshal(p) + if err != nil { + t.logger.Errorf("Failed to marshal rpc status: %s, error: %v", pretty.ToJSON(p), err) + } + if err == nil { + hf = append(hf, hpack.HeaderField{Name: grpcStatusDetailsBinHeader, Value: encodeBinHeader(stBytes)}) + } + } + success, _ := t.controlBuf.executeAndPut(func() bool { + return t.checkForHeaderListSize(hf) + }, &earlyAbortStream{ + streamID: streamID, + rst: rst, + hf: hf, + }) + if !success { + t.controlBuf.put(&cleanupStream{ + streamID: streamID, + rst: true, + rstCode: http2.ErrCodeInternal, + onWrite: func() {}, + }) + } +} + func (t *http2Server) streamContextErr(s *ServerStream) error { select { case <-t.done: @@ -1041,7 +1045,7 @@ func (t *http2Server) writeHeaderLocked(s *ServerStream) error { endStream: false, onWrite: t.setResetPingStrikes, } - success, err := t.controlBuf.executeAndPut(func() bool { return t.checkForHeaderListSize(hf) }, hf) + success, err := t.controlBuf.executeAndPut(func() bool { return t.checkForHeaderListSize(hf.hf) }, hf) if !success { if err != nil { return err @@ -1111,7 +1115,7 @@ func (t *http2Server) writeStatus(s *ServerStream, st *status.Status) error { } success, err := t.controlBuf.executeAndPut(func() bool { - return t.checkForHeaderListSize(trailingHeader) + return t.checkForHeaderListSize(trailingHeader.hf) }, nil) if !success { if err != nil { diff --git a/vendor/google.golang.org/grpc/internal/transport/http_util.go b/vendor/google.golang.org/grpc/internal/transport/http_util.go index 6209eb23c..5bbb641ad 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http_util.go +++ b/vendor/google.golang.org/grpc/internal/transport/http_util.go @@ -411,12 +411,6 @@ var writeBufferPoolMap = make(map[int]*sync.Pool) var writeBufferMutex sync.Mutex func newFramer(conn io.ReadWriter, writeBufferSize, readBufferSize int, sharedWriteBuffer bool, maxHeaderListSize uint32, memPool mem.BufferPool) *framer { - if memPool == nil { - // Note that this is only supposed to be nil in tests. Otherwise, stream - // is always initialized with a BufferPool. - memPool = mem.DefaultBufferPool() - } - if writeBufferSize < 0 { writeBufferSize = 0 } diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go index 5ff83a7d7..b86094da9 100644 --- a/vendor/google.golang.org/grpc/internal/transport/transport.go +++ b/vendor/google.golang.org/grpc/internal/transport/transport.go @@ -378,12 +378,28 @@ func (s *Stream) ReadMessageHeader(header []byte) (err error) { return nil } +// ceil returns the ceil after dividing the numerator and denominator while +// avoiding integer overflows. +func ceil(numerator, denominator int) int { + if numerator == 0 { + return 0 + } + return (numerator-1)/denominator + 1 +} + // Read reads n bytes from the wire for this stream. func (s *Stream) read(n int) (data mem.BufferSlice, err error) { // Don't request a read if there was an error earlier if er := s.trReader.er; er != nil { return nil, er } + // gRPC Go accepts data frames with a maximum length of 16KB. Larger + // messages must be split into multiple frames. We pre-allocate the + // buffer to avoid resizing during the read loop, but cap the initial + // capacity to 128 frames (2MB) to prevent over-allocation or panics + // when reading extremely large streams. + allocCap := min(ceil(n, http2MaxFrameLen), 128) + data = make(mem.BufferSlice, 0, allocCap) s.readRequester.requestRead(n) for n != 0 { buf, err := s.trReader.Read(n) @@ -553,6 +569,12 @@ type CallHdr struct { // outbound message. SendCompress string + // AcceptedCompressors overrides the grpc-accept-encoding header for this + // call. When nil, the transport advertises the default set of registered + // compressors. A non-nil pointer overrides that value (including the empty + // string to advertise none). + AcceptedCompressors *string + // Creds specifies credentials.PerRPCCredentials for a call. Creds credentials.PerRPCCredentials @@ -568,9 +590,14 @@ type CallHdr struct { DoneFunc func() // called when the stream is finished - // Authority is used to explicitly override the `:authority` header. If set, - // this value takes precedence over the Host field and will be used as the - // value for the `:authority` header. + // Authority is used to explicitly override the `:authority` header. + // + // This value comes from one of two sources: + // 1. The `CallAuthority` call option, if specified by the user. + // 2. An override provided by the LB picker (e.g. xDS authority rewriting). + // + // The `CallAuthority` call option always takes precedence over the LB + // picker override. Authority string } @@ -590,7 +617,7 @@ type ClientTransport interface { GracefulClose() // NewStream creates a Stream for an RPC. - NewStream(ctx context.Context, callHdr *CallHdr) (*ClientStream, error) + NewStream(ctx context.Context, callHdr *CallHdr, handler stats.Handler) (*ClientStream, error) // Error returns a channel that is closed when some I/O error // happens. Typically the caller should have a goroutine to monitor @@ -608,8 +635,9 @@ type ClientTransport interface { // with a human readable string with debug info. GetGoAwayReason() (GoAwayReason, string) - // RemoteAddr returns the remote network address. - RemoteAddr() net.Addr + // Peer returns information about the peer associated with the Transport. + // The returned information includes authentication and network address details. + Peer() *peer.Peer } // ServerTransport is the common interface for all gRPC server-side transport diff --git a/vendor/google.golang.org/grpc/mem/buffer_pool.go b/vendor/google.golang.org/grpc/mem/buffer_pool.go index f211e7274..3b02b9091 100644 --- a/vendor/google.golang.org/grpc/mem/buffer_pool.go +++ b/vendor/google.golang.org/grpc/mem/buffer_pool.go @@ -19,10 +19,10 @@ package mem import ( - "sort" - "sync" + "fmt" "google.golang.org/grpc/internal" + "google.golang.org/grpc/internal/mem" ) // BufferPool is a pool of buffers that can be shared and reused, resulting in @@ -38,20 +38,25 @@ type BufferPool interface { Put(*[]byte) } -var defaultBufferPoolSizes = []int{ - 256, - 4 << 10, // 4KB (go page size) - 16 << 10, // 16KB (max HTTP/2 frame size used by gRPC) - 32 << 10, // 32KB (default buffer size for io.Copy) - 1 << 20, // 1MB -} - -var defaultBufferPool BufferPool +var ( + defaultBufferPoolSizeExponents = []uint8{ + 8, + 12, // Go page size, 4KB + 14, // 16KB (max HTTP/2 frame size used by gRPC) + 15, // 32KB (default buffer size for io.Copy) + 20, // 1MB + } + defaultBufferPool BufferPool +) func init() { - defaultBufferPool = NewTieredBufferPool(defaultBufferPoolSizes...) + var err error + defaultBufferPool, err = NewBinaryTieredBufferPool(defaultBufferPoolSizeExponents...) + if err != nil { + panic(fmt.Sprintf("Failed to create default buffer pool: %v", err)) + } - internal.SetDefaultBufferPoolForTesting = func(pool BufferPool) { + internal.SetDefaultBufferPool = func(pool BufferPool) { defaultBufferPool = pool } @@ -70,127 +75,22 @@ func DefaultBufferPool() BufferPool { // NewTieredBufferPool returns a BufferPool implementation that uses multiple // underlying pools of the given pool sizes. func NewTieredBufferPool(poolSizes ...int) BufferPool { - sort.Ints(poolSizes) - pools := make([]*sizedBufferPool, len(poolSizes)) - for i, s := range poolSizes { - pools[i] = newSizedBufferPool(s) - } - return &tieredBufferPool{ - sizedPools: pools, - } -} - -// tieredBufferPool implements the BufferPool interface with multiple tiers of -// buffer pools for different sizes of buffers. -type tieredBufferPool struct { - sizedPools []*sizedBufferPool - fallbackPool simpleBufferPool -} - -func (p *tieredBufferPool) Get(size int) *[]byte { - return p.getPool(size).Get(size) + return mem.NewTieredBufferPool(poolSizes...) } -func (p *tieredBufferPool) Put(buf *[]byte) { - p.getPool(cap(*buf)).Put(buf) +// NewBinaryTieredBufferPool returns a BufferPool backed by multiple sub-pools. +// This structure enables O(1) lookup time for Get and Put operations. +// +// The arguments provided are the exponents for the buffer capacities (powers +// of 2), not the raw byte sizes. For example, to create a pool of 16KB buffers +// (2^14 bytes), pass 14 as the argument. +func NewBinaryTieredBufferPool(powerOfTwoExponents ...uint8) (BufferPool, error) { + return mem.NewBinaryTieredBufferPool(powerOfTwoExponents...) } -func (p *tieredBufferPool) getPool(size int) BufferPool { - poolIdx := sort.Search(len(p.sizedPools), func(i int) bool { - return p.sizedPools[i].defaultSize >= size - }) - - if poolIdx == len(p.sizedPools) { - return &p.fallbackPool - } - - return p.sizedPools[poolIdx] -} - -// sizedBufferPool is a BufferPool implementation that is optimized for specific -// buffer sizes. For example, HTTP/2 frames within gRPC have a default max size -// of 16kb and a sizedBufferPool can be configured to only return buffers with a -// capacity of 16kb. Note that however it does not support returning larger -// buffers and in fact panics if such a buffer is requested. Because of this, -// this BufferPool implementation is not meant to be used on its own and rather -// is intended to be embedded in a tieredBufferPool such that Get is only -// invoked when the required size is smaller than or equal to defaultSize. -type sizedBufferPool struct { - pool sync.Pool - defaultSize int -} - -func (p *sizedBufferPool) Get(size int) *[]byte { - buf, ok := p.pool.Get().(*[]byte) - if !ok { - buf := make([]byte, size, p.defaultSize) - return &buf - } - b := *buf - clear(b[:cap(b)]) - *buf = b[:size] - return buf -} - -func (p *sizedBufferPool) Put(buf *[]byte) { - if cap(*buf) < p.defaultSize { - // Ignore buffers that are too small to fit in the pool. Otherwise, when - // Get is called it will panic as it tries to index outside the bounds - // of the buffer. - return - } - p.pool.Put(buf) -} - -func newSizedBufferPool(size int) *sizedBufferPool { - return &sizedBufferPool{ - defaultSize: size, - } -} - -var _ BufferPool = (*simpleBufferPool)(nil) - -// simpleBufferPool is an implementation of the BufferPool interface that -// attempts to pool buffers with a sync.Pool. When Get is invoked, it tries to -// acquire a buffer from the pool but if that buffer is too small, it returns it -// to the pool and creates a new one. -type simpleBufferPool struct { - pool sync.Pool -} - -func (p *simpleBufferPool) Get(size int) *[]byte { - bs, ok := p.pool.Get().(*[]byte) - if ok && cap(*bs) >= size { - clear((*bs)[:cap(*bs)]) - *bs = (*bs)[:size] - return bs - } - - // A buffer was pulled from the pool, but it is too small. Put it back in - // the pool and create one large enough. - if ok { - p.pool.Put(bs) - } - - b := make([]byte, size) - return &b -} - -func (p *simpleBufferPool) Put(buf *[]byte) { - p.pool.Put(buf) -} - -var _ BufferPool = NopBufferPool{} - // NopBufferPool is a buffer pool that returns new buffers without pooling. -type NopBufferPool struct{} - -// Get returns a buffer with specified length from the pool. -func (NopBufferPool) Get(length int) *[]byte { - b := make([]byte, length) - return &b +type NopBufferPool struct { + mem.NopBufferPool } -// Put returns a buffer to the pool. -func (NopBufferPool) Put(*[]byte) { -} +var _ BufferPool = NopBufferPool{} diff --git a/vendor/google.golang.org/grpc/mem/buffers.go b/vendor/google.golang.org/grpc/mem/buffers.go index ecbf0b9a7..db1620e6a 100644 --- a/vendor/google.golang.org/grpc/mem/buffers.go +++ b/vendor/google.golang.org/grpc/mem/buffers.go @@ -62,7 +62,6 @@ var ( bufferPoolingThreshold = 1 << 10 bufferObjectPool = sync.Pool{New: func() any { return new(buffer) }} - refObjectPool = sync.Pool{New: func() any { return new(atomic.Int32) }} ) // IsBelowBufferPoolingThreshold returns true if the given size is less than or @@ -73,9 +72,19 @@ func IsBelowBufferPoolingThreshold(size int) bool { } type buffer struct { + refs atomic.Int32 + data []byte + + // rootBuf is the buffer responsible for returning origData to the pool + // once the reference count drops to 0. + // + // When a buffer is split, the new buffer inherits the rootBuf of the + // original and increments the root's reference count. For the + // initial buffer (the root), this field points to itself. + rootBuf *buffer + + // The following fields are only set for root buffers. origData *[]byte - data []byte - refs *atomic.Int32 pool BufferPool } @@ -103,8 +112,8 @@ func NewBuffer(data *[]byte, pool BufferPool) Buffer { b.origData = data b.data = *data b.pool = pool - b.refs = refObjectPool.Get().(*atomic.Int32) - b.refs.Add(1) + b.rootBuf = b + b.refs.Store(1) return b } @@ -127,42 +136,44 @@ func Copy(data []byte, pool BufferPool) Buffer { } func (b *buffer) ReadOnlyData() []byte { - if b.refs == nil { + if b.rootBuf == nil { panic("Cannot read freed buffer") } return b.data } func (b *buffer) Ref() { - if b.refs == nil { + if b.refs.Add(1) <= 1 { panic("Cannot ref freed buffer") } - b.refs.Add(1) } func (b *buffer) Free() { - if b.refs == nil { + refs := b.refs.Add(-1) + if refs < 0 { panic("Cannot free freed buffer") } - - refs := b.refs.Add(-1) - switch { - case refs > 0: + if refs > 0 { return - case refs == 0: + } + + b.data = nil + if b.rootBuf == b { + // This buffer is the owner of the data slice and its ref count reached + // 0, free the slice. if b.pool != nil { b.pool.Put(b.origData) + b.pool = nil } - - refObjectPool.Put(b.refs) b.origData = nil - b.data = nil - b.refs = nil - b.pool = nil - bufferObjectPool.Put(b) - default: - panic("Cannot free freed buffer") + } else { + // This buffer doesn't own the data slice, decrement a ref on the root + // buffer. + b.rootBuf.Free() } + + b.rootBuf = nil + bufferObjectPool.Put(b) } func (b *buffer) Len() int { @@ -170,16 +181,14 @@ func (b *buffer) Len() int { } func (b *buffer) split(n int) (Buffer, Buffer) { - if b.refs == nil { + if b.rootBuf == nil || b.rootBuf.refs.Add(1) <= 1 { panic("Cannot split freed buffer") } - b.refs.Add(1) split := newBuffer() - split.origData = b.origData split.data = b.data[n:] - split.refs = b.refs - split.pool = b.pool + split.rootBuf = b.rootBuf + split.refs.Store(1) b.data = b.data[:n] @@ -187,7 +196,7 @@ func (b *buffer) split(n int) (Buffer, Buffer) { } func (b *buffer) read(buf []byte) (int, Buffer) { - if b.refs == nil { + if b.rootBuf == nil { panic("Cannot read freed buffer") } diff --git a/vendor/google.golang.org/grpc/picker_wrapper.go b/vendor/google.golang.org/grpc/picker_wrapper.go index aa52bfe95..0183ab22f 100644 --- a/vendor/google.golang.org/grpc/picker_wrapper.go +++ b/vendor/google.golang.org/grpc/picker_wrapper.go @@ -192,7 +192,9 @@ func (pw *pickerWrapper) pick(ctx context.Context, failfast bool, info balancer. // DoneInfo with default value works. pickResult.Done(balancer.DoneInfo{}) } - logger.Infof("blockingPicker: the picked transport is not ready, loop back to repick") + if logger.V(2) { + logger.Infof("blockingPicker: the picked transport is not ready, loop back to repick") + } // If ok == false, ac.state is not READY. // A valid picker always returns READY subConn. This means the state of ac // just changed, and picker will be updated shortly. diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go index 92fdc3afa..556ab033d 100644 --- a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection.pb.go @@ -21,7 +21,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.10 +// protoc-gen-go v1.36.11 // protoc v5.27.1 // source: grpc/reflection/v1/reflection.proto diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go index f4a361c64..81ced2fbf 100644 --- a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1/reflection_grpc.pb.go @@ -21,7 +21,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.1 // - protoc v5.27.1 // source: grpc/reflection/v1/reflection.proto diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go index c803cf3ba..6a46bb51f 100644 --- a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection.pb.go @@ -18,7 +18,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.10 +// protoc-gen-go v1.36.11 // protoc v5.27.1 // grpc/reflection/v1alpha/reflection.proto is a deprecated file. diff --git a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go index 0a43b521c..18061e8ba 100644 --- a/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go +++ b/vendor/google.golang.org/grpc/reflection/grpc_reflection_v1alpha/reflection_grpc.pb.go @@ -18,7 +18,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.1 // - protoc v5.27.1 // grpc/reflection/v1alpha/reflection.proto is a deprecated file. diff --git a/vendor/google.golang.org/grpc/resolver/map.go b/vendor/google.golang.org/grpc/resolver/map.go index c3c15ac96..789a5abab 100644 --- a/vendor/google.golang.org/grpc/resolver/map.go +++ b/vendor/google.golang.org/grpc/resolver/map.go @@ -20,6 +20,7 @@ package resolver import ( "encoding/base64" + "iter" "sort" "strings" ) @@ -135,6 +136,7 @@ func (a *AddressMapV2[T]) Len() int { } // Keys returns a slice of all current map keys. +// Deprecated: Use AddressMapV2.All() instead. func (a *AddressMapV2[T]) Keys() []Address { ret := make([]Address, 0, a.Len()) for _, entryList := range a.m { @@ -146,6 +148,7 @@ func (a *AddressMapV2[T]) Keys() []Address { } // Values returns a slice of all current map values. +// Deprecated: Use AddressMapV2.All() instead. func (a *AddressMapV2[T]) Values() []T { ret := make([]T, 0, a.Len()) for _, entryList := range a.m { @@ -156,6 +159,19 @@ func (a *AddressMapV2[T]) Values() []T { return ret } +// All returns an iterator over all elements. +func (a *AddressMapV2[T]) All() iter.Seq2[Address, T] { + return func(yield func(Address, T) bool) { + for _, entryList := range a.m { + for _, entry := range entryList { + if !yield(entry.addr, entry.value) { + return + } + } + } + } +} + type endpointMapKey string // EndpointMap is a map of endpoints to arbitrary values keyed on only the @@ -223,6 +239,7 @@ func (em *EndpointMap[T]) Len() int { // the unordered set of addresses. Thus, endpoint information returned is not // the full endpoint data (drops duplicated addresses and attributes) but can be // used for EndpointMap accesses. +// Deprecated: Use EndpointMap.All() instead. func (em *EndpointMap[T]) Keys() []Endpoint { ret := make([]Endpoint, 0, len(em.endpoints)) for _, en := range em.endpoints { @@ -232,6 +249,7 @@ func (em *EndpointMap[T]) Keys() []Endpoint { } // Values returns a slice of all current map values. +// Deprecated: Use EndpointMap.All() instead. func (em *EndpointMap[T]) Values() []T { ret := make([]T, 0, len(em.endpoints)) for _, val := range em.endpoints { @@ -240,6 +258,22 @@ func (em *EndpointMap[T]) Values() []T { return ret } +// All returns an iterator over all elements. +// The map keys are endpoints specifying the addresses present in the endpoint +// map, in which uniqueness is determined by the unordered set of addresses. +// Thus, endpoint information returned is not the full endpoint data (drops +// duplicated addresses and attributes) but can be used for EndpointMap +// accesses. +func (em *EndpointMap[T]) All() iter.Seq2[Endpoint, T] { + return func(yield func(Endpoint, T) bool) { + for _, en := range em.endpoints { + if !yield(en.decodedKey, en.value) { + return + } + } + } +} + // Delete removes the specified endpoint from the map. func (em *EndpointMap[T]) Delete(e Endpoint) { en := encodeEndpoint(e) diff --git a/vendor/google.golang.org/grpc/resolver/resolver.go b/vendor/google.golang.org/grpc/resolver/resolver.go index 8e6af9514..598ed21a2 100644 --- a/vendor/google.golang.org/grpc/resolver/resolver.go +++ b/vendor/google.golang.org/grpc/resolver/resolver.go @@ -182,6 +182,7 @@ type BuildOptions struct { // An Endpoint is one network endpoint, or server, which may have multiple // addresses with which it can be accessed. +// TODO(i/8773) : make resolver.Endpoint and resolver.Address immutable type Endpoint struct { // Addresses contains a list of addresses used to access this endpoint. Addresses []Address diff --git a/vendor/google.golang.org/grpc/resolver_wrapper.go b/vendor/google.golang.org/grpc/resolver_wrapper.go index 80e16a327..6e6137643 100644 --- a/vendor/google.golang.org/grpc/resolver_wrapper.go +++ b/vendor/google.golang.org/grpc/resolver_wrapper.go @@ -69,6 +69,7 @@ func (ccr *ccResolverWrapper) start() error { errCh := make(chan error) ccr.serializer.TrySchedule(func(ctx context.Context) { if ctx.Err() != nil { + errCh <- ctx.Err() return } opts := resolver.BuildOptions{ diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go index 6b04c9e87..ee7f7dead 100644 --- a/vendor/google.golang.org/grpc/rpc_util.go +++ b/vendor/google.golang.org/grpc/rpc_util.go @@ -33,6 +33,8 @@ import ( "google.golang.org/grpc/credentials" "google.golang.org/grpc/encoding" "google.golang.org/grpc/encoding/proto" + "google.golang.org/grpc/internal" + "google.golang.org/grpc/internal/grpcutil" "google.golang.org/grpc/internal/transport" "google.golang.org/grpc/mem" "google.golang.org/grpc/metadata" @@ -41,6 +43,10 @@ import ( "google.golang.org/grpc/status" ) +func init() { + internal.AcceptCompressors = acceptCompressors +} + // Compressor defines the interface gRPC uses to compress a message. // // Deprecated: use package encoding. @@ -151,16 +157,32 @@ func (d *gzipDecompressor) Type() string { // callInfo contains all related configuration and information about an RPC. type callInfo struct { - compressorName string - failFast bool - maxReceiveMessageSize *int - maxSendMessageSize *int - creds credentials.PerRPCCredentials - contentSubtype string - codec baseCodec - maxRetryRPCBufferSize int - onFinish []func(err error) - authority string + compressorName string + failFast bool + maxReceiveMessageSize *int + maxSendMessageSize *int + creds credentials.PerRPCCredentials + contentSubtype string + codec baseCodec + maxRetryRPCBufferSize int + onFinish []func(err error) + authority string + acceptedResponseCompressors []string +} + +func acceptedCompressorAllows(allowed []string, name string) bool { + if allowed == nil { + return true + } + if name == "" || name == encoding.Identity { + return true + } + for _, a := range allowed { + if a == name { + return true + } + } + return false } func defaultCallInfo() *callInfo { @@ -170,6 +192,29 @@ func defaultCallInfo() *callInfo { } } +func newAcceptedCompressionConfig(names []string) ([]string, error) { + if len(names) == 0 { + return nil, nil + } + var allowed []string + seen := make(map[string]struct{}, len(names)) + for _, name := range names { + name = strings.TrimSpace(name) + if name == "" || name == encoding.Identity { + continue + } + if !grpcutil.IsCompressorNameRegistered(name) { + return nil, status.Errorf(codes.InvalidArgument, "grpc: compressor %q is not registered", name) + } + if _, dup := seen[name]; dup { + continue + } + seen[name] = struct{}{} + allowed = append(allowed, name) + } + return allowed, nil +} + // CallOption configures a Call before it starts or extracts information from // a Call after it completes. type CallOption interface { @@ -471,6 +516,31 @@ func (o CompressorCallOption) before(c *callInfo) error { } func (o CompressorCallOption) after(*callInfo, *csAttempt) {} +// acceptCompressors returns a CallOption that limits the compression algorithms +// advertised in the grpc-accept-encoding header for response messages. +// Compression algorithms not in the provided list will not be advertised, and +// responses compressed with non-listed algorithms will be rejected. +func acceptCompressors(names ...string) CallOption { + cp := append([]string(nil), names...) + return acceptCompressorsCallOption{names: cp} +} + +// acceptCompressorsCallOption is a CallOption that limits response compression. +type acceptCompressorsCallOption struct { + names []string +} + +func (o acceptCompressorsCallOption) before(c *callInfo) error { + allowed, err := newAcceptedCompressionConfig(o.names) + if err != nil { + return err + } + c.acceptedResponseCompressors = allowed + return nil +} + +func (acceptCompressorsCallOption) after(*callInfo, *csAttempt) {} + // CallContentSubtype returns a CallOption that will set the content-subtype // for a call. For example, if content-subtype is "json", the Content-Type over // the wire will be "application/grpc+json". The content-subtype is converted @@ -857,8 +927,7 @@ func (p *payloadInfo) free() { // the buffer is no longer needed. // TODO: Refactor this function to reduce the number of arguments. // See: https://google.github.io/styleguide/go/best-practices.html#function-argument-lists -func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor, isServer bool, -) (out mem.BufferSlice, err error) { +func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor, isServer bool) (out mem.BufferSlice, err error) { pf, compressed, err := p.recvMsg(maxReceiveMessageSize) if err != nil { return nil, err @@ -892,24 +961,32 @@ func recvAndDecompress(p *parser, s recvCompressor, dc Decompressor, maxReceiveM return out, nil } -// decompress processes the given data by decompressing it using either a custom decompressor or a standard compressor. -// If a custom decompressor is provided, it takes precedence. The function validates that the decompressed data -// does not exceed the specified maximum size and returns an error if this limit is exceeded. -// On success, it returns the decompressed data. Otherwise, it returns an error if decompression fails or the data exceeds the size limit. +// decompress processes the given data by decompressing it using either +// a custom decompressor or a standard compressor. If a custom decompressor +// is provided, it takes precedence. The function validates that +// the decompressed data does not exceed the specified maximum size and returns +// an error if this limit is exceeded. On success, it returns the decompressed +// data. Otherwise, it returns an error if decompression fails or the data +// exceeds the size limit. func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompressor, maxReceiveMessageSize int, pool mem.BufferPool) (mem.BufferSlice, error) { if dc != nil { - uncompressed, err := dc.Do(d.Reader()) + r := d.Reader() + uncompressed, err := dc.Do(r) if err != nil { + r.Close() // ensure buffers are reused return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message: %v", err) } if len(uncompressed) > maxReceiveMessageSize { + r.Close() // ensure buffers are reused return nil, status.Errorf(codes.ResourceExhausted, "grpc: message after decompression larger than max (%d vs. %d)", len(uncompressed), maxReceiveMessageSize) } return mem.BufferSlice{mem.SliceBuffer(uncompressed)}, nil } if compressor != nil { - dcReader, err := compressor.Decompress(d.Reader()) + r := d.Reader() + dcReader, err := compressor.Decompress(r) if err != nil { + r.Close() // ensure buffers are reused return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the message: %v", err) } @@ -921,11 +998,13 @@ func decompress(compressor encoding.Compressor, d mem.BufferSlice, dc Decompress } out, err := mem.ReadAll(dcReader, pool) if err != nil { + r.Close() // ensure buffers are reused out.Free() return nil, status.Errorf(codes.Internal, "grpc: failed to read decompressed data: %v", err) } if out.Len() > maxReceiveMessageSize { + r.Close() // ensure buffers are reused out.Free() return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message after decompression larger than max %d", maxReceiveMessageSize) } diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go index ddd377341..5229adf71 100644 --- a/vendor/google.golang.org/grpc/server.go +++ b/vendor/google.golang.org/grpc/server.go @@ -42,6 +42,7 @@ import ( "google.golang.org/grpc/internal" "google.golang.org/grpc/internal/binarylog" "google.golang.org/grpc/internal/channelz" + "google.golang.org/grpc/internal/envconfig" "google.golang.org/grpc/internal/grpcsync" "google.golang.org/grpc/internal/grpcutil" istats "google.golang.org/grpc/internal/stats" @@ -149,6 +150,8 @@ type Server struct { serverWorkerChannel chan func() serverWorkerChannelClose func() + + strictPathCheckingLogEmitted atomic.Bool } type serverOptions struct { @@ -189,6 +192,7 @@ var defaultServerOptions = serverOptions{ maxSendMessageSize: defaultServerMaxSendMessageSize, connectionTimeout: 120 * time.Second, writeBufferSize: defaultWriteBufSize, + sharedWriteBuffer: true, readBufferSize: defaultReadBufSize, bufferPool: mem.DefaultBufferPool(), } @@ -923,9 +927,7 @@ func (s *Server) Serve(lis net.Listener) error { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 - } - if max := 1 * time.Second; tempDelay > max { - tempDelay = max + tempDelay = min(tempDelay, 1*time.Second) } s.mu.Lock() s.printf("Accept error: %v; retrying in %v", err, tempDelay) @@ -1764,6 +1766,24 @@ func (s *Server) processStreamingRPC(ctx context.Context, stream *transport.Serv return ss.s.WriteStatus(statusOK) } +func (s *Server) handleMalformedMethodName(stream *transport.ServerStream, ti *traceInfo) { + if ti != nil { + ti.tr.LazyLog(&fmtStringer{"Malformed method name %q", []any{stream.Method()}}, true) + ti.tr.SetError() + } + errDesc := fmt.Sprintf("malformed method name: %q", stream.Method()) + if err := stream.WriteStatus(status.New(codes.Unimplemented, errDesc)); err != nil { + if ti != nil { + ti.tr.LazyLog(&fmtStringer{"%v", []any{err}}, true) + ti.tr.SetError() + } + channelz.Warningf(logger, s.channelz, "grpc: Server.handleStream failed to write status: %v", err) + } + if ti != nil { + ti.tr.Finish() + } +} + func (s *Server) handleStream(t transport.ServerTransport, stream *transport.ServerStream) { ctx := stream.Context() ctx = contextWithServer(ctx, s) @@ -1784,26 +1804,30 @@ func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Ser } sm := stream.Method() - if sm != "" && sm[0] == '/' { + if sm == "" { + s.handleMalformedMethodName(stream, ti) + return + } + if sm[0] != '/' { + // TODO(easwars): Add a link to the CVE in the below log messages once + // published. + if envconfig.DisableStrictPathChecking { + if old := s.strictPathCheckingLogEmitted.Swap(true); !old { + channelz.Warningf(logger, s.channelz, "grpc: Server.handleStream received malformed method name %q. Allowing it because the environment variable GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING is set to true, but this option will be removed in a future release.", sm) + } + } else { + if old := s.strictPathCheckingLogEmitted.Swap(true); !old { + channelz.Warningf(logger, s.channelz, "grpc: Server.handleStream rejected malformed method name %q. To temporarily allow such requests, set the environment variable GRPC_GO_EXPERIMENTAL_DISABLE_STRICT_PATH_CHECKING to true. Note that this is not recommended as it may allow requests to bypass security policies.", sm) + } + s.handleMalformedMethodName(stream, ti) + return + } + } else { sm = sm[1:] } pos := strings.LastIndex(sm, "/") if pos == -1 { - if ti != nil { - ti.tr.LazyLog(&fmtStringer{"Malformed method name %q", []any{sm}}, true) - ti.tr.SetError() - } - errDesc := fmt.Sprintf("malformed method name: %q", stream.Method()) - if err := stream.WriteStatus(status.New(codes.Unimplemented, errDesc)); err != nil { - if ti != nil { - ti.tr.LazyLog(&fmtStringer{"%v", []any{err}}, true) - ti.tr.SetError() - } - channelz.Warningf(logger, s.channelz, "grpc: Server.handleStream failed to write status: %v", err) - } - if ti != nil { - ti.tr.Finish() - } + s.handleMalformedMethodName(stream, ti) return } service := sm[:pos] diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go index ca87ff977..eedb5f9b9 100644 --- a/vendor/google.golang.org/grpc/stream.go +++ b/vendor/google.golang.org/grpc/stream.go @@ -25,6 +25,7 @@ import ( "math" rand "math/rand/v2" "strconv" + "strings" "sync" "time" @@ -51,7 +52,8 @@ import ( var metadataFromOutgoingContextRaw = internal.FromOutgoingContextRaw.(func(context.Context) (metadata.MD, [][]string, bool)) // StreamHandler defines the handler called by gRPC server to complete the -// execution of a streaming RPC. +// execution of a streaming RPC. srv is the service implementation on which the +// RPC was invoked. // // If a StreamHandler returns an error, it should either be produced by the // status package, or be one of the context errors. Otherwise, gRPC will use @@ -179,13 +181,41 @@ func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth var emptyMethodConfig = serviceconfig.MethodConfig{} +// endOfClientStream performs cleanup actions required for both successful and +// failed streams. This includes incrementing channelz stats and invoking all +// registered OnFinish call options. +func endOfClientStream(cc *ClientConn, err error, opts ...CallOption) { + if channelz.IsOn() { + if err != nil { + cc.incrCallsFailed() + } else { + cc.incrCallsSucceeded() + } + } + + for _, o := range opts { + if o, ok := o.(OnFinishCallOption); ok { + o.OnFinish(err) + } + } +} + func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) { + if channelz.IsOn() { + cc.incrCallsStarted() + } + defer func() { + if err != nil { + // Ensure cleanup when stream creation fails. + endOfClientStream(cc, err, opts...) + } + }() + // Start tracking the RPC for idleness purposes. This is where a stream is // created for both streaming and unary RPCs, and hence is a good place to // track active RPC count. - if err := cc.idlenessMgr.OnCallBegin(); err != nil { - return nil, err - } + cc.idlenessMgr.OnCallBegin() + // Add a calloption, to decrement the active call count, that gets executed // when the RPC completes. opts = append([]CallOption{OnFinish(func(error) { cc.idlenessMgr.OnCallEnd() })}, opts...) @@ -204,14 +234,6 @@ func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, meth } } } - if channelz.IsOn() { - cc.incrCallsStarted() - defer func() { - if err != nil { - cc.incrCallsFailed() - } - }() - } // Provide an opportunity for the first RPC to see the first service config // provided by the resolver. nameResolutionDelayed, err := cc.waitForResolvedAddrs(ctx) @@ -301,6 +323,10 @@ func newClientStreamWithParams(ctx context.Context, desc *StreamDesc, cc *Client DoneFunc: doneFunc, Authority: callInfo.authority, } + if allowed := callInfo.acceptedResponseCompressors; len(allowed) > 0 { + headerValue := strings.Join(allowed, ",") + callHdr.AcceptedCompressors = &headerValue + } // Set our outgoing compression according to the UseCompressor CallOption, if // set. In that case, also find the compressor from the encoding package. @@ -484,7 +510,7 @@ func (a *csAttempt) getTransport() error { return err } if a.trInfo != nil { - a.trInfo.firstLine.SetRemoteAddr(a.transport.RemoteAddr()) + a.trInfo.firstLine.SetRemoteAddr(a.transport.Peer().Addr) } if pick.blocked && a.statsHandler != nil { a.statsHandler.HandleRPC(a.ctx, &stats.DelayedPickComplete{}) @@ -512,9 +538,17 @@ func (a *csAttempt) newStream() error { md, _ := metadata.FromOutgoingContext(a.ctx) md = metadata.Join(md, a.pickResult.Metadata) a.ctx = metadata.NewOutgoingContext(a.ctx, md) - } - s, err := a.transport.NewStream(a.ctx, cs.callHdr) + // If the `CallAuthority` CallOption is not set, check if the LB picker + // has provided an authority override in the PickResult metadata and + // apply it, as specified in gRFC A81. + if cs.callInfo.authority == "" { + if authMD := a.pickResult.Metadata.Get(":authority"); len(authMD) > 0 { + cs.callHdr.Authority = authMD[0] + } + } + } + s, err := a.transport.NewStream(a.ctx, cs.callHdr, a.statsHandler) if err != nil { nse, ok := err.(*transport.NewStreamError) if !ok { @@ -1042,9 +1076,6 @@ func (cs *clientStream) finish(err error) { return } cs.finished = true - for _, onFinish := range cs.callInfo.onFinish { - onFinish(err) - } cs.commitAttemptLocked() if cs.attempt != nil { cs.attempt.finish(err) @@ -1084,13 +1115,7 @@ func (cs *clientStream) finish(err error) { if err == nil { cs.retryThrottler.successfulRPC() } - if channelz.IsOn() { - if err != nil { - cs.cc.incrCallsFailed() - } else { - cs.cc.incrCallsSucceeded() - } - } + endOfClientStream(cs.cc, err, cs.opts...) cs.cancel() } @@ -1134,6 +1159,10 @@ func (a *csAttempt) recvMsg(m any, payInfo *payloadInfo) (err error) { a.decompressorV0 = nil a.decompressorV1 = encoding.GetCompressor(ct) } + // Validate that the compression method is acceptable for this call. + if !acceptedCompressorAllows(cs.callInfo.acceptedResponseCompressors, ct) { + return status.Errorf(codes.Internal, "grpc: peer compressed the response with %q which is not allowed by AcceptCompressors", ct) + } } else { // No compression is used; disable our decompressor. a.decompressorV0 = nil @@ -1321,10 +1350,12 @@ func newNonRetryClientStream(ctx context.Context, desc *StreamDesc, method strin codec: c.codec, sendCompressorV0: cp, sendCompressorV1: comp, + decompressorV0: ac.cc.dopts.dc, transport: t, } - s, err := as.transport.NewStream(as.ctx, as.callHdr) + // nil stats handler: internal streams like health and ORCA do not support telemetry. + s, err := as.transport.NewStream(as.ctx, as.callHdr, nil) if err != nil { err = toRPCErr(err) return nil, err @@ -1479,6 +1510,10 @@ func (as *addrConnStream) RecvMsg(m any) (err error) { as.decompressorV0 = nil as.decompressorV1 = encoding.GetCompressor(ct) } + // Validate that the compression method is acceptable for this call. + if !acceptedCompressorAllows(as.callInfo.acceptedResponseCompressors, ct) { + return status.Errorf(codes.Internal, "grpc: peer compressed the response with %q which is not allowed by AcceptCompressors", ct) + } } else { // No compression is used; disable our decompressor. as.decompressorV0 = nil diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index 9e6d018fb..12f649dcb 100644 --- a/vendor/google.golang.org/grpc/version.go +++ b/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.77.0" +const Version = "1.80.0" diff --git a/vendor/modules.txt b/vendor/modules.txt index 76c360b23..0d3062ba5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -15,29 +15,65 @@ github.com/emicklei/go-restful/v3/log ## explicit; go 1.18 github.com/evanphx/json-patch/v5 github.com/evanphx/json-patch/v5/internal/json -# github.com/fatih/color v1.18.0 -## explicit; go 1.17 +# github.com/fatih/color v1.19.0 +## explicit; go 1.25.0 github.com/fatih/color # github.com/fsnotify/fsnotify v1.9.0 ## explicit; go 1.17 github.com/fsnotify/fsnotify github.com/fsnotify/fsnotify/internal -# github.com/fxamacker/cbor/v2 v2.9.0 +# github.com/fxamacker/cbor/v2 v2.9.1 ## explicit; go 1.20 github.com/fxamacker/cbor/v2 # github.com/go-logr/logr v1.4.3 ## explicit; go 1.18 github.com/go-logr/logr -# github.com/go-openapi/jsonpointer v0.21.1 -## explicit; go 1.20 +# github.com/go-openapi/jsonpointer v0.23.1 +## explicit; go 1.25.0 github.com/go-openapi/jsonpointer -# github.com/go-openapi/jsonreference v0.21.0 -## explicit; go 1.20 +# github.com/go-openapi/jsonreference v0.21.5 +## explicit; go 1.24.0 github.com/go-openapi/jsonreference github.com/go-openapi/jsonreference/internal -# github.com/go-openapi/swag v0.23.1 -## explicit; go 1.20 +# github.com/go-openapi/swag v0.26.0 +## explicit; go 1.25.0 github.com/go-openapi/swag +# github.com/go-openapi/swag/cmdutils v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/cmdutils +# github.com/go-openapi/swag/conv v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/conv +# github.com/go-openapi/swag/fileutils v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/fileutils +# github.com/go-openapi/swag/jsonname v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/jsonname +# github.com/go-openapi/swag/jsonutils v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/jsonutils +github.com/go-openapi/swag/jsonutils/adapters +github.com/go-openapi/swag/jsonutils/adapters/ifaces +github.com/go-openapi/swag/jsonutils/adapters/stdlib/json +# github.com/go-openapi/swag/loading v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/loading +# github.com/go-openapi/swag/mangling v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/mangling +# github.com/go-openapi/swag/netutils v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/netutils +# github.com/go-openapi/swag/stringutils v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/stringutils +# github.com/go-openapi/swag/typeutils v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/typeutils +# github.com/go-openapi/swag/yamlutils v0.26.0 +## explicit; go 1.25.0 +github.com/go-openapi/swag/yamlutils # github.com/gobwas/glob v0.2.3 ## explicit github.com/gobwas/glob @@ -54,7 +90,7 @@ github.com/golang/protobuf/ptypes/empty # github.com/google/btree v1.1.3 ## explicit; go 1.18 github.com/google/btree -# github.com/google/gnostic-models v0.7.0 +# github.com/google/gnostic-models v0.7.1 ## explicit; go 1.22 github.com/google/gnostic-models/compiler github.com/google/gnostic-models/extensions @@ -71,25 +107,22 @@ github.com/google/go-cmp/cmp/internal/value # github.com/google/uuid v1.6.0 ## explicit github.com/google/uuid -# github.com/hashicorp/go-hclog v0.14.1 +# github.com/hashicorp/go-hclog v1.6.3 ## explicit; go 1.13 github.com/hashicorp/go-hclog -# github.com/hashicorp/go-plugin v1.6.0 -## explicit; go 1.17 +# github.com/hashicorp/go-plugin v1.7.0 +## explicit; go 1.24 github.com/hashicorp/go-plugin github.com/hashicorp/go-plugin/internal/cmdrunner github.com/hashicorp/go-plugin/internal/grpcmux github.com/hashicorp/go-plugin/internal/plugin github.com/hashicorp/go-plugin/runner -# github.com/hashicorp/yamux v0.1.1 -## explicit; go 1.15 +# github.com/hashicorp/yamux v0.1.2 +## explicit; go 1.20 github.com/hashicorp/yamux # github.com/inconshreveable/mousetrap v1.1.0 ## explicit; go 1.18 github.com/inconshreveable/mousetrap -# github.com/josharian/intern v1.0.0 -## explicit; go 1.5 -github.com/josharian/intern # github.com/json-iterator/go v1.1.12 ## explicit; go 1.12 github.com/json-iterator/go @@ -97,20 +130,12 @@ github.com/json-iterator/go ## explicit; go 1.22.0 github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumegroupsnapshot/v1beta1 github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1 -# github.com/mailru/easyjson v0.9.0 -## explicit; go 1.20 -github.com/mailru/easyjson/buffer -github.com/mailru/easyjson/jlexer -github.com/mailru/easyjson/jwriter # github.com/mattn/go-colorable v0.1.14 ## explicit; go 1.18 github.com/mattn/go-colorable -# github.com/mattn/go-isatty v0.0.20 -## explicit; go 1.15 +# github.com/mattn/go-isatty v0.0.21 +## explicit; go 1.21 github.com/mattn/go-isatty -# github.com/mitchellh/go-testing-interface v1.0.0 -## explicit -github.com/mitchellh/go-testing-interface # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd ## explicit github.com/modern-go/concurrent @@ -120,8 +145,8 @@ github.com/modern-go/reflect2 # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 ## explicit github.com/munnerz/goautoneg -# github.com/oklog/run v1.0.0 -## explicit +# github.com/oklog/run v1.2.0 +## explicit; go 1.20 github.com/oklog/run # github.com/onsi/gomega v1.39.1 ## explicit; go 1.24.0 @@ -136,15 +161,14 @@ github.com/onsi/gomega/matchers/support/goraph/edge github.com/onsi/gomega/matchers/support/goraph/node github.com/onsi/gomega/matchers/support/goraph/util github.com/onsi/gomega/types -# github.com/openshift/api v0.0.0-20260304122341-cf5d8996109f -## explicit; go 1.24.0 +# github.com/openshift/api v0.0.0-20260424174501-4f63a40a2970 +## explicit; go 1.25.0 github.com/openshift/api/config/v1 +github.com/openshift/api/machine/v1 +github.com/openshift/api/machine/v1beta1 github.com/openshift/api/operator/v1 -# github.com/openshift/custom-resource-status v1.1.3-0.20220503160415-f2fdb4999d87 -## explicit; go 1.12 -github.com/openshift/custom-resource-status/conditions/v1 -# github.com/openshift/hive/apis v0.0.0-20241220022629-3f49f26197ff -## explicit; go 1.21 +# github.com/openshift/hive/apis v0.0.0-20260424180847-6c66e2052422 +## explicit; go 1.24.0 github.com/openshift/hive/apis/hive/v1 github.com/openshift/hive/apis/hive/v1/agent github.com/openshift/hive/apis/hive/v1/aws @@ -154,11 +178,11 @@ github.com/openshift/hive/apis/hive/v1/gcp github.com/openshift/hive/apis/hive/v1/ibmcloud github.com/openshift/hive/apis/hive/v1/metricsconfig github.com/openshift/hive/apis/hive/v1/none +github.com/openshift/hive/apis/hive/v1/nutanix github.com/openshift/hive/apis/hive/v1/openstack -github.com/openshift/hive/apis/hive/v1/ovirt github.com/openshift/hive/apis/hive/v1/vsphere github.com/openshift/hive/apis/scheme -# github.com/openshift/hypershift/api v0.0.0-20260417092826-5431b93cee3c +# github.com/openshift/hypershift/api v0.0.0-20260424195428-c1a8bb61ff14 ## explicit; go 1.25.3 github.com/openshift/hypershift/api/hypershift/v1beta1 github.com/openshift/hypershift/api/ibmcapi @@ -185,8 +209,8 @@ github.com/prometheus/client_model/go ## explicit; go 1.24.0 github.com/prometheus/common/expfmt github.com/prometheus/common/model -# github.com/prometheus/procfs v0.16.1 -## explicit; go 1.23.0 +# github.com/prometheus/procfs v0.20.1 +## explicit; go 1.25.0 github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util @@ -199,7 +223,7 @@ github.com/spf13/cobra # github.com/spf13/pflag v1.0.10 ## explicit; go 1.12 github.com/spf13/pflag -# github.com/vmware-tanzu/velero v1.14.0 => github.com/openshift/velero v0.10.2-0.20260323191807-216dd62a1caf +# github.com/vmware-tanzu/velero v1.18.0 => github.com/openshift/velero v0.10.2-0.20260323191807-216dd62a1caf ## explicit; go 1.25.7 github.com/vmware-tanzu/velero/internal/credentials github.com/vmware-tanzu/velero/internal/resourcepolicies @@ -245,13 +269,13 @@ github.com/vmware-tanzu/velero/third_party/kubernetes/pkg/kubectl/cmd/util # github.com/x448/float16 v0.8.4 ## explicit; go 1.11 github.com/x448/float16 -# go.yaml.in/yaml/v2 v2.4.3 +# go.yaml.in/yaml/v2 v2.4.4 ## explicit; go 1.15 go.yaml.in/yaml/v2 # go.yaml.in/yaml/v3 v3.0.4 ## explicit; go 1.16 go.yaml.in/yaml/v3 -# golang.org/x/net v0.52.0 +# golang.org/x/net v0.53.0 ## explicit; go 1.25.0 golang.org/x/net/html golang.org/x/net/html/atom @@ -264,22 +288,22 @@ golang.org/x/net/internal/httpcommon golang.org/x/net/internal/httpsfv golang.org/x/net/internal/timeseries golang.org/x/net/trace -# golang.org/x/oauth2 v0.35.0 -## explicit; go 1.24.0 +# golang.org/x/oauth2 v0.36.0 +## explicit; go 1.25.0 golang.org/x/oauth2 golang.org/x/oauth2/internal # golang.org/x/sync v0.20.0 ## explicit; go 1.25.0 golang.org/x/sync/errgroup -# golang.org/x/sys v0.42.0 +# golang.org/x/sys v0.43.0 ## explicit; go 1.25.0 golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/term v0.41.0 +# golang.org/x/term v0.42.0 ## explicit; go 1.25.0 golang.org/x/term -# golang.org/x/text v0.35.0 +# golang.org/x/text v0.36.0 ## explicit; go 1.25.0 golang.org/x/text/encoding golang.org/x/text/encoding/charmap @@ -301,16 +325,16 @@ golang.org/x/text/secure/bidirule golang.org/x/text/transform golang.org/x/text/unicode/bidi golang.org/x/text/unicode/norm -# golang.org/x/time v0.14.0 -## explicit; go 1.24.0 +# golang.org/x/time v0.15.0 +## explicit; go 1.25.0 golang.org/x/time/rate # gomodules.xyz/jsonpatch/v2 v2.5.0 ## explicit; go 1.20 gomodules.xyz/jsonpatch/v2 -# google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 -## explicit; go 1.24.0 +# google.golang.org/genproto/googleapis/rpc v0.0.0-20260420184626-e10c466a9529 +## explicit; go 1.25.0 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.77.0 +# google.golang.org/grpc v1.80.0 ## explicit; go 1.24.0 google.golang.org/grpc google.golang.org/grpc/attributes @@ -339,6 +363,7 @@ google.golang.org/grpc/health/grpc_health_v1 google.golang.org/grpc/internal google.golang.org/grpc/internal/backoff google.golang.org/grpc/internal/balancer/gracefulswitch +google.golang.org/grpc/internal/balancer/weight google.golang.org/grpc/internal/balancerload google.golang.org/grpc/internal/binarylog google.golang.org/grpc/internal/buffer @@ -349,6 +374,7 @@ google.golang.org/grpc/internal/grpclog google.golang.org/grpc/internal/grpcsync google.golang.org/grpc/internal/grpcutil google.golang.org/grpc/internal/idle +google.golang.org/grpc/internal/mem google.golang.org/grpc/internal/metadata google.golang.org/grpc/internal/pretty google.golang.org/grpc/internal/proxyattributes